为什么raster.setPixels()返回灰度图像

时间:2015-11-05 17:18:44

标签: java image bufferedimage

我试图用最快的方法将3个矩阵(R,G和B)保存到BufferedImage中。

我在StackExchange上找到了这个方法,但它并不适用于我,因为它以灰度颜色保存。

如果我做错了事,或者比bufferimage.setRGB()更快地做到这一点,请帮助我。谢谢!

public static BufferedImage array_rasterToBuffer(int[][] imgR,
         int[][]imgG, int[][] imgB) {

    final int width = imgR[0].length;
    final int height = imgR.length;
    int numBandas = 3;
    int[] pixels = new int[width*height*numBandas];
    int cont=0;
    System.out.println("max: "+width*height*3);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            for (int band = 0; band < numBandas; band++) {
                pixels[(((i*width)+j)*numBandas +band)] =Math.abs((  (imgR[i][j] & 0xff) >> 16 | (imgG[i][j] & 0xff) >> 8 | (imgB[i][j] & 0xff)));
                cont+=1;
            }
        }
    }


    BufferedImage bufferImg = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);

    WritableRaster rast = (WritableRaster) bufferImg.getData(); 
    rast.setPixels(0, 0, width, height, pixels);
    bufferImg.setData(rast);

    return bufferImg;
}

2 个答案:

答案 0 :(得分:2)

我认为你因为表达式而变灰了

Math.abs((  (imgR[i][j] & 0xff) >> 16 | (imgG[i][j] & 0xff) >> 8 | (imgB[i][j] & 0xff)));

不依赖于band,所以你的rgb值都是一样的。

表达式看起来很狡猾,因为在将rgb值打包到单个<<时,通常会使用左移位运算符int

我不确定,因为我不熟悉您正在使用的课程,但我猜这样的事情可能有效

for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        pixels[(((i*width)+j)*numBandas)]     = imgR[i][j] & 0xFF;
        pixels[(((i*width)+j)*numBandas + 1)] = imgG[i][j] & 0xFF;
        pixels[(((i*width)+j)*numBandas + 2)] = imgB[i][j] & 0xFF;
    }
}

答案 1 :(得分:1)

如果你想要更快的方法,你需要得到&#34; live&#34;来自WritableRaster的{​​{1}}并设置&#34; native&#34;中的像素图像的格式,即像素打包&#34;为BufferedImage。这将为您节省多个(至少两个)阵列副本和一些数据转换。它还可以节省2/3的转换内存,因为我们每个像素只需要一个阵列组件。

下面的方法应该快得多:

TYPE_INT_RGB

如果您不需要&#34;托管&#34;可以进一步优化这一点。 (可能的硬件加速显示)图像。诀窍是直接创建图像&#34;周围&#34;您的public static BufferedImage array_rasterToBuffer(int[][] imgR, int[][] imgG, int[][] imgB) { final int width = imgR[0].length; final int height = imgR.length; // The bands are "packed" for TYPE_INT_RGB Raster, // so we need only one array component per pixel int[] pixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // "Pack" RGB values to native TYPE_INT_RGB format // (NOTE: Do not use Math.abs on these values, and without alpha there won't be negative values) pixels[((y * width) + x)] = ((imgR[y][x] & 0xff) << 16 | (imgG[y][x] & 0xff) << 8 | (imgB[y][x] & 0xff)); } } BufferedImage bufferImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // NOTE: getRaster rather than getData for "live" view WritableRaster rast = bufferImg.getRaster(); // NOTE: setDataElements rather than setPixels to avoid conversion // This requires pixels to be in "native" packed RGB format (as above) rast.setDataElements(0, 0, width, height, pixels); // No need for setData as we were already working on the live data // thus saving at least two expensive array copies return bufferImg; } // Test method, displaying red/green/blue stripes public static void main(String[] args) { int[][] fooR = new int[99][99]; int[][] fooG = new int[99][99]; int[][] fooB = new int[99][99]; for (int i = 0; i < 33; i++) { Arrays.fill(fooR[i], 0xff); Arrays.fill(fooG[i + 33], 0xff); Arrays.fill(fooB[i + 66], 0xff); } BufferedImage image = array_rasterToBuffer(fooR, fooG, fooB); showIt(image); } // For demonstration only private static void showIt(final BufferedImage image) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame("JPEGTest"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); JScrollPane scroll = new JScrollPane(new JLabel(new ImageIcon(image))); scroll.setBorder(BorderFactory.createEmptyBorder()); frame.add(scroll); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } 数组,从而在pixels中再保存一个数组分配和数组副本。缺点是在某些情况下,绘制到屏幕上的图像会慢一些。这主要是游戏或平滑动画的关注点。

使用以下代码将setDataElements中的行替换为BufferedImage bufferImg = new BufferedImage...语句:

return

PS:请注意,我也改变了x / y循环内的移位,从右移位到左移。可能只是一个小错字。 : - )