Bitmap.java revision 7c42e16eb076b04850b7fa083d31735774bd42dd
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 null or if the config is not
920     *                   {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed.
921     *
922     * @throws IllegalArgumentException if the width or height are <= 0, if
923     *         Config is Config.HARDWARE (because hardware bitmaps are always
924     *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
925     *         or if the specified color space's transfer function is not an
926     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
927     */
928    public static Bitmap createBitmap(int width, int height, @NonNull Config config,
929            boolean hasAlpha, @Nullable ColorSpace colorSpace) {
930        return createBitmap(null, width, height, config, hasAlpha, colorSpace);
931    }
932
933    /**
934     * Returns a mutable bitmap with the specified width and height.  Its
935     * initial density is determined from the given {@link DisplayMetrics}.
936     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
937     * color space.
938     *
939     * @param display  Display metrics for the display this bitmap will be
940     *                 drawn on.
941     * @param width    The width of the bitmap
942     * @param height   The height of the bitmap
943     * @param config   The bitmap config to create.
944     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
945     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
946     *                 instead of transparent.
947     *
948     * @throws IllegalArgumentException if the width or height are <= 0, or if
949     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
950     */
951    public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
952            @NonNull Config config, boolean hasAlpha) {
953        return createBitmap(display, width, height, config, hasAlpha, null);
954    }
955
956    /**
957     * Returns a mutable bitmap with the specified width and height.  Its
958     * initial density is determined from the given {@link DisplayMetrics}.
959     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
960     * color space.
961     *
962     * @param display  Display metrics for the display this bitmap will be
963     *                 drawn on.
964     * @param width    The width of the bitmap
965     * @param height   The height of the bitmap
966     * @param config   The bitmap config to create.
967     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
968     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
969     *                 instead of transparent.
970     * @param colorSpace The color space of the bitmap. If null or if the config is not
971     *                   {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} is assumed.
972     *
973     * @throws IllegalArgumentException if the width or height are <= 0, if
974     *         Config is Config.HARDWARE (because hardware bitmaps are always
975     *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
976     *         or if the specified color space's transfer function is not an
977     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
978     */
979    public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
980            @NonNull Config config, boolean hasAlpha, @Nullable ColorSpace colorSpace) {
981        if (width <= 0 || height <= 0) {
982            throw new IllegalArgumentException("width and height must be > 0");
983        }
984        if (config == Config.HARDWARE) {
985            throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
986        }
987
988        Bitmap bm;
989        if (colorSpace == null || config != Config.ARGB_8888) {
990            bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null);
991        } else {
992            if (!(colorSpace instanceof ColorSpace.Rgb)) {
993                throw new IllegalArgumentException("colorSpace must be an RGB color space");
994            }
995            ColorSpace.Rgb rgb = (ColorSpace.Rgb) colorSpace;
996            ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters();
997            if (parameters == null) {
998                throw new IllegalArgumentException("colorSpace must use an ICC "
999                        + "parametric transfer function");
1000            }
1001
1002            ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50);
1003            bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true,
1004                    d50.getTransform(), parameters);
1005        }
1006
1007        if (display != null) {
1008            bm.mDensity = display.densityDpi;
1009        }
1010        bm.setHasAlpha(hasAlpha);
1011        if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) {
1012            nativeErase(bm.mNativePtr, 0xff000000);
1013        }
1014        // No need to initialize the bitmap to zeroes with other configs;
1015        // it is backed by a VM byte array which is by definition preinitialized
1016        // to all zeroes.
1017        return bm;
1018    }
1019
1020    /**
1021     * Returns a immutable bitmap with the specified width and height, with each
1022     * pixel value set to the corresponding value in the colors array.  Its
1023     * initial density is as per {@link #getDensity}. The newly created
1024     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
1025     *
1026     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1027     * @param offset   Number of values to skip before the first color in the
1028     *                 array of colors.
1029     * @param stride   Number of colors in the array between rows (must be >=
1030     *                 width or <= -width).
1031     * @param width    The width of the bitmap
1032     * @param height   The height of the bitmap
1033     * @param config   The bitmap config to create. If the config does not
1034     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1035     *                 bytes in the colors[] will be ignored (assumed to be FF)
1036     * @throws IllegalArgumentException if the width or height are <= 0, or if
1037     *         the color array's length is less than the number of pixels.
1038     */
1039    public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int offset, int stride,
1040            int width, int height, @NonNull Config config) {
1041        return createBitmap(null, colors, offset, stride, width, height, config);
1042    }
1043
1044    /**
1045     * Returns a immutable bitmap with the specified width and height, with each
1046     * pixel value set to the corresponding value in the colors array.  Its
1047     * initial density is determined from the given {@link DisplayMetrics}.
1048     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
1049     * color space.
1050     *
1051     * @param display  Display metrics for the display this bitmap will be
1052     *                 drawn on.
1053     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1054     * @param offset   Number of values to skip before the first color in the
1055     *                 array of colors.
1056     * @param stride   Number of colors in the array between rows (must be >=
1057     *                 width or <= -width).
1058     * @param width    The width of the bitmap
1059     * @param height   The height of the bitmap
1060     * @param config   The bitmap config to create. If the config does not
1061     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1062     *                 bytes in the colors[] will be ignored (assumed to be FF)
1063     * @throws IllegalArgumentException if the width or height are <= 0, or if
1064     *         the color array's length is less than the number of pixels.
1065     */
1066    public static Bitmap createBitmap(@NonNull DisplayMetrics display,
1067            @NonNull @ColorInt int[] colors, int offset, int stride,
1068            int width, int height, @NonNull Config config) {
1069
1070        checkWidthHeight(width, height);
1071        if (Math.abs(stride) < width) {
1072            throw new IllegalArgumentException("abs(stride) must be >= width");
1073        }
1074        int lastScanline = offset + (height - 1) * stride;
1075        int length = colors.length;
1076        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
1077                (lastScanline + width > length)) {
1078            throw new ArrayIndexOutOfBoundsException();
1079        }
1080        if (width <= 0 || height <= 0) {
1081            throw new IllegalArgumentException("width and height must be > 0");
1082        }
1083        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
1084                            config.nativeInt, false, null, null);
1085        if (display != null) {
1086            bm.mDensity = display.densityDpi;
1087        }
1088        return bm;
1089    }
1090
1091    /**
1092     * Returns a immutable bitmap with the specified width and height, with each
1093     * pixel value set to the corresponding value in the colors array.  Its
1094     * initial density is as per {@link #getDensity}. The newly created
1095     * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
1096     *
1097     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1098     *                 This array must be at least as large as width * height.
1099     * @param width    The width of the bitmap
1100     * @param height   The height of the bitmap
1101     * @param config   The bitmap config to create. If the config does not
1102     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1103     *                 bytes in the colors[] will be ignored (assumed to be FF)
1104     * @throws IllegalArgumentException if the width or height are <= 0, or if
1105     *         the color array's length is less than the number of pixels.
1106     */
1107    public static Bitmap createBitmap(@NonNull @ColorInt int[] colors,
1108            int width, int height, Config config) {
1109        return createBitmap(null, colors, 0, width, width, height, config);
1110    }
1111
1112    /**
1113     * Returns a immutable bitmap with the specified width and height, with each
1114     * pixel value set to the corresponding value in the colors array.  Its
1115     * initial density is determined from the given {@link DisplayMetrics}.
1116     * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
1117     * color space.
1118     *
1119     * @param display  Display metrics for the display this bitmap will be
1120     *                 drawn on.
1121     * @param colors   Array of sRGB {@link Color colors} used to initialize the pixels.
1122     *                 This array must be at least as large as width * height.
1123     * @param width    The width of the bitmap
1124     * @param height   The height of the bitmap
1125     * @param config   The bitmap config to create. If the config does not
1126     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
1127     *                 bytes in the colors[] will be ignored (assumed to be FF)
1128     * @throws IllegalArgumentException if the width or height are <= 0, or if
1129     *         the color array's length is less than the number of pixels.
1130     */
1131    public static Bitmap createBitmap(@Nullable DisplayMetrics display,
1132            @NonNull @ColorInt int colors[], int width, int height, @NonNull Config config) {
1133        return createBitmap(display, colors, 0, width, width, height, config);
1134    }
1135
1136    /**
1137     * Returns an optional array of private data, used by the UI system for
1138     * some bitmaps. Not intended to be called by applications.
1139     */
1140    public byte[] getNinePatchChunk() {
1141        return mNinePatchChunk;
1142    }
1143
1144    /**
1145     * Populates a rectangle with the bitmap's optical insets.
1146     *
1147     * @param outInsets Rect to populate with optical insets
1148     * @hide
1149     */
1150    public void getOpticalInsets(@NonNull Rect outInsets) {
1151        if (mNinePatchInsets == null) {
1152            outInsets.setEmpty();
1153        } else {
1154            outInsets.set(mNinePatchInsets.opticalRect);
1155        }
1156    }
1157
1158    /** @hide */
1159    public NinePatch.InsetStruct getNinePatchInsets() {
1160        return mNinePatchInsets;
1161    }
1162
1163    /**
1164     * Specifies the known formats a bitmap can be compressed into
1165     */
1166    public enum CompressFormat {
1167        JPEG    (0),
1168        PNG     (1),
1169        WEBP    (2);
1170
1171        CompressFormat(int nativeInt) {
1172            this.nativeInt = nativeInt;
1173        }
1174        final int nativeInt;
1175    }
1176
1177    /**
1178     * Number of bytes of temp storage we use for communicating between the
1179     * native compressor and the java OutputStream.
1180     */
1181    private final static int WORKING_COMPRESS_STORAGE = 4096;
1182
1183    /**
1184     * Write a compressed version of the bitmap to the specified outputstream.
1185     * If this returns true, the bitmap can be reconstructed by passing a
1186     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
1187     * all Formats support all bitmap configs directly, so it is possible that
1188     * the returned bitmap from BitmapFactory could be in a different bitdepth,
1189     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
1190     * pixels).
1191     *
1192     * @param format   The format of the compressed image
1193     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
1194     *                 small size, 100 meaning compress for max quality. Some
1195     *                 formats, like PNG which is lossless, will ignore the
1196     *                 quality setting
1197     * @param stream   The outputstream to write the compressed data.
1198     * @return true if successfully compressed to the specified stream.
1199     */
1200    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
1201        checkRecycled("Can't compress a recycled bitmap");
1202        // do explicit check before calling the native method
1203        if (stream == null) {
1204            throw new NullPointerException();
1205        }
1206        if (quality < 0 || quality > 100) {
1207            throw new IllegalArgumentException("quality must be 0..100");
1208        }
1209        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
1210        boolean result = nativeCompress(mNativePtr, format.nativeInt,
1211                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
1212        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1213        return result;
1214    }
1215
1216    /**
1217     * Returns true if the bitmap is marked as mutable (i.e.&nbsp;can be drawn into)
1218     */
1219    public final boolean isMutable() {
1220        return mIsMutable;
1221    }
1222
1223    /**
1224     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
1225     * When a pixel is pre-multiplied, the RGB components have been multiplied by
1226     * the alpha component. For instance, if the original color is a 50%
1227     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
1228     * <code>(128, 128, 0, 0)</code>.</p>
1229     *
1230     * <p>This method always returns false if {@link #getConfig()} is
1231     * {@link Bitmap.Config#RGB_565}.</p>
1232     *
1233     * <p>The return value is undefined if {@link #getConfig()} is
1234     * {@link Bitmap.Config#ALPHA_8}.</p>
1235     *
1236     * <p>This method only returns true if {@link #hasAlpha()} returns true.
1237     * A bitmap with no alpha channel can be used both as a pre-multiplied and
1238     * as a non pre-multiplied bitmap.</p>
1239     *
1240     * <p>Only pre-multiplied bitmaps may be drawn by the view system or
1241     * {@link Canvas}. If a non-pre-multiplied bitmap with an alpha channel is
1242     * drawn to a Canvas, a RuntimeException will be thrown.</p>
1243     *
1244     * @return true if the underlying pixels have been pre-multiplied, false
1245     *         otherwise
1246     *
1247     * @see Bitmap#setPremultiplied(boolean)
1248     * @see BitmapFactory.Options#inPremultiplied
1249     */
1250    public final boolean isPremultiplied() {
1251        if (mRecycled) {
1252            Log.w(TAG, "Called isPremultiplied() on a recycle()'d bitmap! This is undefined behavior!");
1253        }
1254        return nativeIsPremultiplied(mNativePtr);
1255    }
1256
1257    /**
1258     * Sets whether the bitmap should treat its data as pre-multiplied.
1259     *
1260     * <p>Bitmaps are always treated as pre-multiplied by the view system and
1261     * {@link Canvas} for performance reasons. Storing un-pre-multiplied data in
1262     * a Bitmap (through {@link #setPixel}, {@link #setPixels}, or {@link
1263     * BitmapFactory.Options#inPremultiplied BitmapFactory.Options.inPremultiplied})
1264     * can lead to incorrect blending if drawn by the framework.</p>
1265     *
1266     * <p>This method will not affect the behavior of a bitmap without an alpha
1267     * channel, or if {@link #hasAlpha()} returns false.</p>
1268     *
1269     * <p>Calling {@link #createBitmap} or {@link #createScaledBitmap} with a source
1270     * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
1271     * since those functions require drawing the source, which is not supported for
1272     * un-pre-multiplied Bitmaps.</p>
1273     *
1274     * @see Bitmap#isPremultiplied()
1275     * @see BitmapFactory.Options#inPremultiplied
1276     */
1277    public final void setPremultiplied(boolean premultiplied) {
1278        checkRecycled("setPremultiplied called on a recycled bitmap");
1279        mRequestPremultiplied = premultiplied;
1280        nativeSetPremultiplied(mNativePtr, premultiplied);
1281    }
1282
1283    /** Returns the bitmap's width */
1284    public final int getWidth() {
1285        if (mRecycled) {
1286            Log.w(TAG, "Called getWidth() on a recycle()'d bitmap! This is undefined behavior!");
1287        }
1288        return mWidth;
1289    }
1290
1291    /** Returns the bitmap's height */
1292    public final int getHeight() {
1293        if (mRecycled) {
1294            Log.w(TAG, "Called getHeight() on a recycle()'d bitmap! This is undefined behavior!");
1295        }
1296        return mHeight;
1297    }
1298
1299    /**
1300     * Convenience for calling {@link #getScaledWidth(int)} with the target
1301     * density of the given {@link Canvas}.
1302     */
1303    public int getScaledWidth(Canvas canvas) {
1304        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
1305    }
1306
1307    /**
1308     * Convenience for calling {@link #getScaledHeight(int)} with the target
1309     * density of the given {@link Canvas}.
1310     */
1311    public int getScaledHeight(Canvas canvas) {
1312        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
1313    }
1314
1315    /**
1316     * Convenience for calling {@link #getScaledWidth(int)} with the target
1317     * density of the given {@link DisplayMetrics}.
1318     */
1319    public int getScaledWidth(DisplayMetrics metrics) {
1320        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
1321    }
1322
1323    /**
1324     * Convenience for calling {@link #getScaledHeight(int)} with the target
1325     * density of the given {@link DisplayMetrics}.
1326     */
1327    public int getScaledHeight(DisplayMetrics metrics) {
1328        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
1329    }
1330
1331    /**
1332     * Convenience method that returns the width of this bitmap divided
1333     * by the density scale factor.
1334     *
1335     * @param targetDensity The density of the target canvas of the bitmap.
1336     * @return The scaled width of this bitmap, according to the density scale factor.
1337     */
1338    public int getScaledWidth(int targetDensity) {
1339        return scaleFromDensity(getWidth(), mDensity, targetDensity);
1340    }
1341
1342    /**
1343     * Convenience method that returns the height of this bitmap divided
1344     * by the density scale factor.
1345     *
1346     * @param targetDensity The density of the target canvas of the bitmap.
1347     * @return The scaled height of this bitmap, according to the density scale factor.
1348     */
1349    public int getScaledHeight(int targetDensity) {
1350        return scaleFromDensity(getHeight(), mDensity, targetDensity);
1351    }
1352
1353    /**
1354     * @hide
1355     */
1356    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
1357        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
1358            return size;
1359        }
1360
1361        // Scale by tdensity / sdensity, rounding up.
1362        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
1363    }
1364
1365    /**
1366     * Return the number of bytes between rows in the bitmap's pixels. Note that
1367     * this refers to the pixels as stored natively by the bitmap. If you call
1368     * getPixels() or setPixels(), then the pixels are uniformly treated as
1369     * 32bit values, packed according to the Color class.
1370     *
1371     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, this method
1372     * should not be used to calculate the memory usage of the bitmap. Instead,
1373     * see {@link #getAllocationByteCount()}.
1374     *
1375     * @return number of bytes between rows of the native bitmap pixels.
1376     */
1377    public final int getRowBytes() {
1378        if (mRecycled) {
1379            Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");
1380        }
1381        return nativeRowBytes(mNativePtr);
1382    }
1383
1384    /**
1385     * Returns the minimum number of bytes that can be used to store this bitmap's pixels.
1386     *
1387     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can
1388     * no longer be used to determine memory usage of a bitmap. See {@link
1389     * #getAllocationByteCount()}.</p>
1390     */
1391    public final int getByteCount() {
1392        if (mRecycled) {
1393            Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! "
1394                    + "This is undefined behavior!");
1395            return 0;
1396        }
1397        // int result permits bitmaps up to 46,340 x 46,340
1398        return getRowBytes() * getHeight();
1399    }
1400
1401    /**
1402     * Returns the size of the allocated memory used to store this bitmap's pixels.
1403     *
1404     * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to
1405     * decode other bitmaps of smaller size, or by manual reconfiguration. See {@link
1406     * #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link
1407     * #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap
1408     * BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be
1409     * the same as that returned by {@link #getByteCount()}.</p>
1410     *
1411     * <p>This value will not change over the lifetime of a Bitmap.</p>
1412     *
1413     * @see #reconfigure(int, int, Config)
1414     */
1415    public final int getAllocationByteCount() {
1416        if (mRecycled) {
1417            Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
1418                    + "This is undefined behavior!");
1419            return 0;
1420        }
1421        return nativeGetAllocationByteCount(mNativePtr);
1422    }
1423
1424    /**
1425     * If the bitmap's internal config is in one of the public formats, return
1426     * that config, otherwise return null.
1427     */
1428    public final Config getConfig() {
1429        if (mRecycled) {
1430            Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!");
1431        }
1432        return Config.nativeToConfig(nativeConfig(mNativePtr));
1433    }
1434
1435    /** Returns true if the bitmap's config supports per-pixel alpha, and
1436     * if the pixels may contain non-opaque alpha values. For some configs,
1437     * this is always false (e.g. RGB_565), since they do not support per-pixel
1438     * alpha. However, for configs that do, the bitmap may be flagged to be
1439     * known that all of its pixels are opaque. In this case hasAlpha() will
1440     * also return false. If a config such as ARGB_8888 is not so flagged,
1441     * it will return true by default.
1442     */
1443    public final boolean hasAlpha() {
1444        if (mRecycled) {
1445            Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!");
1446        }
1447        return nativeHasAlpha(mNativePtr);
1448    }
1449
1450    /**
1451     * Tell the bitmap if all of the pixels are known to be opaque (false)
1452     * or if some of the pixels may contain non-opaque alpha values (true).
1453     * Note, for some configs (e.g. RGB_565) this call is ignored, since it
1454     * does not support per-pixel alpha values.
1455     *
1456     * This is meant as a drawing hint, as in some cases a bitmap that is known
1457     * to be opaque can take a faster drawing case than one that may have
1458     * non-opaque per-pixel alpha values.
1459     */
1460    public void setHasAlpha(boolean hasAlpha) {
1461        checkRecycled("setHasAlpha called on a recycled bitmap");
1462        nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied);
1463    }
1464
1465    /**
1466     * Indicates whether the renderer responsible for drawing this
1467     * bitmap should attempt to use mipmaps when this bitmap is drawn
1468     * scaled down.
1469     *
1470     * If you know that you are going to draw this bitmap at less than
1471     * 50% of its original size, you may be able to obtain a higher
1472     * quality
1473     *
1474     * This property is only a suggestion that can be ignored by the
1475     * renderer. It is not guaranteed to have any effect.
1476     *
1477     * @return true if the renderer should attempt to use mipmaps,
1478     *         false otherwise
1479     *
1480     * @see #setHasMipMap(boolean)
1481     */
1482    public final boolean hasMipMap() {
1483        if (mRecycled) {
1484            Log.w(TAG, "Called hasMipMap() on a recycle()'d bitmap! This is undefined behavior!");
1485        }
1486        return nativeHasMipMap(mNativePtr);
1487    }
1488
1489    /**
1490     * Set a hint for the renderer responsible for drawing this bitmap
1491     * indicating that it should attempt to use mipmaps when this bitmap
1492     * is drawn scaled down.
1493     *
1494     * If you know that you are going to draw this bitmap at less than
1495     * 50% of its original size, you may be able to obtain a higher
1496     * quality by turning this property on.
1497     *
1498     * Note that if the renderer respects this hint it might have to
1499     * allocate extra memory to hold the mipmap levels for this bitmap.
1500     *
1501     * This property is only a suggestion that can be ignored by the
1502     * renderer. It is not guaranteed to have any effect.
1503     *
1504     * @param hasMipMap indicates whether the renderer should attempt
1505     *                  to use mipmaps
1506     *
1507     * @see #hasMipMap()
1508     */
1509    public final void setHasMipMap(boolean hasMipMap) {
1510        checkRecycled("setHasMipMap called on a recycled bitmap");
1511        nativeSetHasMipMap(mNativePtr, hasMipMap);
1512    }
1513
1514    /**
1515     * Returns the color space associated with this bitmap. If the color
1516     * space is unknown, this method returns null.
1517     */
1518    @Nullable
1519    public final ColorSpace getColorSpace() {
1520        // A reconfigure can change the configuration and rgba16f is
1521        // always linear scRGB at this time
1522        if (getConfig() == Config.RGBA_F16) {
1523            // Reset the color space for potential future reconfigurations
1524            mColorSpace = null;
1525            return ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
1526        }
1527
1528        // Cache the color space retrieval since it can be fairly expensive
1529        if (mColorSpace == null) {
1530            if (nativeIsSRGB(mNativePtr)) {
1531                mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
1532            } else {
1533                float[] xyz = new float[9];
1534                float[] params = new float[7];
1535
1536                boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params);
1537                if (hasColorSpace) {
1538                    ColorSpace.Rgb.TransferParameters parameters =
1539                            new ColorSpace.Rgb.TransferParameters(
1540                                    params[0], params[1], params[2],
1541                                    params[3], params[4], params[5], params[6]);
1542                    ColorSpace cs = ColorSpace.match(xyz, parameters);
1543                    if (cs != null) {
1544                        mColorSpace = cs;
1545                    } else {
1546                        mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters);
1547                    }
1548                }
1549            }
1550        }
1551
1552        return mColorSpace;
1553    }
1554
1555    /**
1556     * Fills the bitmap's pixels with the specified {@link Color}.
1557     *
1558     * @throws IllegalStateException if the bitmap is not mutable.
1559     */
1560    public void eraseColor(@ColorInt int c) {
1561        checkRecycled("Can't erase a recycled bitmap");
1562        if (!isMutable()) {
1563            throw new IllegalStateException("cannot erase immutable bitmaps");
1564        }
1565        nativeErase(mNativePtr, c);
1566    }
1567
1568    /**
1569     * Returns the {@link Color} at the specified location. Throws an exception
1570     * if x or y are out of bounds (negative or >= to the width or height
1571     * respectively). The returned color is a non-premultiplied ARGB value in
1572     * the {@link ColorSpace.Named#SRGB sRGB} color space.
1573     *
1574     * @param x    The x coordinate (0...width-1) of the pixel to return
1575     * @param y    The y coordinate (0...height-1) of the pixel to return
1576     * @return     The argb {@link Color} at the specified coordinate
1577     * @throws IllegalArgumentException if x, y exceed the bitmap's bounds
1578     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1579     */
1580    @ColorInt
1581    public int getPixel(int x, int y) {
1582        checkRecycled("Can't call getPixel() on a recycled bitmap");
1583        checkHardware("unable to getPixel(), "
1584                + "pixel access is not supported on Config#HARDWARE bitmaps");
1585        checkPixelAccess(x, y);
1586        return nativeGetPixel(mNativePtr, x, y);
1587    }
1588
1589    /**
1590     * Returns in pixels[] a copy of the data in the bitmap. Each value is
1591     * a packed int representing a {@link Color}. The stride parameter allows
1592     * the caller to allow for gaps in the returned pixels array between
1593     * rows. For normal packed results, just pass width for the stride value.
1594     * The returned colors are non-premultiplied ARGB values in the
1595     * {@link ColorSpace.Named#SRGB sRGB} color space.
1596     *
1597     * @param pixels   The array to receive the bitmap's colors
1598     * @param offset   The first index to write into pixels[]
1599     * @param stride   The number of entries in pixels[] to skip between
1600     *                 rows (must be >= bitmap's width). Can be negative.
1601     * @param x        The x coordinate of the first pixel to read from
1602     *                 the bitmap
1603     * @param y        The y coordinate of the first pixel to read from
1604     *                 the bitmap
1605     * @param width    The number of pixels to read from each row
1606     * @param height   The number of rows to read
1607     *
1608     * @throws IllegalArgumentException if x, y, width, height exceed the
1609     *         bounds of the bitmap, or if abs(stride) < width.
1610     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1611     *         to receive the specified number of pixels.
1612     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1613     */
1614    public void getPixels(@ColorInt int[] pixels, int offset, int stride,
1615                          int x, int y, int width, int height) {
1616        checkRecycled("Can't call getPixels() on a recycled bitmap");
1617        checkHardware("unable to getPixels(), "
1618                + "pixel access is not supported on Config#HARDWARE bitmaps");
1619        if (width == 0 || height == 0) {
1620            return; // nothing to do
1621        }
1622        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1623        nativeGetPixels(mNativePtr, pixels, offset, stride,
1624                        x, y, width, height);
1625    }
1626
1627    /**
1628     * Shared code to check for illegal arguments passed to getPixel()
1629     * or setPixel()
1630     *
1631     * @param x x coordinate of the pixel
1632     * @param y y coordinate of the pixel
1633     */
1634    private void checkPixelAccess(int x, int y) {
1635        checkXYSign(x, y);
1636        if (x >= getWidth()) {
1637            throw new IllegalArgumentException("x must be < bitmap.width()");
1638        }
1639        if (y >= getHeight()) {
1640            throw new IllegalArgumentException("y must be < bitmap.height()");
1641        }
1642    }
1643
1644    /**
1645     * Shared code to check for illegal arguments passed to getPixels()
1646     * or setPixels()
1647     *
1648     * @param x left edge of the area of pixels to access
1649     * @param y top edge of the area of pixels to access
1650     * @param width width of the area of pixels to access
1651     * @param height height of the area of pixels to access
1652     * @param offset offset into pixels[] array
1653     * @param stride number of elements in pixels[] between each logical row
1654     * @param pixels array to hold the area of pixels being accessed
1655    */
1656    private void checkPixelsAccess(int x, int y, int width, int height,
1657                                   int offset, int stride, int pixels[]) {
1658        checkXYSign(x, y);
1659        if (width < 0) {
1660            throw new IllegalArgumentException("width must be >= 0");
1661        }
1662        if (height < 0) {
1663            throw new IllegalArgumentException("height must be >= 0");
1664        }
1665        if (x + width > getWidth()) {
1666            throw new IllegalArgumentException(
1667                    "x + width must be <= bitmap.width()");
1668        }
1669        if (y + height > getHeight()) {
1670            throw new IllegalArgumentException(
1671                    "y + height must be <= bitmap.height()");
1672        }
1673        if (Math.abs(stride) < width) {
1674            throw new IllegalArgumentException("abs(stride) must be >= width");
1675        }
1676        int lastScanline = offset + (height - 1) * stride;
1677        int length = pixels.length;
1678        if (offset < 0 || (offset + width > length)
1679                || lastScanline < 0
1680                || (lastScanline + width > length)) {
1681            throw new ArrayIndexOutOfBoundsException();
1682        }
1683    }
1684
1685    /**
1686     * <p>Write the specified {@link Color} into the bitmap (assuming it is
1687     * mutable) at the x,y coordinate. The color must be a
1688     * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
1689     * color space.</p>
1690     *
1691     * @param x     The x coordinate of the pixel to replace (0...width-1)
1692     * @param y     The y coordinate of the pixel to replace (0...height-1)
1693     * @param color The ARGB color to write into the bitmap
1694     *
1695     * @throws IllegalStateException if the bitmap is not mutable
1696     * @throws IllegalArgumentException if x, y are outside of the bitmap's
1697     *         bounds.
1698     */
1699    public void setPixel(int x, int y, @ColorInt int color) {
1700        checkRecycled("Can't call setPixel() on a recycled bitmap");
1701        if (!isMutable()) {
1702            throw new IllegalStateException();
1703        }
1704        checkPixelAccess(x, y);
1705        nativeSetPixel(mNativePtr, x, y, color);
1706    }
1707
1708    /**
1709     * <p>Replace pixels in the bitmap with the colors in the array. Each element
1710     * in the array is a packed int representing a non-premultiplied ARGB
1711     * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
1712     *
1713     * @param pixels   The colors to write to the bitmap
1714     * @param offset   The index of the first color to read from pixels[]
1715     * @param stride   The number of colors in pixels[] to skip between rows.
1716     *                 Normally this value will be the same as the width of
1717     *                 the bitmap, but it can be larger (or negative).
1718     * @param x        The x coordinate of the first pixel to write to in
1719     *                 the bitmap.
1720     * @param y        The y coordinate of the first pixel to write to in
1721     *                 the bitmap.
1722     * @param width    The number of colors to copy from pixels[] per row
1723     * @param height   The number of rows to write to the bitmap
1724     *
1725     * @throws IllegalStateException if the bitmap is not mutable
1726     * @throws IllegalArgumentException if x, y, width, height are outside of
1727     *         the bitmap's bounds.
1728     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1729     *         to receive the specified number of pixels.
1730     */
1731    public void setPixels(@ColorInt int[] pixels, int offset, int stride,
1732            int x, int y, int width, int height) {
1733        checkRecycled("Can't call setPixels() on a recycled bitmap");
1734        if (!isMutable()) {
1735            throw new IllegalStateException();
1736        }
1737        if (width == 0 || height == 0) {
1738            return; // nothing to do
1739        }
1740        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1741        nativeSetPixels(mNativePtr, pixels, offset, stride,
1742                        x, y, width, height);
1743    }
1744
1745    public static final Parcelable.Creator<Bitmap> CREATOR
1746            = new Parcelable.Creator<Bitmap>() {
1747        /**
1748         * Rebuilds a bitmap previously stored with writeToParcel().
1749         *
1750         * @param p    Parcel object to read the bitmap from
1751         * @return a new bitmap created from the data in the parcel
1752         */
1753        public Bitmap createFromParcel(Parcel p) {
1754            Bitmap bm = nativeCreateFromParcel(p);
1755            if (bm == null) {
1756                throw new RuntimeException("Failed to unparcel Bitmap");
1757            }
1758            return bm;
1759        }
1760        public Bitmap[] newArray(int size) {
1761            return new Bitmap[size];
1762        }
1763    };
1764
1765    /**
1766     * No special parcel contents.
1767     */
1768    public int describeContents() {
1769        return 0;
1770    }
1771
1772    /**
1773     * Write the bitmap and its pixels to the parcel. The bitmap can be
1774     * rebuilt from the parcel by calling CREATOR.createFromParcel().
1775     *
1776     * If this bitmap is {@link Config#HARDWARE}, it may be unparceled with a different pixel
1777     * format (e.g. 565, 8888), but the content will be preserved to the best quality permitted
1778     * by the final pixel format
1779     * @param p    Parcel object to write the bitmap data into
1780     */
1781    public void writeToParcel(Parcel p, int flags) {
1782        checkRecycled("Can't parcel a recycled bitmap");
1783        if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) {
1784            throw new RuntimeException("native writeToParcel failed");
1785        }
1786    }
1787
1788    /**
1789     * Returns a new bitmap that captures the alpha values of the original.
1790     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be
1791     * taken from the paint that is passed to the draw call.
1792     *
1793     * @return new bitmap containing the alpha channel of the original bitmap.
1794     */
1795    @CheckResult
1796    public Bitmap extractAlpha() {
1797        return extractAlpha(null, null);
1798    }
1799
1800    /**
1801     * Returns a new bitmap that captures the alpha values of the original.
1802     * These values may be affected by the optional Paint parameter, which
1803     * can contain its own alpha, and may also contain a MaskFilter which
1804     * could change the actual dimensions of the resulting bitmap (e.g.
1805     * a blur maskfilter might enlarge the resulting bitmap). If offsetXY
1806     * is not null, it returns the amount to offset the returned bitmap so
1807     * that it will logically align with the original. For example, if the
1808     * paint contains a blur of radius 2, then offsetXY[] would contains
1809     * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
1810     * drawing the original would result in the blur visually aligning with
1811     * the original.
1812     *
1813     * <p>The initial density of the returned bitmap is the same as the original's.
1814     *
1815     * @param paint Optional paint used to modify the alpha values in the
1816     *              resulting bitmap. Pass null for default behavior.
1817     * @param offsetXY Optional array that returns the X (index 0) and Y
1818     *                 (index 1) offset needed to position the returned bitmap
1819     *                 so that it visually lines up with the original.
1820     * @return new bitmap containing the (optionally modified by paint) alpha
1821     *         channel of the original bitmap. This may be drawn with
1822     *         Canvas.drawBitmap(), where the color(s) will be taken from the
1823     *         paint that is passed to the draw call.
1824     */
1825    @CheckResult
1826    public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
1827        checkRecycled("Can't extractAlpha on a recycled bitmap");
1828        long nativePaint = paint != null ? paint.getNativeInstance() : 0;
1829        Bitmap bm = nativeExtractAlpha(mNativePtr, nativePaint, offsetXY);
1830        if (bm == null) {
1831            throw new RuntimeException("Failed to extractAlpha on Bitmap");
1832        }
1833        bm.mDensity = mDensity;
1834        return bm;
1835    }
1836
1837    /**
1838     *  Given another bitmap, return true if it has the same dimensions, config,
1839     *  and pixel data as this bitmap. If any of those differ, return false.
1840     *  If other is null, return false.
1841     */
1842    public boolean sameAs(Bitmap other) {
1843        checkRecycled("Can't call sameAs on a recycled bitmap!");
1844        if (this == other) return true;
1845        if (other == null) return false;
1846        if (other.isRecycled()) {
1847            throw new IllegalArgumentException("Can't compare to a recycled bitmap!");
1848        }
1849        return nativeSameAs(mNativePtr, other.mNativePtr);
1850    }
1851
1852    /**
1853     * Rebuilds any caches associated with the bitmap that are used for
1854     * drawing it. In the case of purgeable bitmaps, this call will attempt to
1855     * ensure that the pixels have been decoded.
1856     * If this is called on more than one bitmap in sequence, the priority is
1857     * given in LRU order (i.e. the last bitmap called will be given highest
1858     * priority).
1859     *
1860     * For bitmaps with no associated caches, this call is effectively a no-op,
1861     * and therefore is harmless.
1862     */
1863    public void prepareToDraw() {
1864        checkRecycled("Can't prepareToDraw on a recycled bitmap!");
1865        // Kick off an update/upload of the bitmap outside of the normal
1866        // draw path.
1867        nativePrepareToDraw(mNativePtr);
1868    }
1869
1870    /**
1871     *
1872     * @return {@link GraphicBuffer} which is internally used by hardware bitmap
1873     * @hide
1874     */
1875    public GraphicBuffer createGraphicBufferHandle() {
1876        return nativeCreateGraphicBufferHandle(mNativePtr);
1877    }
1878
1879    //////////// native methods
1880
1881    private static native Bitmap nativeCreate(int[] colors, int offset,
1882                                              int stride, int width, int height,
1883                                              int nativeConfig, boolean mutable,
1884                                              @Nullable @Size(9) float[] xyzD50,
1885                                              @Nullable ColorSpace.Rgb.TransferParameters p);
1886    private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig,
1887                                            boolean isMutable);
1888    private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap);
1889    private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
1890    private static native long nativeGetNativeFinalizer();
1891    private static native boolean nativeRecycle(long nativeBitmap);
1892    private static native void nativeReconfigure(long nativeBitmap, int width, int height,
1893                                                 int config, boolean isPremultiplied);
1894
1895    private static native boolean nativeCompress(long nativeBitmap, int format,
1896                                            int quality, OutputStream stream,
1897                                            byte[] tempStorage);
1898    private static native void nativeErase(long nativeBitmap, int color);
1899    private static native int nativeRowBytes(long nativeBitmap);
1900    private static native int nativeConfig(long nativeBitmap);
1901
1902    private static native int nativeGetPixel(long nativeBitmap, int x, int y);
1903    private static native void nativeGetPixels(long nativeBitmap, int[] pixels,
1904                                               int offset, int stride, int x, int y,
1905                                               int width, int height);
1906
1907    private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color);
1908    private static native void nativeSetPixels(long nativeBitmap, int[] colors,
1909                                               int offset, int stride, int x, int y,
1910                                               int width, int height);
1911    private static native void nativeCopyPixelsToBuffer(long nativeBitmap,
1912                                                        Buffer dst);
1913    private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src);
1914    private static native int nativeGenerationId(long nativeBitmap);
1915
1916    private static native Bitmap nativeCreateFromParcel(Parcel p);
1917    // returns true on success
1918    private static native boolean nativeWriteToParcel(long nativeBitmap,
1919                                                      boolean isMutable,
1920                                                      int density,
1921                                                      Parcel p);
1922    // returns a new bitmap built from the native bitmap's alpha, and the paint
1923    private static native Bitmap nativeExtractAlpha(long nativeBitmap,
1924                                                    long nativePaint,
1925                                                    int[] offsetXY);
1926
1927    private static native boolean nativeHasAlpha(long nativeBitmap);
1928    private static native boolean nativeIsPremultiplied(long nativeBitmap);
1929    private static native void nativeSetPremultiplied(long nativeBitmap,
1930                                                      boolean isPremul);
1931    private static native void nativeSetHasAlpha(long nativeBitmap,
1932                                                 boolean hasAlpha,
1933                                                 boolean requestPremul);
1934    private static native boolean nativeHasMipMap(long nativeBitmap);
1935    private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
1936    private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
1937    private static native void nativePrepareToDraw(long nativeBitmap);
1938    private static native int nativeGetAllocationByteCount(long nativeBitmap);
1939    private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
1940    private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
1941    private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
1942    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
1943    private static native boolean nativeIsSRGB(long nativePtr);
1944    private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap);
1945}
1946