/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics;

import android.annotation.CheckResult;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.WorkerThread;
import android.content.res.ResourcesImpl;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.StrictMode;
import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.DisplayListCanvas;
import android.view.RenderNode;
import android.view.ThreadedRenderer;

import libcore.util.NativeAllocationRegistry;

import java.io.OutputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

public final class Bitmap implements Parcelable {
    private static final String TAG = "Bitmap";

    
Indicates that the bitmap was created for an unknown pixel density.
See Also:
/** * Indicates that the bitmap was created for an unknown pixel density. * * @see Bitmap#getDensity() * @see Bitmap#setDensity(int) */
public static final int DENSITY_NONE = 0; // Estimated size of the Bitmap native allocation, not including // pixel data. private static final long NATIVE_ALLOCATION_SIZE = 32; // Convenience for JNI access private final long mNativePtr; private final boolean mIsMutable;
Represents whether the Bitmap's content is requested to be pre-multiplied. Note that isPremultiplied() does not directly return this value, because isPremultiplied() may never return true for a 565 Bitmap or a bitmap without alpha. setPremultiplied() does directly set the value so that setConfig() and setPremultiplied() aren't order dependent, despite being setters. The native bitmap's premultiplication state is kept up to date by pushing down this preference for every config change.
/** * Represents whether the Bitmap's content is requested to be pre-multiplied. * Note that isPremultiplied() does not directly return this value, because * isPremultiplied() may never return true for a 565 Bitmap or a bitmap * without alpha. * * setPremultiplied() does directly set the value so that setConfig() and * setPremultiplied() aren't order dependent, despite being setters. * * The native bitmap's premultiplication state is kept up to date by * pushing down this preference for every config change. */
private boolean mRequestPremultiplied; private byte[] mNinePatchChunk; // may be null private NinePatch.InsetStruct mNinePatchInsets; // may be null private int mWidth; private int mHeight; private boolean mRecycled; private ColorSpace mColorSpace;
@hide
/** @hide */
public int mDensity = getDefaultDensity(); private static volatile int sDefaultDensity = -1;
@hideUsed only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true.
/** @hide Used only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true. */
public static volatile int sPreloadTracingNumInstantiatedBitmaps;
@hideUsed only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true.
/** @hide Used only when ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD is true. */
public static volatile long sPreloadTracingTotalBitmapsSize;
For backwards compatibility, allows the app layer to change the default density when running old apps.
@hide
/** * For backwards compatibility, allows the app layer to change the default * density when running old apps. * @hide */
public static void setDefaultDensity(int density) { sDefaultDensity = density; } @SuppressWarnings("deprecation") static int getDefaultDensity() { if (sDefaultDensity >= 0) { return sDefaultDensity; } sDefaultDensity = DisplayMetrics.DENSITY_DEVICE; return sDefaultDensity; }
Private constructor that must received an already allocated native bitmap int (pointer).
/** * Private constructor that must received an already allocated native bitmap * int (pointer). */
// called from JNI Bitmap(long nativeBitmap, int width, int height, int density, boolean isMutable, boolean requestPremultiplied, byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) { if (nativeBitmap == 0) { throw new RuntimeException("internal error: native bitmap is 0"); } mWidth = width; mHeight = height; mIsMutable = isMutable; mRequestPremultiplied = requestPremultiplied; mNinePatchChunk = ninePatchChunk; mNinePatchInsets = ninePatchInsets; if (density >= 0) { mDensity = density; } mNativePtr = nativeBitmap; long nativeSize = NATIVE_ALLOCATION_SIZE + getAllocationByteCount(); NativeAllocationRegistry registry = new NativeAllocationRegistry( Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), nativeSize); registry.registerNativeAllocation(this, nativeBitmap); if (ResourcesImpl.TRACE_FOR_DETAILED_PRELOAD) { sPreloadTracingNumInstantiatedBitmaps++; sPreloadTracingTotalBitmapsSize += nativeSize; } }
Return the pointer to the native object.
@hide
/** * Return the pointer to the native object. * @hide */
public long getNativeInstance() { return mNativePtr; }
Native bitmap has been reconfigured, so set premult and cached width/height values
/** * Native bitmap has been reconfigured, so set premult and cached * width/height values */
@SuppressWarnings("unused") // called from JNI void reinit(int width, int height, boolean requestPremultiplied) { mWidth = width; mHeight = height; mRequestPremultiplied = requestPremultiplied; mColorSpace = null; }

Returns the density for this bitmap.

The default density is the same density as the current display, unless the current application does not support different screen densities in which case it is DisplayMetrics.DENSITY_DEFAULT. Note that compatibility mode is determined by the application that was initially loaded into a process -- applications that share the same process should all have the same compatibility, or ensure they explicitly set the density of their bitmaps appropriately.

See Also:
Returns:A scaling factor of the default density or DENSITY_NONE if the scaling factor is unknown.
/** * <p>Returns the density for this bitmap.</p> * * <p>The default density is the same density as the current display, * unless the current application does not support different screen * densities in which case it is * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}. Note that * compatibility mode is determined by the application that was initially * loaded into a process -- applications that share the same process should * all have the same compatibility, or ensure they explicitly set the * density of their bitmaps appropriately.</p> * * @return A scaling factor of the default density or {@link #DENSITY_NONE} * if the scaling factor is unknown. * * @see #setDensity(int) * @see android.util.DisplayMetrics#DENSITY_DEFAULT * @see android.util.DisplayMetrics#densityDpi * @see #DENSITY_NONE */
public int getDensity() { if (mRecycled) { Log.w(TAG, "Called getDensity() on a recycle()'d bitmap! This is undefined behavior!"); } return mDensity; }

Specifies the density for this bitmap. When the bitmap is drawn to a Canvas that also has a density, it will be scaled appropriately.

Params:
  • density – The density scaling factor to use with this bitmap or DENSITY_NONE if the density is unknown.
See Also:
/** * <p>Specifies the density for this bitmap. When the bitmap is * drawn to a Canvas that also has a density, it will be scaled * appropriately.</p> * * @param density The density scaling factor to use with this bitmap or * {@link #DENSITY_NONE} if the density is unknown. * * @see #getDensity() * @see android.util.DisplayMetrics#DENSITY_DEFAULT * @see android.util.DisplayMetrics#densityDpi * @see #DENSITY_NONE */
public void setDensity(int density) { mDensity = density; }

Modifies the bitmap to have a specified width, height, and Config, without affecting the underlying allocation backing the bitmap. Bitmap pixel data is not re-initialized for the new configuration.

This method can be used to avoid allocating a new bitmap, instead reusing an existing bitmap's allocation for a new configuration of equal or lesser size. If the Bitmap's allocation isn't large enough to support the new configuration, an IllegalArgumentException will be thrown and the bitmap will not be modified.

The result of getByteCount() will reflect the new configuration, while getAllocationByteCount() will reflect that of the initial configuration.

Note: This may change this result of hasAlpha(). When converting to 565, the new bitmap will always be considered opaque. When converting from 565, the new bitmap will be considered non-opaque, and will respect the value set by setPremultiplied().

WARNING: This method should NOT be called on a bitmap currently in use by the view system, Canvas, or the AndroidBitmap NDK API. It does not make guarantees about how the underlying pixel buffer is remapped to the new config, just that the allocation is reused. Additionally, the view system does not account for bitmap properties being modifying during use, e.g. while attached to drawables.

In order to safely ensure that a Bitmap is no longer in use by the View system it is necessary to wait for a draw pass to occur after invalidate()'ing any view that had previously drawn the Bitmap in the last draw pass due to hardware acceleration's caching of draw commands. As an example, here is how this can be done for an ImageView:

     ImageView myImageView = ...;
     final Bitmap myBitmap = ...;
     myImageView.setImageDrawable(null);
     myImageView.post(new Runnable() {
         public void run() {
             // myBitmap is now no longer in use by the ImageView
             // and can be safely reconfigured.
             myBitmap.reconfigure(...);
         }
     });

See Also:
/** * <p>Modifies the bitmap to have a specified width, height, and {@link * Config}, without affecting the underlying allocation backing the bitmap. * Bitmap pixel data is not re-initialized for the new configuration.</p> * * <p>This method can be used to avoid allocating a new bitmap, instead * reusing an existing bitmap's allocation for a new configuration of equal * or lesser size. If the Bitmap's allocation isn't large enough to support * the new configuration, an IllegalArgumentException will be thrown and the * bitmap will not be modified.</p> * * <p>The result of {@link #getByteCount()} will reflect the new configuration, * while {@link #getAllocationByteCount()} will reflect that of the initial * configuration.</p> * * <p>Note: This may change this result of hasAlpha(). When converting to 565, * the new bitmap will always be considered opaque. When converting from 565, * the new bitmap will be considered non-opaque, and will respect the value * set by setPremultiplied().</p> * * <p>WARNING: This method should NOT be called on a bitmap currently in use * by the view system, Canvas, or the AndroidBitmap NDK API. It does not * make guarantees about how the underlying pixel buffer is remapped to the * new config, just that the allocation is reused. Additionally, the view * system does not account for bitmap properties being modifying during use, * e.g. while attached to drawables.</p> * * <p>In order to safely ensure that a Bitmap is no longer in use by the * View system it is necessary to wait for a draw pass to occur after * invalidate()'ing any view that had previously drawn the Bitmap in the last * draw pass due to hardware acceleration's caching of draw commands. As * an example, here is how this can be done for an ImageView: * <pre class="prettyprint"> * ImageView myImageView = ...; * final Bitmap myBitmap = ...; * myImageView.setImageDrawable(null); * myImageView.post(new Runnable() { * public void run() { * // myBitmap is now no longer in use by the ImageView * // and can be safely reconfigured. * myBitmap.reconfigure(...); * } * }); * </pre></p> * * @see #setWidth(int) * @see #setHeight(int) * @see #setConfig(Config) */
public void reconfigure(int width, int height, Config config) { checkRecycled("Can't call reconfigure() on a recycled bitmap"); if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } if (!isMutable()) { throw new IllegalStateException("only mutable bitmaps may be reconfigured"); } nativeReconfigure(mNativePtr, width, height, config.nativeInt, mRequestPremultiplied); mWidth = width; mHeight = height; mColorSpace = null; }

Convenience method for calling reconfigure(int, int, Config) with the current height and config.

WARNING: this method should not be used on bitmaps currently used by the view system, see reconfigure(int, int, Config) for more details.

See Also:
/** * <p>Convenience method for calling {@link #reconfigure(int, int, Config)} * with the current height and config.</p> * * <p>WARNING: this method should not be used on bitmaps currently used by * the view system, see {@link #reconfigure(int, int, Config)} for more * details.</p> * * @see #reconfigure(int, int, Config) * @see #setHeight(int) * @see #setConfig(Config) */
public void setWidth(int width) { reconfigure(width, getHeight(), getConfig()); }

