Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8633,6 +8633,7 @@ package android.graphics { method public void eraseColor(int); method public android.graphics.Bitmap extractAlpha(); method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]); method public final int getAllocationByteCount(); method public final int getByteCount(); method public final android.graphics.Bitmap.Config getConfig(); method public int getDensity(); core/jni/android/graphics/BitmapFactory.cpp +23 −5 Original line number Diff line number Diff line Loading @@ -211,19 +211,17 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, SkBitmap* bitmap; bool useExistingBitmap = false; unsigned int existingBufferSize = 0; if (javaBitmap == NULL) { bitmap = new SkBitmap; } else { if (sampleSize != 1) { return nullObjectReturn("SkImageDecoder: Cannot reuse bitmap with sampleSize != 1"); } bitmap = (SkBitmap*) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID); // only reuse the provided bitmap if it is immutable // only reuse the provided bitmap if it is mutable if (!bitmap->isImmutable()) { useExistingBitmap = true; // config of supplied bitmap overrules config set in options prefConfig = bitmap->getConfig(); existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap); } else { ALOGW("Unable to reuse an immutable bitmap as an image decoder target."); bitmap = new SkBitmap; Loading Loading @@ -252,6 +250,26 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decodeMode = SkImageDecoder::kDecodeBounds_Mode; } if (javaBitmap != NULL) { // If we're reusing the pixelref from an existing bitmap, decode the bounds and // reinitialize the native object for the new content, keeping the pixelRef SkPixelRef* pixelRef = bitmap->pixelRef(); SkSafeRef(pixelRef); SkBitmap boundsBitmap; decoder->decode(stream, &boundsBitmap, prefConfig, SkImageDecoder::kDecodeBounds_Mode); stream->rewind(); if (boundsBitmap.getSize() > existingBufferSize) { return nullObjectReturn("bitmap marked for reuse too small to contain decoded data"); } bitmap->setConfig(boundsBitmap.config(), boundsBitmap.width(), boundsBitmap.height(), 0); bitmap->setPixelRef(pixelRef); SkSafeUnref(pixelRef); GraphicsJNI::reinitBitmap(env, javaBitmap); } SkBitmap* decoded; if (willScale) { decoded = new SkBitmap; Loading core/jni/android/graphics/Graphics.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,8 @@ static jfieldID gPointF_yFieldID; static jclass gBitmap_class; static jfieldID gBitmap_nativeInstanceID; static jmethodID gBitmap_constructorMethodID; static jmethodID gBitmap_reinitMethodID; static jmethodID gBitmap_getAllocationByteCountMethodID; static jclass gBitmapConfig_class; static jfieldID gBitmapConfig_nativeInstanceID; Loading Loading @@ -363,6 +365,15 @@ jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density); } void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap) { env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID); } int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) { return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID); } jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) { Loading Loading @@ -584,6 +595,8 @@ int register_android_graphics_Graphics(JNIEnv* env) gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I"); gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(I[BZ[B[II)V"); gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "()V"); gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I"); gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V"); Loading core/jni/android/graphics/GraphicsJNI.h +4 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public: static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, jbyteArray ninepatch, int density = -1); static void reinitBitmap(JNIEnv* env, jobject javaBitmap); static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap); static jobject createRegion(JNIEnv* env, SkRegion* region); static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap); Loading graphics/java/android/graphics/Bitmap.java +38 −14 Original line number Diff line number Diff line Loading @@ -85,26 +85,20 @@ public final class Bitmap implements Parcelable { } /** * @noinspection UnusedDeclaration */ /* Private constructor that must received an already allocated native bitmap int (pointer). This can be called from JNI code. * Private constructor that must received an already allocated native * bitmap int (pointer). */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk, int density) { this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density); } /** * @noinspection UnusedDeclaration */ /* Private constructor that must received an already allocated native bitmap int (pointer). This can be called from JNI code. * Private constructor that must received an already allocated native bitmap * int (pointer). */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk, int[] layoutBounds, int density) { if (nativeBitmap == 0) { Loading @@ -124,6 +118,14 @@ public final class Bitmap implements Parcelable { } } /** * Native bitmap has been reconfigured, so discard cached width/height */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI void reinit() { mWidth = mHeight = -1; } /** * <p>Returns the density for this bitmap.</p> * Loading Loading @@ -454,7 +456,7 @@ public final class Bitmap implements Parcelable { /** * 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 btimap, the source bitmap is returned and now new bitmap is * the source bitmap, the source bitmap is returned and no new bitmap is * created. * * @param src The source bitmap. Loading Loading @@ -989,6 +991,10 @@ public final class Bitmap implements Parcelable { * 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#KEY_LIME_PIE}, 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() { Loading @@ -996,13 +1002,31 @@ public final class Bitmap implements Parcelable { } /** * Returns the number of bytes used to store this bitmap's pixels. * 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#KEY_LIME_PIE}, the result of this method can * no longer be used to determine memory usage of a bitmap. See {@link * #getAllocationByteCount()}. */ public final int getByteCount() { // 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. * * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to * decode other bitmaps of smaller size. See {@link BitmapFactory.Options#inBitmap inBitmap in * BitmapFactory.Options}. If a bitmap is not reused in this way, this value will be the same as * that returned by {@link #getByteCount()}. * * <p>This value will not change over the lifetime of a Bitmap. */ public final int getAllocationByteCount() { return mBuffer.length; } /** * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8633,6 +8633,7 @@ package android.graphics { method public void eraseColor(int); method public android.graphics.Bitmap extractAlpha(); method public android.graphics.Bitmap extractAlpha(android.graphics.Paint, int[]); method public final int getAllocationByteCount(); method public final int getByteCount(); method public final android.graphics.Bitmap.Config getConfig(); method public int getDensity();
core/jni/android/graphics/BitmapFactory.cpp +23 −5 Original line number Diff line number Diff line Loading @@ -211,19 +211,17 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, SkBitmap* bitmap; bool useExistingBitmap = false; unsigned int existingBufferSize = 0; if (javaBitmap == NULL) { bitmap = new SkBitmap; } else { if (sampleSize != 1) { return nullObjectReturn("SkImageDecoder: Cannot reuse bitmap with sampleSize != 1"); } bitmap = (SkBitmap*) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID); // only reuse the provided bitmap if it is immutable // only reuse the provided bitmap if it is mutable if (!bitmap->isImmutable()) { useExistingBitmap = true; // config of supplied bitmap overrules config set in options prefConfig = bitmap->getConfig(); existingBufferSize = GraphicsJNI::getBitmapAllocationByteCount(env, javaBitmap); } else { ALOGW("Unable to reuse an immutable bitmap as an image decoder target."); bitmap = new SkBitmap; Loading Loading @@ -252,6 +250,26 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decodeMode = SkImageDecoder::kDecodeBounds_Mode; } if (javaBitmap != NULL) { // If we're reusing the pixelref from an existing bitmap, decode the bounds and // reinitialize the native object for the new content, keeping the pixelRef SkPixelRef* pixelRef = bitmap->pixelRef(); SkSafeRef(pixelRef); SkBitmap boundsBitmap; decoder->decode(stream, &boundsBitmap, prefConfig, SkImageDecoder::kDecodeBounds_Mode); stream->rewind(); if (boundsBitmap.getSize() > existingBufferSize) { return nullObjectReturn("bitmap marked for reuse too small to contain decoded data"); } bitmap->setConfig(boundsBitmap.config(), boundsBitmap.width(), boundsBitmap.height(), 0); bitmap->setPixelRef(pixelRef); SkSafeUnref(pixelRef); GraphicsJNI::reinitBitmap(env, javaBitmap); } SkBitmap* decoded; if (willScale) { decoded = new SkBitmap; Loading
core/jni/android/graphics/Graphics.cpp +13 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,8 @@ static jfieldID gPointF_yFieldID; static jclass gBitmap_class; static jfieldID gBitmap_nativeInstanceID; static jmethodID gBitmap_constructorMethodID; static jmethodID gBitmap_reinitMethodID; static jmethodID gBitmap_getAllocationByteCountMethodID; static jclass gBitmapConfig_class; static jfieldID gBitmapConfig_nativeInstanceID; Loading Loading @@ -363,6 +365,15 @@ jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density); } void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap) { env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID); } int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) { return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID); } jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) { Loading Loading @@ -584,6 +595,8 @@ int register_android_graphics_Graphics(JNIEnv* env) gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I"); gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(I[BZ[B[II)V"); gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "()V"); gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I"); gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V"); Loading
core/jni/android/graphics/GraphicsJNI.h +4 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public: static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, jbyteArray ninepatch, int density = -1); static void reinitBitmap(JNIEnv* env, jobject javaBitmap); static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap); static jobject createRegion(JNIEnv* env, SkRegion* region); static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap); Loading
graphics/java/android/graphics/Bitmap.java +38 −14 Original line number Diff line number Diff line Loading @@ -85,26 +85,20 @@ public final class Bitmap implements Parcelable { } /** * @noinspection UnusedDeclaration */ /* Private constructor that must received an already allocated native bitmap int (pointer). This can be called from JNI code. * Private constructor that must received an already allocated native * bitmap int (pointer). */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk, int density) { this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density); } /** * @noinspection UnusedDeclaration */ /* Private constructor that must received an already allocated native bitmap int (pointer). This can be called from JNI code. * Private constructor that must received an already allocated native bitmap * int (pointer). */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk, int[] layoutBounds, int density) { if (nativeBitmap == 0) { Loading @@ -124,6 +118,14 @@ public final class Bitmap implements Parcelable { } } /** * Native bitmap has been reconfigured, so discard cached width/height */ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI void reinit() { mWidth = mHeight = -1; } /** * <p>Returns the density for this bitmap.</p> * Loading Loading @@ -454,7 +456,7 @@ public final class Bitmap implements Parcelable { /** * 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 btimap, the source bitmap is returned and now new bitmap is * the source bitmap, the source bitmap is returned and no new bitmap is * created. * * @param src The source bitmap. Loading Loading @@ -989,6 +991,10 @@ public final class Bitmap implements Parcelable { * 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#KEY_LIME_PIE}, 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() { Loading @@ -996,13 +1002,31 @@ public final class Bitmap implements Parcelable { } /** * Returns the number of bytes used to store this bitmap's pixels. * 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#KEY_LIME_PIE}, the result of this method can * no longer be used to determine memory usage of a bitmap. See {@link * #getAllocationByteCount()}. */ public final int getByteCount() { // 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. * * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to * decode other bitmaps of smaller size. See {@link BitmapFactory.Options#inBitmap inBitmap in * BitmapFactory.Options}. If a bitmap is not reused in this way, this value will be the same as * that returned by {@link #getByteCount()}. * * <p>This value will not change over the lifetime of a Bitmap. */ public final int getAllocationByteCount() { return mBuffer.length; } /** * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. Loading