Bitmap.java revision 1c2bf03d1082fc6b7eb42cbd163c60c07cf2bccc
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
19import android.annotation.CheckResult;
20import android.annotation.ColorInt;
21import android.annotation.NonNull;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.os.Trace;
25import android.util.DisplayMetrics;
26
27import dalvik.system.VMRuntime;
28
29import java.io.OutputStream;
30import java.nio.Buffer;
31import java.nio.ByteBuffer;
32import java.nio.IntBuffer;
33import java.nio.ShortBuffer;
34
35public final class Bitmap implements Parcelable {
36    /**
37     * Indicates that the bitmap was created for an unknown pixel density.
38     *
39     * @see Bitmap#getDensity()
40     * @see Bitmap#setDensity(int)
41     */
42    public static final int DENSITY_NONE = 0;
43
44    private final long mSkBitmapPtr;
45
46    /**
47     * Backing buffer for the Bitmap.
48     */
49    private byte[] mBuffer;
50
51    private final BitmapFinalizer mFinalizer;
52
53    private final boolean mIsMutable;
54
55    /**
56     * Represents whether the Bitmap's content is requested to be pre-multiplied.
57     * Note that isPremultiplied() does not directly return this value, because
58     * isPremultiplied() may never return true for a 565 Bitmap or a bitmap
59     * without alpha.
60     *
61     * setPremultiplied() does directly set the value so that setConfig() and
62     * setPremultiplied() aren't order dependent, despite being setters.
63     *
64     * The native bitmap's premultiplication state is kept up to date by
65     * pushing down this preference for every config change.
66     */
67    private boolean mRequestPremultiplied;
68
69    private byte[] mNinePatchChunk; // may be null
70    private NinePatch.InsetStruct mNinePatchInsets; // may be null
71    private int mWidth;
72    private int mHeight;
73    private boolean mRecycled;
74
75    // Package-scoped for fast access.
76    int mDensity = getDefaultDensity();
77
78    private static volatile Matrix sScaleMatrix;
79
80    private static volatile int sDefaultDensity = -1;
81
82    /**
83     * For backwards compatibility, allows the app layer to change the default
84     * density when running old apps.
85     * @hide
86     */
87    public static void setDefaultDensity(int density) {
88        sDefaultDensity = density;
89    }
90
91    @SuppressWarnings("deprecation")
92    static int getDefaultDensity() {
93        if (sDefaultDensity >= 0) {
94            return sDefaultDensity;
95        }
96        sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
97        return sDefaultDensity;
98    }
99
100    /**
101     * Private constructor that must received an already allocated native bitmap
102     * int (pointer).
103     */
104    // called from JNI
105    Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
106            boolean isMutable, boolean requestPremultiplied,
107            byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
108        if (nativeBitmap == 0) {
109            throw new RuntimeException("internal error: native bitmap is 0");
110        }
111
112        mWidth = width;
113        mHeight = height;
114        mIsMutable = isMutable;
115        mRequestPremultiplied = requestPremultiplied;
116        mBuffer = buffer;
117
118        // we delete this in our finalizer
119        mSkBitmapPtr = nativeBitmap;
120
121        mNinePatchChunk = ninePatchChunk;
122        mNinePatchInsets = ninePatchInsets;
123        if (density >= 0) {
124            mDensity = density;
125        }
126
127        int nativeAllocationByteCount = buffer == null ? getByteCount() : 0;
128        mFinalizer = new BitmapFinalizer(nativeBitmap, nativeAllocationByteCount);
129    }
130
131    /**
132     * Native bitmap has been reconfigured, so set premult and cached
133     * width/height values
134     */
135    // called from JNI
136    void reinit(int width, int height, boolean requestPremultiplied) {
137        mWidth = width;
138        mHeight = height;
139        mRequestPremultiplied = requestPremultiplied;
140    }
141
142    /**
143     * <p>Returns the density for this bitmap.</p>
144     *
145     * <p>The default density is the same density as the current display,
146     * unless the current application does not support different screen
147     * densities in which case it is
148     * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}.  Note that
149     * compatibility mode is determined by the application that was initially
150     * loaded into a process -- applications that share the same process should
151     * all have the same compatibility, or ensure they explicitly set the
152     * density of their bitmaps appropriately.</p>
153     *
154     * @return A scaling factor of the default density or {@link #DENSITY_NONE}
155     *         if the scaling factor is unknown.
156     *
157     * @see #setDensity(int)
158     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
159     * @see android.util.DisplayMetrics#densityDpi
160     * @see #DENSITY_NONE
161     */
162    public int getDensity() {
163        return mDensity;
164    }
165
166    /**
167     * <p>Specifies the density for this bitmap.  When the bitmap is
168     * drawn to a Canvas that also has a density, it will be scaled
169     * appropriately.</p>
170     *
171     * @param density The density scaling factor to use with this bitmap or
172     *        {@link #DENSITY_NONE} if the density is unknown.
173     *
174     * @see #getDensity()
175     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
176     * @see android.util.DisplayMetrics#densityDpi
177     * @see #DENSITY_NONE
178     */
179    public void setDensity(int density) {
180        mDensity = density;
181    }
182
183    /**
184     * <p>Modifies the bitmap to have a specified width, height, and {@link
185     * Config}, without affecting the underlying allocation backing the bitmap.
186     * Bitmap pixel data is not re-initialized for the new configuration.</p>
187     *
188     * <p>This method can be used to avoid allocating a new bitmap, instead
189     * reusing an existing bitmap's allocation for a new configuration of equal
190     * or lesser size. If the Bitmap's allocation isn't large enough to support
191     * the new configuration, an IllegalArgumentException will be thrown and the
192     * bitmap will not be modified.</p>
193     *
194     * <p>The result of {@link #getByteCount()} will reflect the new configuration,
195     * while {@link #getAllocationByteCount()} will reflect that of the initial
196     * configuration.</p>
197     *
198     * <p>Note: This may change this result of hasAlpha(). When converting to 565,
199     * the new bitmap will always be considered opaque. When converting from 565,
200     * the new bitmap will be considered non-opaque, and will respect the value
201     * set by setPremultiplied().</p>
202     *
203     * <p>WARNING: This method should NOT be called on a bitmap currently used
204     * by the view system. It does not make guarantees about how the underlying
205     * pixel buffer is remapped to the new config, just that the allocation is
206     * reused. Additionally, the view system does not account for bitmap
207     * properties being modifying during use, e.g. while attached to
208     * drawables.</p>
209     *
210     * @see #setWidth(int)
211     * @see #setHeight(int)
212     * @see #setConfig(Config)
213     */
214    public void reconfigure(int width, int height, Config config) {
215        checkRecycled("Can't call reconfigure() on a recycled bitmap");
216        if (width <= 0 || height <= 0) {
217            throw new IllegalArgumentException("width and height must be > 0");
218        }
219        if (!isMutable()) {
220            throw new IllegalStateException("only mutable bitmaps may be reconfigured");
221        }
222        if (mBuffer == null) {
223            throw new IllegalStateException("native-backed bitmaps may not be reconfigured");
224        }
225
226        nativeReconfigure(mSkBitmapPtr, width, height, config.nativeInt, mBuffer.length,
227                mRequestPremultiplied);
228        mWidth = width;
229        mHeight = height;
230    }
231
232    /**
233     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
234     * with the current height and config.</p>
235     *
236     * <p>WARNING: this method should not be used on bitmaps currently used by
237     * the view system, see {@link #reconfigure(int, int, Config)} for more
238     * details.</p>
239     *
240     * @see #reconfigure(int, int, Config)
241     * @see #setHeight(int)
242     * @see #setConfig(Config)
243     */
244    public void setWidth(int width) {
245        reconfigure(width, getHeight(), getConfig());
246    }
247
248    /**
249     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
250     * with the current width and config.</p>
251     *
252     * <p>WARNING: this method should not be used on bitmaps currently used by
253     * the view system, see {@link #reconfigure(int, int, Config)} for more
254     * details.</p>
255     *
256     * @see #reconfigure(int, int, Config)
257     * @see #setWidth(int)
258     * @see #setConfig(Config)
259     */
260    public void setHeight(int height) {
261        reconfigure(getWidth(), height, getConfig());
262    }
263
264    /**
265     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
266     * with the current height and width.</p>
267     *
268     * <p>WARNING: this method should not be used on bitmaps currently used by
269     * the view system, see {@link #reconfigure(int, int, Config)} for more
270     * details.</p>
271     *
272     * @see #reconfigure(int, int, Config)
273     * @see #setWidth(int)
274     * @see #setHeight(int)
275     */
276    public void setConfig(Config config) {
277        reconfigure(getWidth(), getHeight(), config);
278    }
279
280    /**
281     * Sets the nine patch chunk.
282     *
283     * @param chunk The definition of the nine patch
284     *
285     * @hide
286     */
287    public void setNinePatchChunk(byte[] chunk) {
288        mNinePatchChunk = chunk;
289    }
290
291    /**
292     * Free the native object associated with this bitmap, and clear the
293     * reference to the pixel data. This will not free the pixel data synchronously;
294     * it simply allows it to be garbage collected if there are no other references.
295     * The bitmap is marked as "dead", meaning it will throw an exception if
296     * getPixels() or setPixels() is called, and will draw nothing. This operation
297     * cannot be reversed, so it should only be called if you are sure there are no
298     * further uses for the bitmap. This is an advanced call, and normally need
299     * not be called, since the normal GC process will free up this memory when
300     * there are no more references to this bitmap.
301     */
302    public void recycle() {
303        if (!mRecycled && mFinalizer.mNativeBitmap != 0) {
304            if (nativeRecycle(mSkBitmapPtr)) {
305                // return value indicates whether native pixel object was actually recycled.
306                // false indicates that it is still in use at the native level and these
307                // objects should not be collected now. They will be collected later when the
308                // Bitmap itself is collected.
309                mBuffer = null;
310                mNinePatchChunk = null;
311            }
312            mRecycled = true;
313        }
314    }
315
316    /**
317     * Returns true if this bitmap has been recycled. If so, then it is an error
318     * to try to access its pixels, and the bitmap will not draw.
319     *
320     * @return true if the bitmap has been recycled
321     */
322    public final boolean isRecycled() {
323        return mRecycled;
324    }
325
326    /**
327     * Returns the generation ID of this bitmap. The generation ID changes
328     * whenever the bitmap is modified. This can be used as an efficient way to
329     * check if a bitmap has changed.
330     *
331     * @return The current generation ID for this bitmap.
332     */
333    public int getGenerationId() {
334        return nativeGenerationId(mSkBitmapPtr);
335    }
336
337    /**
338     * This is called by methods that want to throw an exception if the bitmap
339     * has already been recycled.
340     */
341    private void checkRecycled(String errorMessage) {
342        if (mRecycled) {
343            throw new IllegalStateException(errorMessage);
344        }
345    }
346
347    /**
348     * Common code for checking that x and y are >= 0
349     *
350     * @param x x coordinate to ensure is >= 0
351     * @param y y coordinate to ensure is >= 0
352     */
353    private static void checkXYSign(int x, int y) {
354        if (x < 0) {
355            throw new IllegalArgumentException("x must be >= 0");
356        }
357        if (y < 0) {
358            throw new IllegalArgumentException("y must be >= 0");
359        }
360    }
361
362    /**
363     * Common code for checking that width and height are > 0
364     *
365     * @param width  width to ensure is > 0
366     * @param height height to ensure is > 0
367     */
368    private static void checkWidthHeight(int width, int height) {
369        if (width <= 0) {
370            throw new IllegalArgumentException("width must be > 0");
371        }
372        if (height <= 0) {
373            throw new IllegalArgumentException("height must be > 0");
374        }
375    }
376
377    /**
378     * Possible bitmap configurations. A bitmap configuration describes
379     * how pixels are stored. This affects the quality (color depth) as
380     * well as the ability to display transparent/translucent colors.
381     */
382    public enum Config {
383        // these native values must match up with the enum in SkBitmap.h
384
385        /**
386         * Each pixel is stored as a single translucency (alpha) channel.
387         * This is very useful to efficiently store masks for instance.
388         * No color information is stored.
389         * With this configuration, each pixel requires 1 byte of memory.
390         */
391        ALPHA_8     (1),
392
393        /**
394         * Each pixel is stored on 2 bytes and only the RGB channels are
395         * encoded: red is stored with 5 bits of precision (32 possible
396         * values), green is stored with 6 bits of precision (64 possible
397         * values) and blue is stored with 5 bits of precision.
398         *
399         * This configuration can produce slight visual artifacts depending
400         * on the configuration of the source. For instance, without
401         * dithering, the result might show a greenish tint. To get better
402         * results dithering should be applied.
403         *
404         * This configuration may be useful when using opaque bitmaps
405         * that do not require high color fidelity.
406         */
407        RGB_565     (3),
408
409        /**
410         * Each pixel is stored on 2 bytes. The three RGB color channels
411         * and the alpha channel (translucency) are stored with a 4 bits
412         * precision (16 possible values.)
413         *
414         * This configuration is mostly useful if the application needs
415         * to store translucency information but also needs to save
416         * memory.
417         *
418         * It is recommended to use {@link #ARGB_8888} instead of this
419         * configuration.
420         *
421         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
422         * any bitmap created with this configuration will be created
423         * using {@link #ARGB_8888} instead.
424         *
425         * @deprecated Because of the poor quality of this configuration,
426         *             it is advised to use {@link #ARGB_8888} instead.
427         */
428        @Deprecated
429        ARGB_4444   (4),
430
431        /**
432         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
433         * for translucency) is stored with 8 bits of precision (256
434         * possible values.)
435         *
436         * This configuration is very flexible and offers the best
437         * quality. It should be used whenever possible.
438         */
439        ARGB_8888   (5);
440
441        final int nativeInt;
442
443        private static Config sConfigs[] = {
444            null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
445        };
446
447        Config(int ni) {
448            this.nativeInt = ni;
449        }
450
451        static Config nativeToConfig(int ni) {
452            return sConfigs[ni];
453        }
454    }
455
456    /**
457     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
458     * caller). An exception is thrown if the buffer is not large enough to
459     * hold all of the pixels (taking into account the number of bytes per
460     * pixel) or if the Buffer subclass is not one of the support types
461     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
462     * <p>The content of the bitmap is copied into the buffer as-is. This means
463     * that if this bitmap stores its pixels pre-multiplied
464     * (see {@link #isPremultiplied()}, the values in the buffer will also be
465     * pre-multiplied.</p>
466     * <p>After this method returns, the current position of the buffer is
467     * updated: the position is incremented by the number of elements written
468     * in the buffer.</p>
469     */
470    public void copyPixelsToBuffer(Buffer dst) {
471        int elements = dst.remaining();
472        int shift;
473        if (dst instanceof ByteBuffer) {
474            shift = 0;
475        } else if (dst instanceof ShortBuffer) {
476            shift = 1;
477        } else if (dst instanceof IntBuffer) {
478            shift = 2;
479        } else {
480            throw new RuntimeException("unsupported Buffer subclass");
481        }
482
483        long bufferSize = (long)elements << shift;
484        long pixelSize = getByteCount();
485
486        if (bufferSize < pixelSize) {
487            throw new RuntimeException("Buffer not large enough for pixels");
488        }
489
490        nativeCopyPixelsToBuffer(mSkBitmapPtr, dst);
491
492        // now update the buffer's position
493        int position = dst.position();
494        position += pixelSize >> shift;
495        dst.position(position);
496    }
497
498    /**
499     * <p>Copy the pixels from the buffer, beginning at the current position,
500     * overwriting the bitmap's pixels. The data in the buffer is not changed
501     * in any way (unlike setPixels(), which converts from unpremultipled 32bit
502     * to whatever the bitmap's native format is.</p>
503     * <p>After this method returns, the current position of the buffer is
504     * updated: the position is incremented by the number of elements read from
505     * the buffer. If you need to read the bitmap from the buffer again you must
506     * first rewind the buffer.</p>
507     */
508    public void copyPixelsFromBuffer(Buffer src) {
509        checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
510
511        int elements = src.remaining();
512        int shift;
513        if (src instanceof ByteBuffer) {
514            shift = 0;
515        } else if (src instanceof ShortBuffer) {
516            shift = 1;
517        } else if (src instanceof IntBuffer) {
518            shift = 2;
519        } else {
520            throw new RuntimeException("unsupported Buffer subclass");
521        }
522
523        long bufferBytes = (long) elements << shift;
524        long bitmapBytes = getByteCount();
525
526        if (bufferBytes < bitmapBytes) {
527            throw new RuntimeException("Buffer not large enough for pixels");
528        }
529
530        nativeCopyPixelsFromBuffer(mSkBitmapPtr, src);
531
532        // now update the buffer's position
533        int position = src.position();
534        position += bitmapBytes >> shift;
535        src.position(position);
536    }
537
538    /**
539     * Tries to make a new bitmap based on the dimensions of this bitmap,
540     * setting the new bitmap's config to the one specified, and then copying
541     * this bitmap's pixels into the new bitmap. If the conversion is not
542     * supported, or the allocator fails, then this returns NULL.  The returned
543     * bitmap initially has the same density as the original.
544     *
545     * @param config    The desired config for the resulting bitmap
546     * @param isMutable True if the resulting bitmap should be mutable (i.e.
547     *                  its pixels can be modified)
548     * @return the new bitmap, or null if the copy could not be made.
549     */
550    public Bitmap copy(Config config, boolean isMutable) {
551        checkRecycled("Can't copy a recycled bitmap");
552        Bitmap b = nativeCopy(mSkBitmapPtr, config.nativeInt, isMutable);
553        if (b != null) {
554            b.setPremultiplied(mRequestPremultiplied);
555            b.mDensity = mDensity;
556        }
557        return b;
558    }
559
560    /**
561     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
562     * specified width and height are the same as the current width and height of
563     * the source bitmap, the source bitmap is returned and no new bitmap is
564     * created.
565     *
566     * @param src       The source bitmap.
567     * @param dstWidth  The new bitmap's desired width.
568     * @param dstHeight The new bitmap's desired height.
569     * @param filter    true if the source should be filtered.
570     * @return The new scaled bitmap or the source bitmap if no scaling is required.
571     * @throws IllegalArgumentException if width is <= 0, or height is <= 0
572     */
573    public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
574            boolean filter) {
575        Matrix m;
576        synchronized (Bitmap.class) {
577            // small pool of just 1 matrix
578            m = sScaleMatrix;
579            sScaleMatrix = null;
580        }
581
582        if (m == null) {
583            m = new Matrix();
584        }
585
586        final int width = src.getWidth();
587        final int height = src.getHeight();
588        final float sx = dstWidth  / (float)width;
589        final float sy = dstHeight / (float)height;
590        m.setScale(sx, sy);
591        Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
592
593        synchronized (Bitmap.class) {
594            // do we need to check for null? why not just assign everytime?
595            if (sScaleMatrix == null) {
596                sScaleMatrix = m;
597            }
598        }
599
600        return b;
601    }
602
603    /**
604     * Returns an immutable bitmap from the source bitmap. The new bitmap may
605     * be the same object as source, or a copy may have been made.  It is
606     * initialized with the same density as the original bitmap.
607     */
608    public static Bitmap createBitmap(Bitmap src) {
609        return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
610    }
611
612    /**
613     * Returns an immutable bitmap from the specified subset of the source
614     * bitmap. The new bitmap may be the same object as source, or a copy may
615     * have been made. It is initialized with the same density as the original
616     * bitmap.
617     *
618     * @param source   The bitmap we are subsetting
619     * @param x        The x coordinate of the first pixel in source
620     * @param y        The y coordinate of the first pixel in source
621     * @param width    The number of pixels in each row
622     * @param height   The number of rows
623     * @return A copy of a subset of the source bitmap or the source bitmap itself.
624     * @throws IllegalArgumentException if the x, y, width, height values are
625     *         outside of the dimensions of the source bitmap, or width is <= 0,
626     *         or height is <= 0
627     */
628    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
629        return createBitmap(source, x, y, width, height, null, false);
630    }
631
632    /**
633     * Returns an immutable bitmap from subset of the source bitmap,
634     * transformed by the optional matrix. The new bitmap may be the
635     * same object as source, or a copy may have been made. It is
636     * initialized with the same density as the original bitmap.
637     *
638     * If the source bitmap is immutable and the requested subset is the
639     * same as the source bitmap itself, then the source bitmap is
640     * returned and no new bitmap is created.
641     *
642     * @param source   The bitmap we are subsetting
643     * @param x        The x coordinate of the first pixel in source
644     * @param y        The y coordinate of the first pixel in source
645     * @param width    The number of pixels in each row
646     * @param height   The number of rows
647     * @param m        Optional matrix to be applied to the pixels
648     * @param filter   true if the source should be filtered.
649     *                   Only applies if the matrix contains more than just
650     *                   translation.
651     * @return A bitmap that represents the specified subset of source
652     * @throws IllegalArgumentException if the x, y, width, height values are
653     *         outside of the dimensions of the source bitmap, or width is <= 0,
654     *         or height is <= 0
655     */
656    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
657            Matrix m, boolean filter) {
658
659        checkXYSign(x, y);
660        checkWidthHeight(width, height);
661        if (x + width > source.getWidth()) {
662            throw new IllegalArgumentException("x + width must be <= bitmap.width()");
663        }
664        if (y + height > source.getHeight()) {
665            throw new IllegalArgumentException("y + height must be <= bitmap.height()");
666        }
667
668        // check if we can just return our argument unchanged
669        if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
670                height == source.getHeight() && (m == null || m.isIdentity())) {
671            return source;
672        }
673
674        int neww = width;
675        int newh = height;
676        Canvas canvas = new Canvas();
677        Bitmap bitmap;
678        Paint paint;
679
680        Rect srcR = new Rect(x, y, x + width, y + height);
681        RectF dstR = new RectF(0, 0, width, height);
682
683        Config newConfig = Config.ARGB_8888;
684        final Config config = source.getConfig();
685        // GIF files generate null configs, assume ARGB_8888
686        if (config != null) {
687            switch (config) {
688                case RGB_565:
689                    newConfig = Config.RGB_565;
690                    break;
691                case ALPHA_8:
692                    newConfig = Config.ALPHA_8;
693                    break;
694                //noinspection deprecation
695                case ARGB_4444:
696                case ARGB_8888:
697                default:
698                    newConfig = Config.ARGB_8888;
699                    break;
700            }
701        }
702
703        if (m == null || m.isIdentity()) {
704            bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
705            paint = null;   // not needed
706        } else {
707            final boolean transformed = !m.rectStaysRect();
708
709            RectF deviceR = new RectF();
710            m.mapRect(deviceR, dstR);
711
712            neww = Math.round(deviceR.width());
713            newh = Math.round(deviceR.height());
714
715            bitmap = createBitmap(neww, newh, transformed ? Config.ARGB_8888 : newConfig,
716                    transformed || source.hasAlpha());
717
718            canvas.translate(-deviceR.left, -deviceR.top);
719            canvas.concat(m);
720
721            paint = new Paint();
722            paint.setFilterBitmap(filter);
723            if (transformed) {
724                paint.setAntiAlias(true);
725            }
726        }
727
728        // The new bitmap was created from a known bitmap source so assume that
729        // they use the same density
730        bitmap.mDensity = source.mDensity;
731        bitmap.setHasAlpha(source.hasAlpha());
732        bitmap.setPremultiplied(source.mRequestPremultiplied);
733
734        canvas.setBitmap(bitmap);
735        canvas.drawBitmap(source, srcR, dstR, paint);
736        canvas.setBitmap(null);
737
738        return bitmap;
739    }
740
741    /**
742     * Returns a mutable bitmap with the specified width and height.  Its
743     * initial density is as per {@link #getDensity}.
744     *
745     * @param width    The width of the bitmap
746     * @param height   The height of the bitmap
747     * @param config   The bitmap config to create.
748     * @throws IllegalArgumentException if the width or height are <= 0
749     */
750    public static Bitmap createBitmap(int width, int height, Config config) {
751        return createBitmap(width, height, config, true);
752    }
753
754    /**
755     * Returns a mutable bitmap with the specified width and height.  Its
756     * initial density is determined from the given {@link DisplayMetrics}.
757     *
758     * @param display  Display metrics for the display this bitmap will be
759     *                 drawn on.
760     * @param width    The width of the bitmap
761     * @param height   The height of the bitmap
762     * @param config   The bitmap config to create.
763     * @throws IllegalArgumentException if the width or height are <= 0
764     */
765    public static Bitmap createBitmap(DisplayMetrics display, int width,
766            int height, Config config) {
767        return createBitmap(display, width, height, config, true);
768    }
769
770    /**
771     * Returns a mutable bitmap with the specified width and height.  Its
772     * initial density is as per {@link #getDensity}.
773     *
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     * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
778     *                 bitmap as opaque. Doing so will clear the bitmap in black
779     *                 instead of transparent.
780     *
781     * @throws IllegalArgumentException if the width or height are <= 0
782     */
783    private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
784        return createBitmap(null, width, height, config, hasAlpha);
785    }
786
787    /**
788     * Returns a mutable bitmap with the specified width and height.  Its
789     * initial density is determined from the given {@link DisplayMetrics}.
790     *
791     * @param display  Display metrics for the display this bitmap will be
792     *                 drawn on.
793     * @param width    The width of the bitmap
794     * @param height   The height of the bitmap
795     * @param config   The bitmap config to create.
796     * @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
797     *                 bitmap as opaque. Doing so will clear the bitmap in black
798     *                 instead of transparent.
799     *
800     * @throws IllegalArgumentException if the width or height are <= 0
801     */
802    private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
803            Config config, boolean hasAlpha) {
804        if (width <= 0 || height <= 0) {
805            throw new IllegalArgumentException("width and height must be > 0");
806        }
807        Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
808        if (display != null) {
809            bm.mDensity = display.densityDpi;
810        }
811        bm.setHasAlpha(hasAlpha);
812        if (config == Config.ARGB_8888 && !hasAlpha) {
813            nativeErase(bm.mSkBitmapPtr, 0xff000000);
814        }
815        // No need to initialize the bitmap to zeroes with other configs;
816        // it is backed by a VM byte array which is by definition preinitialized
817        // to all zeroes.
818        return bm;
819    }
820
821    /**
822     * Returns a immutable bitmap with the specified width and height, with each
823     * pixel value set to the corresponding value in the colors array.  Its
824     * initial density is as per {@link #getDensity}.
825     *
826     * @param colors   Array of {@link Color} used to initialize the pixels.
827     * @param offset   Number of values to skip before the first color in the
828     *                 array of colors.
829     * @param stride   Number of colors in the array between rows (must be >=
830     *                 width or <= -width).
831     * @param width    The width of the bitmap
832     * @param height   The height of the bitmap
833     * @param config   The bitmap config to create. If the config does not
834     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
835     *                 bytes in the colors[] will be ignored (assumed to be FF)
836     * @throws IllegalArgumentException if the width or height are <= 0, or if
837     *         the color array's length is less than the number of pixels.
838     */
839    public static Bitmap createBitmap(int colors[], int offset, int stride,
840            int width, int height, Config config) {
841        return createBitmap(null, colors, offset, stride, width, height, config);
842    }
843
844    /**
845     * Returns a immutable bitmap with the specified width and height, with each
846     * pixel value set to the corresponding value in the colors array.  Its
847     * initial density is determined from the given {@link DisplayMetrics}.
848     *
849     * @param display  Display metrics for the display this bitmap will be
850     *                 drawn on.
851     * @param colors   Array of {@link Color} used to initialize the pixels.
852     * @param offset   Number of values to skip before the first color in the
853     *                 array of colors.
854     * @param stride   Number of colors in the array between rows (must be >=
855     *                 width or <= -width).
856     * @param width    The width of the bitmap
857     * @param height   The height of the bitmap
858     * @param config   The bitmap config to create. If the config does not
859     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
860     *                 bytes in the colors[] will be ignored (assumed to be FF)
861     * @throws IllegalArgumentException if the width or height are <= 0, or if
862     *         the color array's length is less than the number of pixels.
863     */
864    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
865            int offset, int stride, int width, int height, Config config) {
866
867        checkWidthHeight(width, height);
868        if (Math.abs(stride) < width) {
869            throw new IllegalArgumentException("abs(stride) must be >= width");
870        }
871        int lastScanline = offset + (height - 1) * stride;
872        int length = colors.length;
873        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
874                (lastScanline + width > length)) {
875            throw new ArrayIndexOutOfBoundsException();
876        }
877        if (width <= 0 || height <= 0) {
878            throw new IllegalArgumentException("width and height must be > 0");
879        }
880        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
881                            config.nativeInt, false);
882        if (display != null) {
883            bm.mDensity = display.densityDpi;
884        }
885        return bm;
886    }
887
888    /**
889     * Returns a immutable bitmap with the specified width and height, with each
890     * pixel value set to the corresponding value in the colors array.  Its
891     * initial density is as per {@link #getDensity}.
892     *
893     * @param colors   Array of {@link Color} used to initialize the pixels.
894     *                 This array must be at least as large as width * height.
895     * @param width    The width of the bitmap
896     * @param height   The height of the bitmap
897     * @param config   The bitmap config to create. If the config does not
898     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
899     *                 bytes in the colors[] will be ignored (assumed to be FF)
900     * @throws IllegalArgumentException if the width or height are <= 0, or if
901     *         the color array's length is less than the number of pixels.
902     */
903    public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
904        return createBitmap(null, colors, 0, width, width, height, config);
905    }
906
907    /**
908     * Returns a immutable bitmap with the specified width and height, with each
909     * pixel value set to the corresponding value in the colors array.  Its
910     * initial density is determined from the given {@link DisplayMetrics}.
911     *
912     * @param display  Display metrics for the display this bitmap will be
913     *                 drawn on.
914     * @param colors   Array of {@link Color} used to initialize the pixels.
915     *                 This array must be at least as large as width * height.
916     * @param width    The width of the bitmap
917     * @param height   The height of the bitmap
918     * @param config   The bitmap config to create. If the config does not
919     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
920     *                 bytes in the colors[] will be ignored (assumed to be FF)
921     * @throws IllegalArgumentException if the width or height are <= 0, or if
922     *         the color array's length is less than the number of pixels.
923     */
924    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
925            int width, int height, Config config) {
926        return createBitmap(display, colors, 0, width, width, height, config);
927    }
928
929    /**
930     * Returns an optional array of private data, used by the UI system for
931     * some bitmaps. Not intended to be called by applications.
932     */
933    public byte[] getNinePatchChunk() {
934        return mNinePatchChunk;
935    }
936
937    /**
938     * Populates a rectangle with the bitmap's optical insets.
939     *
940     * @param outInsets Rect to populate with optical insets
941     * @hide
942     */
943    public void getOpticalInsets(@NonNull Rect outInsets) {
944        if (mNinePatchInsets == null) {
945            outInsets.setEmpty();
946        } else {
947            outInsets.set(mNinePatchInsets.opticalRect);
948        }
949    }
950
951    /** @hide */
952    public NinePatch.InsetStruct getNinePatchInsets() {
953        return mNinePatchInsets;
954    }
955
956    /**
957     * Specifies the known formats a bitmap can be compressed into
958     */
959    public enum CompressFormat {
960        JPEG    (0),
961        PNG     (1),
962        WEBP    (2);
963
964        CompressFormat(int nativeInt) {
965            this.nativeInt = nativeInt;
966        }
967        final int nativeInt;
968    }
969
970    /**
971     * Number of bytes of temp storage we use for communicating between the
972     * native compressor and the java OutputStream.
973     */
974    private final static int WORKING_COMPRESS_STORAGE = 4096;
975
976    /**
977     * Write a compressed version of the bitmap to the specified outputstream.
978     * If this returns true, the bitmap can be reconstructed by passing a
979     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
980     * all Formats support all bitmap configs directly, so it is possible that
981     * the returned bitmap from BitmapFactory could be in a different bitdepth,
982     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
983     * pixels).
984     *
985     * @param format   The format of the compressed image
986     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
987     *                 small size, 100 meaning compress for max quality. Some
988     *                 formats, like PNG which is lossless, will ignore the
989     *                 quality setting
990     * @param stream   The outputstream to write the compressed data.
991     * @return true if successfully compressed to the specified stream.
992     */
993    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
994        checkRecycled("Can't compress a recycled bitmap");
995        // do explicit check before calling the native method
996        if (stream == null) {
997            throw new NullPointerException();
998        }
999        if (quality < 0 || quality > 100) {
1000            throw new IllegalArgumentException("quality must be 0..100");
1001        }
1002        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
1003        boolean result = nativeCompress(mSkBitmapPtr, format.nativeInt, quality,
1004                              stream, new byte[WORKING_COMPRESS_STORAGE]);
1005        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
1006        return result;
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(mSkBitmapPtr);
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(mSkBitmapPtr, 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(mSkBitmapPtr);
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(mSkBitmapPtr));
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(mSkBitmapPtr);
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(mSkBitmapPtr, 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(mSkBitmapPtr);
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(mSkBitmapPtr, 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(@ColorInt int c) {
1284        checkRecycled("Can't erase a recycled bitmap");
1285        if (!isMutable()) {
1286            throw new IllegalStateException("cannot erase immutable bitmaps");
1287        }
1288        nativeErase(mSkBitmapPtr, 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    @ColorInt
1302    public int getPixel(int x, int y) {
1303        checkRecycled("Can't call getPixel() on a recycled bitmap");
1304        checkPixelAccess(x, y);
1305        return nativeGetPixel(mSkBitmapPtr, x, y);
1306    }
1307
1308    /**
1309     * Returns in pixels[] a copy of the data in the bitmap. Each value is
1310     * a packed int representing a {@link Color}. The stride parameter allows
1311     * the caller to allow for gaps in the returned pixels array between
1312     * rows. For normal packed results, just pass width for the stride value.
1313     * The returned colors are non-premultiplied ARGB values.
1314     *
1315     * @param pixels   The array to receive the bitmap's colors
1316     * @param offset   The first index to write into pixels[]
1317     * @param stride   The number of entries in pixels[] to skip between
1318     *                 rows (must be >= bitmap's width). Can be negative.
1319     * @param x        The x coordinate of the first pixel to read from
1320     *                 the bitmap
1321     * @param y        The y coordinate of the first pixel to read from
1322     *                 the bitmap
1323     * @param width    The number of pixels to read from each row
1324     * @param height   The number of rows to read
1325     *
1326     * @throws IllegalArgumentException if x, y, width, height exceed the
1327     *         bounds of the bitmap, or if abs(stride) < width.
1328     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1329     *         to receive the specified number of pixels.
1330     */
1331    public void getPixels(@ColorInt int[] pixels, int offset, int stride,
1332                          int x, int y, int width, int height) {
1333        checkRecycled("Can't call getPixels() on a recycled bitmap");
1334        if (width == 0 || height == 0) {
1335            return; // nothing to do
1336        }
1337        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1338        nativeGetPixels(mSkBitmapPtr, pixels, offset, stride,
1339                        x, y, width, height);
1340    }
1341
1342    /**
1343     * Shared code to check for illegal arguments passed to getPixel()
1344     * or setPixel()
1345     *
1346     * @param x x coordinate of the pixel
1347     * @param y y coordinate of the pixel
1348     */
1349    private void checkPixelAccess(int x, int y) {
1350        checkXYSign(x, y);
1351        if (x >= getWidth()) {
1352            throw new IllegalArgumentException("x must be < bitmap.width()");
1353        }
1354        if (y >= getHeight()) {
1355            throw new IllegalArgumentException("y must be < bitmap.height()");
1356        }
1357    }
1358
1359    /**
1360     * Shared code to check for illegal arguments passed to getPixels()
1361     * or setPixels()
1362     *
1363     * @param x left edge of the area of pixels to access
1364     * @param y top edge of the area of pixels to access
1365     * @param width width of the area of pixels to access
1366     * @param height height of the area of pixels to access
1367     * @param offset offset into pixels[] array
1368     * @param stride number of elements in pixels[] between each logical row
1369     * @param pixels array to hold the area of pixels being accessed
1370    */
1371    private void checkPixelsAccess(int x, int y, int width, int height,
1372                                   int offset, int stride, int pixels[]) {
1373        checkXYSign(x, y);
1374        if (width < 0) {
1375            throw new IllegalArgumentException("width must be >= 0");
1376        }
1377        if (height < 0) {
1378            throw new IllegalArgumentException("height must be >= 0");
1379        }
1380        if (x + width > getWidth()) {
1381            throw new IllegalArgumentException(
1382                    "x + width must be <= bitmap.width()");
1383        }
1384        if (y + height > getHeight()) {
1385            throw new IllegalArgumentException(
1386                    "y + height must be <= bitmap.height()");
1387        }
1388        if (Math.abs(stride) < width) {
1389            throw new IllegalArgumentException("abs(stride) must be >= width");
1390        }
1391        int lastScanline = offset + (height - 1) * stride;
1392        int length = pixels.length;
1393        if (offset < 0 || (offset + width > length)
1394                || lastScanline < 0
1395                || (lastScanline + width > length)) {
1396            throw new ArrayIndexOutOfBoundsException();
1397        }
1398    }
1399
1400    /**
1401     * <p>Write the specified {@link Color} into the bitmap (assuming it is
1402     * mutable) at the x,y coordinate. The color must be a
1403     * non-premultiplied ARGB value.</p>
1404     *
1405     * @param x     The x coordinate of the pixel to replace (0...width-1)
1406     * @param y     The y coordinate of the pixel to replace (0...height-1)
1407     * @param color The ARGB color to write into the bitmap
1408     *
1409     * @throws IllegalStateException if the bitmap is not mutable
1410     * @throws IllegalArgumentException if x, y are outside of the bitmap's
1411     *         bounds.
1412     */
1413    public void setPixel(int x, int y, @ColorInt int color) {
1414        checkRecycled("Can't call setPixel() on a recycled bitmap");
1415        if (!isMutable()) {
1416            throw new IllegalStateException();
1417        }
1418        checkPixelAccess(x, y);
1419        nativeSetPixel(mSkBitmapPtr, x, y, color);
1420    }
1421
1422    /**
1423     * <p>Replace pixels in the bitmap with the colors in the array. Each element
1424     * in the array is a packed int prepresenting a non-premultiplied ARGB
1425     * {@link Color}.</p>
1426     *
1427     * @param pixels   The colors to write to the bitmap
1428     * @param offset   The index of the first color to read from pixels[]
1429     * @param stride   The number of colors in pixels[] to skip between rows.
1430     *                 Normally this value will be the same as the width of
1431     *                 the bitmap, but it can be larger (or negative).
1432     * @param x        The x coordinate of the first pixel to write to in
1433     *                 the bitmap.
1434     * @param y        The y coordinate of the first pixel to write to in
1435     *                 the bitmap.
1436     * @param width    The number of colors to copy from pixels[] per row
1437     * @param height   The number of rows to write to the bitmap
1438     *
1439     * @throws IllegalStateException if the bitmap is not mutable
1440     * @throws IllegalArgumentException if x, y, width, height are outside of
1441     *         the bitmap's bounds.
1442     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1443     *         to receive the specified number of pixels.
1444     */
1445    public void setPixels(@ColorInt int[] pixels, int offset, int stride,
1446            int x, int y, int width, int height) {
1447        checkRecycled("Can't call setPixels() on a recycled bitmap");
1448        if (!isMutable()) {
1449            throw new IllegalStateException();
1450        }
1451        if (width == 0 || height == 0) {
1452            return; // nothing to do
1453        }
1454        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1455        nativeSetPixels(mSkBitmapPtr, pixels, offset, stride,
1456                        x, y, width, height);
1457    }
1458
1459    public static final Parcelable.Creator<Bitmap> CREATOR
1460            = new Parcelable.Creator<Bitmap>() {
1461        /**
1462         * Rebuilds a bitmap previously stored with writeToParcel().
1463         *
1464         * @param p    Parcel object to read the bitmap from
1465         * @return a new bitmap created from the data in the parcel
1466         */
1467        public Bitmap createFromParcel(Parcel p) {
1468            Bitmap bm = nativeCreateFromParcel(p);
1469            if (bm == null) {
1470                throw new RuntimeException("Failed to unparcel Bitmap");
1471            }
1472            return bm;
1473        }
1474        public Bitmap[] newArray(int size) {
1475            return new Bitmap[size];
1476        }
1477    };
1478
1479    /**
1480     * No special parcel contents.
1481     */
1482    public int describeContents() {
1483        return 0;
1484    }
1485
1486    /**
1487     * Write the bitmap and its pixels to the parcel. The bitmap can be
1488     * rebuilt from the parcel by calling CREATOR.createFromParcel().
1489     * @param p    Parcel object to write the bitmap data into
1490     */
1491    public void writeToParcel(Parcel p, int flags) {
1492        checkRecycled("Can't parcel a recycled bitmap");
1493        if (!nativeWriteToParcel(mSkBitmapPtr, mIsMutable, mDensity, p)) {
1494            throw new RuntimeException("native writeToParcel failed");
1495        }
1496    }
1497
1498    /**
1499     * Returns a new bitmap that captures the alpha values of the original.
1500     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be
1501     * taken from the paint that is passed to the draw call.
1502     *
1503     * @return new bitmap containing the alpha channel of the original bitmap.
1504     */
1505    @CheckResult
1506    public Bitmap extractAlpha() {
1507        return extractAlpha(null, null);
1508    }
1509
1510    /**
1511     * Returns a new bitmap that captures the alpha values of the original.
1512     * These values may be affected by the optional Paint parameter, which
1513     * can contain its own alpha, and may also contain a MaskFilter which
1514     * could change the actual dimensions of the resulting bitmap (e.g.
1515     * a blur maskfilter might enlarge the resulting bitmap). If offsetXY
1516     * is not null, it returns the amount to offset the returned bitmap so
1517     * that it will logically align with the original. For example, if the
1518     * paint contains a blur of radius 2, then offsetXY[] would contains
1519     * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
1520     * drawing the original would result in the blur visually aligning with
1521     * the original.
1522     *
1523     * <p>The initial density of the returned bitmap is the same as the original's.
1524     *
1525     * @param paint Optional paint used to modify the alpha values in the
1526     *              resulting bitmap. Pass null for default behavior.
1527     * @param offsetXY Optional array that returns the X (index 0) and Y
1528     *                 (index 1) offset needed to position the returned bitmap
1529     *                 so that it visually lines up with the original.
1530     * @return new bitmap containing the (optionally modified by paint) alpha
1531     *         channel of the original bitmap. This may be drawn with
1532     *         Canvas.drawBitmap(), where the color(s) will be taken from the
1533     *         paint that is passed to the draw call.
1534     */
1535    @CheckResult
1536    public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
1537        checkRecycled("Can't extractAlpha on a recycled bitmap");
1538        long nativePaint = paint != null ? paint.getNativeInstance() : 0;
1539        Bitmap bm = nativeExtractAlpha(mSkBitmapPtr, nativePaint, offsetXY);
1540        if (bm == null) {
1541            throw new RuntimeException("Failed to extractAlpha on Bitmap");
1542        }
1543        bm.mDensity = mDensity;
1544        return bm;
1545    }
1546
1547    /**
1548     *  Given another bitmap, return true if it has the same dimensions, config,
1549     *  and pixel data as this bitmap. If any of those differ, return false.
1550     *  If other is null, return false.
1551     */
1552    public boolean sameAs(Bitmap other) {
1553        return this == other || (other != null && nativeSameAs(mSkBitmapPtr, other.mSkBitmapPtr));
1554    }
1555
1556    /**
1557     * Rebuilds any caches associated with the bitmap that are used for
1558     * drawing it. In the case of purgeable bitmaps, this call will attempt to
1559     * ensure that the pixels have been decoded.
1560     * If this is called on more than one bitmap in sequence, the priority is
1561     * given in LRU order (i.e. the last bitmap called will be given highest
1562     * priority).
1563     *
1564     * For bitmaps with no associated caches, this call is effectively a no-op,
1565     * and therefore is harmless.
1566     */
1567    public void prepareToDraw() {
1568        nativePrepareToDraw(mSkBitmapPtr);
1569    }
1570
1571    /** @hide */
1572    public final long getSkBitmap() {
1573        return mSkBitmapPtr;
1574    }
1575
1576    private static class BitmapFinalizer {
1577        private long mNativeBitmap;
1578
1579        // Native memory allocated for the duration of the Bitmap,
1580        // if pixel data allocated into native memory, instead of java byte[]
1581        private final int mNativeAllocationByteCount;
1582
1583        BitmapFinalizer(long nativeBitmap, int nativeAllocationByteCount) {
1584            mNativeBitmap = nativeBitmap;
1585            mNativeAllocationByteCount = nativeAllocationByteCount;
1586
1587            if (mNativeAllocationByteCount != 0) {
1588                VMRuntime.getRuntime().registerNativeAllocation(mNativeAllocationByteCount);
1589            }
1590        }
1591
1592        @Override
1593        public void finalize() {
1594            try {
1595                super.finalize();
1596            } catch (Throwable t) {
1597                // Ignore
1598            } finally {
1599                if (mNativeAllocationByteCount != 0) {
1600                    VMRuntime.getRuntime().registerNativeFree(mNativeAllocationByteCount);
1601                }
1602                nativeDestructor(mNativeBitmap);
1603                mNativeBitmap = 0;
1604            }
1605        }
1606    }
1607
1608    //////////// native methods
1609
1610    private static native Bitmap nativeCreate(int[] colors, int offset,
1611                                              int stride, int width, int height,
1612                                              int nativeConfig, boolean mutable);
1613    private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig,
1614                                            boolean isMutable);
1615    private static native void nativeDestructor(long nativeBitmap);
1616    private static native boolean nativeRecycle(long nativeBitmap);
1617    private static native void nativeReconfigure(long nativeBitmap, int width, int height,
1618                                                 int config, int allocSize,
1619                                                 boolean isPremultiplied);
1620
1621    private static native boolean nativeCompress(long nativeBitmap, int format,
1622                                            int quality, OutputStream stream,
1623                                            byte[] tempStorage);
1624    private static native void nativeErase(long nativeBitmap, int color);
1625    private static native int nativeRowBytes(long nativeBitmap);
1626    private static native int nativeConfig(long nativeBitmap);
1627
1628    private static native int nativeGetPixel(long nativeBitmap, int x, int y);
1629    private static native void nativeGetPixels(long nativeBitmap, int[] pixels,
1630                                               int offset, int stride, int x, int y,
1631                                               int width, int height);
1632
1633    private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color);
1634    private static native void nativeSetPixels(long nativeBitmap, int[] colors,
1635                                               int offset, int stride, int x, int y,
1636                                               int width, int height);
1637    private static native void nativeCopyPixelsToBuffer(long nativeBitmap,
1638                                                        Buffer dst);
1639    private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src);
1640    private static native int nativeGenerationId(long nativeBitmap);
1641
1642    private static native Bitmap nativeCreateFromParcel(Parcel p);
1643    // returns true on success
1644    private static native boolean nativeWriteToParcel(long nativeBitmap,
1645                                                      boolean isMutable,
1646                                                      int density,
1647                                                      Parcel p);
1648    // returns a new bitmap built from the native bitmap's alpha, and the paint
1649    private static native Bitmap nativeExtractAlpha(long nativeBitmap,
1650                                                    long nativePaint,
1651                                                    int[] offsetXY);
1652
1653    private static native void nativePrepareToDraw(long nativeBitmap);
1654    private static native boolean nativeHasAlpha(long nativeBitmap);
1655    private static native boolean nativeIsPremultiplied(long nativeBitmap);
1656    private static native void nativeSetPremultiplied(long nativeBitmap,
1657                                                      boolean isPremul);
1658    private static native void nativeSetHasAlpha(long nativeBitmap,
1659                                                 boolean hasAlpha,
1660                                                 boolean requestPremul);
1661    private static native boolean nativeHasMipMap(long nativeBitmap);
1662    private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
1663    private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
1664}
1665