Convenience method for calling reconfigure(int, int, Config) with the current width and config.

WARNING: this method should not be used on bitmaps currently used by the view system, see reconfigure(int, int, Config) for more details.

See Also:
/** * <p>Convenience method for calling {@link #reconfigure(int, int, Config)} * with the current width and config.</p> * * <p>WARNING: this method should not be used on bitmaps currently used by * the view system, see {@link #reconfigure(int, int, Config)} for more * details.</p> * * @see #reconfigure(int, int, Config) * @see #setWidth(int) * @see #setConfig(Config) */
public void setHeight(int height) { reconfigure(getWidth(), height, getConfig()); }

Convenience method for calling reconfigure(int, int, Config) with the current height and width.

WARNING: this method should not be used on bitmaps currently used by the view system, see reconfigure(int, int, Config) for more details.

See Also:
/** * <p>Convenience method for calling {@link #reconfigure(int, int, Config)} * with the current height and width.</p> * * <p>WARNING: this method should not be used on bitmaps currently used by * the view system, see {@link #reconfigure(int, int, Config)} for more * details.</p> * * @see #reconfigure(int, int, Config) * @see #setWidth(int) * @see #setHeight(int) */
public void setConfig(Config config) { reconfigure(getWidth(), getHeight(), config); }
Sets the nine patch chunk.
Params:
  • chunk – The definition of the nine patch
