Android 位图操作

发布于 2024-12-14 22:18:30 字数 488 浏览 1 评论 0原文

你能告诉我这段代码有什么问题吗?

//bmp is a bitmap of already present image
int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
rgbval=actual(rgbval);
Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval, 0, width, 0, 0, width, height);

actual 是我创建的一个函数,用于操作 bmp 的 rgb 值。通过使用 eclipse 的调试功能,我已经检查它是否正常工作,但是当我尝试恢复 bmp2 的 rgb 值时,我没有得到操纵的值。

Can you tell me what's wrong with this piece of code?

//bmp is a bitmap of already present image
int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
rgbval=actual(rgbval);
Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval, 0, width, 0, 0, width, height);

actual is a function I have created to manipulate the rgb values of a bmp. By using debug functions of eclipse I have checked that it is working correctly , but when I try to recover rgb values of bmp2 , I don't get the manipulated values.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

微暖i 2024-12-21 22:18:30

首先,请参阅这个答案: Android 位图 setPixel 无法正常工作? (设置值,然后读取不同的值)

所以,似乎如果你的原始图像没有 Alpha 通道(即 hasAlpha() 返回 false),它会自动将 rgb 值转换为预乘格式。
这就是你所经历的吗? bmp.hasAlpha() 是假的吗?

我刚刚使用默认的 android 图标作为位图测试了您的代码,其中 hasAlpha() 返回 true。输入和输出颜色数组中的 Alpha 通道是相同的。然而,2304 个像素中有 15 个的红色通道偏离一两个。我没有检查蓝色或绿色通道。我认为这是内部舍入错误?我发布了我使用的相当冗长且仅用于测试的代码,以防万一有人有其他需要添加的内容。

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
int rgbval2[] = actual(rgbval);

Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval2, 0, width, 0, 0, width, height);

int rgb2[] = new int[width*height];
bmp2.getPixels(rgb2, 0, width, 0, 0, width, height);

int alpha1[] = new int[width*height];
int alpha2[] = new int[width*height];
int red1[] = new int[width*height];
int red2[] = new int[width*height];

for(int i=0; i<alpha2.length; ++i) {
    alpha1[i] = Color.alpha(rgbval2[i]);
    alpha2[i] = Color.alpha(rgb2[i]);
    red1[i] = Color.red(rgbval2[i]);
    red2[i] = Color.red(rgb2[i]);

    if(red1[i]!=red2[i]) {
        int a1 = alpha1[i];
        int a2 = alpha2[i];
        int r1 = red1[i];
        int r2 = red2[i];


        Log.e("E", String.format("a1: %d, a2: %d, r1: %d, r2: %d", a1, a2, r1, r2));
    }
}


private int[] actual(int rgb[]) {
    int rgb2[] = new int[rgb.length];

    for(int i=0; i<rgb.length; ++i) {
        rgb2[i] = Color.argb(Color.alpha(rgb[i]), Color.red(rgb[i])/2,  
                      Color.green(rgb[i])/2, Color.blue(rgb[i])/2);
    }

    return rgb2;
}

这是 LogCat 输出

a1: 64, a2: 64, r1: 30, r2: 32
a1: 64, a2: 64, r1: 30, r2: 32
a1: 142, a2: 142, r1: 58, r2: 57
a1: 142, a2: 142, r1: 58, r2: 57
a1: 216, a2: 216, r1: 56, r2: 55
a1: 216, a2: 216, r1: 56, r2: 55
a1: 57, a2: 57, r1: 6, r2: 4
a1: 59, a2: 59, r1: 6, r2: 4
a1: 231, a2: 231, r1: 90, r2: 91
a1: 216, a2: 216, r1: 95, r2: 94
a1: 216, a2: 216, r1: 95, r2: 94
a1: 217, a2: 217, r1: 57, r2: 58
a1: 216, a2: 216, r1: 88, r2: 89
a1: 199, a2: 199, r1: 66, r2: 67
a1: 199, a2: 199, r1: 39, r2: 38

First of all, see this answer: Android Bitmap setPixel doens't work correctly? (set value, then read a different value)

