【问题标题】:Convert JavaFX Image object to byte array将 JavaFX Image 对象转换为字节数组
【发布时间】:2016-10-31 22:45:26
【问题描述】:

我们可以通过使用来创建 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。 此外,我想将其转换为字节数组,以便将其写入图像文件。

【问题讨论】:

标签: image javafx bytearray


【解决方案1】:

使用ByteArrayInputStream 创建JavaFX Image 只能使用supported formats 中的原始、未修改的图像文件字节(bmp、jpg、gif、png)。

使用PixelReader 读取Image 后,字节数组将包含只能使用PixelWriter 写回WritableImage 的原始图像字节,这就是使用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 图像字节时的另一个问题是,您必须以某种方式将宽度和高度存储为数据库中的单独字段,或者作为额外字节添加/附加到图像字节数组中。

【讨论】:

    【解决方案2】:

    这是以后的事情了,但如果有人想知道,试试这个:

    // 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. */
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-28
      • 2021-11-30
      • 1970-01-01
      • 2014-01-07
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      • 2016-10-24
      相关资源
      最近更新 更多