@hide
/** * Sets the nine patch chunk. * * @param chunk The definition of the nine patch * * @hide */
public void setNinePatchChunk(byte[] chunk) { mNinePatchChunk = chunk; }
Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.
/** * Free the native object associated with this bitmap, and clear the * reference to the pixel data. This will not free the pixel data synchronously; * it simply allows it to be garbage collected if there are no other references. * The bitmap is marked as "dead", meaning it will throw an exception if * getPixels() or setPixels() is called, and will draw nothing. This operation * cannot be reversed, so it should only be called if you are sure there are no * further uses for the bitmap. This is an advanced call, and normally need * not be called, since the normal GC process will free up this memory when * there are no more references to this bitmap. */
public void recycle() { if (!mRecycled && mNativePtr != 0) { if (nativeRecycle(mNativePtr)) { // return value indicates whether native pixel object was actually recycled. // false indicates that it is still in use at the native level and these // objects should not be collected now. They will be collected later when the // Bitmap itself is collected. mNinePatchChunk = null; } mRecycled = true; } }
Returns true if this bitmap has been recycled. If so, then it is an error to try to access its pixels, and the bitmap will not draw.
Returns:true if the bitmap has been recycled
/** * Returns true if this bitmap has been recycled. If so, then it is an error * to try to access its pixels, and the bitmap will not draw. * * @return true if the bitmap has been recycled */
public final boolean isRecycled() { return mRecycled; }
Returns the generation ID of this bitmap. The generation ID changes whenever the bitmap is modified. This can be used as an efficient way to check if a bitmap has changed.
Returns:The current generation ID for this bitmap.
/** * Returns the generation ID of this bitmap. The generation ID changes * whenever the bitmap is modified. This can be used as an efficient way to * check if a bitmap has changed. * * @return The current generation ID for this bitmap. */
public int getGenerationId() { if (mRecycled) { Log.w(TAG, "Called getGenerationId() on a recycle()'d bitmap! This is undefined behavior!"); } return nativeGenerationId(mNativePtr); }
This is called by methods that want to throw an exception if the bitmap has already been recycled.
/** * This is called by methods that want to throw an exception if the bitmap * has already been recycled. */
private void checkRecycled(String errorMessage) { if (mRecycled) { throw new IllegalStateException(errorMessage); } }
This is called by methods that want to throw an exception if the bitmap is Config.HARDWARE.
/** * This is called by methods that want to throw an exception if the bitmap * is {@link Config#HARDWARE}. */
private void checkHardware(String errorMessage) { if (getConfig() == Config.HARDWARE) { throw new IllegalStateException(errorMessage); } }
Common code for checking that x and y are >= 0
Params:
  • x – x coordinate to ensure is >= 0
  • y – y coordinate to ensure is >= 0
/** * Common code for checking that x and y are >= 0 * * @param x x coordinate to ensure is >= 0 * @param y y coordinate to ensure is >= 0 */
private static void checkXYSign(int x, int y) { if (x < 0) { throw new IllegalArgumentException("x must be >= 0"); } if (y < 0) { throw new IllegalArgumentException("y must be >= 0"); } }
Common code for checking that width and height are > 0
Params:
  • width – width to ensure is > 0
  • height – height to ensure is > 0
/** * Common code for checking that width and height are > 0 * * @param width width to ensure is > 0 * @param height height to ensure is > 0 */
private static void checkWidthHeight(int width, int height) { if (width <= 0) { throw new IllegalArgumentException("width must be > 0"); } if (height <= 0) { throw new IllegalArgumentException("height must be > 0"); } }
Possible bitmap configurations. A bitmap configuration describes how pixels are stored. This affects the quality (color depth) as well as the ability to display transparent/translucent colors.
/** * Possible bitmap configurations. A bitmap configuration describes * how pixels are stored. This affects the quality (color depth) as * well as the ability to display transparent/translucent colors. */
public enum Config { // these native values must match up with the enum in SkBitmap.h
Each pixel is stored as a single translucency (alpha) channel. This is very useful to efficiently store masks for instance. No color information is stored. With this configuration, each pixel requires 1 byte of memory.
/** * Each pixel is stored as a single translucency (alpha) channel. * This is very useful to efficiently store masks for instance. * No color information is stored. * With this configuration, each pixel requires 1 byte of memory. */
ALPHA_8 (1),
Each pixel is stored on 2 bytes and only the RGB channels are encoded: red is stored with 5 bits of precision (32 possible values), green is stored with 6 bits of precision (64 possible values) and blue is stored with 5 bits of precision. This configuration can produce slight visual artifacts depending on the configuration of the source. For instance, without dithering, the result might show a greenish tint. To get better results dithering should be applied. This configuration may be useful when using opaque bitmaps that do not require high color fidelity.

Use this formula to pack into 16 bits:

short color = (R & 0x1f) << 11 | (G & 0x3f) << 5 | (B & 0x1f);
/** * Each pixel is stored on 2 bytes and only the RGB channels are * encoded: red is stored with 5 bits of precision (32 possible * values), green is stored with 6 bits of precision (64 possible * values) and blue is stored with 5 bits of precision. * * This configuration can produce slight visual artifacts depending * on the configuration of the source. For instance, without * dithering, the result might show a greenish tint. To get better * results dithering should be applied. * * This configuration may be useful when using opaque bitmaps * that do not require high color fidelity. * * <p>Use this formula to pack into 16 bits:</p> * <pre class="prettyprint"> * short color = (R & 0x1f) << 11 | (G & 0x3f) << 5 | (B & 0x1f); * </pre> */
RGB_565 (3),
Each pixel is stored on 2 bytes. The three RGB color channels and the alpha channel (translucency) are stored with a 4 bits precision (16 possible values.) This configuration is mostly useful if the application needs to store translucency information but also needs to save memory. It is recommended to use ARGB_8888 instead of this configuration. Note: as of VERSION_CODES.KITKAT, any bitmap created with this configuration will be created using ARGB_8888 instead.
Deprecated:Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead.
/** * Each pixel is stored on 2 bytes. The three RGB color channels * and the alpha channel (translucency) are stored with a 4 bits * precision (16 possible values.) * * This configuration is mostly useful if the application needs * to store translucency information but also needs to save * memory. * * It is recommended to use {@link #ARGB_8888} instead of this * configuration. * * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT}, * any bitmap created with this configuration will be created * using {@link #ARGB_8888} instead. * * @deprecated Because of the poor quality of this configuration, * it is advised to use {@link #ARGB_8888} instead. */
@Deprecated ARGB_4444 (4),
Each pixel is stored on 4 bytes. Each channel (RGB and alpha for translucency) is stored with 8 bits of precision (256 possible values.) This configuration is very flexible and offers the best quality. It should be used whenever possible.

Use this formula to pack into 32 bits:

int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff);
/** * Each pixel is stored on 4 bytes. Each channel (RGB and alpha * for translucency) is stored with 8 bits of precision (256 * possible values.) * * This configuration is very flexible and offers the best * quality. It should be used whenever possible. * * <p>Use this formula to pack into 32 bits:</p> * <pre class="prettyprint"> * int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff); * </pre> */
ARGB_8888 (5),
Each pixels is stored on 8 bytes. Each channel (RGB and alpha for translucency) is stored as a half-precision floating point value. This configuration is particularly suited for wide-gamut and HDR content.

Use this formula to pack into 64 bits:

long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff);
/** * Each pixels is stored on 8 bytes. Each channel (RGB and alpha * for translucency) is stored as a * {@link android.util.Half half-precision floating point value}. * * This configuration is particularly suited for wide-gamut and * HDR content. * * <p>Use this formula to pack into 64 bits:</p> * <pre class="prettyprint"> * long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff); * </pre> */
RGBA_F16 (6),
Special configuration, when bitmap is stored only in graphic memory. Bitmaps in this configuration are always immutable. It is optimal for cases, when the only operation with the bitmap is to draw it on a screen.
/** * Special configuration, when bitmap is stored only in graphic memory. * Bitmaps in this configuration are always immutable. * * It is optimal for cases, when the only operation with the bitmap is to draw it on a * screen. */
HARDWARE (7); final int nativeInt; private static Config sConfigs[] = { null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE }; Config(int ni) { this.nativeInt = ni; } static Config nativeToConfig(int ni) { return sConfigs[ni]; } }

Copy the bitmap's pixels into the specified buffer (allocated by the caller). An exception is thrown if the buffer is not large enough to hold all of the pixels (taking into account the number of bytes per pixel) or if the Buffer subclass is not one of the support types (ByteBuffer, ShortBuffer, IntBuffer).

The content of the bitmap is copied into the buffer as-is. This means that if this bitmap stores its pixels pre-multiplied (see isPremultiplied(), the values in the buffer will also be pre-multiplied. The pixels remain in the color space of the bitmap.

After this method returns, the current position of the buffer is updated: the position is incremented by the number of elements written in the buffer.

Throws:
/** * <p>Copy the bitmap's pixels into the specified buffer (allocated by the * caller). An exception is thrown if the buffer is not large enough to * hold all of the pixels (taking into account the number of bytes per * pixel) or if the Buffer subclass is not one of the support types * (ByteBuffer, ShortBuffer, IntBuffer).</p> * <p>The content of the bitmap is copied into the buffer as-is. This means * that if this bitmap stores its pixels pre-multiplied * (see {@link #isPremultiplied()}, the values in the buffer will also be * pre-multiplied. The pixels remain in the color space of the bitmap.</p> * <p>After this method returns, the current position of the buffer is * updated: the position is incremented by the number of elements written * in the buffer.</p> * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */
public void copyPixelsToBuffer(Buffer dst) { checkHardware("unable to copyPixelsToBuffer, " + "pixel access is not supported on Config#HARDWARE bitmaps"); int elements = dst.remaining(); int shift; if (dst instanceof ByteBuffer) { shift = 0; } else if (dst instanceof ShortBuffer) { shift = 1; } else if (dst instanceof IntBuffer) { shift = 2; } else { throw new RuntimeException("unsupported Buffer subclass"); } long bufferSize = (long)elements << shift; long pixelSize = getByteCount(); if (bufferSize < pixelSize) { throw new RuntimeException("Buffer not large enough for pixels"); } nativeCopyPixelsToBuffer(mNativePtr, dst); // now update the buffer's position int position = dst.position(); position += pixelSize >> shift; dst.position(position); }

Copy the pixels from the buffer, beginning at the current position, overwriting the bitmap's pixels. The data in the buffer is not changed in any way (unlike setPixels(), which converts from unpremultipled 32bit to whatever the bitmap's native format is. The pixels in the source buffer are assumed to be in the bitmap's color space.

After this method returns, the current position of the buffer is updated: the position is incremented by the number of elements read from the buffer. If you need to read the bitmap from the buffer again you must first rewind the buffer.

Throws:
/** * <p>Copy the pixels from the buffer, beginning at the current position, * overwriting the bitmap's pixels. The data in the buffer is not changed * in any way (unlike setPixels(), which converts from unpremultipled 32bit * to whatever the bitmap's native format is. The pixels in the source * buffer are assumed to be in the bitmap's color space.</p> * <p>After this method returns, the current position of the buffer is * updated: the position is incremented by the number of elements read from * the buffer. If you need to read the bitmap from the buffer again you must * first rewind the buffer.</p> * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */
public void copyPixelsFromBuffer(Buffer src) { checkRecycled("copyPixelsFromBuffer called on recycled bitmap"); checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable"); int elements = src.remaining(); int shift; if (src instanceof ByteBuffer) { shift = 0; } else if (src instanceof ShortBuffer) { shift = 1; } else if (src instanceof IntBuffer) { shift = 2; } else { throw new RuntimeException("unsupported Buffer subclass"); } long bufferBytes = (long) elements << shift; long bitmapBytes = getByteCount(); if (bufferBytes < bitmapBytes) { throw new RuntimeException("Buffer not large enough for pixels"); } nativeCopyPixelsFromBuffer(mNativePtr, src); // now update the buffer's position int position = src.position(); position += bitmapBytes >> shift; src.position(position); } private void noteHardwareBitmapSlowCall() { if (getConfig() == Config.HARDWARE) { StrictMode.noteSlowCall("Warning: attempt to read pixels from hardware " + "bitmap, which is very slow operation"); } }
Tries to make a new bitmap based on the dimensions of this bitmap, setting the new bitmap's config to the one specified, and then copying this bitmap's pixels into the new bitmap. If the conversion is not supported, or the allocator fails, then this returns NULL. The returned bitmap has the same density and color space as the original.
Params:
  • config – The desired config for the resulting bitmap
  • isMutable – True if the resulting bitmap should be mutable (i.e. its pixels can be modified)
Throws:
Returns:the new bitmap, or null if the copy could not be made.
/** * Tries to make a new bitmap based on the dimensions of this bitmap, * setting the new bitmap's config to the one specified, and then copying * this bitmap's pixels into the new bitmap. If the conversion is not * supported, or the allocator fails, then this returns NULL. The returned * bitmap has the same density and color space as the original. * * @param config The desired config for the resulting bitmap * @param isMutable True if the resulting bitmap should be mutable (i.e. * its pixels can be modified) * @return the new bitmap, or null if the copy could not be made. * @throws IllegalArgumentException if config is {@link Config#HARDWARE} and isMutable is true */
public Bitmap copy(Config config, boolean isMutable) { checkRecycled("Can't copy a recycled bitmap"); if (config == Config.HARDWARE && isMutable) { throw new IllegalArgumentException("Hardware bitmaps are always immutable"); } noteHardwareBitmapSlowCall(); Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable); if (b != null) { b.setPremultiplied(mRequestPremultiplied); b.mDensity = mDensity; } return b; }
Creates a new immutable bitmap backed by ashmem which can efficiently be passed between processes. The bitmap is assumed to be in the sRGB color space.
@hide
/** * Creates a new immutable bitmap backed by ashmem which can efficiently * be passed between processes. The bitmap is assumed to be in the sRGB * color space. * * @hide */
public Bitmap createAshmemBitmap() { checkRecycled("Can't copy a recycled bitmap"); noteHardwareBitmapSlowCall(); Bitmap b = nativeCopyAshmem(mNativePtr); if (b != null) { b.setPremultiplied(mRequestPremultiplied); b.mDensity = mDensity; } return b; }
Creates a new immutable bitmap backed by ashmem which can efficiently be passed between processes. The bitmap is assumed to be in the sRGB color space.
@hide
/** * Creates a new immutable bitmap backed by ashmem which can efficiently * be passed between processes. The bitmap is assumed to be in the sRGB * color space. * * @hide */
public Bitmap createAshmemBitmap(Config config) { checkRecycled("Can't copy a recycled bitmap"); noteHardwareBitmapSlowCall(); Bitmap b = nativeCopyAshmemConfig(mNativePtr, config.nativeInt); if (b != null) { b.setPremultiplied(mRequestPremultiplied); b.mDensity = mDensity; } return b; }
Create hardware bitmap backed GraphicBuffer.
Returns:Bitmap or null if this GraphicBuffer has unsupported PixelFormat. currently PIXEL_FORMAT_RGBA_8888 is the only supported format
@hide
/** * Create hardware bitmap backed GraphicBuffer. * * @return Bitmap or null if this GraphicBuffer has unsupported PixelFormat. * currently PIXEL_FORMAT_RGBA_8888 is the only supported format * @hide */
public static Bitmap createHardwareBitmap(@NonNull GraphicBuffer graphicBuffer) { return nativeCreateHardwareBitmap(graphicBuffer); }
Creates a new bitmap, scaled from an existing bitmap, when possible. If the specified width and height are the same as the current width and height of the source bitmap, the source bitmap is returned and no new bitmap is created.
Params:
  • src – The source bitmap.
  • dstWidth – The new bitmap's desired width.
  • dstHeight – The new bitmap's desired height.
  • filter – true if the source should be filtered.
Throws:
Returns:The new scaled bitmap or the source bitmap if no scaling is required.
/** * Creates a new bitmap, scaled from an existing bitmap, when possible. If the * specified width and height are the same as the current width and height of * the source bitmap, the source bitmap is returned and no new bitmap is * created. * * @param src The source bitmap. * @param dstWidth The new bitmap's desired width. * @param dstHeight The new bitmap's desired height. * @param filter true if the source should be filtered. * @return The new scaled bitmap or the source bitmap if no scaling is required. * @throws IllegalArgumentException if width is <= 0, or height is <= 0 */
public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight, boolean filter) { Matrix m = new Matrix(); final int width = src.getWidth(); final int height = src.getHeight(); if (width != dstWidth || height != dstHeight) { final float sx = dstWidth / (float) width; final float sy = dstHeight / (float) height; m.setScale(sx, sy); } return Bitmap.createBitmap(src, 0, 0, width, height, m, filter); }
Returns an immutable bitmap from the source bitmap. The new bitmap may be the same object as source, or a copy may have been made. It is initialized with the same density and color space as the original bitmap.
/** * Returns an immutable bitmap from the source bitmap. The new bitmap may * be the same object as source, or a copy may have been made. It is * initialized with the same density and color space as the original bitmap. */
public static Bitmap createBitmap(@NonNull Bitmap src) { return createBitmap(src, 0, 0, src.getWidth(), src.getHeight()); }
Returns an immutable bitmap from the specified subset of the source bitmap. The new bitmap may be the same object as source, or a copy may have been made. It is initialized with the same density and color space as the original bitmap.
Params:
  • source – The bitmap we are subsetting
  • x – The x coordinate of the first pixel in source
  • y – The y coordinate of the first pixel in source
  • width – The number of pixels in each row
  • height – The number of rows
Throws:
  • IllegalArgumentException – if the x, y, width, height values are outside of the dimensions of the source bitmap, or width is <= 0, or height is <= 0
Returns:A copy of a subset of the source bitmap or the source bitmap itself.
/** * Returns an immutable bitmap from the specified subset of the source * bitmap. The new bitmap may be the same object as source, or a copy may * have been made. It is initialized with the same density and color space * as the original bitmap. * * @param source The bitmap we are subsetting * @param x The x coordinate of the first pixel in source * @param y The y coordinate of the first pixel in source * @param width The number of pixels in each row * @param height The number of rows * @return A copy of a subset of the source bitmap or the source bitmap itself. * @throws IllegalArgumentException if the x, y, width, height values are * outside of the dimensions of the source bitmap, or width is <= 0, * or height is <= 0 */
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height) { return createBitmap(source, x, y, width, height, null, false); }
Returns an immutable bitmap from subset of the source bitmap, transformed by the optional matrix. The new bitmap may be the same object as source, or a copy may have been made. It is initialized with the same density and color space as the original bitmap. If the source bitmap is immutable and the requested subset is the same as the source bitmap itself, then the source bitmap is returned and no new bitmap is created.
Params:
  • source – The bitmap we are subsetting
  • x – The x coordinate of the first pixel in source
  • y – The y coordinate of the first pixel in source
  • width – The number of pixels in each row
  • height – The number of rows
  • m – Optional matrix to be applied to the pixels
  • filter – true if the source should be filtered. Only applies if the matrix contains more than just translation.
Throws:
  • IllegalArgumentException – if the x, y, width, height values are outside of the dimensions of the source bitmap, or width is <= 0, or height is <= 0
Returns:A bitmap that represents the specified subset of source
/** * Returns an immutable bitmap from subset of the source bitmap, * transformed by the optional matrix. The new bitmap may be the * same object as source, or a copy may have been made. It is * initialized with the same density and color space as the original * bitmap. * * If the source bitmap is immutable and the requested subset is the * same as the source bitmap itself, then the source bitmap is * returned and no new bitmap is created. * * @param source The bitmap we are subsetting * @param x The x coordinate of the first pixel in source * @param y The y coordinate of the first pixel in source * @param width The number of pixels in each row * @param height The number of rows * @param m Optional matrix to be applied to the pixels * @param filter true if the source should be filtered. * Only applies if the matrix contains more than just * translation. * @return A bitmap that represents the specified subset of source * @throws IllegalArgumentException if the x, y, width, height values are * outside of the dimensions of the source bitmap, or width is <= 0, * or height is <= 0 */
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height, @Nullable Matrix m, boolean filter) { checkXYSign(x, y); checkWidthHeight(width, height); if (x + width > source.getWidth()) { throw new IllegalArgumentException("x + width must be <= bitmap.width()"); } if (y + height > source.getHeight()) { throw new IllegalArgumentException("y + height must be <= bitmap.height()"); } // check if we can just return our argument unchanged if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() && height == source.getHeight() && (m == null || m.isIdentity())) { return source; } boolean isHardware = source.getConfig() == Config.HARDWARE; if (isHardware) { source.noteHardwareBitmapSlowCall(); source = nativeCopyPreserveInternalConfig(source.mNativePtr); } int neww = width; int newh = height; Bitmap bitmap; Paint paint; Rect srcR = new Rect(x, y, x + width, y + height); RectF dstR = new RectF(0, 0, width, height); RectF deviceR = new RectF(); Config newConfig = Config.ARGB_8888; final Config config = source.getConfig(); // GIF files generate null configs, assume ARGB_8888 if (config != null) { switch (config) { case RGB_565: newConfig = Config.RGB_565; break; case ALPHA_8: newConfig = Config.ALPHA_8; break; case RGBA_F16: newConfig = Config.RGBA_F16; break; //noinspection deprecation case ARGB_4444: case ARGB_8888: default: newConfig = Config.ARGB_8888; break; } } if (m == null || m.isIdentity()) { bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha()); paint = null; // not needed } else { final boolean transformed = !m.rectStaysRect(); m.mapRect(deviceR, dstR); neww = Math.round(deviceR.width()); newh = Math.round(deviceR.height()); Config transformedConfig = newConfig; if (transformed) { if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) { transformedConfig = Config.ARGB_8888; } } bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha()); paint = new Paint(); paint.setFilterBitmap(filter); if (transformed) { paint.setAntiAlias(true); } } nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr); // The new bitmap was created from a known bitmap source so assume that // they use the same density bitmap.mDensity = source.mDensity; bitmap.setHasAlpha(source.hasAlpha()); bitmap.setPremultiplied(source.mRequestPremultiplied); Canvas canvas = new Canvas(bitmap); canvas.translate(-deviceR.left, -deviceR.top); canvas.concat(m); canvas.drawBitmap(source, srcR, dstR, paint); canvas.setBitmap(null); if (isHardware) { return bitmap.copy(Config.HARDWARE, false); } return bitmap; }
Returns a mutable bitmap with the specified width and height. Its initial density is as per getDensity. The newly created bitmap is in the sRGB color space.
Params:
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if Config is Config.HARDWARE, because hardware bitmaps are always immutable
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is as per {@link #getDensity}. The newly created * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space. * * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */
public static Bitmap createBitmap(int width, int height, @NonNull Config config) { return createBitmap(width, height, config, true); }
Returns a mutable bitmap with the specified width and height. Its initial density is determined from the given DisplayMetrics. The newly created bitmap is in the sRGB color space.
Params:
  • display – Display metrics for the display this bitmap will be drawn on.
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if Config is Config.HARDWARE, because hardware bitmaps are always immutable
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is determined from the given {@link DisplayMetrics}. * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB} * color space. * * @param display Display metrics for the display this bitmap will be * drawn on. * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */
public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config) { return createBitmap(display, width, height, config, true); }
Returns a mutable bitmap with the specified width and height. Its initial density is as per getDensity. The newly created bitmap is in the sRGB color space.
Params:
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
  • hasAlpha – If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to mark the bitmap as opaque. Doing so will clear the bitmap in black instead of transparent.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if Config is Config.HARDWARE, because hardware bitmaps are always immutable
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is as per {@link #getDensity}. The newly created * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space. * * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. * * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */
public static Bitmap createBitmap(int width, int height, @NonNull Config config, boolean hasAlpha) { return createBitmap(null, width, height, config, hasAlpha); }
Returns a mutable bitmap with the specified width and height. Its initial density is as per getDensity.
Params:
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
  • hasAlpha – If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to mark the bitmap as opaque. Doing so will clear the bitmap in black instead of transparent.
  • colorSpace – The color space of the bitmap. If the config is Config.RGBA_F16, scRGB is assumed, and if the config is not Config.ARGB_8888, sRGB is assumed.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, if Config is Config.HARDWARE (because hardware bitmaps are always immutable), if the specified color space is not RGB, if the specified color space's transfer function is not an ICC parametric curve, or if the color space is null
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is as per {@link #getDensity}. * * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}, * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} * is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always * immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB}, * if the specified color space's transfer function is not an * {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if * the color space is null */
public static Bitmap createBitmap(int width, int height, @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) { return createBitmap(null, width, height, config, hasAlpha, colorSpace); }
Returns a mutable bitmap with the specified width and height. Its initial density is determined from the given DisplayMetrics. The newly created bitmap is in the sRGB color space.
Params:
  • display – Display metrics for the display this bitmap will be drawn on.
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
  • hasAlpha – If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to mark the bitmap as opaque. Doing so will clear the bitmap in black instead of transparent.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if Config is Config.HARDWARE, because hardware bitmaps are always immutable
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is determined from the given {@link DisplayMetrics}. * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB} * color space. * * @param display Display metrics for the display this bitmap will be * drawn on. * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. * * @throws IllegalArgumentException if the width or height are <= 0, or if * Config is Config.HARDWARE, because hardware bitmaps are always immutable */
public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config, boolean hasAlpha) { return createBitmap(display, width, height, config, hasAlpha, ColorSpace.get(ColorSpace.Named.SRGB)); }
Returns a mutable bitmap with the specified width and height. Its initial density is determined from the given DisplayMetrics. The newly created bitmap is in the sRGB color space.
Params:
  • display – Display metrics for the display this bitmap will be drawn on.
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create.
  • hasAlpha – If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to mark the bitmap as opaque. Doing so will clear the bitmap in black instead of transparent.
  • colorSpace – The color space of the bitmap. If the config is Config.RGBA_F16, scRGB is assumed, and if the config is not Config.ARGB_8888, sRGB is assumed.
