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