将short []转换为灰度图像

Sha*_*ton 6 java bufferedimage grayscale

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

    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)]);
Run Code Online (Sandbox Code Playgroud)

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

Rus*_*ser 7

这里的问题是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));
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是您可以控制基础像素阵列.您可以对该阵列进行更改并调用newPixels()您的MemoryImageSource,并且它将实时更新.除了灰度外,它还为您提供了定义自己的调色板的全部功能:

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);
Run Code Online (Sandbox Code Playgroud)

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

JFrame frame = new JFrame();
frame.getContentPane().add(new JLabel(new ImageIcon(image)));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Run Code Online (Sandbox Code Playgroud)

但是,如果您想将其写入文件并保留每像素一次短格式(例如,加载到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);
Run Code Online (Sandbox Code Playgroud)