Throws:
  • IllegalArgumentException – if the width or height are <= 0, if Config is Config.HARDWARE (because hardware bitmaps are always immutable), if the specified color space is not RGB, if the specified color space's transfer function is not an ICC parametric curve, or if the color space is null
/** * Returns a mutable bitmap with the specified width and height. Its * initial density is determined from the given {@link DisplayMetrics}. * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB} * color space. * * @param display Display metrics for the display this bitmap will be * drawn on. * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to * mark the bitmap as opaque. Doing so will clear the bitmap in black * instead of transparent. * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}, * {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the * config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB} * is assumed. * * @throws IllegalArgumentException if the width or height are <= 0, if * Config is Config.HARDWARE (because hardware bitmaps are always * immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB}, * if the specified color space's transfer function is not an * {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if * the color space is null */
public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height, @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } if (config == Config.HARDWARE) { throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE"); } if (colorSpace == null) { throw new IllegalArgumentException("can't create bitmap without a color space"); } Bitmap bm; // nullptr color spaces have a particular meaning in native and are interpreted as sRGB // (we also avoid the unnecessary extra work of the else branch) if (config != Config.ARGB_8888 || colorSpace == ColorSpace.get(ColorSpace.Named.SRGB)) { bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null); } else { if (!(colorSpace instanceof ColorSpace.Rgb)) { throw new IllegalArgumentException("colorSpace must be an RGB color space"); } ColorSpace.Rgb rgb = (ColorSpace.Rgb) colorSpace; ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters(); if (parameters == null) { throw new IllegalArgumentException("colorSpace must use an ICC " + "parametric transfer function"); } ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50); bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, d50.getTransform(), parameters); } if (display != null) { bm.mDensity = display.densityDpi; } bm.setHasAlpha(hasAlpha); if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) { nativeErase(bm.mNativePtr, 0xff000000); } // No need to initialize the bitmap to zeroes with other configs; // it is backed by a VM byte array which is by definition preinitialized // to all zeroes. return bm; }
Returns a immutable bitmap with the specified width and height, with each pixel value set to the corresponding value in the colors array. Its initial density is as per getDensity. The newly created bitmap is in the sRGB color space.
Params:
  • colors – Array of sRGB colors used to initialize the pixels.
  • offset – Number of values to skip before the first color in the array of colors.
  • stride – Number of colors in the array between rows (must be >= width or <= -width).
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create. If the config does not support per-pixel alpha (e.g. RGB_565), then the alpha bytes in the colors[] will be ignored (assumed to be FF)
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if the color array's length is less than the number of pixels.
/** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. Its * initial density is as per {@link #getDensity}. The newly created * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space. * * @param colors Array of sRGB {@link Color colors} used to initialize the pixels. * @param offset Number of values to skip before the first color in the * array of colors. * @param stride Number of colors in the array between rows (must be >= * width or <= -width). * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. If the config does not * support per-pixel alpha (e.g. RGB_565), then the alpha * bytes in the colors[] will be ignored (assumed to be FF) * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */
public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int offset, int stride, int width, int height, @NonNull Config config) { return createBitmap(null, colors, offset, stride, width, height, config); }
Returns a immutable bitmap with the specified width and height, with each pixel value set to the corresponding value in the colors array. Its initial density is determined from the given DisplayMetrics. The newly created bitmap is in the sRGB color space.
Params:
  • display – Display metrics for the display this bitmap will be drawn on.
  • colors – Array of sRGB colors used to initialize the pixels.
  • offset – Number of values to skip before the first color in the array of colors.
  • stride – Number of colors in the array between rows (must be >= width or <= -width).
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create. If the config does not support per-pixel alpha (e.g. RGB_565), then the alpha bytes in the colors[] will be ignored (assumed to be FF)
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if the color array's length is less than the number of pixels.
/** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. Its * initial density is determined from the given {@link DisplayMetrics}. * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB} * color space. * * @param display Display metrics for the display this bitmap will be * drawn on. * @param colors Array of sRGB {@link Color colors} used to initialize the pixels. * @param offset Number of values to skip before the first color in the * array of colors. * @param stride Number of colors in the array between rows (must be >= * width or <= -width). * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. If the config does not * support per-pixel alpha (e.g. RGB_565), then the alpha * bytes in the colors[] will be ignored (assumed to be FF) * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */
public static Bitmap createBitmap(@NonNull DisplayMetrics display, @NonNull @ColorInt int[] colors, int offset, int stride, int width, int height, @NonNull Config config) { checkWidthHeight(width, height); if (Math.abs(stride) < width) { throw new IllegalArgumentException("abs(stride) must be >= width"); } int lastScanline = offset + (height - 1) * stride; int length = colors.length; if (offset < 0 || (offset + width > length) || lastScanline < 0 || (lastScanline + width > length)) { throw new ArrayIndexOutOfBoundsException(); } if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } Bitmap bm = nativeCreate(colors, offset, stride, width, height, config.nativeInt, false, null, null); if (display != null) { bm.mDensity = display.densityDpi; } return bm; }
Returns a immutable bitmap with the specified width and height, with each pixel value set to the corresponding value in the colors array. Its initial density is as per getDensity. The newly created bitmap is in the sRGB color space.
Params:
  • colors – Array of sRGB colors used to initialize the pixels. This array must be at least as large as width * height.
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create. If the config does not support per-pixel alpha (e.g. RGB_565), then the alpha bytes in the colors[] will be ignored (assumed to be FF)
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if the color array's length is less than the number of pixels.
/** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. Its * initial density is as per {@link #getDensity}. The newly created * bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space. * * @param colors Array of sRGB {@link Color colors} used to initialize the pixels. * This array must be at least as large as width * height. * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. If the config does not * support per-pixel alpha (e.g. RGB_565), then the alpha * bytes in the colors[] will be ignored (assumed to be FF) * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */
public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int width, int height, Config config) { return createBitmap(null, colors, 0, width, width, height, config); }
Returns a immutable bitmap with the specified width and height, with each pixel value set to the corresponding value in the colors array. Its initial density is determined from the given DisplayMetrics. The newly created bitmap is in the sRGB color space.
Params:
  • display – Display metrics for the display this bitmap will be drawn on.
  • colors – Array of sRGB colors used to initialize the pixels. This array must be at least as large as width * height.
  • width – The width of the bitmap
  • height – The height of the bitmap
  • config – The bitmap config to create. If the config does not support per-pixel alpha (e.g. RGB_565), then the alpha bytes in the colors[] will be ignored (assumed to be FF)
Throws:
  • IllegalArgumentException – if the width or height are <= 0, or if the color array's length is less than the number of pixels.
/** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. Its * initial density is determined from the given {@link DisplayMetrics}. * The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB} * color space. * * @param display Display metrics for the display this bitmap will be * drawn on. * @param colors Array of sRGB {@link Color colors} used to initialize the pixels. * This array must be at least as large as width * height. * @param width The width of the bitmap * @param height The height of the bitmap * @param config The bitmap config to create. If the config does not * support per-pixel alpha (e.g. RGB_565), then the alpha * bytes in the colors[] will be ignored (assumed to be FF) * @throws IllegalArgumentException if the width or height are <= 0, or if * the color array's length is less than the number of pixels. */
public static Bitmap createBitmap(@Nullable DisplayMetrics display, @NonNull @ColorInt int colors[], int width, int height, @NonNull Config config) { return createBitmap(display, colors, 0, width, width, height, config); }
Creates a Bitmap from the given Picture source of recorded drawing commands. Equivalent to calling createBitmap(Picture, int, int, Config) with width and height the same as the Picture's width and height and a Config.HARDWARE config.
Params:
  • source – The recorded Picture of drawing commands that will be drawn into the returned Bitmap.
Returns:An immutable bitmap with a HARDWARE config whose contents are created from the recorded drawing commands in the Picture source.
/** * Creates a Bitmap from the given {@link Picture} source of recorded drawing commands. * * Equivalent to calling {@link #createBitmap(Picture, int, int, Config)} with * width and height the same as the Picture's width and height and a Config.HARDWARE * config. * * @param source The recorded {@link Picture} of drawing commands that will be * drawn into the returned Bitmap. * @return An immutable bitmap with a HARDWARE config whose contents are created * from the recorded drawing commands in the Picture source. */
public static @NonNull Bitmap createBitmap(@NonNull Picture source) { return createBitmap(source, source.getWidth(), source.getHeight(), Config.HARDWARE); }
Creates a Bitmap from the given Picture source of recorded drawing commands. The bitmap will be immutable with the given width and height. If the width and height are not the same as the Picture's width & height, the Picture will be scaled to fit the given width and height.
Params:
  • source – The recorded Picture of drawing commands that will be drawn into the returned Bitmap.
  • width – The width of the bitmap to create. The picture's width will be scaled to match if necessary.
  • height – The height of the bitmap to create. The picture's height will be scaled to match if necessary.
  • config – The Config of the created bitmap. If this is null then the bitmap will be Config.HARDWARE.
Returns:An immutable bitmap with a HARDWARE config whose contents are created from the recorded drawing commands in the Picture source.
/** * Creates a Bitmap from the given {@link Picture} source of recorded drawing commands. * * The bitmap will be immutable with the given width and height. If the width and height * are not the same as the Picture's width & height, the Picture will be scaled to * fit the given width and height. * * @param source The recorded {@link Picture} of drawing commands that will be * drawn into the returned Bitmap. * @param width The width of the bitmap to create. The picture's width will be * scaled to match if necessary. * @param height The height of the bitmap to create. The picture's height will be * scaled to match if necessary. * @param config The {@link Config} of the created bitmap. If this is null then * the bitmap will be {@link Config#HARDWARE}. * * @return An immutable bitmap with a HARDWARE config whose contents are created * from the recorded drawing commands in the Picture source. */
public static @NonNull Bitmap createBitmap(@NonNull Picture source, int width, int height, @NonNull Config config) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width & height must be > 0"); } if (config == null) { throw new IllegalArgumentException("Config must not be null"); } source.endRecording(); if (source.requiresHardwareAcceleration() && config != Config.HARDWARE) { StrictMode.noteSlowCall("GPU readback"); } if (config == Config.HARDWARE || source.requiresHardwareAcceleration()) { final RenderNode node = RenderNode.create("BitmapTemporary", null); node.setLeftTopRightBottom(0, 0, width, height); node.setClipToBounds(false); final DisplayListCanvas canvas = node.start(width, height); if (source.getWidth() != width || source.getHeight() != height) { canvas.scale(width / (float) source.getWidth(), height / (float) source.getHeight()); } canvas.drawPicture(source); node.end(canvas); Bitmap bitmap = ThreadedRenderer.createHardwareBitmap(node, width, height); if (config != Config.HARDWARE) { bitmap = bitmap.copy(config, false); } return bitmap; } else { Bitmap bitmap = Bitmap.createBitmap(width, height, config); Canvas canvas = new Canvas(bitmap); if (source.getWidth() != width || source.getHeight() != height) { canvas.scale(width / (float) source.getWidth(), height / (float) source.getHeight()); } canvas.drawPicture(source); canvas.setBitmap(null); bitmap.makeImmutable(); return bitmap; } }
Returns an optional array of private data, used by the UI system for some bitmaps. Not intended to be called by applications.
/** * Returns an optional array of private data, used by the UI system for * some bitmaps. Not intended to be called by applications. */
public byte[] getNinePatchChunk() { return mNinePatchChunk; }
Populates a rectangle with the bitmap's optical insets.
Params:
  • outInsets – Rect to populate with optical insets
@hide
/** * Populates a rectangle with the bitmap's optical insets. * * @param outInsets Rect to populate with optical insets * @hide */
public void getOpticalInsets(@NonNull Rect outInsets) { if (mNinePatchInsets == null) { outInsets.setEmpty(); } else { outInsets.set(mNinePatchInsets.opticalRect); } }
@hide
/** @hide */
public NinePatch.InsetStruct getNinePatchInsets() { return mNinePatchInsets; }
Specifies the known formats a bitmap can be compressed into
/** * Specifies the known formats a bitmap can be compressed into */
public enum CompressFormat { JPEG (0), PNG (1), WEBP (2); CompressFormat(int nativeInt) { this.nativeInt = nativeInt; } final int nativeInt; }
Number of bytes of temp storage we use for communicating between the native compressor and the java OutputStream.
/** * Number of bytes of temp storage we use for communicating between the * native compressor and the java OutputStream. */
private final static int WORKING_COMPRESS_STORAGE = 4096;
Write a compressed version of the bitmap to the specified outputstream. If this returns true, the bitmap can be reconstructed by passing a corresponding inputstream to BitmapFactory.decodeStream(). Note: not all Formats support all bitmap configs directly, so it is possible that the returned bitmap from BitmapFactory could be in a different bitdepth, and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque pixels).
Params:
  • format – The format of the compressed image
  • quality – Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality. Some formats, like PNG which is lossless, will ignore the quality setting
  • stream – The outputstream to write the compressed data.