So, it seems that if your original image does not have an alpha channel (i.e., hasAlpha() returns false), it will automatically convert the rgb values to a premultiplied format.
Is that what you're experiencing? Is bmp.hasAlpha() false?

I just tested your code with the default android icon as the bitmap, with which hasAlpha() returns true. The alpha channels in the input and output color arrays are identical. However, the red channels are off by one or two for 15 out of 2304 pixels. I didn't check the blue or green channels. I assume this is internal rounding error? I'm posting the rather verbose and used-only-for-testing code I used just in case anyone has anything else to add.

Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);

int width=bmp.getWidth();
int height=bmp.getHeight();
int rgbval[]=new int[width*height];
bmp.getPixels(rgbval, 0, width, 0, 0, width, height);
int rgbval2[] = actual(rgbval);

Bitmap bmp2=bmp.copy(Bitmap.Config.ARGB_8888,true);
bmp2.setPixels(rgbval2, 0, width, 0, 0, width, height);

int rgb2[] = new int[width*height];
bmp2.getPixels(rgb2, 0, width, 0, 0, width, height);

int alpha1[] = new int[width*height];
int alpha2[] = new int[width*height];
int red1[] = new int[width*height];
int red2[] = new int[width*height];

for(int i=0; i<alpha2.length; ++i) {
    alpha1[i] = Color.alpha(rgbval2[i]);
    alpha2[i] = Color.alpha(rgb2[i]);
    red1[i] = Color.red(rgbval2[i]);
    red2[i] = Color.red(rgb2[i]);

    if(red1[i]!=red2[i]) {
        int a1 = alpha1[i];
        int a2 = alpha2[i];
        int r1 = red1[i];
        int r2 = red2[i];


        Log.e("E", String.format("a1: %d, a2: %d, r1: %d, r2: %d", a1, a2, r1, r2));
    }
}


private int[] actual(int rgb[]) {
    int rgb2[] = new int[rgb.length];

    for(int i=0; i<rgb.length; ++i) {
        rgb2[i] = Color.argb(Color.alpha(rgb[i]), Color.red(rgb[i])/2,  
                      Color.green(rgb[i])/2, Color.blue(rgb[i])/2);
    }

    return rgb2;
}

and here is the LogCat output

a1: 64, a2: 64, r1: 30, r2: 32
a1: 64, a2: 64, r1: 30, r2: 32
a1: 142, a2: 142, r1: 58, r2: 57
a1: 142, a2: 142, r1: 58, r2: 57
a1: 216, a2: 216, r1: 56, r2: 55
a1: 216, a2: 216, r1: 56, r2: 55
a1: 57, a2: 57, r1: 6, r2: 4
a1: 59, a2: 59, r1: 6, r2: 4
a1: 231, a2: 231, r1: 90, r2: 91
a1: 216, a2: 216, r1: 95, r2: 94
a1: 216, a2: 216, r1: 95, r2: 94
a1: 217, a2: 217, r1: 57, r2: 58
a1: 216, a2: 216, r1: 88, r2: 89
a1: 199, a2: 199, r1: 66, r2: 67
a1: 199, a2: 199, r1: 39, r2: 38
疯到世界奔溃 2024-12-21 22:18:30

我认为这个问题是由于一些 android bug 造成的。我已经操作了位图的像素,并且需要像素值完全相同,但是当我使用 setPixels 设置位图的完整像素时,它不起作用。我通过使用找到了解决方案,

index=0;
for (int j = 0; j < height; j++)
   for (int i = 0; i < width; i++)
   {
    destBitmap.setPixel(i, j, pixelvalues[index]);

   }

所以如果我一个一个地设置像素而不是一次全部设置像素,它会以某种方式起作用!

I think the problem is due to some android bug. I have manipulated the pixels of the bitmap and i needed the pixel values to exactly the same , but when i used setPixels to set the complete pixels of the bitmap it did not work. I found the solution by using

index=0;
for (int j = 0; j < height; j++)
   for (int i = 0; i < width; i++)
   {
    destBitmap.setPixel(i, j, pixelvalues[index]);

   }

So if i set the pixel one by one instead of all at a time somehow it works!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文