summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--core/jni/android/graphics/Bitmap.cpp21
-rw-r--r--graphics/java/android/graphics/Bitmap.java111
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java46
4 files changed, 155 insertions, 27 deletions
diff --git a/api/current.txt b/api/current.txt
index 201dc58a8fa3..8d03c37a3a42 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8742,13 +8742,17 @@ package android.graphics {
method public final boolean isPremultiplied();
method public final boolean isRecycled();
method public void prepareToDraw();
+ method public void reconfigure(int, int, android.graphics.Bitmap.Config);
method public void recycle();
method public boolean sameAs(android.graphics.Bitmap);
+ method public void setConfig(android.graphics.Bitmap.Config);
method public void setDensity(int);
method public void setHasAlpha(boolean);
method public final void setHasMipMap(boolean);
+ method public void setHeight(int);
method public void setPixel(int, int, int);
method public void setPixels(int[], int, int, int, int, int, int);
+ method public void setWidth(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DENSITY_NONE = 0; // 0x0
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 63683b4f4954..b03d12aa2057 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -271,6 +271,26 @@ static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
return true;
}
+static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jint bitmapInt,
+ int width, int height, SkBitmap::Config config, int allocSize) {
+ if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
+ // done in native as there's no way to get BytesPerPixel in Java
+ doThrowIAE(env, "Bitmap not large enough to support new configuration");
+ return;
+ }
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapInt);
+ SkPixelRef* ref = bitmap->pixelRef();
+ SkSafeRef(ref);
+ bitmap->setConfig(config, width, height);
+ bitmap->setPixelRef(ref);
+
+ // notifyPixelsChanged will increment the generation ID even though the actual pixel data
+ // hasn't been touched. This signals the renderer that the bitmap (including width, height,
+ // and config) has changed.
+ ref->notifyPixelsChanged();
+ SkSafeUnref(ref);
+}
+
// These must match the int values in Bitmap.java
enum JavaEncodeFormat {
kJPEG_JavaEncodeFormat = 0,
@@ -666,6 +686,7 @@ static JNINativeMethod gBitmapMethods[] = {
(void*)Bitmap_copy },
{ "nativeDestructor", "(I)V", (void*)Bitmap_destructor },
{ "nativeRecycle", "(I)Z", (void*)Bitmap_recycle },
+ { "nativeReconfigure", "(IIIII)V", (void*)Bitmap_reconfigure },
{ "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
(void*)Bitmap_compress },
{ "nativeErase", "(II)V", (void*)Bitmap_erase },
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 50231da8f17c..ad5bfc8007fb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -170,7 +170,98 @@ public final class Bitmap implements Parcelable {
public void setDensity(int density) {
mDensity = density;
}
-
+
+ /**
+ * <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>WARNING: This method should NOT be called on a bitmap currently used
+ * by the view system. 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>
+ *
+ * @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 IllegalArgumentException("only mutable bitmaps may be reconfigured");
+ }
+ if (mBuffer == null) {
+ throw new IllegalArgumentException("only non-inPurgeable bitmaps may be reconfigured");
+ }
+
+ nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length);
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * <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());
+ }
+
+ /**
+ * <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());
+ }
+
+ /**
+ * <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.
*
@@ -1010,7 +1101,7 @@ public final class Bitmap implements Parcelable {
*
* <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()}.
+ * #getAllocationByteCount()}.</p>
*/
public final int getByteCount() {
// int result permits bitmaps up to 46,340 x 46,340
@@ -1021,11 +1112,15 @@ public final class Bitmap implements Parcelable {
* 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()}.
+ * 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>
*
- * <p>This value will not change over the lifetime of a Bitmap.
+ * @see #reconfigure(int, int, Config)
*/
public final int getAllocationByteCount() {
return mBuffer.length;
@@ -1423,11 +1518,13 @@ public final class Bitmap implements Parcelable {
private static native Bitmap nativeCreate(int[] colors, int offset,
int stride, int width, int height,
- int nativeConfig, boolean mutable);
+ int nativeConfig, boolean mutable);
private static native Bitmap nativeCopy(int srcBitmap, int nativeConfig,
boolean isMutable);
private static native void nativeDestructor(int nativeBitmap);
private static native boolean nativeRecycle(int nativeBitmap);
+ private static native void nativeReconfigure(int nativeBitmap, int width, int height,
+ int config, int allocSize);
private static native boolean nativeCompress(int nativeBitmap, int format,
int quality, OutputStream stream,
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index aff4cd8b9c6a..a4124bfc8481 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -48,34 +48,40 @@ public class BitmapFactory {
/**
* If set, decode methods that take the Options object will attempt to
- * reuse this bitmap when loading content. If the decode operation cannot
- * use this bitmap, the decode method will return <code>null</code> and
- * will throw an IllegalArgumentException. The current implementation
- * necessitates that the reused bitmap be mutable, and the resulting
- * reused bitmap will continue to remain mutable even when decoding a
- * resource which would normally result in an immutable bitmap.
+ * reuse this bitmap when loading content. If the decode operation
+ * cannot use this bitmap, the decode method will return
+ * <code>null</code> and will throw an IllegalArgumentException. The
+ * current implementation necessitates that the reused bitmap be
+ * mutable, and the resulting reused bitmap will continue to remain
+ * mutable even when decoding a resource which would normally result in
+ * an immutable bitmap.</p>
*
- * <p>As of {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, any mutable
- * bitmap can be reused to decode any other bitmaps as long as the resulting
- * {@link Bitmap#getByteCount() byte count} of the decoded bitmap is less
- * than or equal to the {@link Bitmap#getAllocationByteCount() allocated byte count}
- * of the reused bitmap. This can be because the intrinsic size is smaller,
- * or the size after density / sampled size scaling is smaller.
+ * <p>As of {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}, any
+ * mutable bitmap can be reused to decode any other bitmaps as long as
+ * the resulting {@link Bitmap#getByteCount() byte count} of the decoded
+ * bitmap is less than or equal to the {@link
+ * Bitmap#getAllocationByteCount() allocated byte count} of the reused
+ * bitmap. This can be because the intrinsic size is smaller, or its
+ * size post scaling (for density / sample size) is smaller.</p>
*
- * <p>Prior to {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE} additional
- * constraints apply: The image being decoded (whether as a resource or
- * as a stream) must be in jpeg or png format. Only equal sized bitmaps
- * are supported, with {@link #inSampleSize} set to 1. Additionally, the
- * {@link android.graphics.Bitmap.Config configuration} of the reused
- * bitmap will override the setting of {@link #inPreferredConfig}, if set.
+ * <p>Prior to {@link android.os.Build.VERSION_CODES#KEY_LIME_PIE}
+ * additional constraints apply: The image being decoded (whether as a
+ * resource or as a stream) must be in jpeg or png format. Only equal
+ * sized bitmaps are supported, with {@link #inSampleSize} set to 1.
+ * Additionally, the {@link android.graphics.Bitmap.Config
+ * configuration} of the reused bitmap will override the setting of
+ * {@link #inPreferredConfig}, if set.</p>
*
* <p>You should still always use the returned Bitmap of the decode
* method and not assume that reusing the bitmap worked, due to the
* constraints outlined above and failure situations that can occur.
* Checking whether the return value matches the value of the inBitmap
* set in the Options structure will indicate if the bitmap was reused,
- * but in all cases you should use the Bitmap returned by the decoding function to ensure
- * that you are using the bitmap that was used as the decode destination.</p>
+ * but in all cases you should use the Bitmap returned by the decoding
+ * function to ensure that you are using the bitmap that was used as the
+ * decode destination.</p>
+ *
+ * @see Bitmap#reconfigure(int,int,Config)
*/
public Bitmap inBitmap;