Returns:true if successfully compressed to the specified stream.
/** * Write a compressed version of the bitmap to the specified outputstream. * If this returns true, the bitmap can be reconstructed by passing a * corresponding inputstream to BitmapFactory.decodeStream(). Note: not * all Formats support all bitmap configs directly, so it is possible that * the returned bitmap from BitmapFactory could be in a different bitdepth, * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque * pixels). * * @param format The format of the compressed image * @param quality Hint to the compressor, 0-100. 0 meaning compress for * small size, 100 meaning compress for max quality. Some * formats, like PNG which is lossless, will ignore the * quality setting * @param stream The outputstream to write the compressed data. * @return true if successfully compressed to the specified stream. */
@WorkerThread public boolean compress(CompressFormat format, int quality, OutputStream stream) { checkRecycled("Can't compress a recycled bitmap"); // do explicit check before calling the native method if (stream == null) { throw new NullPointerException(); } if (quality < 0 || quality > 100) { throw new IllegalArgumentException("quality must be 0..100"); } StrictMode.noteSlowCall("Compression of a bitmap is slow"); Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress"); boolean result = nativeCompress(mNativePtr, format.nativeInt, quality, stream, new byte[WORKING_COMPRESS_STORAGE]); Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); return result; }
Returns true if the bitmap is marked as mutable (i.e. can be drawn into)
/** * Returns true if the bitmap is marked as mutable (i.e.&nbsp;can be drawn into) */
public final boolean isMutable() { return mIsMutable; }
@hide
/** @hide */
public final void makeImmutable() { // todo mIsMutable = false; // todo nMakeImmutable(); }

Indicates whether pixels stored in this bitmaps are stored pre-multiplied. When a pixel is pre-multiplied, the RGB components have been multiplied by the alpha component. For instance, if the original color is a 50% translucent red (128, 255, 0, 0), the pre-multiplied form is (128, 128, 0, 0).

This method always returns false if getConfig() is Config.RGB_565.

The return value is undefined if getConfig() is Config.ALPHA_8.

This method only returns true if hasAlpha() returns true. A bitmap with no alpha channel can be used both as a pre-multiplied and as a non pre-multiplied bitmap.

Only pre-multiplied bitmaps may be drawn by the view system or Canvas. If a non-pre-multiplied bitmap with an alpha channel is drawn to a Canvas, a RuntimeException will be thrown.

See Also:
Returns:true if the underlying pixels have been pre-multiplied, false otherwise
/** * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied. * When a pixel is pre-multiplied, the RGB components have been multiplied by * the alpha component. For instance, if the original color is a 50% * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is * <code>(128, 128, 0, 0)</code>.</p> * * <p>This method always returns false if {@link #getConfig()} is * {@link Bitmap.Config#RGB_565}.</p> * * <p>The return value is undefined if {@link #getConfig()} is * {@link Bitmap.Config#ALPHA_8}.</p> * * <p>This method only returns true if {@link #hasAlpha()} returns true. * A bitmap with no alpha channel can be used both as a pre-multiplied and * as a non pre-multiplied bitmap.</p> * * <p>Only pre-multiplied bitmaps may be drawn by the view system or * {@link Canvas}. If a non-pre-multiplied bitmap with an alpha channel is * drawn to a Canvas, a RuntimeException will be thrown.</p> * * @return true if the underlying pixels have been pre-multiplied, false * otherwise * * @see Bitmap#setPremultiplied(boolean) * @see BitmapFactory.Options#inPremultiplied */
public final boolean isPremultiplied() { if (mRecycled) { Log.w(TAG, "Called isPremultiplied() on a recycle()'d bitmap! This is undefined behavior!"); } return nativeIsPremultiplied(mNativePtr); }
Sets whether the bitmap should treat its data as pre-multiplied.

Bitmaps are always treated as pre-multiplied by the view system and Canvas for performance reasons. Storing un-pre-multiplied data in a Bitmap (through setPixel, setPixels, or BitmapFactory.Options.inPremultiplied) can lead to incorrect blending if drawn by the framework.

This method will not affect the behavior of a bitmap without an alpha channel, or if hasAlpha() returns false.

Calling createBitmap or createScaledBitmap with a source Bitmap whose colors are not pre-multiplied may result in a RuntimeException, since those functions require drawing the source, which is not supported for un-pre-multiplied Bitmaps.

See Also:
/** * Sets whether the bitmap should treat its data as pre-multiplied. * * <p>Bitmaps are always treated as pre-multiplied by the view system and * {@link Canvas} for performance reasons. Storing un-pre-multiplied data in * a Bitmap (through {@link #setPixel}, {@link #setPixels}, or {@link * BitmapFactory.Options#inPremultiplied BitmapFactory.Options.inPremultiplied}) * can lead to incorrect blending if drawn by the framework.</p> * * <p>This method will not affect the behavior of a bitmap without an alpha * channel, or if {@link #hasAlpha()} returns false.</p> * * <p>Calling {@link #createBitmap} or {@link #createScaledBitmap} with a source * Bitmap whose colors are not pre-multiplied may result in a RuntimeException, * since those functions require drawing the source, which is not supported for * un-pre-multiplied Bitmaps.</p> * * @see Bitmap#isPremultiplied() * @see BitmapFactory.Options#inPremultiplied */
public final void setPremultiplied(boolean premultiplied) { checkRecycled("setPremultiplied called on a recycled bitmap"); mRequestPremultiplied = premultiplied; nativeSetPremultiplied(mNativePtr, premultiplied); }
Returns the bitmap's width
/** Returns the bitmap's width */
public final int getWidth() { if (mRecycled) { Log.w(TAG, "Called getWidth() on a recycle()'d bitmap! This is undefined behavior!"); } return mWidth; }
Returns the bitmap's height
/** Returns the bitmap's height */
public final int getHeight() { if (mRecycled) { Log.w(TAG, "Called getHeight() on a recycle()'d bitmap! This is undefined behavior!"); } return mHeight; }
Convenience for calling getScaledWidth(int) with the target density of the given Canvas.
/** * Convenience for calling {@link #getScaledWidth(int)} with the target * density of the given {@link Canvas}. */
public int getScaledWidth(Canvas canvas) { return scaleFromDensity(getWidth(), mDensity, canvas.mDensity); }
Convenience for calling getScaledHeight(int) with the target density of the given Canvas.
/** * Convenience for calling {@link #getScaledHeight(int)} with the target * density of the given {@link Canvas}. */
public int getScaledHeight(Canvas canvas) { return scaleFromDensity(getHeight(), mDensity, canvas.mDensity); }
Convenience for calling getScaledWidth(int) with the target density of the given DisplayMetrics.
/** * Convenience for calling {@link #getScaledWidth(int)} with the target * density of the given {@link DisplayMetrics}. */
public int getScaledWidth(DisplayMetrics metrics) { return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi); }
Convenience for calling getScaledHeight(int) with the target density of the given DisplayMetrics.
/** * Convenience for calling {@link #getScaledHeight(int)} with the target * density of the given {@link DisplayMetrics}. */
public int getScaledHeight(DisplayMetrics metrics) { return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi); }
Convenience method that returns the width of this bitmap divided by the density scale factor.
Params:
  • targetDensity – The density of the target canvas of the bitmap.
Returns:The scaled width of this bitmap, according to the density scale factor.
/** * Convenience method that returns the width of this bitmap divided * by the density scale factor. * * @param targetDensity The density of the target canvas of the bitmap. * @return The scaled width of this bitmap, according to the density scale factor. */
public int getScaledWidth(int targetDensity) { return scaleFromDensity(getWidth(), mDensity, targetDensity); }
Convenience method that returns the height of this bitmap divided by the density scale factor.
Params:
  • targetDensity – The density of the target canvas of the bitmap.
Returns:The scaled height of this bitmap, according to the density scale factor.
/** * Convenience method that returns the height of this bitmap divided * by the density scale factor. * * @param targetDensity The density of the target canvas of the bitmap. * @return The scaled height of this bitmap, according to the density scale factor. */
public int getScaledHeight(int targetDensity) { return scaleFromDensity(getHeight(), mDensity, targetDensity); }
@hide
/** * @hide */
static public int scaleFromDensity(int size, int sdensity, int tdensity) { if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) { return size; } // Scale by tdensity / sdensity, rounding up. return ((size * tdensity) + (sdensity >> 1)) / sdensity; }
Return the number of bytes between rows in the bitmap's pixels. Note that this refers to the pixels as stored natively by the bitmap. If you call getPixels() or setPixels(), then the pixels are uniformly treated as 32bit values, packed according to the Color class.

As of VERSION_CODES.KITKAT, this method should not be used to calculate the memory usage of the bitmap. Instead, see getAllocationByteCount().

