有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在RGB通道之间切换

我需要打开/关闭图像的RGB通道,但我被卡住了,代码有问题

你能帮我找出正确的方法吗?这是我的代码:

当3个复选框中的1个已更改其状态并提供参数true == selected时,将调用函数channels

public void channels(boolean red, boolean green, boolean blue) {
    if (this.img != null) {// checks if the image is set
        char r = 0xFF, g = 0xFF, b = 0xFF;
        if (red == false) {
            r = 0x00;
        }
        if (green == false) {
            g = 0x00;
        }
        if (blue == false) {
            b = 0x00;
        }
        BufferedImage tmp = new BufferedImage(
                img.getWidth(),
                img.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                int rgb = img.getRGB(i, j);
                int red = (rgb >> 16) & r;
                int green = (rgb >> 8) & g;
                int blue = (rgb >> 0) & b;
                int gbr = (red << 16) | (green << 8) | blue;// EDITED
                tmp.setRGB(i, j, gbr);
            }
        }
        img = tmp;
        repaint();
    } else {
        //show error
    }
}

谢谢你的帮助


共 (2) 个答案

  1. # 1 楼答案

    看起来你把位子换错了。它不应该是:int gbr = (red << 16) | (green << 8) | blue;?基本上,你想按照你开始时换出去的顺序换回去

    而且,一旦你清除了相应的颜色,你就没有办法把它拿回来了。您需要在某处存储原始图像的副本。当该重新打开通道时,只需将原始图像中的原始像素复制回来即可

    假设您将原始图像作为origImg存储在某处,我将修改您的for循环,以便在切换频道时,从原始图像复制

    for (int i = 0; i < img.getWidth(); i++) {
        for (int j = 0; j < img.getHeight(); j++) {
            int rgb = img.getRGB(i, j);
            int origRGB = origImg.getRGB(i, j);              
            int redPixel = red ? (origRGB >> 16) & r : (rgb >> 16) & r;
            int greenPixel = green ? (origRGB >> 8) & g : (rgb >> 8) & g;
            int bluePixel = blue ? origRGB & b : rgb & b;
            int gbr = (redPixel << 16) | (greenPixel << 8) | bluePixel;
            tmp.setRGB(i, j, gbr); 
       }
    }
    
  2. # 2 楼答案

    这个优化的版本怎么样,位移动少很多

    public void channels(boolean showRed, boolean showGreen, boolean showBlue) {
        if (this.origImg!= null) {// checks if the image is set
            int channelMask = 0xff << 24 | (showRed ? 0xff : 0) << 16 | (showGreen ? 0xff : 0) << 8 | (showBlue ? 0xff : 0);
    
            BufferedImage tmp = new BufferedImage(origImg.getWidth(), origImg.getHeight(), BufferedImage.TYPE_INT_RGB);
    
            for (int i = 0; i < origImg.getWidth(); i++) {
                for (int j = 0; j < origImg.getHeight(); j++) {
                    int rgb = origImg.getRGB(i, j);
                    tmp.setRGB(i, j, rgb & channelMask);
                }
            }
    
            img = tmp;
            repaint();
        } else {
            //show error
        }
    }
    

    更快的方法可能是使用通道化的Raster,或者至少使用允许带次采样的Raster配置(请参见Raster.createChild(...)方法,尤其是最后一个参数)

    @trashgood提到的LookupOp也是一个好主意,可能比getRGB()/setRGB()方法更快