Bitmap.java revision 1fa9d86ea4ce1d2344deaccad002413f88317010
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
19import android.annotation.CheckResult;
20import android.annotation.ColorInt;
21import android.annotation.NonNull;
22import android.annotation.Nullable;
23import android.annotation.Size;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.os.Trace;
27import android.util.DisplayMetrics;
28import android.util.Log;
29import libcore.util.NativeAllocationRegistry;
30
31import java.io.OutputStream;
32import java.nio.Buffer;
33import java.nio.ByteBuffer;
34import java.nio.IntBuffer;
35import java.nio.ShortBuffer;
36
37public final class Bitmap implements Parcelable {
38    private static final String TAG = "Bitmap";
39
40    /**
41     * Indicates that the bitmap was created for an unknown pixel density.
42     *
43     * @see Bitmap#getDensity()
44     * @see Bitmap#setDensity(int)
45     */
46    public static final int DENSITY_NONE = 0;
47
48    // Estimated size of the Bitmap native allocation, not including
49    // pixel data.
50    private static final long NATIVE_ALLOCATION_SIZE = 32;
51
52    // Convenience for JNI access
53    private final long mNativePtr;
54
55    private final boolean mIsMutable;
56
57    /**
58     * Represents whether the Bitmap's content is requested to be pre-multiplied.
59     * Note that isPremultiplied() does not directly return this value, because
60     * isPremultiplied() may never return true for a 565 Bitmap or a bitmap
61     * without alpha.
62     *
63     * setPremultiplied() does directly set the value so that setConfig() and
64     * setPremultiplied() aren't order dependent, despite being setters.
65     *
66     * The native bitmap's premultiplication state is kept up to date by
67     * pushing down this preference for every config change.
68     */
69    private boolean mRequestPremultiplied;
70
71    private byte[] mNinePatchChunk; // may be null
72    private NinePatch.InsetStruct mNinePatchInsets; // may be null
73    private int mWidth;
74    private int mHeight;
75    private boolean mRecycled;
76
77    private ColorSpace mColorSpace;
78
79    /** @hide */
80    public int mDensity = getDefaultDensity();
81
82    private static volatile int sDefaultDensity = -1;
83
84    /**
85     * For backwards compatibility, allows the app layer to change the default
86     * density when running old apps.
87     * @hide
88     */
89    public static void setDefaultDensity(int density) {
90        sDefaultDensity = density;
91    }
92
93    @SuppressWarnings("deprecation")
94    static int getDefaultDensity() {
95        if (sDefaultDensity >= 0) {
96            return sDefaultDensity;
97        }
98        sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
99        return sDefaultDensity;
100    }
101
102    /**
103     * Private constructor that must received an already allocated native bitmap
104     * int (pointer).
105     */
106    // called from JNI
107    Bitmap(long nativeBitmap, int width, int height, int density,
108            boolean isMutable, boolean requestPremultiplied,
109            byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
110        if (nativeBitmap == 0) {
111            throw new RuntimeException("internal error: native bitmap is 0");
112        }
113
114        mWidth = width;
115        mHeight = height;
116        mIsMutable = isMutable;
117        mRequestPremultiplied = requestPremultiplied;
118
119        mNinePatchChunk = ninePatchChunk;
120        mNinePatchInsets = ninePatchInsets;
121        if (density >= 0) {
122            mDensity = density;
123        }
124
125        mNativePtr = nativeBitmap;
126        long nativeSize = NATIVE_ALLOCATION_SIZE + getAllocationByteCount();
127        NativeAllocationRegistry registry = new NativeAllocationRegistry(
128            Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), nativeSize);
129        registry.registerNativeAllocation(this, nativeBitmap);
130    }
131
132    /**
133     * Return the pointer to the native object.
134     * @hide
135     */
136    public long getNativeInstance() {
137        return mNativePtr;
138    }
139
140    /**
141     * Native bitmap has been reconfigured, so set premult and cached
142     * width/height values
143     */
144    @SuppressWarnings("unused") // called from JNI
145    void reinit(int width, int height, boolean requestPremultiplied) {
146        mWidth = width;
147        mHeight = height;
148        mRequestPremultiplied = requestPremultiplied;
149        mColorSpace = null;
150    }
151
152    /**
153     * <p>Returns the density for this bitmap.</p>
154     *
155     * <p>The default density is the same density as the current display,
156     * unless the current application does not support different screen
157     * densities in which case it is
158     * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}.  Note that
159     * compatibility mode is determined by the application that was initially
160     * loaded into a process -- applications that share the same process should
161     * all have the same compatibility, or ensure they explicitly set the
162     * density of their bitmaps appropriately.</p>
163     *
164     * @return A scaling factor of the default density or {@link #DENSITY_NONE}
165     *         if the scaling factor is unknown.
166     *
167     * @see #setDensity(int)
168     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
169     * @see android.util.DisplayMetrics#densityDpi
170     * @see #DENSITY_NONE
171     */
172    public int getDensity() {
173        if (mRecycled) {
174            Log.w(TAG, "Called getDensity() on a recycle()'d bitmap! This is undefined behavior!");
175        }
176        return mDensity;
177    }
178
179    /**
180     * <p>Specifies the density for this bitmap.  When the bitmap is
181     * drawn to a Canvas that also has a density, it will be scaled
182     * appropriately.</p>
183     *
184     * @param density The density scaling factor to use with this bitmap or
185     *        {@link #DENSITY_NONE} if the density is unknown.
186     *
187     * @see #getDensity()
188     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
189     * @see android.util.DisplayMetrics#densityDpi
190     * @see #DENSITY_NONE
191     */
192    public void setDensity(int density) {
193        mDensity = density;
194    }
195
196    /**
197     * <p>Modifies the bitmap to have a specified width, height, and {@link
198     * Config}, without affecting the underlying allocation backing the bitmap.
199     * Bitmap pixel data is not re-initialized for the new configuration.</p>
200     *
201     * <p>This method can be used to avoid allocating a new bitmap, instead
202     * reusing an existing bitmap's allocation for a new configuration of equal
203     * or lesser size. If the Bitmap's allocation isn't large enough to support
204     * the new configuration, an IllegalArgumentException will be thrown and the
205     * bitmap will not be modified.</p>
206     *
207     * <p>The result of {@link #getByteCount()} will reflect the new configuration,
208     * while {@link #getAllocationByteCount()} will reflect that of the initial
209     * configuration.</p>
210     *
211     * <p>Note: This may change this result of hasAlpha(). When converting to 565,
212     * the new bitmap will always be considered opaque. When converting from 565,
213     * the new bitmap will be considered non-opaque, and will respect the value
214     * set by setPremultiplied().</p>
215     *
216     * <p>WARNING: This method should NOT be called on a bitmap currently in use
217     * by the view system, Canvas, or the AndroidBitmap NDK API. It does not
218     * make guarantees about how the underlying pixel buffer is remapped to the
219     * new config, just that the allocation is reused. Additionally, the view
220     * system does not account for bitmap properties being modifying during use,
221     * e.g. while attached to drawables.</p>
222     *
223     * <p>In order to safely ensure that a Bitmap is no longer in use by the
224     * View system it is necessary to wait for a draw pass to occur after
225     * invalidate()'ing any view that had previously drawn the Bitmap in the last
226     * draw pass due to hardware acceleration's caching of draw commands. As
227     * an example, here is how this can be done for an ImageView:
228     * <pre class="prettyprint">
229     *      ImageView myImageView = ...;
230     *      final Bitmap myBitmap = ...;
231     *      myImageView.setImageDrawable(null);
232     *      myImageView.post(new Runnable() {
233     *          public void run() {
234     *              // myBitmap is now no longer in use by the ImageView
235     *              // and can be safely reconfigured.
236     *              myBitmap.reconfigure(...);
237     *          }
238     *      });
239     * </pre></p>
240     *
241     * @see #setWidth(int)
242     * @see #setHeight(int)
243     * @see #setConfig(Config)
244     */
245    public void reconfigure(int width, int height, Config config) {
246        checkRecycled("Can't call reconfigure() on a recycled bitmap");
247        if (width <= 0 || height <= 0) {
248            throw new IllegalArgumentException("width and height must be > 0");
249        }
250        if (!isMutable()) {
251            throw new IllegalStateException("only mutable bitmaps may be reconfigured");
252        }
253
254        nativeReconfigure(mNativePtr, width, height, config.nativeInt, mRequestPremultiplied);
255        mWidth = width;
256        mHeight = height;
257        mColorSpace = null;
258    }
259
260    /**
261     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
262     * with the current height and config.</p>
263     *
264     * <p>WARNING: this method should not be used on bitmaps currently used by
265     * the view system, see {@link #reconfigure(int, int, Config)} for more
266     * details.</p>
267     *
268     * @see #reconfigure(int, int, Config)
269     * @see #setHeight(int)
270     * @see #setConfig(Config)
271     */
272    public void setWidth(int width) {
273        reconfigure(width, getHeight(), getConfig());
274    }
275
276    /**
277     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
278     * with the current width and config.</p>
279     *
280     * <p>WARNING: this method should not be used on bitmaps currently used by
281     * the view system, see {@link #reconfigure(int, int, Config)} for more
282     * details.</p>
283     *
284     * @see #reconfigure(int, int, Config)
285     * @see #setWidth(int)
286     * @see #setConfig(Config)
287     */
288    public void setHeight(int height) {
289        reconfigure(getWidth(), height, getConfig());
290    }
291
292    /**
293     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
294     * with the current height and width.</p>
295     *
296     * <p>WARNING: this method should not be used on bitmaps currently used by
297     * the view system, see {@link #reconfigure(int, int, Config)} for more
298     * details.</p>
299     *
300     * @see #reconfigure(int, int, Config)
301     * @see #setWidth(int)
302     * @see #setHeight(int)
303     */
304    public void setConfig(Config config) {
305        reconfigure(getWidth(), getHeight(), config);
306    }
307
308    /**
309     * Sets the nine patch chunk.
310     *
311     * @param chunk The definition of the nine patch
312     *
313     * @hide
314     */
315    public void setNinePatchChunk(byte[] chunk) {
316        mNinePatchChunk = chunk;
317    }
318
319    /**
320     * Free the native object associated with this bitmap, and clear the
321     * reference to the pixel data. This will not free the pixel data synchronously;
322     * it simply allows it to be garbage collected if there are no other references.
323     * The bitmap is marked as "dead", meaning it will throw an exception if
324     * getPixels() or setPixels() is called, and will draw nothing. This operation
325     * cannot be reversed, so it should only be called if you are sure there are no
326     * further uses for the bitmap. This is an advanced call, and normally need
327     * not be called, since the normal GC process will free up this memory when
328     * there are no more references to this bitmap.
329     */
330    public void recycle() {
331        if (!mRecycled && mNativePtr != 0) {
332            if (nativeRecycle(mNativePtr)) {
333                // return value indicates whether native pixel object was actually recycled.
334                // false indicates that it is still in use at the native level and these
335                // objects should not be collected now. They will be collected later when the
336                // Bitmap itself is collected.
337                mNinePatchChunk = null;
338            }
339            mRecycled = true;
340        }
341    }
342
343    /**
344     * Returns true if this bitmap has been recycled. If so, then it is an error
345     * to try to access its pixels, and the bitmap will not draw.
346     *
347     * @return true if the bitmap has been recycled
348     */
349    public final boolean isRecycled() {
350        return mRecycled;
351    }
352
353    /**
354     * Returns the generation ID of this bitmap. The generation ID changes
355     * whenever the bitmap is modified. This can be used as an efficient way to
356     * check if a bitmap has changed.
357     *
358     * @return The current generation ID for this bitmap.
359     */
360    public int getGenerationId() {
361        if (mRecycled) {
362            Log.w(TAG, "Called getGenerationId() on a recycle()'d bitmap! This is undefined behavior!");
363        }
364        return nativeGenerationId(mNativePtr);
365    }
366
367    /**
368     * This is called by methods that want to throw an exception if the bitmap
369     * has already been recycled.
370     */
371    private void checkRecycled(String errorMessage) {
372        if (mRecycled) {
373            throw new IllegalStateException(errorMessage);
374        }
375    }
376
377    /**
378     * This is called by methods that want to throw an exception if the bitmap
379     * is {@link Config#HARDWARE}.
380     */
381    private void checkHardware(String errorMessage) {
382        if (getConfig() == Config.HARDWARE) {
383            throw new IllegalStateException(errorMessage);
384        }
385    }
386
387    /**
388     * Common code for checking that x and y are >= 0
389     *
390     * @param x x coordinate to ensure is >= 0
391     * @param y y coordinate to ensure is >= 0
392     */
393    private static void checkXYSign(int x, int y) {
394        if (x < 0) {
395            throw new IllegalArgumentException("x must be >= 0");
396        }
397        if (y < 0) {
398            throw new IllegalArgumentException("y must be >= 0");
399        }
400    }
401
402    /**
403     * Common code for checking that width and height are > 0
404     *
405     * @param width  width to ensure is > 0
406     * @param height height to ensure is > 0
407     */
408    private static void checkWidthHeight(int width, int height) {
409        if (width <= 0) {
410            throw new IllegalArgumentException("width must be > 0");
411        }
412        if (height <= 0) {
413            throw new IllegalArgumentException("height must be > 0");
414        }
415    }
416
417    /**
418     * Possible bitmap configurations. A bitmap configuration describes
419     * how pixels are stored. This affects the quality (color depth) as
420     * well as the ability to display transparent/translucent colors.
421     */
422    public enum Config {
423        // these native values must match up with the enum in SkBitmap.h
424
425        /**
426         * Each pixel is stored as a single translucency (alpha) channel.
427         * This is very useful to efficiently store masks for instance.
428         * No color information is stored.
429         * With this configuration, each pixel requires 1 byte of memory.
430         */
431        ALPHA_8     (1),
432
433        /**
434         * Each pixel is stored on 2 bytes and only the RGB channels are
435         * encoded: red is stored with 5 bits of precision (32 possible
436         * values), green is stored with 6 bits of precision (64 possible
437         * values) and blue is stored with 5 bits of precision.
438         *
439         * This configuration can produce slight visual artifacts depending
440         * on the configuration of the source. For instance, without
441         * dithering, the result might show a greenish tint. To get better
442         * results dithering should be applied.
443         *
444         * This configuration may be useful when using opaque bitmaps
445         * that do not require high color fidelity.
446         */
447        RGB_565     (3),
448
449        /**
450         * Each pixel is stored on 2 bytes. The three RGB color channels
451         * and the alpha channel (translucency) are stored with a 4 bits
452         * precision (16 possible values.)
453         *
454         * This configuration is mostly useful if the application needs
455         * to store translucency information but also needs to save
456         * memory.
457         *
458         * It is recommended to use {@link #ARGB_8888} instead of this
459         * configuration.
460         *
461         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
462         * any bitmap created with this configuration will be created
463         * using {@link #ARGB_8888} instead.
464         *
465         * @deprecated Because of the poor quality of this configuration,
466         *             it is advised to use {@link #ARGB_8888} instead.
467         */
468        @Deprecated
469        ARGB_4444   (4),
470
471        /**
472         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
473         * for translucency) is stored with 8 bits of precision (256
474         * possible values.)
475         *
476         * This configuration is very flexible and offers the best
477         * quality. It should be used whenever possible.
478         */
479        ARGB_8888   (5),
480
481        /**
482         * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
483         * for translucency) is stored as a
484         * {@link android.util.Half half-precision floating point value}.
485         *
486         * This configuration is particularly suited for wide-gamut and
487         * HDR content.
488         */
489        RGBA_F16    (6),
490
491        /**
492         * Special configuration, when bitmap is stored only in graphic memory.
493         * Bitmaps in this configuration are always immutable.
494         *
495         * It is optimal for cases, when the only operation with the bitmap is to draw it on a
496         * screen.
497         */
498        HARDWARE    (7);
499
500        final int nativeInt;
501
502        private static Config sConfigs[] = {
503            null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
504        };
505
506        Config(int ni) {
507            this.nativeInt = ni;
508        }
509
510        static Config nativeToConfig(int ni) {
511            return sConfigs[ni];
512        }
513    }
514
515    /**
516     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
517     * caller). An exception is thrown if the buffer is not large enough to
518     * hold all of the pixels (taking into account the number of bytes per
519     * pixel) or if the Buffer subclass is not one of the support types
520     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
521     * <p>The content of the bitmap is copied into the buffer as-is. This means
522     * that if this bitmap stores its pixels pre-multiplied
523     * (see {@link #isPremultiplied()}, the values in the buffer will also be
524     * pre-multiplied. The pixels remain in the color space of the bitmap.</p>
525     * <p>After this method returns, the current position of the buffer is
526     * updated: the position is incremented by the number of elements written
527     * in the buffer.</p>
528     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
529     */
530    public void copyPixelsToBuffer(Buffer dst) {
531        checkHardware("unable to copyPixelsToBuffer, "
532                + "pixel access is not supported on Config#HARDWARE bitmaps");
533        int elements = dst.remaining();
534        int shift;
535        if (dst instanceof ByteBuffer) {
536            shift = 0;
537        } else if (dst instanceof ShortBuffer) {
538            shift = 1;
539        } else if (dst instanceof IntBuffer) {
540            shift = 2;
541        } else {
542            throw new RuntimeException("unsupported Buffer subclass");
543        }
544
545        long bufferSize = (long)elements << shift;
546        long pixelSize = getByteCount();
547
548        if (bufferSize < pixelSize) {
549            throw new RuntimeException("Buffer not large enough for pixels");
550        }
551
552        nativeCopyPixelsToBuffer(mNativePtr, dst);
553
554        // now update the buffer's position
555        int position = dst.position();
556        position += pixelSize >> shift;
557        dst.position(position);
558    }
559
560    /**
561     * <p>Copy the pixels from the buffer, beginning at the current position,
562     * overwriting the bitmap's pixels. The data in the buffer is not changed
563     * in any way (unlike setPixels(), which converts from unpremultipled 32bit
564     * to whatever the bitmap's native format is. The pixels in the source
565     * buffer are assumed to be in the bitmap's color space.</p>
566     * <p>After this method returns, the current position of the buffer is
567     * updated: the position is incremented by the number of elements read from
568     * the buffer. If you need to read the bitmap from the buffer again you must
569     * first rewind the buffer.</p>
570     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
571     */
572    public void copyPixelsFromBuffer(Buffer src) {
573        checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
574        checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable");
575
576        int elements = src.remaining();
577        int shift;
578        if (src instanceof ByteBuffer) {
579            shift = 0;
580        } else if (src instanceof ShortBuffer) {
581            shift = 1;
582        } else if (src instanceof IntBuffer) {
583            shift = 2;
584        } else {
585            throw new RuntimeException("unsupported Buffer subclass");
586        }
587
588        long bufferBytes = (long) elements << shift;
589        long bitmapBytes = getByteCount();
590
591        if (bufferBytes < bitmapBytes) {
592            throw new RuntimeException("Buffer not large enough for pixels");
593        }
594
595        nativeCopyPixelsFromBuffer(mNativePtr, src);
596
597        // now update the buffer's position
598        int position = src.position();
599        position += bitmapBytes >> shift;
600        src.position(position);
601    }
602
603    /**
604     * Tries to make a new bitmap based on the dimensions of this bitmap,
605     * setting the new bitmap's config to the one specified, and then copying
606     * this bitmap's pixels into the new bitmap. If the conversion is not
607     * supported, or the allocator fails, then this returns NULL.  The returned
608     * bitmap has the same density and color space as the original.
609     *
610     * @param config    The desired config for the resulting bitmap
611     * @param isMutable True if the resulting bitmap should be mutable (i.e.
612     *                  its pixels can be modified)
613     * @return the new bitmap, or null if the copy could not be made.
614     * @throws IllegalArgumentException if config is {@link Config#HARDWARE} and isMutable is true
615     */
616    public Bitmap copy(Config config, boolean isMutable) {
617        checkRecycled("Can't copy a recycled bitmap");
618        if (config == Config.HARDWARE && isMutable) {
619            throw new IllegalArgumentException("Hardware bitmaps are always immutable");
620        }
621        Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable);
622        if (b != null) {
623            b.setPremultiplied(mRequestPremultiplied);
624            b.mDensity = mDensity;
625        }
626        return b;
627    }
628
629    /**
630     * Creates a new immutable bitmap backed by ashmem which can efficiently
631     * be passed between processes. The bitmap is assumed to be in the sRGB
632     * color space.
633     *
634     * @hide
635     */
636    public Bitmap createAshmemBitmap() {
637        checkRecycled("Can't copy a recycled bitmap");
638        Bitmap b = nativeCopyAshmem(mNativePtr);
639        if (b != null) {
640            b.setPremultiplied(mRequestPremultiplied);
641            b.mDensity = mDensity;
642        }
643        return b;
644    }
645
646    /**
647     * Creates a new immutable bitmap backed by ashmem which can efficiently
648     * be passed between processes. The bitmap is assumed to be in the sRGB
649     * color space.
650     *
651     * @hide
652     */
653    public Bitmap createAshmemBitmap(Config config) {
654        checkRecycled("Can't copy a recycled bitmap");
655        Bitmap b = nativeCopyAshmemConfig(mNativePtr, config.nativeInt);
656        if (b != null) {
657            b.setPremultiplied(mRequestPremultiplied);
658            b.mDensity = mDensity;
659        }
660        return b;
661    }
662
663    /**
664     * Create hardware bitmap backed GraphicBuffer.
665     *
666     * @return Bitmap or null if this GraphicBuffer has unsupported PixelFormat.
667     *         currently PIXEL_FORMAT_RGBA_8888 is the only supported format
668     * @hide
669     */
670    public static Bitmap createHardwareBitmap(@NonNull GraphicBuffer graphicBuffer) {
671        return nativeCreateHardwareBitmap(graphicBuffer);
672    }
673
674    /**
675     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
676     * specified width and height are the same as the current width and height of
677     * the source bitmap, the source bitmap is returned and no new bitmap is
678     * created.
679     *
680     * @param src       The source bitmap.
681     * @param dstWidth  The new bitmap's desired width.
682     * @param dstHeight The new bitmap's desired height.
683     * @param filter    true if the source should be filtered.
684     * @return The new scaled bitmap or the source bitmap if no scaling is required.
685     * @throws IllegalArgumentException if width is <= 0, or height is <= 0
686     */
687    public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight,
688            boolean filter) {
689        Matrix m = new Matrix();
690
691        final int width = src.getWidth();
692        final int height = src.getHeight();
693        if (width != dstWidth || height != dstHeight) {
694            final float sx = dstWidth / (float) width;
695            final float sy = dstHeight / (float) height;
696            m.setScale(sx, sy);
697        }
698        return Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
699    }
700
701    /**
702     * Returns an immutable bitmap from the source bitmap. The new bitmap may
703     * be the same object as source, or a copy may have been made.  It is
704     * initialized with the same density and color space as the original bitmap.
705     */
706    public static Bitmap createBitmap(@NonNull Bitmap src) {
707        return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
708    }
709
710    /**
711     * Returns an immutable bitmap from the specified subset of the source
712     * bitmap. The new bitmap may be the same object as source, or a copy may
713     * have been made. It is initialized with the same density and color space
714     * as the original bitmap.
715     *
716     * @param source   The bitmap we are subsetting
717     * @param x        The x coordinate of the first pixel in source
718     * @param y        The y coordinate of the first pixel in source
719     * @param width    The number of pixels in each row
720     * @param height   The number of rows
721     * @return A copy of a subset of the source bitmap or the source bitmap itself.
722     * @throws IllegalArgumentException if the x, y, width, height values are
723     *         outside of the dimensions of the source bitmap, or width is <= 0,
724     *         or height is <= 0
725     */
726    public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height) {
727        return createBitmap(source, x, y, width, height, null, false);
728    }
729
730    /**
731     * Returns an immutable bitmap from subset of the source bitmap,
732     * transformed by the optional matrix. The new bitmap may be the
733     * same object as source, or a copy may have been made. It is
734     * initialized with the same density and color space as the original
735     * bitmap.
736     *
737     * If the source bitmap is immutable and the requested subset is the
738     * same as the source bitmap itself, then the source bitmap is
739     * returned and no new bitmap is created.
740     *
741     * @param source   The bitmap we are subsetting
742     * @param x        The x coordinate of the first pixel in source
743     * @param y        The y coordinate of the first pixel in source
744     * @param width    The number of pixels in each row
745     * @param height   The number of rows
746     * @param m        Optional matrix to be applied to the pixels
747     * @param filter   true if the source should be filtered.
748     *                   Only applies if the matrix contains more than just
749     *                   translation.
750     * @return A bitmap that represents the specified subset of source
751     * @throws IllegalArgumentException if the x, y, width, height values are
752     *         outside of the dimensions of the source bitmap, or width is <= 0,
753     *         or height is <= 0
754     */
755    public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height,
756            @Nullable Matrix m, boolean filter) {
757
758        checkXYSign(x, y);
759        checkWidthHeight(width, height);
760        if (x + width > source.getWidth()) {
761            throw new IllegalArgumentException("x + width must be <= bitmap.width()");
762        }
763        if (y + height > source.getHeight()) {
764            throw new IllegalArgumentException("y + height must be <= bitmap.height()");
765        }
766
767        // check if we can just return our argument unchanged
768        if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
769                height == source.getHeight() && (m == null || m.isIdentity())) {
770            return source;
771        }
772
773        boolean isHardware = source.getConfig() == Config.HARDWARE;
774        if (isHardware) {
775            source = nativeCopyPreserveInternalConfig(source.mNativePtr);
776        }
777
778        int neww = width;
779        int newh = height;
780        Bitmap bitmap;
781        Paint paint;
782
783        Rect srcR = new Rect(x, y, x + width, y + height);
784        RectF dstR = new RectF(0, 0, width, height);
785        RectF deviceR = new RectF();
786
787        Config newConfig = Config.ARGB_8888;
788        final Config config = source.getConfig();
789        // GIF files generate null configs, assume ARGB_8888
790        if (config != null) {
791            switch (config) {
792                case RGB_565:
793                    newConfig = Config.RGB_565;
794                    break;
795                case ALPHA_8:
796                    newConfig = Config.ALPHA_8;
797                    break;
798                case RGBA_F16:
799                    newConfig = Config.RGBA_F16;
800                    break;
801                //noinspection deprecation
802                case ARGB_4444:
803                case ARGB_8888:
804                default:
805                    newConfig = Config.ARGB_8888;
806                    break;
807            }
808        }
809
810        if (m == null || m.isIdentity()) {
811            bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
812            paint = null;   // not needed
813        } else {
814            final boolean transformed = !m.rectStaysRect();
815
816            m.mapRect(deviceR, dstR);
817
818            neww = Math.round(deviceR.width());
819            newh = Math.round(deviceR.height());
820
821            Config transformedConfig = newConfig;
822            if (transformed) {
823                if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
824                    transformedConfig = Config.ARGB_8888;
825                }
826            }
827            bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());
828
829            paint = new Paint();
830            paint.setFilterBitmap(filter);
831            if (transformed) {
832                paint.setAntiAlias(true);
833            }
834        }
835
836        nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr);
837
838        // The new bitmap was created from a known bitmap source so assume that
839        // they use the same density
840        bitmap.mDensity = source.mDensity;
841        bitmap.setHasAlpha(source.hasAlpha());
842        bitmap.setPremultiplied(source.mRequestPremultiplied);
843
844        Canvas canvas = new Canvas(bitmap);
845        canvas.translate(-deviceR.left, -deviceR.top);
846        canvas.concat(m);
847        canvas.drawBitmap(source, srcR, dstR, paint);
848        canvas.setBitmap(null);
849        if (isHardware) {
850            return bitmap.copy(Config.HARDWARE, false);
851        }
852        return bitmap;
853    }
854
855    /**
856     * Returns a mutable bitmap with the specified width and height.  Its
857     * initial density is as per {@link #getDensity}. The newly created
858     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
859     *
860     * @param width    The width of the bitmap
861     * @param height   The height of the bitmap
862     * @param config   The bitmap config to create.
863     * @throws IllegalArgumentException if the width or height are <= 0, or if
864     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
865     */
866    public static Bitmap createBitmap(int width, int height, @NonNull Config config) {
867        return createBitmap(width, height, config, true);
868    }
869
870    /**
871     * Returns a mutable bitmap with the specified width and height.  Its
872     * initial density is determined from the given {@link DisplayMetrics}.
873     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
874     * color space.
875     *
876     * @param display  Display metrics for the display this bitmap will be
877     *                 drawn on.
878     * @param width    The width of the bitmap
879     * @param height   The height of the bitmap
880     * @param config   The bitmap config to create.
881     * @throws IllegalArgumentException if the width or height are <= 0, or if
882     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
883     */
884    public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width,
885            int height, @NonNull Config config) {
886        return createBitmap(display, width, height, config, true);
887    }
888
889    /**
890     * Returns a mutable bitmap with the specified width and height.  Its
891     * initial density is as per {@link #getDensity}. The newly created
892     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
893     *
894     * @param width    The width of the bitmap
895     * @param height   The height of the bitmap
896     * @param config   The bitmap config to create.
897     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
898     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
899     *                 instead of transparent.
900     *
901     * @throws IllegalArgumentException if the width or height are <= 0, or if
902     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
903     */
904    public static Bitmap createBitmap(int width, int height,
905            @NonNull Config config, boolean hasAlpha) {
906        return createBitmap(null, width, height, config, hasAlpha);
907    }
908
909    /**
910     * Returns a mutable bitmap with the specified width and height.  Its
911     * initial density is as per {@link #getDensity}.
912     *
913     * @param width    The width of the bitmap
914     * @param height   The height of the bitmap
915     * @param config   The bitmap config to create.
916     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
917     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
918     *                 instead of transparent.
919     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
920     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
921     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
922     *                   is assumed.
923     *
924     * @throws IllegalArgumentException if the width or height are <= 0, if
925     *         Config is Config.HARDWARE (because hardware bitmaps are always
926     *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
927     *         if the specified color space's transfer function is not an
928     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
929     *         the color space is null
930     */
931    public static Bitmap createBitmap(int width, int height, @NonNull Config config,
932            boolean hasAlpha, @NonNull ColorSpace colorSpace) {
933        return createBitmap(null, width, height, config, hasAlpha, colorSpace);
934    }
935
936    /**
937     * Returns a mutable bitmap with the specified width and height.  Its
938     * initial density is determined from the given {@link DisplayMetrics}.
939     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
940     * color space.
941     *
942     * @param display  Display metrics for the display this bitmap will be
943     *                 drawn on.
944     * @param width    The width of the bitmap
945     * @param height   The height of the bitmap
946     * @param config   The bitmap config to create.
947     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
948     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
949     *                 instead of transparent.
950     *
951     * @throws IllegalArgumentException if the width or height are <= 0, or if
952     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
953     */
954    public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
955            @NonNull Config config, boolean hasAlpha) {
956        return createBitmap(display, width, height, config, hasAlpha,
957                ColorSpace.get(ColorSpace.Named.SRGB));
958    }
959
960    /**
961     * Returns a mutable bitmap with the specified width and height.  Its
962     * initial density is determined from the given {@link DisplayMetrics}.
963     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
964     * color space.
965     *
966     * @param display  Display metrics for the display this bitmap will be
967     *                 drawn on.
968     * @param width    The width of the bitmap
969     * @param height   The height of the bitmap
970     * @param config   The bitmap config to create.
971     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
972     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
973     *                 instead of transparent.
974     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
975     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
976     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
977     *                   is assumed.
978     *
979     * @throws IllegalArgumentException if the width or height are <= 0, if
980     *         Config is Config.HARDWARE (because hardware bitmaps are always
981     *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
982     *         if the specified color space's transfer function is not an
983     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
984     *         the color space is null
985     */
986    public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
987            @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) {
988        if (width <= 0 || height <= 0) {
989            throw new IllegalArgumentException("width and height must be > 0");
990        }
991        if (config == Config.HARDWARE) {
992            throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
993        }
994        if (colorSpace == null) {
995            throw new IllegalArgumentException("can't create bitmap without a color space");
996        }
997
998        Bitmap bm;
999        if (config != Config.ARGB_8888) {
1000            bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null);
1001        } else {
1002            if (!(colorSpace instanceof ColorSpace.Rgb)) {
1003                throw new IllegalArgumentException("colorSpace must be an RGB color space");
1004            }
1005            ColorSpace.Rgb rgb = (ColorSpace.Rgb) colorSpace;
1006            ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters();
1007            if (parameters == null) {
1008                throw new IllegalArgumentException("colorSpace must use an ICC "
1009                        + "parametric transfer function");
1010            }
1011
1012            ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50);
1013            bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true,
1014                    d50.getTransform(), parameters);
1015        }
1016
1017        if (display != null) {
1018            bm.mDensity = display.densityDpi;
1019        }
1020        bm.setHasAlpha(hasAlpha);
1021        if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) {
1022            nativeErase(bm.mNativePtr, 0xff000000);
1023        }
1024        // No need to initialize the bitmap to zeroes with other configs;
1025        // it is backed by a VM byte array which is by definition preinitialized
1026        // to all zeroes.
1027        return bm;
1028    }
1029
1030    /**
1031     * Returns a immutable bitmap with the specified width and height, with each
1032     * pixel value set to the corresponding value in the colors array.  Its
1033     * initial density is as per {@link #getDensity}. The newly created
1034     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
1035     *
1036     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1037     * @param offset   Number of values to skip before the first color in the
1038     *                 array of colors.
1039     * @param stride   Number of colors in the array between rows (must be >=
1040     *                 width or <= -width).
1041     * @param width    The width of the bitmap
1042     * @param height   The height of the bitmap
1043     * @param config   The bitmap config to create. If the config does not
1044     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1045     *                 bytes in the colors[] will be ignored (assumed to be FF)
1046     * @throws IllegalArgumentException if the width or height are <= 0, or if
1047     *         the color array's length is less than the number of pixels.
1048     */
1049    public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int offset, int stride,
1050            int width, int height, @NonNull Config config) {
1051        return createBitmap(null, colors, offset, stride, width, height, config);
1052    }
1053
1054    /**
1055     * Returns a immutable bitmap with the specified width and height, with each
1056     * pixel value set to the corresponding value in the colors array.  Its
1057     * initial density is determined from the given {@link DisplayMetrics}.
1058     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
1059     * color space.
1060     *
1061     * @param display  Display metrics for the display this bitmap will be
1062     *                 drawn on.
1063     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1064     * @param offset   Number of values to skip before the first color in the
1065     *                 array of colors.
1066     * @param stride   Number of colors in the array between rows (must be >=
1067     *                 width or <= -width).
1068     * @param width    The width of the bitmap
1069     * @param height   The height of the bitmap
1070     * @param config   The bitmap config to create. If the config does not
1071     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1072     *                 bytes in the colors[] will be ignored (assumed to be FF)
1073     * @throws IllegalArgumentException if the width or height are <= 0, or if
1074     *         the color array's length is less than the number of pixels.
1075     */
1076    public static Bitmap createBitmap(@NonNull DisplayMetrics display,
1077            @NonNull @ColorInt int[] colors, int offset, int stride,
1078            int width, int height, @NonNull Config config) {
1079
1080        checkWidthHeight(width, height);
1081        if (Math.abs(stride) < width) {
1082            throw new IllegalArgumentException("abs(stride) must be >= width");
1083        }
1084        int lastScanline = offset + (height - 1) * stride;
1085        int length = colors.length;
1086        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
1087                (lastScanline + width > length)) {
1088            throw new ArrayIndexOutOfBoundsException();
1089        }
1090        if (width <= 0 || height <= 0) {
1091            throw new IllegalArgumentException("width and height must be > 0");
1092        }
1093        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
1094                            config.nativeInt, false, null, null);
1095        if (display != null) {
1096            bm.mDensity = display.densityDpi;
1097        }
1098        return bm;
1099    }
1100
1101    /**
1102     * Returns a immutable bitmap with the specified width and height, with each
1103     * pixel value set to the corresponding value in the colors array.  Its
1104     * initial density is as per {@link #getDensity}. The newly created
1105     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
1106     *
1107     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1108     *                 This array must be at least as large as width * height.
1109     * @param width    The width of the bitmap
1110     * @param height   The height of the bitmap
1111     * @param config   The bitmap config to create. If the config does not
1112     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1113     *                 bytes in the colors[] will be ignored (assumed to be FF)
1114     * @throws IllegalArgumentException if the width or height are <= 0, or if
1115     *         the color array's length is less than the number of pixels.
1116     */
1117    public static Bitmap createBitmap(@NonNull @ColorInt int[] colors,
1118            int width, int height, Config config) {
1119        return createBitmap(null, colors, 0, width, width, height, config);
1120    }
1121
1122    /**
1123     * Returns a immutable bitmap with the specified width and height, with each
1124     * pixel value set to the corresponding value in the colors array.  Its
1125     * initial density is determined from the given {@link DisplayMetrics}.
1126     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
1127     * color space.
1128     *
1129     * @param display  Display metrics for the display this bitmap will be
1130     *                 drawn on.
1131     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1132     *                 This array must be at least as large as width * height.
1133     * @param width    The width of the bitmap
1134     * @param height   The height of the bitmap
1135     * @param config   The bitmap config to create. If the config does not
1136     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1137     *                 bytes in the colors[] will be ignored (assumed to be FF)
1138     * @throws IllegalArgumentException if the width or height are <= 0, or if
1139     *         the color array's length is less than the number of pixels.
1140     */
1141    public static Bitmap createBitmap(@Nullable DisplayMetrics display,
1142            @NonNull @ColorInt int colors[], int width, int height, @NonNull Config config) {
1143        return createBitmap(display, colors, 0, width, width, height, config);
1144    }
1145
1146    /**
1147     * Returns an optional array of private data, used by the UI system for
1148     * some bitmaps. Not intended to be called by applications.
1149     */
1150    public byte[] getNinePatchChunk() {
1151        return mNinePatchChunk;
1152    }
1153
1154    /**
1155     * Populates a rectangle with the bitmap's optical insets.
1156     *
1157     * @param outInsets Rect to populate with optical insets
1158     * @hide
1159     */
1160    public void getOpticalInsets(@NonNull Rect outInsets) {
1161        if (mNinePatchInsets == null) {
1162            outInsets.setEmpty();
1163        } else {
1164            outInsets.set(mNinePatchInsets.opticalRect);
1165        }
1166    }
1167
1168    /** @hide */
1169    public NinePatch.InsetStruct getNinePatchInsets() {
1170        return mNinePatchInsets;
1171    }
1172
1173    /**
1174     * Specifies the known formats a bitmap can be compressed into
1175     */
1176    public enum CompressFormat {
1177        JPEG    (0),
1178        PNG     (1),
1179        WEBP    (2);
1180
1181        CompressFormat(int nativeInt) {
1182            this.nativeInt = nativeInt;
1183        }
1184        final int nativeInt;
1185    }
1186
1187    /**
1188     * Number of bytes of temp storage we use for communicating between the
1189     * native compressor and the java OutputStream.
1190     */
1191    private final static int WORKING_COMPRESS_STORAGE = 4096;
1192
1193    /**
1194     * Write a compressed version of the bitmap to the specified outputstream.
1195     * If this returns true, the bitmap can be reconstructed by passing a
1196     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
1197     * all Formats support all bitmap configs directly, so it is possible that
1198     * the returned bitmap from BitmapFactory could be in a different bitdepth,
1199     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
1200     * pixels).
1201     *
1202     * @param format   The format of the compressed image
1203     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
1204     *                 small size, 100 meaning compress for max quality. Some
1205     *                 formats, like PNG which is lossless, will ignore the
1206     *                 quality setting
1207     * @param stream   The outputstream to write the compressed data.
1208     * @return true if successfully compressed to the specified stream.
1209     */
1210    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
1211        checkRecycled("Can't compress a recycled bitmap");
1212        // do explicit check before calling the native method
1213        if (stream == null) {
1214            throw new NullPointerException();
1215        }
1216        if (quality < 0 || quality > 100) {
1217            throw new IllegalArgumentException("quality must be 0..100");
1218        }
1219        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
1220        boolean result = nativeCompress(mNativePtr, format.nativeInt,
1221                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
1222        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1223        return result;
1224    }
1225
1226    /**
1227     * Returns true if the bitmap is marked as mutable (i.e.&nbsp;can be drawn into)
1228     */
1229    public final boolean isMutable() {
1230        return mIsMutable;
1231    }
1232
1233    /**
1234     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
1235     * When a pixel is pre-multiplied, the RGB components have been multiplied by
1236     * the alpha component. For instance, if the original color is a 50%
1237     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
1238     * <code>(128, 128, 0, 0)</code>.</p>
1239     *
1240     * <p>This method always returns false if {@link #getConfig()} is
1241     * {@link Bitmap.Config#RGB_565}.</p>
1242     *
1243     * <p>The return value is undefined if {@link #getConfig()} is
1244     * {@link Bitmap.Config#ALPHA_8}.</p>
1245     *
1246     * <p>This method only returns true if {@link #hasAlpha()} returns true.
1247     * A bitmap with no alpha channel can be used both as a pre-multiplied and
1248     * as a non pre-multiplied bitmap.</p>
1249     *
1250     * <p>Only pre-multiplied bitmaps may be drawn by the view system or
1251     * {@link Canvas}. If a non-pre-multiplied bitmap with an alpha channel is
1252     * drawn to a Canvas, a RuntimeException will be thrown.</p>
1253     *
1254     * @return true if the underlying pixels have been pre-multiplied, false
1255     *         otherwise
1256     *
1257     * @see Bitmap#setPremultiplied(boolean)
1258     * @see BitmapFactory.Options#inPremultiplied
1259     */
1260    public final boolean isPremultiplied() {
1261        if (mRecycled) {
1262            Log.w(TAG, "Called isPremultiplied() on a recycle()'d bitmap! This is undefined behavior!");
1263        }
1264        return nativeIsPremultiplied(mNativePtr);
1265    }
1266
1267    /**
1268     * Sets whether the bitmap should treat its data as pre-multiplied.
1269     *
1270     * <p>Bitmaps are always treated as pre-multiplied by the view system and
1271     * {@link Canvas} for performance reasons. Storing un-pre-multiplied data in
1272     * a Bitmap (through {@link #setPixel}, {@link #setPixels}, or {@link
1273     * BitmapFactory.Options#inPremultiplied BitmapFactory.Options.inPremultiplied})
1274     * can lead to incorrect blending if drawn by the framework.</p>
1275     *
1276     * <p>This method will not affect the behavior of a bitmap without an alpha
1277     * channel, or if {@link #hasAlpha()} returns false.</p>
1278     *
1279     * <p>Calling {@link #createBitmap} or {@link #createScaledBitmap} with a source
1280     * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
1281     * since those functions require drawing the source, which is not supported for
1282     * un-pre-multiplied Bitmaps.</p>
1283     *
1284     * @see Bitmap#isPremultiplied()
1285     * @see BitmapFactory.Options#inPremultiplied
1286     */
1287    public final void setPremultiplied(boolean premultiplied) {
1288        checkRecycled("setPremultiplied called on a recycled bitmap");
1289        mRequestPremultiplied = premultiplied;
1290        nativeSetPremultiplied(mNativePtr, premultiplied);
1291    }
1292
1293    /** Returns the bitmap's width */
1294    public final int getWidth() {
1295        if (mRecycled) {
1296            Log.w(TAG, "Called getWidth() on a recycle()'d bitmap! This is undefined behavior!");
1297        }
1298        return mWidth;
1299    }
1300
1301    /** Returns the bitmap's height */
1302    public final int getHeight() {
1303        if (mRecycled) {
1304            Log.w(TAG, "Called getHeight() on a recycle()'d bitmap! This is undefined behavior!");
1305        }
1306        return mHeight;
1307    }
1308
1309    /**
1310     * Convenience for calling {@link #getScaledWidth(int)} with the target
1311     * density of the given {@link Canvas}.
1312     */
1313    public int getScaledWidth(Canvas canvas) {
1314        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
1315    }
1316
1317    /**
1318     * Convenience for calling {@link #getScaledHeight(int)} with the target
1319     * density of the given {@link Canvas}.
1320     */
1321    public int getScaledHeight(Canvas canvas) {
1322        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
1323    }
1324
1325    /**
1326     * Convenience for calling {@link #getScaledWidth(int)} with the target
1327     * density of the given {@link DisplayMetrics}.
1328     */
1329    public int getScaledWidth(DisplayMetrics metrics) {
1330        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
1331    }
1332
1333    /**
1334     * Convenience for calling {@link #getScaledHeight(int)} with the target
1335     * density of the given {@link DisplayMetrics}.
1336     */
1337    public int getScaledHeight(DisplayMetrics metrics) {
1338        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
1339    }
1340
1341    /**
1342     * Convenience method that returns the width of this bitmap divided
1343     * by the density scale factor.
1344     *
1345     * @param targetDensity The density of the target canvas of the bitmap.
1346     * @return The scaled width of this bitmap, according to the density scale factor.
1347     */
1348    public int getScaledWidth(int targetDensity) {
1349        return scaleFromDensity(getWidth(), mDensity, targetDensity);
1350    }
1351
1352    /**
1353     * Convenience method that returns the height of this bitmap divided
1354     * by the density scale factor.
1355     *
1356     * @param targetDensity The density of the target canvas of the bitmap.
1357     * @return The scaled height of this bitmap, according to the density scale factor.
1358     */
1359    public int getScaledHeight(int targetDensity) {
1360        return scaleFromDensity(getHeight(), mDensity, targetDensity);
1361    }
1362
1363    /**
1364     * @hide
1365     */
1366    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
1367        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
1368            return size;
1369        }
1370
1371        // Scale by tdensity / sdensity, rounding up.
1372        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
1373    }
1374
1375    /**
1376     * Return the number of bytes between rows in the bitmap's pixels. Note that
1377     * this refers to the pixels as stored natively by the bitmap. If you call
1378     * getPixels() or setPixels(), then the pixels are uniformly treated as
1379     * 32bit values, packed according to the Color class.
1380     *
1381     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, this method
1382     * should not be used to calculate the memory usage of the bitmap. Instead,
1383     * see {@link #getAllocationByteCount()}.
1384     *
1385     * @return number of bytes between rows of the native bitmap pixels.
1386     */
1387    public final int getRowBytes() {
1388        if (mRecycled) {
1389            Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");
1390        }
1391        return nativeRowBytes(mNativePtr);
1392    }
1393
1394    /**
1395     * Returns the minimum number of bytes that can be used to store this bitmap's pixels.
1396     *
1397     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can
1398     * no longer be used to determine memory usage of a bitmap. See {@link
1399     * #getAllocationByteCount()}.</p>
1400     */
1401    public final int getByteCount() {
1402        if (mRecycled) {
1403            Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! "
1404                    + "This is undefined behavior!");
1405            return 0;
1406        }
1407        // int result permits bitmaps up to 46,340 x 46,340
1408        return getRowBytes() * getHeight();
1409    }
1410
1411    /**
1412     * Returns the size of the allocated memory used to store this bitmap's pixels.
1413     *
1414     * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to
1415     * decode other bitmaps of smaller size, or by manual reconfiguration. See {@link
1416     * #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link
1417     * #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap
1418     * BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be
1419     * the same as that returned by {@link #getByteCount()}.</p>
1420     *
1421     * <p>This value will not change over the lifetime of a Bitmap.</p>
1422     *
1423     * @see #reconfigure(int, int, Config)
1424     */
1425    public final int getAllocationByteCount() {
1426        if (mRecycled) {
1427            Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
1428                    + "This is undefined behavior!");
1429            return 0;
1430        }
1431        return nativeGetAllocationByteCount(mNativePtr);
1432    }
1433
1434    /**
1435     * If the bitmap's internal config is in one of the public formats, return
1436     * that config, otherwise return null.
1437     */
1438    public final Config getConfig() {
1439        if (mRecycled) {
1440            Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!");
1441        }
1442        return Config.nativeToConfig(nativeConfig(mNativePtr));
1443    }
1444
1445    /** Returns true if the bitmap's config supports per-pixel alpha, and
1446     * if the pixels may contain non-opaque alpha values. For some configs,
1447     * this is always false (e.g. RGB_565), since they do not support per-pixel
1448     * alpha. However, for configs that do, the bitmap may be flagged to be
1449     * known that all of its pixels are opaque. In this case hasAlpha() will
1450     * also return false. If a config such as ARGB_8888 is not so flagged,
1451     * it will return true by default.
1452     */
1453    public final boolean hasAlpha() {
1454        if (mRecycled) {
1455            Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!");
1456        }
1457        return nativeHasAlpha(mNativePtr);
1458    }
1459
1460    /**
1461     * Tell the bitmap if all of the pixels are known to be opaque (false)
1462     * or if some of the pixels may contain non-opaque alpha values (true).
1463     * Note, for some configs (e.g. RGB_565) this call is ignored, since it
1464     * does not support per-pixel alpha values.
1465     *
1466     * This is meant as a drawing hint, as in some cases a bitmap that is known
1467     * to be opaque can take a faster drawing case than one that may have
1468     * non-opaque per-pixel alpha values.
1469     */
1470    public void setHasAlpha(boolean hasAlpha) {
1471        checkRecycled("setHasAlpha called on a recycled bitmap");
1472        nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied);
1473    }
1474
1475    /**
1476     * Indicates whether the renderer responsible for drawing this
1477     * bitmap should attempt to use mipmaps when this bitmap is drawn
1478     * scaled down.
1479     *
1480     * If you know that you are going to draw this bitmap at less than
1481     * 50% of its original size, you may be able to obtain a higher
1482     * quality
1483     *
1484     * This property is only a suggestion that can be ignored by the
1485     * renderer. It is not guaranteed to have any effect.
1486     *
1487     * @return true if the renderer should attempt to use mipmaps,
1488     *         false otherwise
1489     *
1490     * @see #setHasMipMap(boolean)
1491     */
1492    public final boolean hasMipMap() {
1493        if (mRecycled) {
1494            Log.w(TAG, "Called hasMipMap() on a recycle()'d bitmap! This is undefined behavior!");
1495        }
1496        return nativeHasMipMap(mNativePtr);
1497    }
1498
1499    /**
1500     * Set a hint for the renderer responsible for drawing this bitmap
1501     * indicating that it should attempt to use mipmaps when this bitmap
1502     * is drawn scaled down.
1503     *
1504     * If you know that you are going to draw this bitmap at less than
1505     * 50% of its original size, you may be able to obtain a higher
1506     * quality by turning this property on.
1507     *
1508     * Note that if the renderer respects this hint it might have to
1509     * allocate extra memory to hold the mipmap levels for this bitmap.
1510     *
1511     * This property is only a suggestion that can be ignored by the
1512     * renderer. It is not guaranteed to have any effect.
1513     *
1514     * @param hasMipMap indicates whether the renderer should attempt
1515     *                  to use mipmaps
1516     *
1517     * @see #hasMipMap()
1518     */
1519    public final void setHasMipMap(boolean hasMipMap) {
1520        checkRecycled("setHasMipMap called on a recycled bitmap");
1521        nativeSetHasMipMap(mNativePtr, hasMipMap);
1522    }
1523
1524    /**
1525     * Returns the color space associated with this bitmap. If the color
1526     * space is unknown, this method returns null.
1527     */
1528    @Nullable
1529    public final ColorSpace getColorSpace() {
1530        // A reconfigure can change the configuration and rgba16f is
1531        // always linear scRGB at this time
1532        if (getConfig() == Config.RGBA_F16) {
1533            // Reset the color space for potential future reconfigurations
1534            mColorSpace = null;
1535            return ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
1536        }
1537
1538        // Cache the color space retrieval since it can be fairly expensive
1539        if (mColorSpace == null) {
1540            if (nativeIsSRGB(mNativePtr)) {
1541                mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
1542            } else {
1543                float[] xyz = new float[9];
1544                float[] params = new float[7];
1545
1546                boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params);
1547                if (hasColorSpace) {
1548                    ColorSpace.Rgb.TransferParameters parameters =
1549                            new ColorSpace.Rgb.TransferParameters(
1550                                    params[0], params[1], params[2],
1551                                    params[3], params[4], params[5], params[6]);
1552                    ColorSpace cs = ColorSpace.match(xyz, parameters);
1553                    if (cs != null) {
1554                        mColorSpace = cs;
1555                    } else {
1556                        mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters);
1557                    }
1558                }
1559            }
1560        }
1561
1562        return mColorSpace;
1563    }
1564
1565    /**
1566     * Fills the bitmap's pixels with the specified {@link Color}.
1567     *
1568     * @throws IllegalStateException if the bitmap is not mutable.
1569     */
1570    public void eraseColor(@ColorInt int c) {
1571        checkRecycled("Can't erase a recycled bitmap");
1572        if (!isMutable()) {
1573            throw new IllegalStateException("cannot erase immutable bitmaps");
1574        }
1575        nativeErase(mNativePtr, c);
1576    }
1577
1578    /**
1579     * Returns the {@link Color} at the specified location. Throws an exception
1580     * if x or y are out of bounds (negative or >= to the width or height
1581     * respectively). The returned color is a non-premultiplied ARGB value in
1582     * the {@link ColorSpace.Named#SRGB sRGB} color space.
1583     *
1584     * @param x    The x coordinate (0...width-1) of the pixel to return
1585     * @param y    The y coordinate (0...height-1) of the pixel to return
1586     * @return     The argb {@link Color} at the specified coordinate
1587     * @throws IllegalArgumentException if x, y exceed the bitmap's bounds
1588     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1589     */
1590    @ColorInt
1591    public int getPixel(int x, int y) {
1592        checkRecycled("Can't call getPixel() on a recycled bitmap");
1593        checkHardware("unable to getPixel(), "
1594                + "pixel access is not supported on Config#HARDWARE bitmaps");
1595        checkPixelAccess(x, y);
1596        return nativeGetPixel(mNativePtr, x, y);
1597    }
1598
1599    /**
1600     * Returns in pixels[] a copy of the data in the bitmap. Each value is
1601     * a packed int representing a {@link Color}. The stride parameter allows
1602     * the caller to allow for gaps in the returned pixels array between
1603     * rows. For normal packed results, just pass width for the stride value.
1604     * The returned colors are non-premultiplied ARGB values in the
1605     * {@link ColorSpace.Named#SRGB sRGB} color space.
1606     *
1607     * @param pixels   The array to receive the bitmap's colors
1608     * @param offset   The first index to write into pixels[]
1609     * @param stride   The number of entries in pixels[] to skip between
1610     *                 rows (must be >= bitmap's width). Can be negative.
1611     * @param x        The x coordinate of the first pixel to read from
1612     *                 the bitmap
1613     * @param y        The y coordinate of the first pixel to read from
1614     *                 the bitmap
1615     * @param width    The number of pixels to read from each row
1616     * @param height   The number of rows to read
1617     *
1618     * @throws IllegalArgumentException if x, y, width, height exceed the
1619     *         bounds of the bitmap, or if abs(stride) < width.
1620     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1621     *         to receive the specified number of pixels.
1622     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1623     */
1624    public void getPixels(@ColorInt int[] pixels, int offset, int stride,
1625                          int x, int y, int width, int height) {
1626        checkRecycled("Can't call getPixels() on a recycled bitmap");
1627        checkHardware("unable to getPixels(), "
1628                + "pixel access is not supported on Config#HARDWARE bitmaps");
1629        if (width == 0 || height == 0) {
1630            return; // nothing to do
1631        }
1632        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1633        nativeGetPixels(mNativePtr, pixels, offset, stride,
1634                        x, y, width, height);
1635    }
1636
1637    /**
1638     * Shared code to check for illegal arguments passed to getPixel()
1639     * or setPixel()
1640     *
1641     * @param x x coordinate of the pixel
1642     * @param y y coordinate of the pixel
1643     */
1644    private void checkPixelAccess(int x, int y) {
1645        checkXYSign(x, y);
1646        if (x >= getWidth()) {
1647            throw new IllegalArgumentException("x must be < bitmap.width()");
1648        }
1649        if (y >= getHeight()) {
1650            throw new IllegalArgumentException("y must be < bitmap.height()");
1651        }
1652    }
1653
1654    /**
1655     * Shared code to check for illegal arguments passed to getPixels()
1656     * or setPixels()
1657     *
1658     * @param x left edge of the area of pixels to access
1659     * @param y top edge of the area of pixels to access
1660     * @param width width of the area of pixels to access
1661     * @param height height of the area of pixels to access
1662     * @param offset offset into pixels[] array
1663     * @param stride number of elements in pixels[] between each logical row
1664     * @param pixels array to hold the area of pixels being accessed
1665    */
1666    private void checkPixelsAccess(int x, int y, int width, int height,
1667                                   int offset, int stride, int pixels[]) {
1668        checkXYSign(x, y);
1669        if (width < 0) {
1670            throw new IllegalArgumentException("width must be >= 0");
1671        }
1672        if (height < 0) {
1673            throw new IllegalArgumentException("height must be >= 0");
1674        }
1675        if (x + width > getWidth()) {
1676            throw new IllegalArgumentException(
1677                    "x + width must be <= bitmap.width()");
1678        }
1679        if (y + height > getHeight()) {
1680            throw new IllegalArgumentException(
1681                    "y + height must be <= bitmap.height()");
1682        }
1683        if (Math.abs(stride) < width) {
1684            throw new IllegalArgumentException("abs(stride) must be >= width");
1685        }
1686        int lastScanline = offset + (height - 1) * stride;
1687        int length = pixels.length;
1688        if (offset < 0 || (offset + width > length)
1689                || lastScanline < 0
1690                || (lastScanline + width > length)) {
1691            throw new ArrayIndexOutOfBoundsException();
1692        }
1693    }
1694
1695    /**
1696     * <p>Write the specified {@link Color} into the bitmap (assuming it is
1697     * mutable) at the x,y coordinate. The color must be a
1698     * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
1699     * color space.</p>
1700     *
1701     * @param x     The x coordinate of the pixel to replace (0...width-1)
1702     * @param y     The y coordinate of the pixel to replace (0...height-1)
1703     * @param color The ARGB color to write into the bitmap
1704     *
1705     * @throws IllegalStateException if the bitmap is not mutable
1706     * @throws IllegalArgumentException if x, y are outside of the bitmap's
1707     *         bounds.
1708     */
1709    public void setPixel(int x, int y, @ColorInt int color) {
1710        checkRecycled("Can't call setPixel() on a recycled bitmap");
1711        if (!isMutable()) {
1712            throw new IllegalStateException();
1713        }
1714        checkPixelAccess(x, y);
1715        nativeSetPixel(mNativePtr, x, y, color);
1716    }
1717
1718    /**
1719     * <p>Replace pixels in the bitmap with the colors in the array. Each element
1720     * in the array is a packed int representing a non-premultiplied ARGB
1721     * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
1722     *
1723     * @param pixels   The colors to write to the bitmap
1724     * @param offset   The index of the first color to read from pixels[]
1725     * @param stride   The number of colors in pixels[] to skip between rows.
1726     *                 Normally this value will be the same as the width of
1727     *                 the bitmap, but it can be larger (or negative).
1728     * @param x        The x coordinate of the first pixel to write to in
1729     *                 the bitmap.
1730     * @param y        The y coordinate of the first pixel to write to in
1731     *                 the bitmap.
1732     * @param width    The number of colors to copy from pixels[] per row
1733     * @param height   The number of rows to write to the bitmap
1734     *
1735     * @throws IllegalStateException if the bitmap is not mutable
1736     * @throws IllegalArgumentException if x, y, width, height are outside of
1737     *         the bitmap's bounds.
1738     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1739     *         to receive the specified number of pixels.
1740     */
1741    public void setPixels(@ColorInt int[] pixels, int offset, int stride,
1742            int x, int y, int width, int height) {
1743        checkRecycled("Can't call setPixels() on a recycled bitmap");
1744        if (!isMutable()) {
1745            throw new IllegalStateException();
1746        }
1747        if (width == 0 || height == 0) {
1748            return; // nothing to do
1749        }
1750        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1751        nativeSetPixels(mNativePtr, pixels, offset, stride,
1752                        x, y, width, height);
1753    }
1754
1755    public static final Parcelable.Creator<Bitmap> CREATOR
1756            = new Parcelable.Creator<Bitmap>() {
1757        /**
1758         * Rebuilds a bitmap previously stored with writeToParcel().
1759         *
1760         * @param p    Parcel object to read the bitmap from
1761         * @return a new bitmap created from the data in the parcel
1762         */
1763        public Bitmap createFromParcel(Parcel p) {
1764            Bitmap bm = nativeCreateFromParcel(p);
1765            if (bm == null) {
1766                throw new RuntimeException("Failed to unparcel Bitmap");
1767            }
1768            return bm;
1769        }
1770        public Bitmap[] newArray(int size) {
1771            return new Bitmap[size];
1772        }
1773    };
1774
1775    /**
1776     * No special parcel contents.
1777     */
1778    public int describeContents() {
1779        return 0;
1780    }
1781
1782    /**
1783     * Write the bitmap and its pixels to the parcel. The bitmap can be
1784     * rebuilt from the parcel by calling CREATOR.createFromParcel().
1785     *
1786     * If this bitmap is {@link Config#HARDWARE}, it may be unparceled with a different pixel
1787     * format (e.g. 565, 8888), but the content will be preserved to the best quality permitted
1788     * by the final pixel format
1789     * @param p    Parcel object to write the bitmap data into
1790     */
1791    public void writeToParcel(Parcel p, int flags) {
1792        checkRecycled("Can't parcel a recycled bitmap");
1793        if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) {
1794            throw new RuntimeException("native writeToParcel failed");
1795        }
1796    }
1797
1798    /**
1799     * Returns a new bitmap that captures the alpha values of the original.
1800     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be
1801     * taken from the paint that is passed to the draw call.
1802     *
1803     * @return new bitmap containing the alpha channel of the original bitmap.
1804     */
1805    @CheckResult
1806    public Bitmap extractAlpha() {
1807        return extractAlpha(null, null);
1808    }
1809
1810    /**
1811     * Returns a new bitmap that captures the alpha values of the original.
1812     * These values may be affected by the optional Paint parameter, which
1813     * can contain its own alpha, and may also contain a MaskFilter which
1814     * could change the actual dimensions of the resulting bitmap (e.g.
1815     * a blur maskfilter might enlarge the resulting bitmap). If offsetXY
1816     * is not null, it returns the amount to offset the returned bitmap so
1817     * that it will logically align with the original. For example, if the
1818     * paint contains a blur of radius 2, then offsetXY[] would contains
1819     * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
1820     * drawing the original would result in the blur visually aligning with
1821     * the original.
1822     *
1823     * <p>The initial density of the returned bitmap is the same as the original's.
1824     *
1825     * @param paint Optional paint used to modify the alpha values in the
1826     *              resulting bitmap. Pass null for default behavior.
1827     * @param offsetXY Optional array that returns the X (index 0) and Y
1828     *                 (index 1) offset needed to position the returned bitmap
1829     *                 so that it visually lines up with the original.
1830     * @return new bitmap containing the (optionally modified by paint) alpha
1831     *         channel of the original bitmap. This may be drawn with
1832     *         Canvas.drawBitmap(), where the color(s) will be taken from the
1833     *         paint that is passed to the draw call.
1834     */
1835    @CheckResult
1836    public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
1837        checkRecycled("Can't extractAlpha on a recycled bitmap");
1838        long nativePaint = paint != null ? paint.getNativeInstance() : 0;
1839        Bitmap bm = nativeExtractAlpha(mNativePtr, nativePaint, offsetXY);
1840        if (bm == null) {
1841            throw new RuntimeException("Failed to extractAlpha on Bitmap");
1842        }
1843        bm.mDensity = mDensity;
1844        return bm;
1845    }
1846
1847    /**
1848     *  Given another bitmap, return true if it has the same dimensions, config,
1849     *  and pixel data as this bitmap. If any of those differ, return false.
1850     *  If other is null, return false.
1851     */
1852    public boolean sameAs(Bitmap other) {
1853        checkRecycled("Can't call sameAs on a recycled bitmap!");
1854        if (this == other) return true;
1855        if (other == null) return false;
1856        if (other.isRecycled()) {
1857            throw new IllegalArgumentException("Can't compare to a recycled bitmap!");
1858        }
1859        return nativeSameAs(mNativePtr, other.mNativePtr);
1860    }
1861
1862    /**
1863     * Rebuilds any caches associated with the bitmap that are used for
1864     * drawing it. In the case of purgeable bitmaps, this call will attempt to
1865     * ensure that the pixels have been decoded.
1866     * If this is called on more than one bitmap in sequence, the priority is
1867     * given in LRU order (i.e. the last bitmap called will be given highest
1868     * priority).
1869     *
1870     * For bitmaps with no associated caches, this call is effectively a no-op,
1871     * and therefore is harmless.
1872     */
1873    public void prepareToDraw() {
1874        checkRecycled("Can't prepareToDraw on a recycled bitmap!");
1875        // Kick off an update/upload of the bitmap outside of the normal
1876        // draw path.
1877        nativePrepareToDraw(mNativePtr);
1878    }
1879
1880    /**
1881     *
1882     * @return {@link GraphicBuffer} which is internally used by hardware bitmap
1883     * @hide
1884     */
1885    public GraphicBuffer createGraphicBufferHandle() {
1886        return nativeCreateGraphicBufferHandle(mNativePtr);
1887    }
1888
1889    //////////// native methods
1890
1891    private static native Bitmap nativeCreate(int[] colors, int offset,
1892                                              int stride, int width, int height,
1893                                              int nativeConfig, boolean mutable,
1894                                              @Nullable @Size(9) float[] xyzD50,
1895                                              @Nullable ColorSpace.Rgb.TransferParameters p);
1896    private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig,
1897                                            boolean isMutable);
1898    private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap);
1899    private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
1900    private static native long nativeGetNativeFinalizer();
1901    private static native boolean nativeRecycle(long nativeBitmap);
1902    private static native void nativeReconfigure(long nativeBitmap, int width, int height,
1903                                                 int config, boolean isPremultiplied);
1904
1905    private static native boolean nativeCompress(long nativeBitmap, int format,
1906                                            int quality, OutputStream stream,
1907                                            byte[] tempStorage);
1908    private static native void nativeErase(long nativeBitmap, int color);
1909    private static native int nativeRowBytes(long nativeBitmap);
1910    private static native int nativeConfig(long nativeBitmap);
1911
1912    private static native int nativeGetPixel(long nativeBitmap, int x, int y);
1913    private static native void nativeGetPixels(long nativeBitmap, int[] pixels,
1914                                               int offset, int stride, int x, int y,
1915                                               int width, int height);
1916
1917    private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color);
1918    private static native void nativeSetPixels(long nativeBitmap, int[] colors,
1919                                               int offset, int stride, int x, int y,
1920                                               int width, int height);
1921    private static native void nativeCopyPixelsToBuffer(long nativeBitmap,
1922                                                        Buffer dst);
1923    private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src);
1924    private static native int nativeGenerationId(long nativeBitmap);
1925
1926    private static native Bitmap nativeCreateFromParcel(Parcel p);
1927    // returns true on success
1928    private static native boolean nativeWriteToParcel(long nativeBitmap,
1929                                                      boolean isMutable,
1930                                                      int density,
1931                                                      Parcel p);
1932    // returns a new bitmap built from the native bitmap's alpha, and the paint
1933    private static native Bitmap nativeExtractAlpha(long nativeBitmap,
1934                                                    long nativePaint,
1935                                                    int[] offsetXY);
1936
1937    private static native boolean nativeHasAlpha(long nativeBitmap);
1938    private static native boolean nativeIsPremultiplied(long nativeBitmap);
1939    private static native void nativeSetPremultiplied(long nativeBitmap,
1940                                                      boolean isPremul);
1941    private static native void nativeSetHasAlpha(long nativeBitmap,
1942                                                 boolean hasAlpha,
1943                                                 boolean requestPremul);
1944    private static native boolean nativeHasMipMap(long nativeBitmap);
1945    private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
1946    private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
1947    private static native void nativePrepareToDraw(long nativeBitmap);
1948    private static native int nativeGetAllocationByteCount(long nativeBitmap);
1949    private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
1950    private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
1951    private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
1952    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
1953    private static native boolean nativeIsSRGB(long nativePtr);
1954    private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap);
1955}
1956