繁体   English   中英

反转位图颜色

[英]Invert bitmap colors

我有以下问题。 我有一个图表程序,它的设计是黑色的,但图表(我从服务器获得的图像)很轻(它实际上只使用5种颜色:红色,绿色,白色,黑色和灰色)。

为了适应设计倒置做得很好,唯一的问题是红色和绿色也是倒置的(绿色 - >粉红色,红色 - >绿色)。

有没有办法可以反转除了那两种颜色之外的所有颜色,或者在反转后重新绘制这些颜色的方法? 这些操作的成本是多少(因为我经常更新图表)?

提前致谢 :)

UPDATE

我尝试在循环中用setPixel方法替换颜色

for(int x = 0 ;x < chart.getWidth();x++) {
        for(int y = 0;y < chart.getHeight();y++) {
            final int replacement = getColorReplacement(chart.getPixel(x, y));
            if(replacement != 0) {
                chart.setPixel(x, y, replacement);
            }
        }
    }

不幸的是,这个方法花了太长时间(~650ms),是否有更快的方法,并且setPixels()方法工作得更快?

如果通过仅调用一次getPixels将图像数据复制到int数组中,并且不调用循环内的任何函数,则操作位图要快得多。 只需操作数组,然后在结尾调用setPixels。

像这样的东西:

int length = bitmap.getWidth()*bitmap.getHeight();
int[] array = new int[length];
bitmap.getPixels(array,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());
for (int i=0;i<length;i++){
// If the bitmap is in ARGB_8888 format
  if (array[i] == 0xff000000){
    array[i] = 0xffffffff;
  } else if ...
  }
}
bitmap.setPixels(array,0,bitmap.getWidth(),0,0,bitmap.getWidth(),bitmap.getHeight());

如果您将其作为BufferedImage ,则可以访问其栅格并根据需要进行编辑。

WritableRaster raster = my_image.getRaster();

// Edit all the pixels you wanna change in the raster (green -> red, pink -> green)
// for (x,y) in ...
// raster.setPixel(x, y, ...) 

my_image.setData(raster);

好的,你真的只使用5种颜色,这很容易。

关于性能,我不知道Android,但我可以告诉你,在Java中使用setRGB比回到数据缓冲区并直接写入int []要慢得多。

当我写“惊人的慢”时,给你一个想法,在OS X 10.4上有以下代码:

for ( int x = 0; x < width; x++ ) {
    for ( int y = 0; y < height; y++ ) {
        img.setRGB(x,y,0xFFFFFFFF);
    }
}

可以比以下慢100倍(!)

for ( int x = 0; x < width; x++ ) {
    for ( int y = 0; y < height; y++ ) {
        array[y*width+x] = 0xFFFFFFFF;
    }
}

你读得正确:一百次。 在Core 2 Duo / Mac Mini / OS X 10.4上测量。

(当然你需要先访问底层的int []数组,但希望这不应该是困难的)

我不能强调这个问题不是两个for循环:在两种情况下,它都是未经优化的循环。 所以这里真的是setRGB问题。

我不知道它适用于Android,但如果你想要一些表现良好的东西,你可能应该摆脱setRGB。

一种快速的方法是使用AvoidXfermode重新绘制您想要更改的颜色 - 然后您可以在所需的任何颜色之间切换。 你只需要做这样的事情:

// will change red to green
Paint change1 = new Paint();
change1.setColor(Color.GREEN);
change1.setXfermode(new AvoidXfermode(Color.RED, 245, AvoidXfermode.Mode.TARGET));

Canvas c = new Canvas();
c.setBitmap(chart);
c.drawRect(0, 0, width, height, change1);

// rinse, repeat for other colors

您可能需要使用AvoidXfermode的容差,但这应该比每像素计算快得多。 此外,请确保您的图表图像处于ARGB8888模式。 默认情况下,Android倾向于使用RGB565模式下的图像,这会使您想要使用的颜色计算陷入混乱 - 当然,您可以通过调用Bitmap chart = chartFromServer.copy(Config.ARGB_8888, true);来确保您的图像处于ARGB8888模式并且可变Bitmap chart = chartFromServer.copy(Config.ARGB_8888, true); 在设置Xfermode之前。

澄清 :要更改其他颜色,您不必再重新加载图像,您只需创建其他具有您想要更改的颜色的油漆,如下所示:

// changes green to red
Paint change1 = new Paint();
change1.setColor(Color.GREEN);
change1.setXfermode(new AvoidXfermode(Color.RED, 245, AvoidXfermode.Mode.TARGET));

// changes white to blue
Paint change2 = new Paint();
change2.setColor(Color.BLUE);
change2.setXfermode(new AvoidXfermode(Color.WHITE, 245, AvoidXfermode.Mode.TARGET));

// ... other Paints with other changes you want to apply to this image

Canvas c = new Canvas();
c.setBitmap(chart);
c.drawRect(0, 0, width, height, change1);
c.drawRect(0, 0, width, height, change2);
//...
c.drawRect(0, 0, width, height, changeN);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM