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