将short 转换为灰度图像

我正在使用aparapi写一个Buddhabrot分形发生器。 我让它的OpenCL部分工作,产生一个代表每个像素的单维数组。 我将最终图像的尺寸作为最终的int,并编写了代码来获取该数组中任意点的索引。 我想将此保存为图像,我正在尝试使用带有TYPE_USHORT_GRAY的BufferedImage。 这是我到目前为止所拥有的:

BufferedImage image=new BufferedImage(VERTICAL_PIXELS, HORIZONTAL_PIXELS, BufferedImage.TYPE_USHORT_GRAY); for(int i=0; i<VERTICAL_PIXELS; i++) for(int k=0; k<HORIZONTAL_PIXELS; k++) image.setRGB(k, i, normalized[getArrayIndex(k,i,HORIZONTAL_PIXELS)]); 

问题是,我不知道将RGB设置为什么。 我需要做什么?

这里的问题是setRGB()想要一个0xRRGGBB颜色值。 无论数据存储的是什么,BufferedImage都喜欢假装图像是RGB。 你实际上可以得到内部DataBufferShort (使用getTile(0, 0).getDataBuffer() ),但要弄清楚它是如何布局的可能很棘手。

如果你已经将你的像素放在short[] ,一个更简单的解决方案可能是将它们复制到int[]而不是将它插入到MemoryImageSource

 int[] buffer = /* pixels */; ColorModel model = new ComponentColorModel( ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] { 16 }, false, true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); Image image = Toolkit.getDefaultToolkit().createImage( new MemoryImageSource(VERTICAL_PIXELS, HORIZONTAL_PIXELS, model, buffer, 0, VERTICAL_PIXELS)); 

这种方法的优点是您可以控制基础像素arrays。 您可以对该数组进行更改并在MemoryImageSource上调用newPixels() ,它将实时更新。 它还为您提供了完全的能力来定义除灰度之外的自己的调色板:

 int[] cmap = new int[65536]; for(int i = 0; i < 65536; ++i) { cmap[i] = (((i % 10000) * 256 / 10000) << 16) | (((i % 20000) * 256 / 20000) << 8) | (((i % 40000) * 256 / 40000) << 0); } ColorModel model = new IndexColorModel(16, 65536, cmap, 0, false, -1, DataBuffer.TYPE_USHORT); 

如果您只想在屏幕上显示图像,此方法可以正常工作:

 JFrame frame = new JFrame(); frame.getContentPane().add(new JLabel(new ImageIcon(image))); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); 

但是,如果您想将其写入文件并保留每像素一次的格式(例如,加载到Matlab中),那么您就不走运了。 您可以做的最好的事情是将其绘制成BufferedImage并使用ImageIO保存,这将保存为RGB。

如果你最后肯定需要一个BufferedImage ,另一种方法是自己应用调色板,计算RGB值,然后将它们复制到图像中:

 short[] data = /* your data */; int[] cmap = /* as above */; int[] rgb = new int[data.length]; for(int i = i; i < rgb.length; ++i) { rgb[i] = cmap[data[i]]; } BufferedImage image = new BufferedImage( VERTICAL_PIXELS, HORIZONTAL_PIXELS, BufferedImage.TYPE_INT_RGB); image.setRGB(0, 0, VERTICAL_PIXELS, HORIZONTAL_PIXELS, pixels, 0, VERTICAL_PIXELS); 

作为参考,此示例显示了两种不同的BufferedImage类型如何解释相同的16位数据。 您可以将鼠标hover在图像上以查看像素值。

附录:要详细说明单词setRGB() ,请注意setRGB()尝试查找与给定ColorModel指定值最接近的匹配项。

BufferedImageTest

 import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; /** @see http://stackoverflow.com/questions/8765004 */ public class BufferedImageTest extends JPanel { private static final int SIZE = 256; private static final Random r = new Random(); private final BufferedImage image; public BufferedImageTest(int type) { image = new BufferedImage(SIZE, SIZE, type); this.setPreferredSize(new Dimension(SIZE, SIZE)); for (int row = 0; row < SIZE; row++) { for (int col = 0; col < SIZE; col++) { image.setRGB(col, row, 0xff00 << 16 | row << 8 | col); } } this.addMouseMotionListener(new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { Point p = e.getPoint(); int x = px * SIZE / getWidth(); int y = py * SIZE / getHeight(); int c = image.getRGB(x, y); setToolTipText(x + "," + y + ": " + String.format("%08X", c)); } }); } @Override protected void paintComponent(Graphics g) { g.drawImage(image, 0, 0, getWidth(), getHeight(), null); } static private void display() { JFrame f = new JFrame("BufferedImageTest"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setLayout(new GridLayout(1, 0)); f.add(new BufferedImageTest(BufferedImage.TYPE_INT_ARGB)); f.add(new BufferedImageTest(BufferedImage.TYPE_USHORT_GRAY)); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { display(); } }); } }