java setpixel_java – Bitmap中的像素值困惑(使用setPixel预乘色)

在Java中使用Bitmap的setPixel方法设置像素时遇到问题,尤其是在(0,0)位置的像素值不正确。经过调试发现,问题可能与预乘Alpha有关,当设置特定的Alpha值时,会出现不期望的结果。通过进一步测试,发现在某些Alpha值范围内,像素值会发生变化,这可能与预乘Alpha导致的颜色信息损失和舍入误差有关。" 107446518,9898456,Vue.js初学者教程:创建与指令解析,"['Vue.js', 'javascript', '前端开发']
摘要由CSDN通过智能技术生成

我无法解释这一点(来自

Eclipse调试的截图):

(0,0)处的像素没有为其设置的值!

所有其他像素都很好,它们具有相同的值.

编辑

我做了一些挖掘,setPixel的代码调用了一个本机函数:

1391 public void setPixel(int x, int y, int color) {

1392 checkRecycled("Can't call setPixel() on a recycled bitmap");

1393 if (!isMutable()) {

1394 throw new IllegalStateException();

1395 }

1396 checkPixelAccess(x, y);

1397 nativeSetPixel(mNativeBitmap, x, y, color, mIsPremultiplied);

1398 }

所以我用不同的值运行setPixel(0,0),从setPixel(0,1)的OK值开始.

首先,我只改变了其中一个论点.结论是阿尔法值是罪魁祸首,但不确定如何.我尝试了很多其他alpha值,似乎在0xB0左右,结果回来了.

我在其他像素上尝试了相同的值,问题不依赖于像素坐标,对其他像素也是如此.这个问题似乎与数据有关.

source.setPixel(0, 0, Color.argb(0x40, 0x1A, 0x11, 0x12));

int sp00 = source.getPixel(0, 0); // sp00 1075580948 [0x401c1014] BAD

