BufferedImage交换红色和蓝色通道

时间:2018-11-04 00:12:11

标签: java algorithm graphics colors bufferedimage

我的目标是交换Java sorted的红色和蓝色通道。

除了低效地迭代每个像素值并交换通道外,还有什么方法可以实现?我在想一些我不知道的按位魔术或集成函数。

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

也许您使用相同的BufferedImage和相同的属性创建了WritableRaster raster的新实例,但是使用了交换了颜色的ColorModel:

例如:

ColorModel swappedColorModel = new DirectColorModel(24,
                                              0x000000ff,   // Red -> Blue
                                              0x0000ff00,   // Green
                                              0x00ff0000,   // Blue -> Red
                                              0x0           // Alpha
                                              );
BufferedImage swapedColorImage = new BufferedImage (swappedColorModel,
                                                    originalImage.getRaster(),
                                                    swappedColorModel.isAlphaPremultiplied(),
                                                    properties);

我没有尝试过这段代码

答案 1 :(得分:0)

这是一个解决方案,它的确非常快,因为它并没有真正改变数据,只是改变了数据的显示方式。

诀窍是通道顺序(字节顺序)由SampleModel控制。而且,您可以在不实际更改数据的情况下更改样本模型,以使同一数据的显示方式有所不同。

如果您已经拥有BufferedImage,则创建带有交换通道的示例模型的最简单方法是使用Raster方法创建新的子级Raster.createWritableChild(...),并指定通道(或“带”)顺序中的最后一个参数。

bgr.getRaster().createWritableChild(0, 0, bgr.getWidth(), bgr.getHeight(), 0, 0, 
                                    new int[]{2, 1, 0}); // default order is 0, 1, 2

在下面的示例中,图像数据是相同的(如果有疑问,请在克隆图像后尝试移动绘画部分,并查看结果是否相同)。仅交换频道:

public static void main(String[] args) {
    // Original
    final BufferedImage bgr = new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR);

    // Paint something
    Graphics2D graphics = bgr.createGraphics();
    try {
        graphics.setColor(Color.BLUE);
        graphics.fillRect(0, 0, bgr.getWidth(), bgr.getHeight());
        graphics.setColor(Color.YELLOW);
        graphics.fillRect(0, 0, bgr.getWidth(), bgr.getHeight() / 3);
        graphics.setColor(Color.GREEN);
        graphics.fillRect(0, 0, bgr.getWidth() / 3, bgr.getHeight());
    }
    finally {
        graphics.dispose();
    }

    // Clone, and swap BGR -> RGB
    ColorModel colorModel = bgr.getColorModel();
    WritableRaster swapped = bgr.getRaster().createWritableChild(0, 0, bgr.getWidth(), bgr.getHeight(), 0, 0, 
                                                                 new int[]{2, 1, 0}); // default order is 0, 1, 2
    final BufferedImage rgb = new BufferedImage(colorModel, swapped, colorModel.isAlphaPremultiplied(), null);

    System.err.println("bgr: " + bgr); // TYPE_3BYTE_BGR (5)
    System.err.println("rgb: " + rgb); // TYPE_CUSTOM (0)

    // Display it all
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

            frame.add(new JLabel(new ImageIcon(bgr)), BorderLayout.WEST);
            frame.add(new JLabel(new ImageIcon(rgb)));

            frame.pack();
            frame.setLocationRelativeTo(null);

            frame.setVisible(true);
        }
    });
}

PS:我从评论中知道OP不需要这样做,但是如果由于某些原因(例如,本机库需要)确实需要交换像素数据的通道,最快的可能是要获取数据,请循环并交换红色和蓝色(第一和第三)组件:

byte[] data = ((DataBufferByte) bgr.getRaster().getDataBuffer()).getData();
for (int i = 0; i < data.length; i += 3) {
    // Swap 1st and 3rd component
    byte b = data[i];
    data[i] = data[i + 2];
    data[i + 2] = b;
 }