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.os.Parcel;
20import android.os.Parcelable;
21import android.util.DisplayMetrics;
22
23import java.io.OutputStream;
24import java.nio.Buffer;
25import java.nio.ByteBuffer;
26import java.nio.IntBuffer;
27import java.nio.ShortBuffer;
28
29public final class Bitmap implements Parcelable {
30    /**
31     * Indicates that the bitmap was created for an unknown pixel density.
32     *
33     * @see Bitmap#getDensity()
34     * @see Bitmap#setDensity(int)
35     */
36    public static final int DENSITY_NONE = 0;
37
38    /**
39     * Note:  mNativeBitmap is used by FaceDetector_jni.cpp
40     * Don't change/rename without updating FaceDetector_jni.cpp
41     *
42     * @hide
43     */
44    public final int mNativeBitmap;
45
46    /**
47     * Backing buffer for the Bitmap.
48     * Made public for quick access from drawing methods -- do NOT modify
49     * from outside this class.
50     *
51     * @hide
52     */
53    public byte[] mBuffer;
54
55    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
56    private final BitmapFinalizer mFinalizer;
57
58    private final boolean mIsMutable;
59    private byte[] mNinePatchChunk;   // may be null
60    private int[] mLayoutBounds;   // may be null
61    private int mWidth = -1;
62    private int mHeight = -1;
63    private boolean mRecycled;
64
65    // Package-scoped for fast access.
66    int mDensity = getDefaultDensity();
67
68    private static volatile Matrix sScaleMatrix;
69
70    private static volatile int sDefaultDensity = -1;
71
72    /**
73     * For backwards compatibility, allows the app layer to change the default
74     * density when running old apps.
75     * @hide
76     */
77    public static void setDefaultDensity(int density) {
78        sDefaultDensity = density;
79    }
80
81    static int getDefaultDensity() {
82        if (sDefaultDensity >= 0) {
83            return sDefaultDensity;
84        }
85        sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
86        return sDefaultDensity;
87    }
88
89    /**
90     * @noinspection UnusedDeclaration
91     */
92    /*  Private constructor that must received an already allocated native
93        bitmap int (pointer).
94
95        This can be called from JNI code.
96    */
97    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
98            int density) {
99        this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
100    }
101
102    /**
103     * @noinspection UnusedDeclaration
104     */
105    /*  Private constructor that must received an already allocated native
106        bitmap int (pointer).
107
108        This can be called from JNI code.
109    */
110    Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
111            int[] layoutBounds, int density) {
112        if (nativeBitmap == 0) {
113            throw new RuntimeException("internal error: native bitmap is 0");
114        }
115
116        mBuffer = buffer;
117        // we delete this in our finalizer
118        mNativeBitmap = nativeBitmap;
119        mFinalizer = new BitmapFinalizer(nativeBitmap);
120
121        mIsMutable = isMutable;
122        mNinePatchChunk = ninePatchChunk;
123        mLayoutBounds = layoutBounds;
124        if (density >= 0) {
125            mDensity = density;
126        }
127    }
128
129    /**
130     * <p>Returns the density for this bitmap.</p>
131     *
132     * <p>The default density is the same density as the current display,
133     * unless the current application does not support different screen
134     * densities in which case it is
135     * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}.  Note that
136     * compatibility mode is determined by the application that was initially
137     * loaded into a process -- applications that share the same process should
138     * all have the same compatibility, or ensure they explicitly set the
139     * density of their bitmaps appropriately.</p>
140     *
141     * @return A scaling factor of the default density or {@link #DENSITY_NONE}
142     *         if the scaling factor is unknown.
143     *
144     * @see #setDensity(int)
145     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
146     * @see android.util.DisplayMetrics#densityDpi
147     * @see #DENSITY_NONE
148     */
149    public int getDensity() {
150        return mDensity;
151    }
152
153    /**
154     * <p>Specifies the density for this bitmap.  When the bitmap is
155     * drawn to a Canvas that also has a density, it will be scaled
156     * appropriately.</p>
157     *
158     * @param density The density scaling factor to use with this bitmap or
159     *        {@link #DENSITY_NONE} if the density is unknown.
160     *
161     * @see #getDensity()
162     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
163     * @see android.util.DisplayMetrics#densityDpi
164     * @see #DENSITY_NONE
165     */
166    public void setDensity(int density) {
167        mDensity = density;
168    }
169
170    /**
171     * Sets the nine patch chunk.
172     *
173     * @param chunk The definition of the nine patch
174     *
175     * @hide
176     */
177    public void setNinePatchChunk(byte[] chunk) {
178        mNinePatchChunk = chunk;
179    }
180
181    /**
182     * Sets the layout bounds as an array of left, top, right, bottom integers
183     * @param bounds the array containing the padding values
184     *
185     * @hide
186     */
187    public void setLayoutBounds(int[] bounds) {
188        mLayoutBounds = bounds;
189    }
190
191    /**
192     * Free the native object associated with this bitmap, and clear the
193     * reference to the pixel data. This will not free the pixel data synchronously;
194     * it simply allows it to be garbage collected if there are no other references.
195     * The bitmap is marked as "dead", meaning it will throw an exception if
196     * getPixels() or setPixels() is called, and will draw nothing. This operation
197     * cannot be reversed, so it should only be called if you are sure there are no
198     * further uses for the bitmap. This is an advanced call, and normally need
199     * not be called, since the normal GC process will free up this memory when
200     * there are no more references to this bitmap.
201     */
202    public void recycle() {
203        if (!mRecycled) {
204            if (nativeRecycle(mNativeBitmap)) {
205                // return value indicates whether native pixel object was actually recycled.
206                // false indicates that it is still in use at the native level and these
207                // objects should not be collected now. They will be collected later when the
208                // Bitmap itself is collected.
209                mBuffer = null;
210                mNinePatchChunk = null;
211            }
212            mRecycled = true;
213        }
214    }
215
216    /**
217     * Returns true if this bitmap has been recycled. If so, then it is an error
218     * to try to access its pixels, and the bitmap will not draw.
219     *
220     * @return true if the bitmap has been recycled
221     */
222    public final boolean isRecycled() {
223        return mRecycled;
224    }
225
226    /**
227     * Returns the generation ID of this bitmap. The generation ID changes
228     * whenever the bitmap is modified. This can be used as an efficient way to
229     * check if a bitmap has changed.
230     *
231     * @return The current generation ID for this bitmap.
232     */
233    public int getGenerationId() {
234        return nativeGenerationId(mNativeBitmap);
235    }
236
237    /**
238     * This is called by methods that want to throw an exception if the bitmap
239     * has already been recycled.
240     */
241    private void checkRecycled(String errorMessage) {
242        if (mRecycled) {
243            throw new IllegalStateException(errorMessage);
244        }
245    }
246
247    /**
248     * Common code for checking that x and y are >= 0
249     *
250     * @param x x coordinate to ensure is >= 0
251     * @param y y coordinate to ensure is >= 0
252     */
253    private static void checkXYSign(int x, int y) {
254        if (x < 0) {
255            throw new IllegalArgumentException("x must be >= 0");
256        }
257        if (y < 0) {
258            throw new IllegalArgumentException("y must be >= 0");
259        }
260    }
261
262    /**
263     * Common code for checking that width and height are > 0
264     *
265     * @param width  width to ensure is > 0
266     * @param height height to ensure is > 0
267     */
268    private static void checkWidthHeight(int width, int height) {
269        if (width <= 0) {
270            throw new IllegalArgumentException("width must be > 0");
271        }
272        if (height <= 0) {
273            throw new IllegalArgumentException("height must be > 0");
274        }
275    }
276
277    /**
278     * Possible bitmap configurations. A bitmap configuration describes
279     * how pixels are stored. This affects the quality (color depth) as
280     * well as the ability to display transparent/translucent colors.
281     */
282    public enum Config {
283        // these native values must match up with the enum in SkBitmap.h
284
285        /**
286         * Each pixel is stored as a single translucency (alpha) channel.
287         * This is very useful to efficiently store masks for instance.
288         * No color information is stored.
289         * With this configuration, each pixel requires 1 byte of memory.
290         */
291        ALPHA_8     (2),
292
293        /**
294         * Each pixel is stored on 2 bytes and only the RGB channels are
295         * encoded: red is stored with 5 bits of precision (32 possible
296         * values), green is stored with 6 bits of precision (64 possible
297         * values) and blue is stored with 5 bits of precision.
298         *
299         * This configuration can produce slight visual artifacts depending
300         * on the configuration of the source. For instance, without
301         * dithering, the result might show a greenish tint. To get better
302         * results dithering should be applied.
303         *
304         * This configuration may be useful when using opaque bitmaps
305         * that do not require high color fidelity.
306         */
307        RGB_565     (4),
308
309        /**
310         * Each pixel is stored on 2 bytes. The three RGB color channels
311         * and the alpha channel (translucency) are stored with a 4 bits
312         * precision (16 possible values.)
313         *
314         * This configuration is mostly useful if the application needs
315         * to store translucency information but also needs to save
316         * memory.
317         *
318         * It is recommended to use {@link #ARGB_8888} instead of this
319         * configuration.
320         *
321         * @deprecated Because of the poor quality of this configuration,
322         *             it is advised to use {@link #ARGB_8888} instead.
323         */
324        @Deprecated
325        ARGB_4444   (5),
326
327        /**
328         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
329         * for translucency) is stored with 8 bits of precision (256
330         * possible values.)
331         *
332         * This configuration is very flexible and offers the best
333         * quality. It should be used whenever possible.
334         */
335        ARGB_8888   (6);
336
337        final int nativeInt;
338
339        @SuppressWarnings({"deprecation"})
340        private static Config sConfigs[] = {
341            null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
342        };
343
344        Config(int ni) {
345            this.nativeInt = ni;
346        }
347
348        static Config nativeToConfig(int ni) {
349            return sConfigs[ni];
350        }
351    }
352
353    /**
354     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
355     * caller). An exception is thrown if the buffer is not large enough to
356     * hold all of the pixels (taking into account the number of bytes per
357     * pixel) or if the Buffer subclass is not one of the support types
358     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
359     * <p>The content of the bitmap is copied into the buffer as-is. This means
360     * that if this bitmap stores its pixels pre-multiplied
361     * (see {@link #isPremultiplied()}, the values in the buffer will also be
362     * pre-multiplied.</p>
363     */
364    public void copyPixelsToBuffer(Buffer dst) {
365        int elements = dst.remaining();
366        int shift;
367        if (dst instanceof ByteBuffer) {
368            shift = 0;
369        } else if (dst instanceof ShortBuffer) {
370            shift = 1;
371        } else if (dst instanceof IntBuffer) {
372            shift = 2;
373        } else {
374            throw new RuntimeException("unsupported Buffer subclass");
375        }
376
377        long bufferSize = (long)elements << shift;
378        long pixelSize = getByteCount();
379
380        if (bufferSize < pixelSize) {
381            throw new RuntimeException("Buffer not large enough for pixels");
382        }
383
384        nativeCopyPixelsToBuffer(mNativeBitmap, dst);
385
386        // now update the buffer's position
387        int position = dst.position();
388        position += pixelSize >> shift;
389        dst.position(position);
390    }
391
392    /**
393     * <p>Copy the pixels from the buffer, beginning at the current position,
394     * overwriting the bitmap's pixels. The data in the buffer is not changed
395     * in any way (unlike setPixels(), which converts from unpremultipled 32bit
396     * to whatever the bitmap's native format is.</p>
397     */
398    public void copyPixelsFromBuffer(Buffer src) {
399        checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
400
401        int elements = src.remaining();
402        int shift;
403        if (src instanceof ByteBuffer) {
404            shift = 0;
405        } else if (src instanceof ShortBuffer) {
406            shift = 1;
407        } else if (src instanceof IntBuffer) {
408            shift = 2;
409        } else {
410            throw new RuntimeException("unsupported Buffer subclass");
411        }
412
413        long bufferBytes = (long) elements << shift;
414        long bitmapBytes = getByteCount();
415
416        if (bufferBytes < bitmapBytes) {
417            throw new RuntimeException("Buffer not large enough for pixels");
418        }
419
420        nativeCopyPixelsFromBuffer(mNativeBitmap, src);
421
422        // now update the buffer's position
423        int position = src.position();
424        position += bitmapBytes >> shift;
425        src.position(position);
426    }
427
428    /**
429     * Tries to make a new bitmap based on the dimensions of this bitmap,
430     * setting the new bitmap's config to the one specified, and then copying
431     * this bitmap's pixels into the new bitmap. If the conversion is not
432     * supported, or the allocator fails, then this returns NULL.  The returned
433     * bitmap initially has the same density as the original.
434     *
435     * @param config    The desired config for the resulting bitmap
436     * @param isMutable True if the resulting bitmap should be mutable (i.e.
437     *                  its pixels can be modified)
438     * @return the new bitmap, or null if the copy could not be made.
439     */
440    public Bitmap copy(Config config, boolean isMutable) {
441        checkRecycled("Can't copy a recycled bitmap");
442        Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
443        if (b != null) {
444            b.mDensity = mDensity;
445        }
446        return b;
447    }
448
449    /**
450     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
451     * specified width and height are the same as the current width and height of
452     * the source btimap, the source bitmap is returned and now new bitmap is
453     * created.
454     *
455     * @param src       The source bitmap.
456     * @param dstWidth  The new bitmap's desired width.
457     * @param dstHeight The new bitmap's desired height.
458     * @param filter    true if the source should be filtered.
459     * @return The new scaled bitmap or the source bitmap if no scaling is required.
460     */
461    public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
462            boolean filter) {
463        Matrix m;
464        synchronized (Bitmap.class) {
465            // small pool of just 1 matrix
466            m = sScaleMatrix;
467            sScaleMatrix = null;
468        }
469
470        if (m == null) {
471            m = new Matrix();
472        }
473
474        final int width = src.getWidth();
475        final int height = src.getHeight();
476        final float sx = dstWidth  / (float)width;
477        final float sy = dstHeight / (float)height;
478        m.setScale(sx, sy);
479        Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
480
481        synchronized (Bitmap.class) {
482            // do we need to check for null? why not just assign everytime?
483            if (sScaleMatrix == null) {
484                sScaleMatrix = m;
485            }
486        }
487
488        return b;
489    }
490
491    /**
492     * Returns an immutable bitmap from the source bitmap. The new bitmap may
493     * be the same object as source, or a copy may have been made.  It is
494     * initialized with the same density as the original bitmap.
495     */
496    public static Bitmap createBitmap(Bitmap src) {
497        return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
498    }
499
500    /**
501     * Returns an immutable bitmap from the specified subset of the source
502     * bitmap. The new bitmap may be the same object as source, or a copy may
503     * have been made. It is initialized with the same density as the original
504     * bitmap.
505     *
506     * @param source   The bitmap we are subsetting
507     * @param x        The x coordinate of the first pixel in source
508     * @param y        The y coordinate of the first pixel in source
509     * @param width    The number of pixels in each row
510     * @param height   The number of rows
511     * @return A copy of a subset of the source bitmap or the source bitmap itself.
512     */
513    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
514        return createBitmap(source, x, y, width, height, null, false);
515    }
516
517    /**
518     * Returns an immutable bitmap from subset of the source bitmap,
519     * transformed by the optional matrix. The new bitmap may be the
520     * same object as source, or a copy may have been made. It is
521     * initialized with the same density as the original bitmap.
522     *
523     * If the source bitmap is immutable and the requested subset is the
524     * same as the source bitmap itself, then the source bitmap is
525     * returned and no new bitmap is created.
526     *
527     * @param source   The bitmap we are subsetting
528     * @param x        The x coordinate of the first pixel in source
529     * @param y        The y coordinate of the first pixel in source
530     * @param width    The number of pixels in each row
531     * @param height   The number of rows
532     * @param m        Optional matrix to be applied to the pixels
533     * @param filter   true if the source should be filtered.
534     *                   Only applies if the matrix contains more than just
535     *                   translation.
536     * @return A bitmap that represents the specified subset of source
537     * @throws IllegalArgumentException if the x, y, width, height values are
538     *         outside of the dimensions of the source bitmap.
539     */
540    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
541            Matrix m, boolean filter) {
542
543        checkXYSign(x, y);
544        checkWidthHeight(width, height);
545        if (x + width > source.getWidth()) {
546            throw new IllegalArgumentException("x + width must be <= bitmap.width()");
547        }
548        if (y + height > source.getHeight()) {
549            throw new IllegalArgumentException("y + height must be <= bitmap.height()");
550        }
551
552        // check if we can just return our argument unchanged
553        if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
554                height == source.getHeight() && (m == null || m.isIdentity())) {
555            return source;
556        }
557
558        int neww = width;
559        int newh = height;
560        Canvas canvas = new Canvas();
561        Bitmap bitmap;
562        Paint paint;
563
564        Rect srcR = new Rect(x, y, x + width, y + height);
565        RectF dstR = new RectF(0, 0, width, height);
566
567        Config newConfig = Config.ARGB_8888;
568        final Config config = source.getConfig();
569        // GIF files generate null configs, assume ARGB_8888
570        if (config != null) {
571            switch (config) {
572                case RGB_565:
573                    newConfig = Config.RGB_565;
574                    break;
575                case ALPHA_8:
576                    newConfig = Config.ALPHA_8;
577                    break;
578                //noinspection deprecation
579                case ARGB_4444:
580                case ARGB_8888:
581                default:
582                    newConfig = Config.ARGB_8888;
583                    break;
584            }
585        }
586
587        if (m == null || m.isIdentity()) {
588            bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
589            paint = null;   // not needed
590        } else {
591            final boolean transformed = !m.rectStaysRect();
592
593            RectF deviceR = new RectF();
594            m.mapRect(deviceR, dstR);
595
596            neww = Math.round(deviceR.width());
597            newh = Math.round(deviceR.height());
598
599            bitmap = createBitmap(neww, newh, transformed ? Config.ARGB_8888 : newConfig,
600                    transformed || source.hasAlpha());
601
602            canvas.translate(-deviceR.left, -deviceR.top);
603            canvas.concat(m);
604
605            paint = new Paint();
606            paint.setFilterBitmap(filter);
607            if (transformed) {
608                paint.setAntiAlias(true);
609            }
610        }
611
612        // The new bitmap was created from a known bitmap source so assume that
613        // they use the same density
614        bitmap.mDensity = source.mDensity;
615
616        canvas.setBitmap(bitmap);
617        canvas.drawBitmap(source, srcR, dstR, paint);
618        canvas.setBitmap(null);
619
620        return bitmap;
621    }
622
623    /**
624     * Returns a mutable bitmap with the specified width and height.  Its
625     * initial density is as per {@link #getDensity}.
626     *
627     * @param width    The width of the bitmap
628     * @param height   The height of the bitmap
629     * @param config   The bitmap config to create.
630     * @throws IllegalArgumentException if the width or height are <= 0
631     */
632    public static Bitmap createBitmap(int width, int height, Config config) {
633        return createBitmap(width, height, config, true);
634    }
635
636    /**
637     * Returns a mutable bitmap with the specified width and height.  Its
638     * initial density is determined from the given {@link DisplayMetrics}.
639     *
640     * @param display  Display metrics for the display this bitmap will be
641     *                 drawn on.
642     * @param width    The width of the bitmap
643     * @param height   The height of the bitmap
644     * @param config   The bitmap config to create.
645     * @throws IllegalArgumentException if the width or height are <= 0
646     */
647    public static Bitmap createBitmap(DisplayMetrics display, int width,
648            int height, Config config) {
649        return createBitmap(display, width, height, config, true);
650    }
651
652    /**
653     * Returns a mutable bitmap with the specified width and height.  Its
654     * initial density is as per {@link #getDensity}.
655     *
656     * @param width    The width of the bitmap
657     * @param height   The height of the bitmap
658     * @param config   The bitmap config to create.
659     * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
660     *                 bitmap as opaque. Doing so will clear the bitmap in black
661     *                 instead of transparent.
662     *
663     * @throws IllegalArgumentException if the width or height are <= 0
664     */
665    private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
666        return createBitmap(null, width, height, config, hasAlpha);
667    }
668
669    /**
670     * Returns a mutable bitmap with the specified width and height.  Its
671     * initial density is determined from the given {@link DisplayMetrics}.
672     *
673     * @param display  Display metrics for the display this bitmap will be
674     *                 drawn on.
675     * @param width    The width of the bitmap
676     * @param height   The height of the bitmap
677     * @param config   The bitmap config to create.
678     * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
679     *                 bitmap as opaque. Doing so will clear the bitmap in black
680     *                 instead of transparent.
681     *
682     * @throws IllegalArgumentException if the width or height are <= 0
683     */
684    private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
685            Config config, boolean hasAlpha) {
686        if (width <= 0 || height <= 0) {
687            throw new IllegalArgumentException("width and height must be > 0");
688        }
689        Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
690        if (display != null) {
691            bm.mDensity = display.densityDpi;
692        }
693        if (config == Config.ARGB_8888 && !hasAlpha) {
694            nativeErase(bm.mNativeBitmap, 0xff000000);
695            nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha);
696        } else {
697            // No need to initialize it to zeroes; it is backed by a VM byte array
698            // which is by definition preinitialized to all zeroes.
699            //
700            //nativeErase(bm.mNativeBitmap, 0);
701        }
702        return bm;
703    }
704
705    /**
706     * Returns a immutable bitmap with the specified width and height, with each
707     * pixel value set to the corresponding value in the colors array.  Its
708     * initial density is as per {@link #getDensity}.
709     *
710     * @param colors   Array of {@link Color} used to initialize the pixels.
711     * @param offset   Number of values to skip before the first color in the
712     *                 array of colors.
713     * @param stride   Number of colors in the array between rows (must be >=
714     *                 width or <= -width).
715     * @param width    The width of the bitmap
716     * @param height   The height of the bitmap
717     * @param config   The bitmap config to create. If the config does not
718     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
719     *                 bytes in the colors[] will be ignored (assumed to be FF)
720     * @throws IllegalArgumentException if the width or height are <= 0, or if
721     *         the color array's length is less than the number of pixels.
722     */
723    public static Bitmap createBitmap(int colors[], int offset, int stride,
724            int width, int height, Config config) {
725        return createBitmap(null, colors, offset, stride, width, height, config);
726    }
727
728    /**
729     * Returns a immutable bitmap with the specified width and height, with each
730     * pixel value set to the corresponding value in the colors array.  Its
731     * initial density is determined from the given {@link DisplayMetrics}.
732     *
733     * @param display  Display metrics for the display this bitmap will be
734     *                 drawn on.
735     * @param colors   Array of {@link Color} used to initialize the pixels.
736     * @param offset   Number of values to skip before the first color in the
737     *                 array of colors.
738     * @param stride   Number of colors in the array between rows (must be >=
739     *                 width or <= -width).
740     * @param width    The width of the bitmap
741     * @param height   The height of the bitmap
742     * @param config   The bitmap config to create. If the config does not
743     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
744     *                 bytes in the colors[] will be ignored (assumed to be FF)
745     * @throws IllegalArgumentException if the width or height are <= 0, or if
746     *         the color array's length is less than the number of pixels.
747     */
748    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
749            int offset, int stride, int width, int height, Config config) {
750
751        checkWidthHeight(width, height);
752        if (Math.abs(stride) < width) {
753            throw new IllegalArgumentException("abs(stride) must be >= width");
754        }
755        int lastScanline = offset + (height - 1) * stride;
756        int length = colors.length;
757        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
758                (lastScanline + width > length)) {
759            throw new ArrayIndexOutOfBoundsException();
760        }
761        if (width <= 0 || height <= 0) {
762            throw new IllegalArgumentException("width and height must be > 0");
763        }
764        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
765                            config.nativeInt, false);
766        if (display != null) {
767            bm.mDensity = display.densityDpi;
768        }
769        return bm;
770    }
771
772    /**
773     * Returns a immutable bitmap with the specified width and height, with each
774     * pixel value set to the corresponding value in the colors array.  Its
775     * initial density is as per {@link #getDensity}.
776     *
777     * @param colors   Array of {@link Color} used to initialize the pixels.
778     *                 This array must be at least as large as width * height.
779     * @param width    The width of the bitmap
780     * @param height   The height of the bitmap
781     * @param config   The bitmap config to create. If the config does not
782     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
783     *                 bytes in the colors[] will be ignored (assumed to be FF)
784     * @throws IllegalArgumentException if the width or height are <= 0, or if
785     *         the color array's length is less than the number of pixels.
786     */
787    public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
788        return createBitmap(null, colors, 0, width, width, height, config);
789    }
790
791    /**
792     * Returns a immutable bitmap with the specified width and height, with each
793     * pixel value set to the corresponding value in the colors array.  Its
794     * initial density is determined from the given {@link DisplayMetrics}.
795     *
796     * @param display  Display metrics for the display this bitmap will be
797     *                 drawn on.
798     * @param colors   Array of {@link Color} used to initialize the pixels.
799     *                 This array must be at least as large as width * height.
800     * @param width    The width of the bitmap
801     * @param height   The height of the bitmap
802     * @param config   The bitmap config to create. If the config does not
803     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
804     *                 bytes in the colors[] will be ignored (assumed to be FF)
805     * @throws IllegalArgumentException if the width or height are <= 0, or if
806     *         the color array's length is less than the number of pixels.
807     */
808    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
809            int width, int height, Config config) {
810        return createBitmap(display, colors, 0, width, width, height, config);
811    }
812
813    /**
814     * Returns an optional array of private data, used by the UI system for
815     * some bitmaps. Not intended to be called by applications.
816     */
817    public byte[] getNinePatchChunk() {
818        return mNinePatchChunk;
819    }
820
821    /**
822     * @hide
823     * @return the layout padding [left, right, top, bottom]
824     */
825    public int[] getLayoutBounds() {
826        return mLayoutBounds;
827    }
828
829    /**
830     * Specifies the known formats a bitmap can be compressed into
831     */
832    public enum CompressFormat {
833        JPEG    (0),
834        PNG     (1),
835        WEBP    (2);
836
837        CompressFormat(int nativeInt) {
838            this.nativeInt = nativeInt;
839        }
840        final int nativeInt;
841    }
842
843    /**
844     * Number of bytes of temp storage we use for communicating between the
845     * native compressor and the java OutputStream.
846     */
847    private final static int WORKING_COMPRESS_STORAGE = 4096;
848
849    /**
850     * Write a compressed version of the bitmap to the specified outputstream.
851     * If this returns true, the bitmap can be reconstructed by passing a
852     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
853     * all Formats support all bitmap configs directly, so it is possible that
854     * the returned bitmap from BitmapFactory could be in a different bitdepth,
855     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
856     * pixels).
857     *
858     * @param format   The format of the compressed image
859     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
860     *                 small size, 100 meaning compress for max quality. Some
861     *                 formats, like PNG which is lossless, will ignore the
862     *                 quality setting
863     * @param stream   The outputstream to write the compressed data.
864     * @return true if successfully compressed to the specified stream.
865     */
866    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
867        checkRecycled("Can't compress a recycled bitmap");
868        // do explicit check before calling the native method
869        if (stream == null) {
870            throw new NullPointerException();
871        }
872        if (quality < 0 || quality > 100) {
873            throw new IllegalArgumentException("quality must be 0..100");
874        }
875        return nativeCompress(mNativeBitmap, format.nativeInt, quality,
876                              stream, new byte[WORKING_COMPRESS_STORAGE]);
877    }
878
879    /**
880     * Returns true if the bitmap is marked as mutable (i.e. can be drawn into)
881     */
882    public final boolean isMutable() {
883        return mIsMutable;
884    }
885
886    /**
887     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
888     * When a pixel is pre-multiplied, the RGB components have been multiplied by
889     * the alpha component. For instance, if the original color is a 50%
890     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
891     * <code>(128, 128, 0, 0)</code>.</p>
892     *
893     * <p>This method always returns false if {@link #getConfig()} is
894     * {@link Bitmap.Config#RGB_565}.</p>
895     *
896     * <p>This method only returns true if {@link #hasAlpha()} returns true.
897     * A bitmap with no alpha channel can be used both as a pre-multiplied and
898     * as a non pre-multiplied bitmap.</p>
899     *
900     * @return true if the underlying pixels have been pre-multiplied, false
901     *         otherwise
902     */
903    public final boolean isPremultiplied() {
904        return getConfig() != Config.RGB_565 && hasAlpha();
905    }
906
907    /** Returns the bitmap's width */
908    public final int getWidth() {
909        return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
910    }
911
912    /** Returns the bitmap's height */
913    public final int getHeight() {
914        return mHeight == -1 ? mHeight = nativeHeight(mNativeBitmap) : mHeight;
915    }
916
917    /**
918     * Convenience for calling {@link #getScaledWidth(int)} with the target
919     * density of the given {@link Canvas}.
920     */
921    public int getScaledWidth(Canvas canvas) {
922        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
923    }
924
925    /**
926     * Convenience for calling {@link #getScaledHeight(int)} with the target
927     * density of the given {@link Canvas}.
928     */
929    public int getScaledHeight(Canvas canvas) {
930        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
931    }
932
933    /**
934     * Convenience for calling {@link #getScaledWidth(int)} with the target
935     * density of the given {@link DisplayMetrics}.
936     */
937    public int getScaledWidth(DisplayMetrics metrics) {
938        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
939    }
940
941    /**
942     * Convenience for calling {@link #getScaledHeight(int)} with the target
943     * density of the given {@link DisplayMetrics}.
944     */
945    public int getScaledHeight(DisplayMetrics metrics) {
946        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
947    }
948
949    /**
950     * Convenience method that returns the width of this bitmap divided
951     * by the density scale factor.
952     *
953     * @param targetDensity The density of the target canvas of the bitmap.
954     * @return The scaled width of this bitmap, according to the density scale factor.
955     */
956    public int getScaledWidth(int targetDensity) {
957        return scaleFromDensity(getWidth(), mDensity, targetDensity);
958    }
959
960    /**
961     * Convenience method that returns the height of this bitmap divided
962     * by the density scale factor.
963     *
964     * @param targetDensity The density of the target canvas of the bitmap.
965     * @return The scaled height of this bitmap, according to the density scale factor.
966     */
967    public int getScaledHeight(int targetDensity) {
968        return scaleFromDensity(getHeight(), mDensity, targetDensity);
969    }
970
971    /**
972     * @hide
973     */
974    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
975        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
976            return size;
977        }
978
979        // Scale by tdensity / sdensity, rounding up.
980        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
981    }
982
983    /**
984     * Return the number of bytes between rows in the bitmap's pixels. Note that
985     * this refers to the pixels as stored natively by the bitmap. If you call
986     * getPixels() or setPixels(), then the pixels are uniformly treated as
987     * 32bit values, packed according to the Color class.
988     *
989     * @return number of bytes between rows of the native bitmap pixels.
990     */
991    public final int getRowBytes() {
992        return nativeRowBytes(mNativeBitmap);
993    }
994
995    /**
996     * Returns the number of bytes used to store this bitmap's pixels.
997     */
998    public final int getByteCount() {
999        // int result permits bitmaps up to 46,340 x 46,340
1000        return getRowBytes() * getHeight();
1001    }
1002
1003    /**
1004     * If the bitmap's internal config is in one of the public formats, return
1005     * that config, otherwise return null.
1006     */
1007    public final Config getConfig() {
1008        return Config.nativeToConfig(nativeConfig(mNativeBitmap));
1009    }
1010
1011    /** Returns true if the bitmap's config supports per-pixel alpha, and
1012     * if the pixels may contain non-opaque alpha values. For some configs,
1013     * this is always false (e.g. RGB_565), since they do not support per-pixel
1014     * alpha. However, for configs that do, the bitmap may be flagged to be
1015     * known that all of its pixels are opaque. In this case hasAlpha() will
1016     * also return false. If a config such as ARGB_8888 is not so flagged,
1017     * it will return true by default.
1018     */
1019    public final boolean hasAlpha() {
1020        return nativeHasAlpha(mNativeBitmap);
1021    }
1022
1023    /**
1024     * Tell the bitmap if all of the pixels are known to be opaque (false)
1025     * or if some of the pixels may contain non-opaque alpha values (true).
1026     * Note, for some configs (e.g. RGB_565) this call is ignored, since it
1027     * does not support per-pixel alpha values.
1028     *
1029     * This is meant as a drawing hint, as in some cases a bitmap that is known
1030     * to be opaque can take a faster drawing case than one that may have
1031     * non-opaque per-pixel alpha values.
1032     */
1033    public void setHasAlpha(boolean hasAlpha) {
1034        nativeSetHasAlpha(mNativeBitmap, hasAlpha);
1035    }
1036
1037    /**
1038     * Indicates whether the renderer responsible for drawing this
1039     * bitmap should attempt to use mipmaps when this bitmap is drawn
1040     * scaled down.
1041     *
1042     * If you know that you are going to draw this bitmap at less than
1043     * 50% of its original size, you may be able to obtain a higher
1044     * quality
1045     *
1046     * This property is only a suggestion that can be ignored by the
1047     * renderer. It is not guaranteed to have any effect.
1048     *
1049     * @return true if the renderer should attempt to use mipmaps,
1050     *         false otherwise
1051     *
1052     * @see #setHasMipMap(boolean)
1053     */
1054    public final boolean hasMipMap() {
1055        return nativeHasMipMap(mNativeBitmap);
1056    }
1057
1058    /**
1059     * Set a hint for the renderer responsible for drawing this bitmap
1060     * indicating that it should attempt to use mipmaps when this bitmap
1061     * is drawn scaled down.
1062     *
1063     * If you know that you are going to draw this bitmap at less than
1064     * 50% of its original size, you may be able to obtain a higher
1065     * quality by turning this property on.
1066     *
1067     * Note that if the renderer respects this hint it might have to
1068     * allocate extra memory to hold the mipmap levels for this bitmap.
1069     *
1070     * This property is only a suggestion that can be ignored by the
1071     * renderer. It is not guaranteed to have any effect.
1072     *
1073     * @param hasMipMap indicates whether the renderer should attempt
1074     *                  to use mipmaps
1075     *
1076     * @see #hasMipMap()
1077     */
1078    public final void setHasMipMap(boolean hasMipMap) {
1079        nativeSetHasMipMap(mNativeBitmap, hasMipMap);
1080    }
1081
1082    /**
1083     * Fills the bitmap's pixels with the specified {@link Color}.
1084     *
1085     * @throws IllegalStateException if the bitmap is not mutable.
1086     */
1087    public void eraseColor(int c) {
1088        checkRecycled("Can't erase a recycled bitmap");
1089        if (!isMutable()) {
1090            throw new IllegalStateException("cannot erase immutable bitmaps");
1091        }
1092        nativeErase(mNativeBitmap, c);
1093    }
1094
1095    /**
1096     * Returns the {@link Color} at the specified location. Throws an exception
1097     * if x or y are out of bounds (negative or >= to the width or height
1098     * respectively). The returned color is a non-premultiplied ARGB value.
1099     *
1100     * @param x    The x coordinate (0...width-1) of the pixel to return
1101     * @param y    The y coordinate (0...height-1) of the pixel to return
1102     * @return     The argb {@link Color} at the specified coordinate
1103     * @throws IllegalArgumentException if x, y exceed the bitmap's bounds
1104     */
1105    public int getPixel(int x, int y) {
1106        checkRecycled("Can't call getPixel() on a recycled bitmap");
1107        checkPixelAccess(x, y);
1108        return nativeGetPixel(mNativeBitmap, x, y);
1109    }
1110
1111    /**
1112     * Returns in pixels[] a copy of the data in the bitmap. Each value is
1113     * a packed int representing a {@link Color}. The stride parameter allows
1114     * the caller to allow for gaps in the returned pixels array between
1115     * rows. For normal packed results, just pass width for the stride value.
1116     * The returned colors are non-premultiplied ARGB values.
1117     *
1118     * @param pixels   The array to receive the bitmap's colors
1119     * @param offset   The first index to write into pixels[]
1120     * @param stride   The number of entries in pixels[] to skip between
1121     *                 rows (must be >= bitmap's width). Can be negative.
1122     * @param x        The x coordinate of the first pixel to read from
1123     *                 the bitmap
1124     * @param y        The y coordinate of the first pixel to read from
1125     *                 the bitmap
1126     * @param width    The number of pixels to read from each row
1127     * @param height   The number of rows to read
1128     *
1129     * @throws IllegalArgumentException if x, y, width, height exceed the
1130     *         bounds of the bitmap, or if abs(stride) < width.
1131     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1132     *         to receive the specified number of pixels.
1133     */
1134    public void getPixels(int[] pixels, int offset, int stride,
1135                          int x, int y, int width, int height) {
1136        checkRecycled("Can't call getPixels() on a recycled bitmap");
1137        if (width == 0 || height == 0) {
1138            return; // nothing to do
1139        }
1140        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1141        nativeGetPixels(mNativeBitmap, pixels, offset, stride,
1142                        x, y, width, height);
1143    }
1144
1145    /**
1146     * Shared code to check for illegal arguments passed to getPixel()
1147     * or setPixel()
1148     *
1149     * @param x x coordinate of the pixel
1150     * @param y y coordinate of the pixel
1151     */
1152    private void checkPixelAccess(int x, int y) {
1153        checkXYSign(x, y);
1154        if (x >= getWidth()) {
1155            throw new IllegalArgumentException("x must be < bitmap.width()");
1156        }
1157        if (y >= getHeight()) {
1158            throw new IllegalArgumentException("y must be < bitmap.height()");
1159        }
1160    }
1161
1162    /**
1163     * Shared code to check for illegal arguments passed to getPixels()
1164     * or setPixels()
1165     *
1166     * @param x left edge of the area of pixels to access
1167     * @param y top edge of the area of pixels to access
1168     * @param width width of the area of pixels to access
1169     * @param height height of the area of pixels to access
1170     * @param offset offset into pixels[] array
1171     * @param stride number of elements in pixels[] between each logical row
1172     * @param pixels array to hold the area of pixels being accessed
1173    */
1174    private void checkPixelsAccess(int x, int y, int width, int height,
1175                                   int offset, int stride, int pixels[]) {
1176        checkXYSign(x, y);
1177        if (width < 0) {
1178            throw new IllegalArgumentException("width must be >= 0");
1179        }
1180        if (height < 0) {
1181            throw new IllegalArgumentException("height must be >= 0");
1182        }
1183        if (x + width > getWidth()) {
1184            throw new IllegalArgumentException(
1185                    "x + width must be <= bitmap.width()");
1186        }
1187        if (y + height > getHeight()) {
1188            throw new IllegalArgumentException(
1189                    "y + height must be <= bitmap.height()");
1190        }
1191        if (Math.abs(stride) < width) {
1192            throw new IllegalArgumentException("abs(stride) must be >= width");
1193        }
1194        int lastScanline = offset + (height - 1) * stride;
1195        int length = pixels.length;
1196        if (offset < 0 || (offset + width > length)
1197                || lastScanline < 0
1198                || (lastScanline + width > length)) {
1199            throw new ArrayIndexOutOfBoundsException();
1200        }
1201    }
1202
1203    /**
1204     * <p>Write the specified {@link Color} into the bitmap (assuming it is
1205     * mutable) at the x,y coordinate. The color must be a
1206     * non-premultiplied ARGB value.</p>
1207     *
1208     * @param x     The x coordinate of the pixel to replace (0...width-1)
1209     * @param y     The y coordinate of the pixel to replace (0...height-1)
1210     * @param color The ARGB color to write into the bitmap
1211     *
1212     * @throws IllegalStateException if the bitmap is not mutable
1213     * @throws IllegalArgumentException if x, y are outside of the bitmap's
1214     *         bounds.
1215     */
1216    public void setPixel(int x, int y, int color) {
1217        checkRecycled("Can't call setPixel() on a recycled bitmap");
1218        if (!isMutable()) {
1219            throw new IllegalStateException();
1220        }
1221        checkPixelAccess(x, y);
1222        nativeSetPixel(mNativeBitmap, x, y, color);
1223    }
1224
1225    /**
1226     * <p>Replace pixels in the bitmap with the colors in the array. Each element
1227     * in the array is a packed int prepresenting a non-premultiplied ARGB
1228     * {@link Color}.</p>
1229     *
1230     * @param pixels   The colors to write to the bitmap
1231     * @param offset   The index of the first color to read from pixels[]
1232     * @param stride   The number of colors in pixels[] to skip between rows.
1233     *                 Normally this value will be the same as the width of
1234     *                 the bitmap, but it can be larger (or negative).
1235     * @param x        The x coordinate of the first pixel to write to in
1236     *                 the bitmap.
1237     * @param y        The y coordinate of the first pixel to write to in
1238     *                 the bitmap.
1239     * @param width    The number of colors to copy from pixels[] per row
1240     * @param height   The number of rows to write to the bitmap
1241     *
1242     * @throws IllegalStateException if the bitmap is not mutable
1243     * @throws IllegalArgumentException if x, y, width, height are outside of
1244     *         the bitmap's bounds.
1245     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1246     *         to receive the specified number of pixels.
1247     */
1248    public void setPixels(int[] pixels, int offset, int stride,
1249            int x, int y, int width, int height) {
1250        checkRecycled("Can't call setPixels() on a recycled bitmap");
1251        if (!isMutable()) {
1252            throw new IllegalStateException();
1253        }
1254        if (width == 0 || height == 0) {
1255            return; // nothing to do
1256        }
1257        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1258        nativeSetPixels(mNativeBitmap, pixels, offset, stride,
1259                        x, y, width, height);
1260    }
1261
1262    public static final Parcelable.Creator<Bitmap> CREATOR
1263            = new Parcelable.Creator<Bitmap>() {
1264        /**
1265         * Rebuilds a bitmap previously stored with writeToParcel().
1266         *
1267         * @param p    Parcel object to read the bitmap from
1268         * @return a new bitmap created from the data in the parcel
1269         */
1270        public Bitmap createFromParcel(Parcel p) {
1271            Bitmap bm = nativeCreateFromParcel(p);
1272            if (bm == null) {
1273                throw new RuntimeException("Failed to unparcel Bitmap");
1274            }
1275            return bm;
1276        }
1277        public Bitmap[] newArray(int size) {
1278            return new Bitmap[size];
1279        }
1280    };
1281
1282    /**
1283     * No special parcel contents.
1284     */
1285    public int describeContents() {
1286        return 0;
1287    }
1288
1289    /**
1290     * Write the bitmap and its pixels to the parcel. The bitmap can be
1291     * rebuilt from the parcel by calling CREATOR.createFromParcel().
1292     * @param p    Parcel object to write the bitmap data into
1293     */
1294    public void writeToParcel(Parcel p, int flags) {
1295        checkRecycled("Can't parcel a recycled bitmap");
1296        if (!nativeWriteToParcel(mNativeBitmap, mIsMutable, mDensity, p)) {
1297            throw new RuntimeException("native writeToParcel failed");
1298        }
1299    }
1300
1301    /**
1302     * Returns a new bitmap that captures the alpha values of the original.
1303     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be
1304     * taken from the paint that is passed to the draw call.
1305     *
1306     * @return new bitmap containing the alpha channel of the original bitmap.
1307     */
1308    public Bitmap extractAlpha() {
1309        return extractAlpha(null, null);
1310    }
1311
1312    /**
1313     * Returns a new bitmap that captures the alpha values of the original.
1314     * These values may be affected by the optional Paint parameter, which
1315     * can contain its own alpha, and may also contain a MaskFilter which
1316     * could change the actual dimensions of the resulting bitmap (e.g.
1317     * a blur maskfilter might enlarge the resulting bitmap). If offsetXY
1318     * is not null, it returns the amount to offset the returned bitmap so
1319     * that it will logically align with the original. For example, if the
1320     * paint contains a blur of radius 2, then offsetXY[] would contains
1321     * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
1322     * drawing the original would result in the blur visually aligning with
1323     * the original.
1324     *
1325     * <p>The initial density of the returned bitmap is the same as the original's.
1326     *
1327     * @param paint Optional paint used to modify the alpha values in the
1328     *              resulting bitmap. Pass null for default behavior.
1329     * @param offsetXY Optional array that returns the X (index 0) and Y
1330     *                 (index 1) offset needed to position the returned bitmap
1331     *                 so that it visually lines up with the original.
1332     * @return new bitmap containing the (optionally modified by paint) alpha
1333     *         channel of the original bitmap. This may be drawn with
1334     *         Canvas.drawBitmap(), where the color(s) will be taken from the
1335     *         paint that is passed to the draw call.
1336     */
1337    public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
1338        checkRecycled("Can't extractAlpha on a recycled bitmap");
1339        int nativePaint = paint != null ? paint.mNativePaint : 0;
1340        Bitmap bm = nativeExtractAlpha(mNativeBitmap, nativePaint, offsetXY);
1341        if (bm == null) {
1342            throw new RuntimeException("Failed to extractAlpha on Bitmap");
1343        }
1344        bm.mDensity = mDensity;
1345        return bm;
1346    }
1347
1348    /**
1349     *  Given another bitmap, return true if it has the same dimensions, config,
1350     *  and pixel data as this bitmap. If any of those differ, return false.
1351     *  If other is null, return false.
1352     */
1353    public boolean sameAs(Bitmap other) {
1354        return this == other || (other != null && nativeSameAs(mNativeBitmap, other.mNativeBitmap));
1355    }
1356
1357    /**
1358     * Rebuilds any caches associated with the bitmap that are used for
1359     * drawing it. In the case of purgeable bitmaps, this call will attempt to
1360     * ensure that the pixels have been decoded.
1361     * If this is called on more than one bitmap in sequence, the priority is
1362     * given in LRU order (i.e. the last bitmap called will be given highest
1363     * priority).
1364     *
1365     * For bitmaps with no associated caches, this call is effectively a no-op,
1366     * and therefore is harmless.
1367     */
1368    public void prepareToDraw() {
1369        nativePrepareToDraw(mNativeBitmap);
1370    }
1371
1372    private static class BitmapFinalizer {
1373        private final int mNativeBitmap;
1374
1375        BitmapFinalizer(int nativeBitmap) {
1376            mNativeBitmap = nativeBitmap;
1377        }
1378
1379        @Override
1380        public void finalize() {
1381            try {
1382                super.finalize();
1383            } catch (Throwable t) {
1384                // Ignore
1385            } finally {
1386                nativeDestructor(mNativeBitmap);
1387            }
1388        }
1389    }
1390
1391    //////////// native methods
1392
1393    private static native Bitmap nativeCreate(int[] colors, int offset,
1394                                              int stride, int width, int height,
1395                                            int nativeConfig, boolean mutable);
1396    private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
1397                                            boolean isMutable);
1398    private static native void nativeDestructor(int nativeBitmap);
1399    private static native boolean nativeRecycle(int nativeBitmap);
1400
1401    private static native boolean nativeCompress(int nativeBitmap, int format,
1402                                            int quality, OutputStream stream,
1403                                            byte[] tempStorage);
1404    private static native void nativeErase(int nativeBitmap, int color);
1405    private static native int nativeWidth(int nativeBitmap);
1406    private static native int nativeHeight(int nativeBitmap);
1407    private static native int nativeRowBytes(int nativeBitmap);
1408    private static native int nativeConfig(int nativeBitmap);
1409
1410    private static native int nativeGetPixel(int nativeBitmap, int x, int y);
1411    private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
1412                                               int offset, int stride, int x,
1413                                               int y, int width, int height);
1414
1415    private static native void nativeSetPixel(int nativeBitmap, int x, int y,
1416                                              int color);
1417    private static native void nativeSetPixels(int nativeBitmap, int[] colors,
1418                                               int offset, int stride, int x,
1419                                               int y, int width, int height);
1420    private static native void nativeCopyPixelsToBuffer(int nativeBitmap,
1421                                                        Buffer dst);
1422    private static native void nativeCopyPixelsFromBuffer(int nb, Buffer src);
1423    private static native int nativeGenerationId(int nativeBitmap);
1424
1425    private static native Bitmap nativeCreateFromParcel(Parcel p);
1426    // returns true on success
1427    private static native boolean nativeWriteToParcel(int nativeBitmap,
1428                                                      boolean isMutable,
1429                                                      int density,
1430                                                      Parcel p);
1431    // returns a new bitmap built from the native bitmap's alpha, and the paint
1432    private static native Bitmap nativeExtractAlpha(int nativeBitmap,
1433                                                    int nativePaint,
1434                                                    int[] offsetXY);
1435
1436    private static native void nativePrepareToDraw(int nativeBitmap);
1437    private static native boolean nativeHasAlpha(int nativeBitmap);
1438    private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
1439    private static native boolean nativeHasMipMap(int nativeBitmap);
1440    private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
1441    private static native boolean nativeSameAs(int nb0, int nb1);
1442
1443    /* package */ final int ni() {
1444        return mNativeBitmap;
1445    }
1446}
1447