source.setPixel(0, 0, Color.argb(0xFE, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -16781602 [0xfeffeede] OK!

source.setPixel(0, 0, Color.argb(0x40, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 1090514911 [0x40ffefdf] BAD

source.setPixel(0, 0, Color.argb(0xFE, 0x1A, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -31789346 [0xfe1aeede] OK!

source.setPixel(0, 0, Color.argb(0xFE, 0xFF, 0x11, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -16838178 [0xfeff11de] OK!

source.setPixel(0, 0, Color.argb(0xFE, 0xFF, 0xEE, 0x12));

sp00 = source.getPixel(0, 0); // sp00 -16781806 [0xfeffee12] OK!

source.setPixel(0, 0, Color.argb(0x00, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 0 [0x0] Strange, why Color has to police the alpha value?

source.setPixel(0, 0, Color.argb(0x10, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 285208543 [0x10ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x20, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 553643999 [0x20ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x30, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 822079455 [0x30ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x50, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 1358950367 [0x50ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x60, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 1627385823 [0x60ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x70, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 1895821279 [0x70ffefdf] BAD

source.setPixel(0, 0, Color.argb(0x80, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -2130711075 [0x80ffeddd] BAD but change of pattern

source.setPixel(0, 0, Color.argb(0x90, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1862275619 [0x90ffeddd] BAD

source.setPixel(0, 0, Color.argb(0xA0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1593840162 [0xa0ffedde] BAD but change of pattern again

source.setPixel(0, 0, Color.argb(0xB0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1325404450 [0xb0ffeede] OK!

source.setPixel(0, 0, Color.argb(0xC0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1056968994 [0xc0ffeede] OK!

source.setPixel(0, 0, Color.argb(0xD0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -788533538 [0xd0ffeede] OK!

source.setPixel(0, 0, Color.argb(0xE0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -520098082 [0xe0ffeede] OK!

source.setPixel(0, 0, Color.argb(0xF0, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -251662626 [0xf0ffeede] OK!

source.setPixel(0, 0, Color.argb(0xA7, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1476399395 [0xa7ffeedd] BAD

source.setPixel(0, 0, Color.argb(0xA3, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1543508258 [0xa3ffeede] OK!

source.setPixel(0, 0, Color.argb(0xA1, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1577062690 [0xa1ffeede] OK!

source.setPixel(0, 0, Color.argb(0xAB, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1409290274 [0xabffefde] BAD

source.setPixel(0, 0, Color.argb(0xA9, 0xFF, 0xEE, 0xDE));

sp00 = source.getPixel(0, 0); // sp00 -1442844962 [0xa9ffeede] OK!

最佳答案 好吧,或多或少我发现了正在发生的事情.

在api19没有提供任何控制此功能的方法之前,它被称为“预乘Alpha”和位图,默认情况下它们是预乘的,这是无法更改的.

根据新的文件:

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).

Bitmap source = Bitmap.createBitmap(2, 2, Config.ARGB_8888);

source.setPixel(0, 0, Color.argb(0x02, 0x10, 0x20, 0x30));

source.setPixel(0, 1, Color.argb(0x03, 0x10, 0x20, 0x30));

source.setPixel(1, 0, Color.argb(0x05, 0x78, 0x96, 0x64));

source.setPixel(1, 1, Color.argb(128, 255, 200, 150));

int sp00 = source.getPixel(0, 0); // sp00 33554432 [0x2000000]

int sp01 = source.getPixel(0, 1); // sp01 50331733 [0x3000055]

int sp10 = source.getPixel(1, 0); // sp10 90610022 [0x5669966]

int sp11 = source.getPixel(1, 1); // sp11 -2130720875 [0x80ffc795]

对于较低的颜色值,舍入会导致信息丢失(请参阅上面的sp00).

此外,对于较低的值,alpha本身的值不会检索到原始值.

除此之外,给定的公式不解释我看到的值.

最后使用未修改的像素我现在使用此代码来设置位图像素:

Bitmap source = Bitmap.createBitmap(2, 2, Config.ARGB_8888);

IntBuffer data = IntBuffer.wrap(new int[] {

Color.argb(0x06, 0xff, 0xa0, 0x8d),

Color.argb(0x2a, 0xab, 0xce, 0x9f),

Color.argb(0x8f, 0xfe, 0x05, 0x18),

Color.argb(0xff, 0xc8, 0xcf, 0xd4)

});

source.copyPixelsFromBuffer(data);

并检索我使用的像素:

IntBuffer sourceData = IntBuffer.allocate(4);

source.copyPixelsToBuffer(sourceData);

使用这些方法不会预先计算颜色.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaBitmap是一种图像格式,包含了许多颜色信息和像素点数据。如果需要将一张彩色的Bitmap转换为单色Bitmap,可以通过以下步骤实现: 1. 获取原始Bitmap的宽度和高度,同时创建一个单色Bitmap对象。 2. 遍历原始Bitmap的像素,将其转换为灰度值。通过计算RGB值的加权平均数,可以将一个像素点转换为一个灰度值,公式如下: 灰度值 = (Red * 0.299 + Green * 0.587 + Blue * 0.114) 3. 将灰度值与一个阈值比较,如果超过阈值,则将单色Bitmap的相应位置填充为黑色,否则填充为白色。 4. 最后将单色Bitmap返回即可。 下面是一个简单的Java代码示例,用于将一个彩色Bitmap转换为单色Bitmap: ``` public Bitmap convertToBlackAndWhite(Bitmap original){ int width = original.getWidth(); int height = original.getHeight(); Bitmap blackAndWhite = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); for(int x = 0; x < width; x++){ for(int y = 0; y < height; y++){ int color = original.getPixel(x, y); int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); int gray = (int)(red * 0.299 + green * 0.587 + blue * 0.114); if(gray > 128){ blackAndWhite.setPixel(x, y, Color.BLACK); }else{ blackAndWhite.setPixel(x, y, Color.WHITE); } } } return blackAndWhite; } ``` 这段代码通过getPixel()函数获取原始Bitmap的每一个像素,并使用Color类获取其RGB值。然后根据RGB值计算出灰度值,并与阈值128比较。最后使用setPixel()函数将相应位置填充为黑色或白色。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值