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