-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
P3
-
Affects Version/s: jfx11, jfx17, jfx21, jfx25, jfx26
-
Component/s: javafx
-
generic
ADDITIONAL SYSTEM INFORMATION :
openjdk version "25.0.1" 2025-10-21 LTS
OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
SwingFXUtils.toFXImage is used to convert BufferedImage to WritableImage. Howerver, in cases when input BufferedImage was obtained by calling `BufferedImage.getSubimage(offsetX, offsetY, ...)` on BufferedImage with TYPE_INT_ARGB or TYPE_INT_ARGB_PRE , returned WritableImage contains data from original BufferedImage, without offset.
REGRESSION : Last worked in version 8u471
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
* Find some test image, place it into test.png
* Run Reproducer.java (included below)
---------- BEGIN SOURCE ----------
//| jvmId: temurin:25.0.1
//| mvnDeps:
//| - org.openjfx:javafx-base:25.0.1
//| - org.openjfx:javafx-graphics:25.0.1
//| - org.openjfx:javafx-swing:25.0.1
import java.io.File;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import javax.imageio.ImageIO;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.WritableImage;
public class Reproducer {
public static void main(String[] arg) throws Exception {
BufferedImage inputImage = ImageIO.read(new File("test.png"));
BufferedImage argbImage = new BufferedImage(
inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_INT_ARGB
);
Graphics2D g2d = argbImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, null);
g2d.dispose();
BufferedImage croppedImage = argbImage.getSubimage(100, 100, argbImage.getWidth() - 100, argbImage.getHeight() - 100);
WritableImage writableImage = SwingFXUtils.toFXImage(croppedImage, null);
BufferedImage outputImage = SwingFXUtils.fromFXImage(writableImage, null);
if (!ImageIO.write(outputImage, "png", new File("output.png"))) {
System.out.println("boom");
} else {
System.out.println("done");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I tested the following fix locally, it solves the issue:
diff --git a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
index c6c962b34e..c75c0a8bce 100644
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
@@ -110,11 +110,15 @@ public class SwingFXUtils {
PixelWriter pw = wimg.getPixelWriter();
DataBufferInt db = (DataBufferInt)bimg.getRaster().getDataBuffer();
int data[] = db.getData();
- int offset = bimg.getRaster().getDataBuffer().getOffset();
- int scan = 0;
- SampleModel sm = bimg.getRaster().getSampleModel();
+
+ int scan = 0;
+ int offset = bimgRaster.getDataBuffer().getOffset();
+ SampleModel sm = bimgRaster.getSampleModel();
if (sm instanceof SinglePixelPackedSampleModel) {
scan = ((SinglePixelPackedSampleModel)sm).getScanlineStride();
+ offset += (-bimgRaster.getSampleModelTranslateY()) * scan + (-bimgRaster.getSampleModelTranslateX());
+ } else {
+ throw new RuntimeException("toFXImage only supports SinglePixelPackedSampleModel");
}
PixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
FREQUENCY :
ALWAYS
openjdk version "25.0.1" 2025-10-21 LTS
OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
SwingFXUtils.toFXImage is used to convert BufferedImage to WritableImage. Howerver, in cases when input BufferedImage was obtained by calling `BufferedImage.getSubimage(offsetX, offsetY, ...)` on BufferedImage with TYPE_INT_ARGB or TYPE_INT_ARGB_PRE , returned WritableImage contains data from original BufferedImage, without offset.
REGRESSION : Last worked in version 8u471
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
* Find some test image, place it into test.png
* Run Reproducer.java (included below)
---------- BEGIN SOURCE ----------
//| jvmId: temurin:25.0.1
//| mvnDeps:
//| - org.openjfx:javafx-base:25.0.1
//| - org.openjfx:javafx-graphics:25.0.1
//| - org.openjfx:javafx-swing:25.0.1
import java.io.File;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import javax.imageio.ImageIO;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.WritableImage;
public class Reproducer {
public static void main(String[] arg) throws Exception {
BufferedImage inputImage = ImageIO.read(new File("test.png"));
BufferedImage argbImage = new BufferedImage(
inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_INT_ARGB
);
Graphics2D g2d = argbImage.createGraphics();
g2d.drawImage(inputImage, 0, 0, null);
g2d.dispose();
BufferedImage croppedImage = argbImage.getSubimage(100, 100, argbImage.getWidth() - 100, argbImage.getHeight() - 100);
WritableImage writableImage = SwingFXUtils.toFXImage(croppedImage, null);
BufferedImage outputImage = SwingFXUtils.fromFXImage(writableImage, null);
if (!ImageIO.write(outputImage, "png", new File("output.png"))) {
System.out.println("boom");
} else {
System.out.println("done");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I tested the following fix locally, it solves the issue:
diff --git a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
index c6c962b34e..c75c0a8bce 100644
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java
@@ -110,11 +110,15 @@ public class SwingFXUtils {
PixelWriter pw = wimg.getPixelWriter();
DataBufferInt db = (DataBufferInt)bimg.getRaster().getDataBuffer();
int data[] = db.getData();
- int offset = bimg.getRaster().getDataBuffer().getOffset();
- int scan = 0;
- SampleModel sm = bimg.getRaster().getSampleModel();
+
+ int scan = 0;
+ int offset = bimgRaster.getDataBuffer().getOffset();
+ SampleModel sm = bimgRaster.getSampleModel();
if (sm instanceof SinglePixelPackedSampleModel) {
scan = ((SinglePixelPackedSampleModel)sm).getScanlineStride();
+ offset += (-bimgRaster.getSampleModelTranslateY()) * scan + (-bimgRaster.getSampleModelTranslateX());
+ } else {
+ throw new RuntimeException("toFXImage only supports SinglePixelPackedSampleModel");
}
PixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
FREQUENCY :
ALWAYS