使用WritableRaster和DataBufferByte在Java中将图像转换为byte []时出错。

时间:2015-03-18 10:27:01

标签: java image bufferedimage javax.imageio

我正在尝试使用代码

将图像转换为byte []
public static byte[] extractBytes(String ImageName) throws IOException {
    // open image
    File imgPath = new File(ImageName);
    BufferedImage bufferedImage = ImageIO.read(imgPath);

    // get DataBufferBytes from Raster
    WritableRaster raster = bufferedImage.getRaster();
    DataBufferByte data = (DataBufferByte) raster.getDataBuffer();

    return (data.getData());
}

当我使用代码

进行测试时
public static void main(String[] args) throws IOException {

    String filepath = "image_old.jpg";
    byte[] data = extractBytes(filepath);
    System.out.println(data.length);
    BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
    File outputfile = new File("image_new.jpg");
    ImageIO.write(img, "jpeg", outputfile);
}

我收到data.length = 4665600并收到错误

Exception in thread "main" java.lang.IllegalArgumentException: image == null!
    at javax.imageio.ImageTypeSpecifier.createFromRenderedImage(ImageTypeSpecifier.java:925)
    at javax.imageio.ImageIO.getWriter(ImageIO.java:1591)
    at javax.imageio.ImageIO.write(ImageIO.java:1520)
    at com.medianet.hello.HbaseUtil.main(HbaseUtil.java:138)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

但是当我将extractBytes代码更改为

public static byte[] extractBytes (String ImageName) throws IOException {

   ByteArrayOutputStream baos=new ByteArrayOutputStream();
        BufferedImage img=ImageIO.read(new File(ImageName));
        ImageIO.write(img, "jpg", baos);
        baos.flush();

        return baos.toByteArray();
    }

我正在获取data.length = 120905并获得成功(image.jpg在所需位置创建)

1 个答案:

答案 0 :(得分:3)

问题是,extractBytes的第一个版本读取图像,并将图像的像素作为字节数组返回(假设它使用DataBufferByte)。这些字节不是文件格式,如果没有额外信息(如宽度,高度,颜色空间等)则无用。ImageIO无法读取这些字节,因此{{1} }返回(并分配给null,稍后从img导致IllegalArgumentException

第二个版本对图像进行解码,然后再以JPEG格式对其进行编码。这是一种ImageIO.write(...)能够阅读的格式,您可以按预期获得图像(分配给ImageIO)。

然而,您的代码似乎只是一种非常非常昂贵的CPU复制图像(您解码图像,然后编码,然后再次解码,最后编码之前)...对于JPEG文件,此解码/编码周期将也会降低图像质量。除非您计划将图像数据用于任何事情,并且只想将图像从一个地方复制到另一个地方,否则请不要使用imgImageIO。这些类型用于图像处理。

这是您的主要方法的修改版本:

BufferedImage

(使用Java 7中的try-with-resources或Java 8中的NIO2 public static void main(String[] args) throws IOException { byte[] buffer = new byte[1024]; File inFile = new File("image_old.jpg"); File outFile = new File("image_new.jpg"); InputStream in = new FileInputStream(inFile); try { OutputStream out = new FileOutputStream(outFile); try { int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } } finally { out.close(); } } finally { in.close(); } } 可以更好/更优雅地写这个,但我把它留给你。:-))< / p>