Java 图像字节数组到灰度返回图像



我正在尝试对图像处理进行编码,所以我创建了一个方法,该方法可以接收BufferedImage并将其转换为字节数组(方法名称convertToByteArray(BufferedImage inImg))。

然后,我从每个像素的字节中获取 ARGB 或 RGB 值(每个 8 位,使用按位转换)。 然后将 ARGB 或 RGB 的 int 值追加回字节数组(方法名称convertToGrayscale(byte[] inImg))。

然后将字节数组馈送到要转换回图像的方法(方法名convertToBufferedImage(byte[] inImg))。

出于某种原因,当我将BufferedImage传递到方法中以将其转换为字节数组时,然后无需更改,将字节数组传递到方法中以转换回BufferedImage它的工作原理。

这就是我遇到问题的地方。 当我将BufferedImage传递到方法以转换为字节数组时,然后传入方法以将其更改为灰度,并在同一方法中将灰度整数值更改为字节数组。 这是问题所在,当我将更改后的字节数组传递到方法中以转换回BufferedImage时......结果是">img 为空"请帮忙,要么我的转换是错误的,要么我不知道在哪里或出了什么问题。

public byte[] convertToByteArray(BufferedImage inImg) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(inImg, "jpg", baos);
} catch (IOException e) {
e.printStackTrace();
}
outImgByte = baos.toByteArray();
System.out.println("img to byte array length: " + outImgByte.length);
System.out.println("convert to byte array complete...");
return outImgByte;
}
public BufferedImage convertToBufferedImage(byte[] inImg) {
try {
outImg = ImageIO.read(new ByteArrayInputStream(inImg));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("convert byte array to image complete...");
return outImg;
}
public void convertToGrayscale(byte[] inImg) {
int r, g, b;
int grayscale;
// for loop to change each byte value into gray scale
for(int i = 0; i < inImg.length; i++) {
// first must get the value of RGB out from byte 
// array and get the average
r = (inImg[i] >> 16) & 0xff;
g = (inImg[i] >> 8) & 0xff;
b = (inImg[i]) & 0xff;
grayscale = (r + g + b) / 3;
outImgByte[i] = (byte) (grayscale << 16 | grayscale << 8 |   grayscale);
}
System.out.println("byte to grayscale byte array length: " + outImgByte.length);
System.out.println("convert to grayscale from byte array complete...");
}

控制台输出:

Exception in thread "main" java.lang.IllegalArgumentException: image == null!
at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(Unknown Source)
at javax.imageio.ImageIO.getWriter(Unknown Source)
at javax.imageio.ImageIO.write(Unknown Source)
at Main.main(Main.java:50)

BufferedImage后面,有一个数组,很可能是一个字节数组(有时很短)。因此,如果您的BufferedImageTYPE_BYTE_GRAYTYPE_3BYTE_BGRTYPE_4BYTE_ABGR类型,那么您可以使用以下命令直接访问DataBufferbyte[] databuffer = ((DataBufferByte)image.getRaster().getDataBuffer()).getData() ;。这是对像素值的直接访问。但是这样做,您必须自己管理图像编码,因此如果BufferedImage类型为TYPE_USHORT_GRAY,这将不起作用。

如果需要更简单(但更慢)的方法来访问像素值,请使用栅格:

BufferedImage image = ...
for (int y=0 ; y < image.getHeight() ; y++)
for (int x=0 ; x < image.getWidth() ; x++)
for (int c=0 ; c < image.getRaster().getNumBands() ; c++)
final int value = image.getRaster().getSample(x, y, c) ; // Returns the value of the channel C of the pixel (x,y)

因此,使用getSamplesetSample,您可以访问和修改像素值,而无需管理图像编码,但它比直接访问DataBuffer慢。

此外,BufferedImage几乎从不使用TYPE_INT_RGB(或其他INT编码)进行编码,这意味着当您使用getRGB访问像素值时,您要求图像将像素值转换为INT,然后您必须再次分解该值。因此,您进行了两次转换。一般来说,必须禁止getRGB的方法。它比使用栅格慢得多。

[编辑] 对于TYPE_BYTE_GBR类型的图像,您可以使用byte[] databuffer = ((DataBufferByte)image.getRaster().getDataBuffer()).getData()访问像素值。注意,这是对像素的直接访问,因此如果您将值修改到此数组中,则将修改像素。对于具有N像素的图像,编码[b1, g1, r1, b2, g2, r2, ... bN, gN, rN]:so (b, g, r) 三元组。

您的方法convertToByteArray变为:

public byte[] copyIntoByteArray(BufferedImage inImg)
{
byte[] result = null ;
switch ( inImg.getType() )
{
case BufferedImage.TYPE_3BYTE_BGR:
byte[] databuffer = ((DataBufferByte) inImg.getRaster().getDataBuffer()).getData() ;
result = new byte[databuffer.length] ;
System.arraycopy(databuffer, result, databuffer.length) ;
break ;
// Other encodings
default: throw new IllegalArgumentException("Not supported.") ;
}
System.out.print("img to byte array length: " + databuffer.length) ;
System.out.println(", convert to byte array complete...") ;
return result ;
}

[编辑2]

public BufferedImage ByteArrayToBufferedImage(byte[] src, final int width, final int height)
{
// Check first that width*height*3 == src.length
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR) ;
System.arraycopy(src, ((DataBufferByte)result.getRaster().getDataBuffer()).getData(), src.length) ;
return result ;
}

函数ByteArrayToBufferedImage工作得很好。
但是,这是我稍微更改功能的内容

public BufferedImage ByteArrayToBufferedImage(byte[] src, final int width, final int height) {
//create empty bufferedImage
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
//remove System.arraycopy (fill empty image with input byte array)
result.getRaster().setDataElements(0, 0, width, height, src);
return result;
}

我没有理由使用result.getRaster().setDataElements而不是System.arraycopy
如果有人知道任何不同,请比较这两种方法。谢谢

相关内容

  • 没有找到相关文章