Skip to content

Commit 3849f93

Browse files
author
Romain Guy
committed
Add Bitmap.isPremultiplied()
This change also adds extra information in the documentation about premultiplied values. Change-Id: I51aacb8696340d23354ebf6d7284605d1a790b69
1 parent 9c469ca commit 3849f93

File tree

2 files changed

+48
-18
lines changed

2 files changed

+48
-18
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8121,6 +8121,7 @@ package android.graphics {
81218121
method public final int getWidth();
81228122
method public final boolean hasAlpha();
81238123
method public final boolean isMutable();
8124+
method public final boolean isPremultiplied();
81248125
method public final boolean isRecycled();
81258126
method public void prepareToDraw();
81268127
method public void recycle();

graphics/java/android/graphics/Bitmap.java

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.nio.ShortBuffer;
2828

2929
public final class Bitmap implements Parcelable {
30-
3130
/**
3231
* Indicates that the bitmap was created for an unknown pixel density.
3332
*
@@ -64,7 +63,7 @@ public final class Bitmap implements Parcelable {
6463
private boolean mRecycled;
6564

6665
// Package-scoped for fast access.
67-
/*package*/ int mDensity = sDefaultDensity = getDefaultDensity();
66+
int mDensity = sDefaultDensity = getDefaultDensity();
6867

6968
private static volatile Matrix sScaleMatrix;
7069

@@ -78,8 +77,8 @@ public final class Bitmap implements Parcelable {
7877
public static void setDefaultDensity(int density) {
7978
sDefaultDensity = density;
8079
}
81-
82-
/*package*/ static int getDefaultDensity() {
80+
81+
static int getDefaultDensity() {
8382
if (sDefaultDensity >= 0) {
8483
return sDefaultDensity;
8584
}
@@ -95,7 +94,7 @@ bitmap int (pointer).
9594
9695
This can be called from JNI code.
9796
*/
98-
/*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
97+
Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
9998
int density) {
10099
this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
101100
}
@@ -108,7 +107,7 @@ bitmap int (pointer).
108107
109108
This can be called from JNI code.
110109
*/
111-
/*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
110+
Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
112111
int[] layoutBounds, int density) {
113112
if (nativeBitmap == 0) {
114113
throw new RuntimeException("internal error: native bitmap is 0");
@@ -347,11 +346,15 @@ static Config nativeToConfig(int ni) {
347346
}
348347

349348
/**
350-
* Copy the bitmap's pixels into the specified buffer (allocated by the
349+
* <p>Copy the bitmap's pixels into the specified buffer (allocated by the
351350
* caller). An exception is thrown if the buffer is not large enough to
352351
* hold all of the pixels (taking into account the number of bytes per
353352
* pixel) or if the Buffer subclass is not one of the support types
354-
* (ByteBuffer, ShortBuffer, IntBuffer).
353+
* (ByteBuffer, ShortBuffer, IntBuffer).</p>
354+
* <p>The content of the bitmap is copied into the buffer as-is. This means
355+
* that if this bitmap stores its pixels pre-multiplied
356+
* (see {@link #isPremultiplied()}, the values in the buffer will also be
357+
* pre-multiplied.</p>
355358
*/
356359
public void copyPixelsToBuffer(Buffer dst) {
357360
int elements = dst.remaining();
@@ -382,10 +385,10 @@ public void copyPixelsToBuffer(Buffer dst) {
382385
}
383386

384387
/**
385-
* Copy the pixels from the buffer, beginning at the current position,
388+
* <p>Copy the pixels from the buffer, beginning at the current position,
386389
* overwriting the bitmap's pixels. The data in the buffer is not changed
387390
* in any way (unlike setPixels(), which converts from unpremultipled 32bit
388-
* to whatever the bitmap's native format is.
391+
* to whatever the bitmap's native format is.</p>
389392
*/
390393
public void copyPixelsFromBuffer(Buffer src) {
391394
checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
@@ -402,7 +405,7 @@ public void copyPixelsFromBuffer(Buffer src) {
402405
throw new RuntimeException("unsupported Buffer subclass");
403406
}
404407

405-
long bufferBytes = (long)elements << shift;
408+
long bufferBytes = (long) elements << shift;
406409
long bitmapBytes = getByteCount();
407410

408411
if (bufferBytes < bitmapBytes) {
@@ -780,6 +783,25 @@ public final boolean isMutable() {
780783
return mIsMutable;
781784
}
782785

786+
/**
787+
* <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
788+
* When a pixel is pre-multiplied, the RGB components have been multiplied by
789+
* the alpha component. For instance, if the original color is a 50%
790+
* translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
791+
* <code>(128, 128, 0, 0)</code>.</p>
792+
*
793+
* <p>This method always returns false if {@link #getConfig()} is
794+
* {@link Bitmap.Config#ALPHA_8} or {@link Bitmap.Config#RGB_565}.</p>
795+
*
796+
* @return true if the underlying pixels have been pre-multiplied, false
797+
* otherwise
798+
*/
799+
public final boolean isPremultiplied() {
800+
final Config config = getConfig();
801+
//noinspection deprecation
802+
return config == Config.ARGB_8888 || config == Config.ARGB_4444;
803+
}
804+
783805
/** Returns the bitmap's width */
784806
public final int getWidth() {
785807
return mWidth == -1 ? mWidth = nativeWidth(mNativeBitmap) : mWidth;
@@ -926,7 +948,7 @@ public void eraseColor(int c) {
926948
/**
927949
* Returns the {@link Color} at the specified location. Throws an exception
928950
* if x or y are out of bounds (negative or >= to the width or height
929-
* respectively).
951+
* respectively). The returned color is a non-premultiplied ARGB value.
930952
*
931953
* @param x The x coordinate (0...width-1) of the pixel to return
932954
* @param y The y coordinate (0...height-1) of the pixel to return
@@ -944,6 +966,7 @@ public int getPixel(int x, int y) {
944966
* a packed int representing a {@link Color}. The stride parameter allows
945967
* the caller to allow for gaps in the returned pixels array between
946968
* rows. For normal packed results, just pass width for the stride value.
969+
* The returned colors are non-premultiplied ARGB values.
947970
*
948971
* @param pixels The array to receive the bitmap's colors
949972
* @param offset The first index to write into pixels[]
@@ -955,6 +978,7 @@ public int getPixel(int x, int y) {
955978
* the bitmap
956979
* @param width The number of pixels to read from each row
957980
* @param height The number of rows to read
981+
*
958982
* @throws IllegalArgumentException if x, y, width, height exceed the
959983
* bounds of the bitmap, or if abs(stride) < width.
960984
* @throws ArrayIndexOutOfBoundsException if the pixels array is too small
@@ -974,6 +998,7 @@ public void getPixels(int[] pixels, int offset, int stride,
974998
/**
975999
* Shared code to check for illegal arguments passed to getPixel()
9761000
* or setPixel()
1001+
*
9771002
* @param x x coordinate of the pixel
9781003
* @param y y coordinate of the pixel
9791004
*/
@@ -1029,12 +1054,14 @@ private void checkPixelsAccess(int x, int y, int width, int height,
10291054
}
10301055

10311056
/**
1032-
* Write the specified {@link Color} into the bitmap (assuming it is
1033-
* mutable) at the x,y coordinate.
1057+
* <p>Write the specified {@link Color} into the bitmap (assuming it is
1058+
* mutable) at the x,y coordinate. The color must be a
1059+
* non-premultiplied ARGB value.</p>
10341060
*
10351061
* @param x The x coordinate of the pixel to replace (0...width-1)
10361062
* @param y The y coordinate of the pixel to replace (0...height-1)
1037-
* @param color The {@link Color} to write into the bitmap
1063+
* @param color The ARGB color to write into the bitmap
1064+
*
10381065
* @throws IllegalStateException if the bitmap is not mutable
10391066
* @throws IllegalArgumentException if x, y are outside of the bitmap's
10401067
* bounds.
@@ -1049,8 +1076,9 @@ public void setPixel(int x, int y, int color) {
10491076
}
10501077

10511078
/**
1052-
* Replace pixels in the bitmap with the colors in the array. Each element
1053-
* in the array is a packed int prepresenting a {@link Color}
1079+
* <p>Replace pixels in the bitmap with the colors in the array. Each element
1080+
* in the array is a packed int prepresenting a non-premultiplied ARGB
1081+
* {@link Color}.</p>
10541082
*
10551083
* @param pixels The colors to write to the bitmap
10561084
* @param offset The index of the first color to read from pixels[]
@@ -1063,14 +1091,15 @@ public void setPixel(int x, int y, int color) {
10631091
* the bitmap.
10641092
* @param width The number of colors to copy from pixels[] per row
10651093
* @param height The number of rows to write to the bitmap
1094+
*
10661095
* @throws IllegalStateException if the bitmap is not mutable
10671096
* @throws IllegalArgumentException if x, y, width, height are outside of
10681097
* the bitmap's bounds.
10691098
* @throws ArrayIndexOutOfBoundsException if the pixels array is too small
10701099
* to receive the specified number of pixels.
10711100
*/
10721101
public void setPixels(int[] pixels, int offset, int stride,
1073-
int x, int y, int width, int height) {
1102+
int x, int y, int width, int height) {
10741103
checkRecycled("Can't call setPixels() on a recycled bitmap");
10751104
if (!isMutable()) {
10761105
throw new IllegalStateException();

0 commit comments

Comments
 (0)