Returns:number of bytes between rows of the native bitmap pixels.
/** * Return the number of bytes between rows in the bitmap's pixels. Note that * this refers to the pixels as stored natively by the bitmap. If you call * getPixels() or setPixels(), then the pixels are uniformly treated as * 32bit values, packed according to the Color class. * * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, this method * should not be used to calculate the memory usage of the bitmap. Instead, * see {@link #getAllocationByteCount()}. * * @return number of bytes between rows of the native bitmap pixels. */
public final int getRowBytes() { if (mRecycled) { Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!"); } return nativeRowBytes(mNativePtr); }
Returns the minimum number of bytes that can be used to store this bitmap's pixels.

As of VERSION_CODES.KITKAT, the result of this method can no longer be used to determine memory usage of a bitmap. See getAllocationByteCount().

/** * Returns the minimum number of bytes that can be used to store this bitmap's pixels. * * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can * no longer be used to determine memory usage of a bitmap. See {@link * #getAllocationByteCount()}.</p> */
public final int getByteCount() { if (mRecycled) { Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! " + "This is undefined behavior!"); return 0; } // int result permits bitmaps up to 46,340 x 46,340 return getRowBytes() * getHeight(); }
Returns the size of the allocated memory used to store this bitmap's pixels.

This can be larger than the result of getByteCount() if a bitmap is reused to decode other bitmaps of smaller size, or by manual reconfiguration. See reconfigure(int, int, Config), setWidth(int), setHeight(int), setConfig(Config), and BitmapFactory.Options.inBitmap. If a bitmap is not modified in this way, this value will be the same as that returned by getByteCount().

This value will not change over the lifetime of a Bitmap.

See Also:
/** * Returns the size of the allocated memory used to store this bitmap's pixels. * * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to * decode other bitmaps of smaller size, or by manual reconfiguration. See {@link * #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link * #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap * BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be * the same as that returned by {@link #getByteCount()}.</p> * * <p>This value will not change over the lifetime of a Bitmap.</p> * * @see #reconfigure(int, int, Config) */
public final int getAllocationByteCount() { if (mRecycled) { Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! " + "This is undefined behavior!"); return 0; } return nativeGetAllocationByteCount(mNativePtr); }
If the bitmap's internal config is in one of the public formats, return that config, otherwise return null.
/** * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. */
public final Config getConfig() { if (mRecycled) { Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!"); } return Config.nativeToConfig(nativeConfig(mNativePtr)); }
Returns true if the bitmap's config supports per-pixel alpha, and if the pixels may contain non-opaque alpha values. For some configs, this is always false (e.g. RGB_565), since they do not support per-pixel alpha. However, for configs that do, the bitmap may be flagged to be known that all of its pixels are opaque. In this case hasAlpha() will also return false. If a config such as ARGB_8888 is not so flagged, it will return true by default.
/** Returns true if the bitmap's config supports per-pixel alpha, and * if the pixels may contain non-opaque alpha values. For some configs, * this is always false (e.g. RGB_565), since they do not support per-pixel * alpha. However, for configs that do, the bitmap may be flagged to be * known that all of its pixels are opaque. In this case hasAlpha() will * also return false. If a config such as ARGB_8888 is not so flagged, * it will return true by default. */
public final boolean hasAlpha() { if (mRecycled) { Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!"); } return nativeHasAlpha(mNativePtr); }
Tell the bitmap if all of the pixels are known to be opaque (false) or if some of the pixels may contain non-opaque alpha values (true). Note, for some configs (e.g. RGB_565) this call is ignored, since it does not support per-pixel alpha values. This is meant as a drawing hint, as in some cases a bitmap that is known to be opaque can take a faster drawing case than one that may have non-opaque per-pixel alpha values.
/** * Tell the bitmap if all of the pixels are known to be opaque (false) * or if some of the pixels may contain non-opaque alpha values (true). * Note, for some configs (e.g. RGB_565) this call is ignored, since it * does not support per-pixel alpha values. * * This is meant as a drawing hint, as in some cases a bitmap that is known * to be opaque can take a faster drawing case than one that may have * non-opaque per-pixel alpha values. */
public void setHasAlpha(boolean hasAlpha) { checkRecycled("setHasAlpha called on a recycled bitmap"); nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied); }
Indicates whether the renderer responsible for drawing this bitmap should attempt to use mipmaps when this bitmap is drawn scaled down. If you know that you are going to draw this bitmap at less than 50% of its original size, you may be able to obtain a higher quality This property is only a suggestion that can be ignored by the renderer. It is not guaranteed to have any effect.
See Also:
Returns:true if the renderer should attempt to use mipmaps, false otherwise
/** * Indicates whether the renderer responsible for drawing this * bitmap should attempt to use mipmaps when this bitmap is drawn * scaled down. * * If you know that you are going to draw this bitmap at less than * 50% of its original size, you may be able to obtain a higher * quality * * This property is only a suggestion that can be ignored by the * renderer. It is not guaranteed to have any effect. * * @return true if the renderer should attempt to use mipmaps, * false otherwise * * @see #setHasMipMap(boolean) */
public final boolean hasMipMap() { if (mRecycled) { Log.w(TAG, "Called hasMipMap() on a recycle()'d bitmap! This is undefined behavior!"); } return nativeHasMipMap(mNativePtr); }
Set a hint for the renderer responsible for drawing this bitmap indicating that it should attempt to use mipmaps when this bitmap is drawn scaled down. If you know that you are going to draw this bitmap at less than 50% of its original size, you may be able to obtain a higher quality by turning this property on. Note that if the renderer respects this hint it might have to allocate extra memory to hold the mipmap levels for this bitmap. This property is only a suggestion that can be ignored by the renderer. It is not guaranteed to have any effect.
Params:
  • hasMipMap – indicates whether the renderer should attempt to use mipmaps
See Also:
/** * Set a hint for the renderer responsible for drawing this bitmap * indicating that it should attempt to use mipmaps when this bitmap * is drawn scaled down. * * If you know that you are going to draw this bitmap at less than * 50% of its original size, you may be able to obtain a higher * quality by turning this property on. * * Note that if the renderer respects this hint it might have to * allocate extra memory to hold the mipmap levels for this bitmap. * * This property is only a suggestion that can be ignored by the * renderer. It is not guaranteed to have any effect. * * @param hasMipMap indicates whether the renderer should attempt * to use mipmaps * * @see #hasMipMap() */
public final void setHasMipMap(boolean hasMipMap) { checkRecycled("setHasMipMap called on a recycled bitmap"); nativeSetHasMipMap(mNativePtr, hasMipMap); }
Returns the color space associated with this bitmap. If the color space is unknown, this method returns null.
/** * Returns the color space associated with this bitmap. If the color * space is unknown, this method returns null. */
@Nullable public final ColorSpace getColorSpace() { // A reconfigure can change the configuration and rgba16f is // always linear scRGB at this time if (getConfig() == Config.RGBA_F16) { // Reset the color space for potential future reconfigurations mColorSpace = null; return ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); } // Cache the color space retrieval since it can be fairly expensive if (mColorSpace == null) { if (nativeIsSRGB(mNativePtr)) { mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB); } else if (getConfig() == Config.HARDWARE && nativeIsSRGBLinear(mNativePtr)) { mColorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); } else { float[] xyz = new float[9]; float[] params = new float[7]; boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params); if (hasColorSpace) { ColorSpace.Rgb.TransferParameters parameters = new ColorSpace.Rgb.TransferParameters( params[0], params[1], params[2], params[3], params[4], params[5], params[6]); ColorSpace cs = ColorSpace.match(xyz, parameters); if (cs != null) { mColorSpace = cs; } else { mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters); } } } } return mColorSpace; }
Fills the bitmap's pixels with the specified Color.
Throws:
/** * Fills the bitmap's pixels with the specified {@link Color}. * * @throws IllegalStateException if the bitmap is not mutable. */
public void eraseColor(@ColorInt int c) { checkRecycled("Can't erase a recycled bitmap"); if (!isMutable()) { throw new IllegalStateException("cannot erase immutable bitmaps"); } nativeErase(mNativePtr, c); }
Returns the Color at the specified location. Throws an exception if x or y are out of bounds (negative or >= to the width or height respectively). The returned color is a non-premultiplied ARGB value in the sRGB color space.
Params:
  • x – The x coordinate (0...width-1) of the pixel to return
  • y – The y coordinate (0...height-1) of the pixel to return
Throws:
Returns: The argb Color at the specified coordinate
/** * Returns the {@link Color} at the specified location. Throws an exception * if x or y are out of bounds (negative or >= to the width or height * respectively). The returned color is a non-premultiplied ARGB value in * the {@link ColorSpace.Named#SRGB sRGB} color space. * * @param x The x coordinate (0...width-1) of the pixel to return * @param y The y coordinate (0...height-1) of the pixel to return * @return The argb {@link Color} at the specified coordinate * @throws IllegalArgumentException if x, y exceed the bitmap's bounds * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */
@ColorInt public int getPixel(int x, int y) { checkRecycled("Can't call getPixel() on a recycled bitmap"); checkHardware("unable to getPixel(), " + "pixel access is not supported on Config#HARDWARE bitmaps"); checkPixelAccess(x, y); return nativeGetPixel(mNativePtr, x, y); }
Returns in pixels[] a copy of the data in the bitmap. Each value is a packed int representing a Color. The stride parameter allows the caller to allow for gaps in the returned pixels array between rows. For normal packed results, just pass width for the stride value. The returned colors are non-premultiplied ARGB values in the sRGB color space.
Params:
  • pixels – The array to receive the bitmap's colors
  • offset – The first index to write into pixels[]
  • stride – The number of entries in pixels[] to skip between rows (must be >= bitmap's width). Can be negative.
  • x – The x coordinate of the first pixel to read from the bitmap
  • y – The y coordinate of the first pixel to read from the bitmap
  • width – The number of pixels to read from each row
  • height – The number of rows to read
Throws:
/** * Returns in pixels[] a copy of the data in the bitmap. Each value is * a packed int representing a {@link Color}. The stride parameter allows * the caller to allow for gaps in the returned pixels array between * rows. For normal packed results, just pass width for the stride value. * The returned colors are non-premultiplied ARGB values in the * {@link ColorSpace.Named#SRGB sRGB} color space. * * @param pixels The array to receive the bitmap's colors * @param offset The first index to write into pixels[] * @param stride The number of entries in pixels[] to skip between * rows (must be >= bitmap's width). Can be negative. * @param x The x coordinate of the first pixel to read from * the bitmap * @param y The y coordinate of the first pixel to read from * the bitmap * @param width The number of pixels to read from each row * @param height The number of rows to read * * @throws IllegalArgumentException if x, y, width, height exceed the * bounds of the bitmap, or if abs(stride) < width. * @throws ArrayIndexOutOfBoundsException if the pixels array is too small * to receive the specified number of pixels. * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE} */
public void getPixels(@ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height) { checkRecycled("Can't call getPixels() on a recycled bitmap"); checkHardware("unable to getPixels(), " + "pixel access is not supported on Config#HARDWARE bitmaps"); if (width == 0 || height == 0) { return; // nothing to do } checkPixelsAccess(x, y, width, height, offset, stride, pixels); nativeGetPixels(mNativePtr, pixels, offset, stride, x, y, width, height); }
Shared code to check for illegal arguments passed to getPixel() or setPixel()
Params:
  • x – x coordinate of the pixel
  • y – y coordinate of the pixel
/** * Shared code to check for illegal arguments passed to getPixel() * or setPixel() * * @param x x coordinate of the pixel * @param y y coordinate of the pixel */
private void checkPixelAccess(int x, int y) { checkXYSign(x, y); if (x >= getWidth()) { throw new IllegalArgumentException("x must be < bitmap.width()"); } if (y >= getHeight()) { throw new IllegalArgumentException("y must be < bitmap.height()"); } }
Shared code to check for illegal arguments passed to getPixels() or setPixels()
Params:
  • x – left edge of the area of pixels to access
  • y – top edge of the area of pixels to access
  • width – width of the area of pixels to access
  • height – height of the area of pixels to access
  • offset – offset into pixels[] array
  • stride – number of elements in pixels[] between each logical row
  • pixels – array to hold the area of pixels being accessed
/** * Shared code to check for illegal arguments passed to getPixels() * or setPixels() * * @param x left edge of the area of pixels to access * @param y top edge of the area of pixels to access * @param width width of the area of pixels to access * @param height height of the area of pixels to access * @param offset offset into pixels[] array * @param stride number of elements in pixels[] between each logical row * @param pixels array to hold the area of pixels being accessed */
private void checkPixelsAccess(int x, int y, int width, int height, int offset, int stride, int pixels[]) { checkXYSign(x, y); if (width < 0) { throw new IllegalArgumentException("width must be >= 0"); } if (height < 0) { throw new IllegalArgumentException("height must be >= 0"); } if (x + width > getWidth()) { throw new IllegalArgumentException( "x + width must be <= bitmap.width()"); } if (y + height > getHeight()) { throw new IllegalArgumentException( "y + height must be <= bitmap.height()"); } if (Math.abs(stride) < width) { throw new IllegalArgumentException("abs(stride) must be >= width"); } int lastScanline = offset + (height - 1) * stride; int length = pixels.length; if (offset < 0 || (offset + width > length) || lastScanline < 0 || (lastScanline + width > length)) { throw new ArrayIndexOutOfBoundsException(); } }

Write the specified Color into the bitmap (assuming it is mutable) at the x,y coordinate. The color must be a non-premultiplied ARGB value in the sRGB color space.

Params:
  • x – The x coordinate of the pixel to replace (0...width-1)
  • y – The y coordinate of the pixel to replace (0...height-1)
  • color – The ARGB color to write into the bitmap
Throws:
/** * <p>Write the specified {@link Color} into the bitmap (assuming it is * mutable) at the x,y coordinate. The color must be a * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB} * color space.</p> * * @param x The x coordinate of the pixel to replace (0...width-1) * @param y The y coordinate of the pixel to replace (0...height-1) * @param color The ARGB color to write into the bitmap * * @throws IllegalStateException if the bitmap is not mutable * @throws IllegalArgumentException if x, y are outside of the bitmap's * bounds. */
public void setPixel(int x, int y, @ColorInt int color) { checkRecycled("Can't call setPixel() on a recycled bitmap"); if (!isMutable()) { throw new IllegalStateException(); } checkPixelAccess(x, y); nativeSetPixel(mNativePtr, x, y, color); }

Replace pixels in the bitmap with the colors in the array. Each element in the array is a packed int representing a non-premultiplied ARGB Color in the sRGB color space.

Params:
  • pixels – The colors to write to the bitmap
  • offset – The index of the first color to read from pixels[]
  • stride – The number of colors in pixels[] to skip between rows. Normally this value will be the same as the width of the bitmap, but it can be larger (or negative).
  • x – The x coordinate of the first pixel to write to in the bitmap.
  • y – The y coordinate of the first pixel to write to in the bitmap.
  • width – The number of colors to copy from pixels[] per row
  • height – The number of rows to write to the bitmap
Throws:
/** * <p>Replace pixels in the bitmap with the colors in the array. Each element * in the array is a packed int representing a non-premultiplied ARGB * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p> * * @param pixels The colors to write to the bitmap * @param offset The index of the first color to read from pixels[] * @param stride The number of colors in pixels[] to skip between rows. * Normally this value will be the same as the width of * the bitmap, but it can be larger (or negative). * @param x The x coordinate of the first pixel to write to in * the bitmap. * @param y The y coordinate of the first pixel to write to in * the bitmap. * @param width The number of colors to copy from pixels[] per row * @param height The number of rows to write to the bitmap * * @throws IllegalStateException if the bitmap is not mutable * @throws IllegalArgumentException if x, y, width, height are outside of * the bitmap's bounds. * @throws ArrayIndexOutOfBoundsException if the pixels array is too small * to receive the specified number of pixels. */
public void setPixels(@ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height) { checkRecycled("Can't call setPixels() on a recycled bitmap"); if (!isMutable()) { throw new IllegalStateException(); } if (width == 0 || height == 0) { return; // nothing to do } checkPixelsAccess(x, y, width, height, offset, stride, pixels); nativeSetPixels(mNativePtr, pixels, offset, stride, x, y, width, height); } public static final Parcelable.Creator<Bitmap> CREATOR = new Parcelable.Creator<Bitmap>() {
Rebuilds a bitmap previously stored with writeToParcel().
Params:
  • p – Parcel object to read the bitmap from
Returns:a new bitmap created from the data in the parcel
/** * Rebuilds a bitmap previously stored with writeToParcel(). * * @param p Parcel object to read the bitmap from * @return a new bitmap created from the data in the parcel */
public Bitmap createFromParcel(Parcel p) { Bitmap bm = nativeCreateFromParcel(p); if (bm == null) { throw new RuntimeException("Failed to unparcel Bitmap"); } return bm; } public Bitmap[] newArray(int size) { return new Bitmap[size]; } };
No special parcel contents.
/** * No special parcel contents. */
public int describeContents() { return 0; }
Write the bitmap and its pixels to the parcel. The bitmap can be rebuilt from the parcel by calling CREATOR.createFromParcel(). If this bitmap is Config.HARDWARE, it may be unparceled with a different pixel format (e.g. 565, 8888), but the content will be preserved to the best quality permitted by the final pixel format
Params:
  • p – Parcel object to write the bitmap data into
/** * Write the bitmap and its pixels to the parcel. The bitmap can be * rebuilt from the parcel by calling CREATOR.createFromParcel(). * * If this bitmap is {@link Config#HARDWARE}, it may be unparceled with a different pixel * format (e.g. 565, 8888), but the content will be preserved to the best quality permitted * by the final pixel format * @param p Parcel object to write the bitmap data into */
public void writeToParcel(Parcel p, int flags) { checkRecycled("Can't parcel a recycled bitmap"); noteHardwareBitmapSlowCall(); if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) { throw new RuntimeException("native writeToParcel failed"); } }
Returns a new bitmap that captures the alpha values of the original. This may be drawn with Canvas.drawBitmap(), where the color(s) will be taken from the paint that is passed to the draw call.
Returns:new bitmap containing the alpha channel of the original bitmap.
/** * Returns a new bitmap that captures the alpha values of the original. * This may be drawn with Canvas.drawBitmap(), where the color(s) will be * taken from the paint that is passed to the draw call. * * @return new bitmap containing the alpha channel of the original bitmap. */
@CheckResult public Bitmap extractAlpha() { return extractAlpha(null, null); }
Returns a new bitmap that captures the alpha values of the original. These values may be affected by the optional Paint parameter, which can contain its own alpha, and may also contain a MaskFilter which could change the actual dimensions of the resulting bitmap (e.g. a blur maskfilter might enlarge the resulting bitmap). If offsetXY is not null, it returns the amount to offset the returned bitmap so that it will logically align with the original. For example, if the paint contains a blur of radius 2, then offsetXY[] would contains -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then drawing the original would result in the blur visually aligning with the original.

The initial density of the returned bitmap is the same as the original's.

Params:
  • paint – Optional paint used to modify the alpha values in the resulting bitmap. Pass null for default behavior.
  • offsetXY – Optional array that returns the X (index 0) and Y (index 1) offset needed to position the returned bitmap so that it visually lines up with the original.
Returns:new bitmap containing the (optionally modified by paint) alpha channel of the original bitmap. This may be drawn with Canvas.drawBitmap(), where the color(s) will be taken from the paint that is passed to the draw call.
/** * Returns a new bitmap that captures the alpha values of the original. * These values may be affected by the optional Paint parameter, which * can contain its own alpha, and may also contain a MaskFilter which * could change the actual dimensions of the resulting bitmap (e.g. * a blur maskfilter might enlarge the resulting bitmap). If offsetXY * is not null, it returns the amount to offset the returned bitmap so * that it will logically align with the original. For example, if the * paint contains a blur of radius 2, then offsetXY[] would contains * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then * drawing the original would result in the blur visually aligning with * the original. * * <p>The initial density of the returned bitmap is the same as the original's. * * @param paint Optional paint used to modify the alpha values in the * resulting bitmap. Pass null for default behavior. * @param offsetXY Optional array that returns the X (index 0) and Y * (index 1) offset needed to position the returned bitmap * so that it visually lines up with the original. * @return new bitmap containing the (optionally modified by paint) alpha * channel of the original bitmap. This may be drawn with * Canvas.drawBitmap(), where the color(s) will be taken from the * paint that is passed to the draw call. */
@CheckResult public Bitmap extractAlpha(Paint paint, int[] offsetXY) { checkRecycled("Can't extractAlpha on a recycled bitmap"); long nativePaint = paint != null ? paint.getNativeInstance() : 0; noteHardwareBitmapSlowCall(); Bitmap bm = nativeExtractAlpha(mNativePtr, nativePaint, offsetXY); if (bm == null) { throw new RuntimeException("Failed to extractAlpha on Bitmap"); } bm.mDensity = mDensity; return bm; }
Given another bitmap, return true if it has the same dimensions, config, and pixel data as this bitmap. If any of those differ, return false. If other is null, return false.
/** * Given another bitmap, return true if it has the same dimensions, config, * and pixel data as this bitmap. If any of those differ, return false. * If other is null, return false. */
public boolean sameAs(Bitmap other) { checkRecycled("Can't call sameAs on a recycled bitmap!"); noteHardwareBitmapSlowCall(); if (this == other) return true; if (other == null) return false; other.noteHardwareBitmapSlowCall(); if (other.isRecycled()) { throw new IllegalArgumentException("Can't compare to a recycled bitmap!"); } return nativeSameAs(mNativePtr, other.mNativePtr); }
Builds caches associated with the bitmap that are used for drawing it.

Starting in VERSION_CODES.N, this call initiates an asynchronous upload to the GPU on RenderThread, if the Bitmap is not already uploaded. With Hardware Acceleration, Bitmaps must be uploaded to the GPU in order to be rendered. This is done by default the first time a Bitmap is drawn, but the process can take several milliseconds, depending on the size of the Bitmap. Each time a Bitmap is modified and drawn again, it must be re-uploaded.

Calling this method in advance can save time in the first frame it's used. For example, it is recommended to call this on an image decoding worker thread when a decoded Bitmap is about to be displayed. It is recommended to make any pre-draw modifications to the Bitmap before calling this method, so the cached, uploaded copy may be reused without re-uploading.

In VERSION_CODES.KITKAT and below, for purgeable bitmaps, this call would attempt to ensure that the pixels have been decoded.
/** * Builds caches associated with the bitmap that are used for drawing it. * * <p>Starting in {@link android.os.Build.VERSION_CODES#N}, this call initiates an asynchronous * upload to the GPU on RenderThread, if the Bitmap is not already uploaded. With Hardware * Acceleration, Bitmaps must be uploaded to the GPU in order to be rendered. This is done by * default the first time a Bitmap is drawn, but the process can take several milliseconds, * depending on the size of the Bitmap. Each time a Bitmap is modified and drawn again, it must * be re-uploaded.</p> * * <p>Calling this method in advance can save time in the first frame it's used. For example, it * is recommended to call this on an image decoding worker thread when a decoded Bitmap is about * to be displayed. It is recommended to make any pre-draw modifications to the Bitmap before * calling this method, so the cached, uploaded copy may be reused without re-uploading.</p> * * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, for purgeable bitmaps, this call * would attempt to ensure that the pixels have been decoded. */
public void prepareToDraw() { checkRecycled("Can't prepareToDraw on a recycled bitmap!"); // Kick off an update/upload of the bitmap outside of the normal // draw path. nativePrepareToDraw(mNativePtr); }
Returns:GraphicBuffer which is internally used by hardware bitmap
@hide
/** * * @return {@link GraphicBuffer} which is internally used by hardware bitmap * @hide */
public GraphicBuffer createGraphicBufferHandle() { return nativeCreateGraphicBufferHandle(mNativePtr); } //////////// native methods private static native Bitmap nativeCreate(int[] colors, int offset, int stride, int width, int height, int nativeConfig, boolean mutable, @Nullable @Size(9) float[] xyzD50, @Nullable ColorSpace.Rgb.TransferParameters p); private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig, boolean isMutable); private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap); private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig); private static native long nativeGetNativeFinalizer(); private static native boolean nativeRecycle(long nativeBitmap); private static native void nativeReconfigure(long nativeBitmap, int width, int height, int config, boolean isPremultiplied); private static native boolean nativeCompress(long nativeBitmap, int format, int quality, OutputStream stream, byte[] tempStorage); private static native void nativeErase(long nativeBitmap, int color); private static native int nativeRowBytes(long nativeBitmap); private static native int nativeConfig(long nativeBitmap); private static native int nativeGetPixel(long nativeBitmap, int x, int y); private static native void nativeGetPixels(long nativeBitmap, int[] pixels, int offset, int stride, int x, int y, int width, int height); private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color); private static native void nativeSetPixels(long nativeBitmap, int[] colors, int offset, int stride, int x, int y, int width, int height); private static native void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst); private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src); private static native int nativeGenerationId(long nativeBitmap); private static native Bitmap nativeCreateFromParcel(Parcel p); // returns true on success private static native boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable, int density, Parcel p); // returns a new bitmap built from the native bitmap's alpha, and the paint private static native Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint, int[] offsetXY); private static native boolean nativeHasAlpha(long nativeBitmap); private static native boolean nativeIsPremultiplied(long nativeBitmap); private static native void nativeSetPremultiplied(long nativeBitmap, boolean isPremul); private static native void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha, boolean requestPremul); private static native boolean nativeHasMipMap(long nativeBitmap); private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap); private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1); private static native void nativePrepareToDraw(long nativeBitmap); private static native int nativeGetAllocationByteCount(long nativeBitmap); private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap); private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer); private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap); private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params); private static native boolean nativeIsSRGB(long nativePtr); private static native boolean nativeIsSRGBLinear(long nativePtr); private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap); }