将JavaFX Image对象转换为字节数组

时间:2016-06-29 09:46:55

标签: image javafx bytearray

我们可以使用

创建FX Image对象
byte [] bytes = ------; //valid image in bytes
javafx.scene.image.Image image = new Image(new ByteArrayInputStream(bytes));

这可以设置为ImageView。

我需要相反的 ,不用 将其首先转换为 BufferedImage (SwingFXUtils.fromFXImage(image,null ))。

这样我就可以直接将字节写入文件。

我尝试了以下内容:

PixelReader pixelReader = image.getPixelReader();
    int width = (int)image.getWidth();
    int height = (int)image.getHeight();
    byte[] buffer = new byte[width * height * 4];
    pixelReader.getPixels(
            0,
            0,
            width,
            height,
            PixelFormat.getByteBgraInstance(),
            buffer,
            0,
            width * 4
    );

但是,通过写 byte []缓冲区生成的文件不是有效图像。

对此有何见解?

编辑: How to get byte[] from javafx imageView提供的解决方案无法应用于我的问题。正如我已经清楚地提到过,我不想使用SwingFXUtils将其转换为BufferedImage。 此外,我想将其转换为字节数组,以便可以将其写入图像文件。

2 个答案:

答案 0 :(得分:6)

这是稍后的方式,但如果有人想要查找,请尝试:

// Load the Image into a Java FX Image Object //

Image img = new Image(new FileInputStream("SomeImageFile.png") );

// Cache Width and Height to 'int's (because getWidth/getHeight return Double) and getPixels needs 'int's //

int w = (int)img.getWidth();
int h = (int)img.getHeight();

// Create a new Byte Buffer, but we'll use BGRA (1 byte for each channel) //

byte[] buf = new byte[w * h * 4];

/* Since you can get the output in whatever format with a WritablePixelFormat,
   we'll use an already created one for ease-of-use. */

img.getPixelReader().getPixels(0, 0, w, h, PixelFormat.getByteBgraInstance(), buf, 0, w * 4);

/* Second last parameter is byte offset you want to start in your buffer,
   and the last parameter is stride (in bytes) per line for your buffer. */

答案 1 :(得分:0)

使用ByteArrayInputStream创建JavaFX Image仅在supported formats中使用原始的,未修改的图像文件字节(bmp,jpg,gif,png)起作用。

使用PixelReader读取Image之后,字节数组将包含原始图像字节,这些原始图像字节只能使用WritableImage写回到PixelWriter,即为什么使用ByteArrayInputStream会产生无效的图像。

以下是使用此image的可复制示例:

// Original image bytes
File file = new File("F:/Downloads/duke.png");
byte[] fileBytes = Files.readAllBytes(file.toPath());
System.out.println(fileBytes.length);  // 17776 bytes
InputStream in = new ByteArrayInputStream(fileBytes);
Image image = new Image(in);
ImageView view = new ImageView(image);
VBox pane = new VBox();
pane.getChildren().add(view);  // Works
in.close();

// PixelReader generated image bytes
int width = (int) image.getWidth();
int height = (int) image.getHeight();
byte[] pixelBytes = new byte[width * height * 4];
System.out.println(pixelBytes.length);  // 367928 bytes
image.getPixelReader().getPixels(0, 0, width, height,
        PixelFormat.getByteBgraInstance(),
        pixelBytes, 0, width * 4);
Image image2 = new Image(new ByteArrayInputStream(pixelBytes));
ImageView view2 = new ImageView(image2);
pane.getChildren().add(view2);  // Won't work

// PixelWriter generated image
WritableImage image3 = new WritableImage(width, height);
image3.getPixelWriter().setPixels(0, 0, width, height,
        PixelFormat.getByteBgraInstance(),
        pixelBytes, 0, width * 4);
ImageView view3 = new ImageView(image3);
pane.getChildren().add(view3);  // Works

Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();

PixelReader图像是原始图像格式,比原始图像大得多,因此,如果将这些图像存储在数据库中并且担心空间,则应尝试存储原始文件字节。否则,SwingFXUtils类仍可用于转换回压缩格式。

写回PixelReader图像字节时的另一个问题是,您必须以某种方式将宽度和高度存储为数据库中的单独字段,或者作为额外字节在图像字节数组上添加/添加。