Skip to content

"Smooth" scaling produces blurry images after calling image.getImageData().clone() #2052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
tobiasmelcher opened this issue Apr 14, 2025 · 11 comments · Fixed by #1996
Closed
2 tasks done
Assignees
Labels
bug Something isn't working HiDPI Issues related to High resolution monitors Windows Happens on Windows OS

Comments

@tobiasmelcher
Copy link
Contributor

tobiasmelcher commented Apr 14, 2025

Steps to reproduce

From a fresh installation and clean workspace:

  • download the attached sample plugin, extract it, import into workspace and run target platform
    simple.zip
  • open the "Sample view" provided by the simple plugin in the target platform
  • icons in the tree viewer are blurry and not sharp
    Image

Images are no longer blurry after disabling the setting "Use monitor-specific UI scaling" (https://eclipse.dev/eclipse/news/4.36/platform.html#rescaleOnRuntimePreference)

The image is created via following code:

if (cachedElement == null) {
  String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
  cachedElement = workbench.getSharedImages().getImage(imageKey);
}
ImageData imageData = (ImageData) cachedElement.getImageData().clone();
cachedElement = new Image(Display.getCurrent(), imageData);

It looks like that data is lost when calling new Image(Display.getCurrent(), image.getImageData().clone()); when "Use monitor-specific UI scaling" is enabled.

Could you please help in fixing this issue?

Thanks a lot,
Tobias

Tested under this environment:

  • OS & version: Windows 11 - DPIUtil#deviceZoom has value 200

Workarounds

  1. Use the nearest algorithm to scale images by setting this JVM flag: -Dswt.autoScale.method=nearest. The results are not optimal but they are not blurry.
  1. Use the constructor that takes a source Image instead of the one that takes the ImageData.
...
cachedFolder = new Image(cachedFolder.getDevice(), cachedFolder, SWT.IMAGE_COPY);
return cachedFolder;

Community

  • I understand reporting an issue to this OSS project does not mandate anyone to fix it. Other contributors may consider the issue, or not, at their own convenience. The most efficient way to get it fixed is that I fix it myself and contribute it back as a good quality patch to the project.
@HeikoKlare
Copy link
Contributor

Thank you for the report! We will have a look at this.

@fedejeanne fedejeanne assigned fedejeanne and unassigned fedejeanne Apr 16, 2025
@fedejeanne
Copy link
Contributor

fedejeanne commented Apr 22, 2025

I am testing this and I can reproduce it in Windows 10 too. These details are missing in the bug description:

  • The images are blurry only if they are first instantiated in a big monitor (e.g. 200%). If the workbench is started in a 100% monitor the images are not blurry
  • Once the images are blurry, moving them to another monitor doesn't fix the issue.

I am testing with 2 monitors, one at 100% and one at 200%.

@fedejeanne
Copy link
Contributor

I was able to pinpoint the issue: it's the anti-alias that makes the images blurry. I still don't know why is this causing a problem in this particular use-case but commenting out this line in org.eclipse.swt.internal.DPIUtil.autoScaleImageData(Device, ImageData, float) makes the issue go away:

Alternatively, one can use the nearest algorithm to scale images by setting this JVM flag: -Dswt.autoScale.method=nearest.

I'll add it as a workaround in the description and I will continue to dig deeper tomorrow.

fedejeanne referenced this issue in vi-eclipse/eclipse.platform.swt Apr 23, 2025
Defaulting to "smooth" creates blurry images when first displaying the
image in a monitor with a high zoom level (e.g. 200%).

This is a temporary workaround until
https://github.com/eclipse-platform/eclipse.platform.ui/issues/2910 is
properly fixed.
fedejeanne referenced this issue in vi-eclipse/eclipse.platform.swt Apr 23, 2025
Defaulting to "smooth" creates blurry images when first displaying the
image in a monitor with a high zoom level (e.g. 200%).

This is a temporary workaround until
https://github.com/eclipse-platform/eclipse.platform.ui/issues/2910 is
properly fixed.
@fedejeanne
Copy link
Contributor

Since today should be the build for M2, I have a workaround in store just in case there is no proper fix in time: #2051

@fedejeanne fedejeanne transferred this issue from eclipse-platform/eclipse.platform.ui Apr 23, 2025
@fedejeanne fedejeanne self-assigned this Apr 23, 2025
@merks
Copy link
Contributor

merks commented Apr 23, 2025

@akurtakov FYI

Since we've been doing light-weight M* it's generally the build on Friday that is the build that's contributed. And, given all the infrastructure problems, e.g.,

https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/issues/5892

we might well slip into the weekend and contribute a build from Sunday...

@fedejeanne fedejeanne added Windows Happens on Windows OS HiDPI Issues related to High resolution monitors labels Apr 23, 2025
@fedejeanne fedejeanne changed the title Images are getting blurry after calling image.getImageData().clone() "Smooth" scaling produces blurry images. Apr 23, 2025
@fedejeanne
Copy link
Contributor

@akurtakov FYI

Since we've been doing light-weight M* it's generally the build on Friday that is the build that's contributed. And, given all the infrastructure problems, e.g.,

https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/issues/5892

we might well slip into the weekend and contribute a build from Sunday...

... the silver lining :-D

Thanks Ed!

@fedejeanne fedejeanne changed the title "Smooth" scaling produces blurry images. "Smooth" scaling produces blurry images after calling image.getImageData().clone() Apr 23, 2025
@fedejeanne
Copy link
Contributor

I just found out that the issue does not come from cloning the ImageData but from using the constructor with the ImageData i.e. even if you use the original data, images will be blurry.

Said in code:

private Image getImage(Object obj) {
	if (obj instanceof TreeParent) {
		if (cachedFolder == null) {
			String imageKey = ISharedImages.IMG_OBJ_FOLDER;
			cachedFolder = workbench.getSharedImages().getImage(imageKey);
		}

		// Don't use the constructor with ImageData, use the one with a source Image to copy from
		cachedFolder = new Image(cachedFolder.getDevice(), cachedFolder, SWT.IMAGE_COPY);
		return cachedFolder;
	}
	if (cachedElement == null) {
		String imageKey = ISharedImages.IMG_OBJ_ELEMENT;
		cachedElement = workbench.getSharedImages().getImage(imageKey);
	}
	ImageData sameImageData = (ImageData) cachedElement.getImageData()/*.clone()*/;
	
	// This constructor still produces a blurry image.
	cachedElement = new Image(Display.getCurrent(), sameImageData);
	
	return cachedElement;
}

And it looks like this:

Image

@fedejeanne
Copy link
Contributor

After analyzing the provided sample code more in detail, the issue is that the cachedElement and cachedFolder images are generated over and over and this leads to the scaling algorithm being applied several times.

There is probably something that could be done to support these kind of use cases but in the meantime, can you please tell us where does the snippet of code come from @tobiasmelcher ? Is it adapted from code in Platform or is it in your product?

In any case, the code should generated the "original" images only once and, if necessary, produce the "clone" images always based on the original image.

@akoch-yatta
Copy link
Contributor

Btw. after understanding the root cause I tested this issue with #1996 and improves this behavior a lot.

@tobiasmelcher
Copy link
Contributor Author

After analyzing the provided sample code more in detail, the issue is that the cachedElement and cachedFolder images are generated over and over and this leads to the scaling algorithm being applied several times.

There is probably something that could be done to support these kind of use cases but in the meantime, can you please tell us where does the snippet of code come from @tobiasmelcher ? Is it adapted from code in Platform or is it in your product?

In any case, the code should generated the "original" images only once and, if necessary, produce the "clone" images always based on the original image.

The code was used in our product ABAP Development Tools in Eclipse. I think we did clone the images by mistake. It was working fine before introduction of the "Monitor-specific UI scaling" feature. I already adapted our code so that the problem does no longer occur. Anyhow, I think that the eclipse behavior changed here in an incompatible way. new Image(Display.getCurrent(), imageData) behaves now different than before.

@fedejeanne
Copy link
Contributor

The code was used in our product ABAP Development Tools in Eclipse.

Thank you for the info, @tobiasmelcher . Good to know that it's not code in Platform, this means that there is no need to adapt any more code.

Anyhow, I think that the eclipse behavior changed here in an incompatible way. new Image(Display.getCurrent(), imageData) behaves now different than before.

Agreed, the behavior changed. Thank you for reporting it!

HeikoKlare added a commit to vi-eclipse/eclipse.platform.swt that referenced this issue Apr 24, 2025
Due to the on-demand creation of image handles, there is not necessarily
a handles anymore from which image data is retrieved when requesting is
via the getImageData(...) methods. This results in potentially different
kinds of image data (including different anti-aliasing results)
depending on whether a handle has already been created for an image at
the given zoom or not.

This change adapts the implementation of Image based on static ImageData
and streams to always use the image data retrieved from a native handle.
To this end, it temporarily creates a handle if necessary. In order to
avoid repeated loading and handle creation for the same source of image,
a cache for the already retrieved image data is introduced.

Fixes eclipse-platform#2052
HeikoKlare added a commit to vi-eclipse/eclipse.platform.swt that referenced this issue Apr 24, 2025
Due to the on-demand creation of image handles, there is not necessarily
a handles anymore from which image data is retrieved when requesting is
via the getImageData(...) methods. This results in potentially different
kinds of image data (including different anti-aliasing results)
depending on whether a handle has already been created for an image at
the given zoom or not.

This change adapts the implementation of Image based on static ImageData
and streams to always use the image data retrieved from a native handle.
To this end, it temporarily creates a handle if necessary. In order to
avoid repeated loading and handle creation for the same source of image,
a cache for the already retrieved image data is introduced.

Fixes eclipse-platform#2052
HeikoKlare added a commit to vi-eclipse/eclipse.platform.swt that referenced this issue Apr 24, 2025
Due to the on-demand creation of image handles, there is not necessarily
a handles anymore from which image data is retrieved when requesting is
via the getImageData(...) methods. This results in potentially different
kinds of image data (including different anti-aliasing results)
depending on whether a handle has already been created for an image at
the given zoom or not.

This change adapts the implementation of Image based on static ImageData
and streams to always use the image data retrieved from a native handle.
To this end, it temporarily creates a handle if necessary. In order to
avoid repeated loading and handle creation for the same source of image,
a cache for the already retrieved image data is introduced.

Fixes eclipse-platform#2052
HeikoKlare added a commit to vi-eclipse/eclipse.platform.swt that referenced this issue Apr 24, 2025
Due to the on-demand creation of image handles, there is not necessarily
a handles anymore from which image data is retrieved when requesting is
via the getImageData(...) methods. This results in potentially different
kinds of image data (including different anti-aliasing results)
depending on whether a handle has already been created for an image at
the given zoom or not.

This change adapts the implementation of Image based on static ImageData
and streams to always use the image data retrieved from a native handle.
To this end, it temporarily creates a handle if necessary. In order to
avoid repeated loading and handle creation for the same source of image,
a cache for the already retrieved image data is introduced.

Fixes eclipse-platform#2052
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working HiDPI Issues related to High resolution monitors Windows Happens on Windows OS
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants