We can create FX Image object by using
byte [] bytes = ------; //valid image in bytes
javafx.scene.image.Image image = new Image(new ByteArrayInputStream(bytes));
And this can be set to an ImageView.
I need the opposite without converting it first to the BufferedImage (SwingFXUtils.fromFXImage(image,null)).
So that I can directly write the bytes to a file.
I've tried the following:
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
);
But the file generated by writing the byte [] buffer is not a valid image.
Any insights on this?
EDIT: The solutions given at How to get byte[] from javafx imageView cannot be applied to my question. As I've already mentioned clearly that I do not want to use converting it to BufferedImage using SwingFXUtils. Moreover, I want to convert it to the byte array so that it can be written to an image file.
This is way later, but if anybody is wanting to find out, try this:
// 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. */
Using ByteArrayInputStream
to create a JavaFX Image
will only work using the original, unmodified image file bytes in the supported formats (bmp, jpg, gif, png).
After using PixelReader
to read an Image
, the byte array will contain raw image bytes that can only be written back to a WritableImage
using the PixelWriter
, which is why using ByteArrayInputStream
produces an invalid image.
Below is a reproducible example using this 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();
As a raw image format, the PixelReader
image is much larger than the original, so if you are storing these images in a database and are concerned about space then you should try storing the original file bytes instead. Otherwise, the SwingFXUtils
class can still be used to convert back to compressed format.
Another issue when writing back PixelReader
image bytes is that you must somehow store the width and height, either as separate fields in the database or prepended/appended as extra bytes onto the image byte array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With