Skip to content

Conversation

@ptziegler
Copy link
Contributor

When drawing an image on a scaled Graphics object, the image data at 100% zoom is taken and then artificially up-scaled. This results in blurry images when scaling by high factors.

This change adapts the FileImageDataProvider and the SWTGraphics to take this problem into consideration, especially when dealing with SVGs.

The FileImageDataProvider is currently not able to return the ImageData at arbitrary zoom levels, as this is not supported by SWT, which requires the ImageFileNameProvider (or the internal ImageDataAtSizeProvider) to be implemented. The problem with the ImageFileNameProvider is that it can only return proper file paths. So if an image is embedded inside a jar, it first needs to be extracted into a temporary file.

The SWTGraphics then needs to use the new
drawImage(Image,int,int,int,int) method so that SWT uses this provider to probler scale the image to the correct size.

…gef#922

When drawing an image on a scaled `Graphics` object, the image data at
100% zoom is taken and then artificially up-scaled. This results in
blurry images when scaling by high factors.

This change adapts the `FileImageDataProvider` and the `SWTGraphics` to
take this problem into consideration, especially when dealing with SVGs.

The `FileImageDataProvider` is currently not able to return the
`ImageData` at arbitrary zoom levels, as this is not supported by SWT,
which requires the `ImageFileNameProvider` (or the internal
`ImageDataAtSizeProvider`) to be implemented. The problem with the
`ImageFileNameProvider` is that it can only return proper file paths. So
if an image is embedded inside a jar, it first needs to be extracted
into a temporary file.

The `SWTGraphics` then needs to use the new
`drawImage(Image,int,int,int,int)` method so that SWT uses this provider
to probler scale the image to the correct size.
@ptziegler
Copy link
Contributor Author

image
Screencast_20251222_182403.webm

Comment on lines +420 to +448
if (transform == null) {
gc.drawImage(srcImage, x + translateX, y + translateY);
} else {
float[] transformElements = new float[6];
transform.getElements(transformElements);

float scaleHor = transformElements[0];
float scaleVer = transformElements[3];

if (scaleHor == 1.0 && scaleVer == 1.0) {
gc.drawImage(srcImage, x + translateX, y + translateY);
return;
}

ImageData srcImageData = srcImage.getImageData(100);
int scaledX = (int) ((x + translateX) * scaleHor);
int scaledY = (int) ((y + translateY) * scaleVer);
int scaledWidth = (int) (srcImageData.width * scaleHor);
int scaledHeight = (int) (srcImageData.height * scaleVer);

transform.scale(1 / scaleHor, 1 / scaleVer);
gc.setTransform(transform);
try {
gc.drawImage(srcImage, scaledX, scaledY, scaledWidth, scaledHeight);
} finally {
transform.scale(scaleHor, scaleVer);
gc.setTransform(transform);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably safer to add a new drawImage(Image,int,int,int,int) method, rather than changing the behavior of an existing method.

float[] transformElements = new float[6];
transform.getElements(transformElements);

float scaleHor = transformElements[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For #926 I brushed up my knowledge on vector math and transformation matrices. If you want to be correct in cases when rotation is applied then you need to take the elements 1 and 2 also into account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants