使用相同的数据将缓冲的图像转换为2D字节数组

时间:2013-08-29 06:06:56

标签: java image image-processing bytearray bufferedimage

我在Java中编写了一个图像处理应用程序。我已经处理了图像,这是缓冲的图像,现在我想为那个处理过的图像返回byte[],我应该得到二值化图像的字节数组。

这是我的代码:

public static byte[][] binarizeImage(BufferedImage bfImage){

        int red;
        int newPixel;
        int h ;
        int w ;
        int threshold = otsuTreshold(bfImage);   
          // this function returns the threshold value 199

        BufferedImage binarized = new BufferedImage(bfImage.getWidth(), bfImage.getHeight(), bfImage.getType());

        for(int i=0; i<bfImage.getWidth(); i++) {
        for(int j=0; j<bfImage.getHeight(); j++) {

            // Get pixels
            red = new Color(bfImage.getRGB(i, j)).getRed();
            int alpha = new Color(bfImage.getRGB(i, j)).getAlpha();
            if(red > threshold) {
                newPixel = 255;
            }
            else {
                newPixel = 0;
            }
            newPixel = colorToRGB(alpha, newPixel, newPixel, newPixel);
            binarized.setRGB(i, j, newPixel); 
       }

     }
          Raster raster  = binarized.getData();

    h = raster.getHeight();
    w = raster.getWidth();

    byte[][] binarize_image = new byte[w][h];

    for(int i=0 ; i<w ; i++)
    {
        for(int j=0; j<h ; j++)
        {
            binarize_image[i][j]=raster.getSampleModel();  //error at this line 
        }
   }
   return binarize_image;
}

// Convert R, G, B, Alpha to standard 8 bit
    private static int colorToRGB(int alpha, int red, int green, int blue) {

        int newPixel = 0;
        newPixel += alpha;
        newPixel = newPixel << 8;
        newPixel += red; newPixel = newPixel << 8;
        newPixel += green; newPixel = newPixel << 8;
        newPixel += blue;

        return newPixel;

    }

但它不起作用。如何将缓冲图像转换为相同图像数据的字节数组?

4 个答案:

答案 0 :(得分:2)

我不确定术语“二值化”在这种情况下意味着什么。您似乎只想过滤图像(即根据某个阈值切断红色通道)并将结果转换为byte[]

假设上述情况正确,请检查以下代码。它会将图像转换为byte[]以获得32位图像。请考虑以下因素:

  • 您无需先过滤图像,然后转换为byte[]。您可以在转换期间执行此操作。
  • “将RGB转换为标准8位”:如果你的意思是每个颜色通道8位 那么这没关系,但如果你的意思是8位每像素然后你谈论压缩/转换(即你可能会丢失一些信息/质量),在这种情况下你应该提供更多关于你想要实现的信息。
  • 假设我们正在谈论32位图像的情况,那么结果byte[]的大小将为4 * width * height而不是width * height。如果您需要处理其他情况,则应考虑BufferedImage支持的可用图像类型(或至少只考虑您感兴趣的图像类型)。

下面的代码将打印每个转换像素的信息,如下所示(注意如何过滤红色通道):

[0,0] Converting [ffaaccee] --> [0, cc, ee, ff]

package imageio.byteconversion;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;

public class BufferedImageToBytes {

    private static void log(String s) {
        System.out.println(s);
    }

    private static String toByteString(int color) {
        // Perform a bitwise AND for convenience while printing. 
        // Otherwise Integer.toHexString() interprets values as integers and a negative byte 0xFF will be printed as "ffffffff"
        return Integer.toHexString(color & 0xFF);
    }

    public static void main(String[] args) throws IOException {

        // Load the image. This expects the image to be in the same package with this class 
        InputStream stream = BufferedImageToBytes.class.getResourceAsStream("test.png");
        BufferedImage image = ImageIO.read(stream);
        int iw = image.getWidth();
        int ih = image.getHeight();
        log("Image loaded succesfully, width=" + iw + " height=" + ih);
        stream.close();

        log("Image color model: " + image.getColorModel());
        log("Image sample model: " + image.getSampleModel());
        log("Image raster: " + image.getRaster());

        int bands = image.getSampleModel().getNumBands();
        log("Color bands: " + bands);
        if (bands != 4) {
            throw new RuntimeException("The image does not have 4 color bands. Are you sure this is a 32-bit image?");
        }

        int threshold = 199; // <-- decide your threshold here

        byte bytes[] = new byte[4 * iw * ih];
        int index = 0;

        // note that image is processed row by row top to bottom
        for(int y = 0; y < ih; y++) {
            for(int x = 0; x < iw; x++) {

                // returns a packed pixel where each byte is a color channel
                // order is the default ARGB color model
                int pixel = image.getRGB(x, y);

                // Get pixels
                int alpha = (pixel >> 24) & 0xFF;
                int red = (pixel >> 16) & 0xFF;
                int green = (pixel >> 8) & 0xFF;
                int blue = pixel & 0xFF;

                // perform filtering here depending on threshold 
                if (red > threshold) {
                   red = 255;
                } else {
                    red = 0;
                }

                log("[" + x + "," + y + "]" + " Converting [" + Integer.toHexString(pixel)  + "] --> ["
                        + toByteString(red) + ", " + toByteString(green) + ", " 
                        + toByteString(blue) + ", " + toByteString(alpha)
                        + "]");

                bytes[index++] = (byte) red;
                bytes[index++] = (byte) green;
                bytes[index++] = (byte) blue;
                bytes[index++] = (byte) alpha;
           }
        }
    }
}

答案 1 :(得分:2)

为什么不尝试将lib用作Catalano Framework。 http://code.google.com/p/catalano-framework/

FastBitmap fb = new FastBitmap("c:\\files\\image.jpg");
fb.toGrayscale();

OtsuThreshold otsu = new OtsuThreshold();
otsu.applyInPlace(fb);

int[][] image = new int[fb.getHeight()][fb.getWidth()];
fb.toArrayGray(image);

答案 2 :(得分:1)

怎么样:

BufferedImage input;

BufferedImage binary = new BufferedImage(input.getWidth(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY);

Graphics2D g = binary.createGraphics();
try {
    g.drawImage(input, 0, 0, null);
}
finally {
   g.dispose();
}

它不会使用你的otsuTreshold,它会(可能)抖动图像,但它会使用最少的内存来完成二进制(仅黑/白)的工作。

答案 3 :(得分:1)

  try {
                  // get the BufferedImage, using the ImageIO class
                  Bitmap image = 
                    BitmapFactory.decodeStream(getAssets()
                            .open("aa.bmp"));
                  marchThroughImage(image);
                } catch (IOException e) {
                  System.err.println(e.getMessage());
                }
        }
    });


}
public void printPixelARGB(int pixel) {
    int alpha = (pixel >> 24) & 0xff;
    int red = (pixel >> 16) & 0xff;
    int green = (pixel >> 8) & 0xff;
    int blue = (pixel) & 0xff;
    System.out.println("argb: " + alpha + ", " + red + ", " + green + ", " + blue);
  }
private void marchThroughImage(Bitmap image) {
    int w = image.getWidth();
    int h = image.getHeight();
    System.out.println("width, height: " + w + ", " + h);

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        System.out.println("x,y: " + j + ", " + i);
        int pixel = image.getPixel(j, i);
        printPixelARGB(pixel);
        System.out.println("");
      }
    }
  }