问题
Create a bitmap using Bitmap.create(25, 25, Config.ARGB_8888)
Setting a pixel with an alpha value less than or equal to 0xA9 results in the pixel not being set with what's passed in. I read another stack overflow question saying to setHasAlpha(true), which I did in my test -- but that still didn't fix the issue.
Here's my android test case showing my issue:
public void testSettingBitmaps() {
Bitmap bitmap = Bitmap.createBitmap(25, 25, Config.ARGB_8888);
bitmap.setHasAlpha(true);
int color = 0x00fefefe;
int x= 0;
int y = 0;
for(int alpha = 0xFF000000; alpha != 0x00000000; alpha = alpha - 0x01000000) {
int colorPlusAlpha = color + alpha;
bitmap.setPixel(x, y, colorPlusAlpha);
//
// This test succeeds if the bitmap let us set the pixel.
//
assertEquals(String.format("Current alpha value: %x, Expected pixel value: %x, Actual pixel value: %x", alpha, colorPlusAlpha, bitmap.getPixel(x, y)),
colorPlusAlpha, bitmap.getPixel(x, y));
}
}
This code fails with the following output:junit.framework.AssertionFailedError: Current alpha value: a9000000, Expected pixel value: a9fefefe, Actual pixel value: a9fdfdfd expected:<-1442906370> but was:<-1442972163>
回答1:
This actually works as intended.
The problem is that Bitmaps are stored in premultiplied alpha format. This means that when you set a pixel value to 0xa9fefefe, the stored value is actually 0xa9a8a8a8 (0xa9*0xfe/255=0xa8.) Then when you call getPixel(), the stored value is "un-premultiplied." With rounding errors you get 0xa9fdfdfd.
Here is a breakdown, you pass an ARGB value of 0xa9fefefe. Each RGB byte will be multiplied by the alpha value before being stored. To simplify we'll look at the red byte only:
R=169*254/255 R=168 (or 0xa8)
Then when you call getPixel(), the RGB bytes are divided by the alpha:
R=255*168/169 R=253 (or 0xfd)
来源:https://stackoverflow.com/questions/13794029/android-bitmap-setpixelx-y-color-is-setting-passed-in-value