| Summary: | [HiDPI] GC.copyArea() and Image.getImageData() behave differently (and buggy) MacOS 10.13.6. | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | Tim Mueller <legendaerer> | ||||
| Component: | SWT | Assignee: | Sravan Kumar Lakkimsetti <sravankumarl> | ||||
| Status: | RESOLVED FIXED | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | ericwill, felix.hirsch, lshanmug, mariomarinato, p.beauvoir, rkd540 | ||||
| Version: | 4.9 | ||||||
| Target Milestone: | 4.11 | ||||||
| Hardware: | All | ||||||
| OS: | Mac OS X | ||||||
| See Also: |
https://git.eclipse.org/r/133059 https://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=1fdceeecf03490cf104f153703ea774962a5e0a2 |
||||||
| Whiteboard: | |||||||
| Bug Depends on: | |||||||
| Bug Blocks: | 538680, 541840 | ||||||
| Attachments: |
|
||||||
|
Description
Tim Mueller
I found out that the windows behavior of Image.getImageData() seems to be correct to return only the low resolution image with 100% zoom level. The Mac version returns the high resolution version which seems to be wrong, since javadoc says Image.getImageData(int zoom) should be used to obtain the image at different zoom levels. Since SWT operates on logical pixel instead of physical HiDpi pixels the windows behavior seems correct. If using Image.getImageData(200) on Mac, it even returns an image with 2 times the retina resolution => on Mac images seem to be scaled from the HiDpi version as the 100% basis, whereas on Windows the non-HiDpi version is used as 100% basis. That means the proposed fix 2) should be changed to fix the Mac behavior to return the low resolution image for Image.getImageData() like it is done on Windows. Also it would be good to know what is the current display zoom level and what maximum resolution is available for an image captured with GC.copyArea(). Currently I found only the system property org.eclipse.swt.internal.deviceZoom as an official way to get to know the zoom. Could we just get a normal API call instead? (In reply to Tim Mueller from comment #0) > GC.copyArea() and Image.getImageData() behave differently (and buggy) on > HiDPI screens on Windows10 and MacOS 10.13.6. > > GC.copyArea(image, 0,0): > on Mac: makes a copy of the HiDPI screen and stores only the HiDPI (x2) > version in the image. Not a downscaled x1 version. While this seems correct, > it leads to the situation that if the image is drawn with less than 50% zoom > with gc.drawImage(image, 0, 0) then it will draw no image at all. Probably > because MacOS tries to draw or scale from the 100% x1 non-retina image which > is not available in the image. Drawing with zoom>50% works fine. > Can you pls provide a snippet/sample code to reproduce this? (In reply to Tim Mueller from comment #1) > Also it would be good to know what is the current display zoom level and > what maximum resolution is available for an image captured with > GC.copyArea(). Currently I found only the system property > org.eclipse.swt.internal.deviceZoom as an official way to get to know the > zoom. Could we just get a normal API call instead? Since 4.8, Monitor.getZoom() returns the zoom value for the monitor . You can get the monitor using Control.getMonitor(). Here is the code that I am using to take the screenshot on all platforms. It already contains code to work around the issue and obtain a screenshot with full resolution on all platforms:
GC screenGC = new GC(mw.display);
Image screenshot = new Image(mw.display, mw.display.getBounds());
mw.shell.setMinimized(true);
long time = System.currentTimeMillis();
while(System.currentTimeMillis()-time < millis){
try {
Thread.sleep(millis - (System.currentTimeMillis()-time));
} catch (InterruptedException e) {}
}
screenGC.copyArea(screenshot, 0, 0);
mw.shell.setMinimized(false);
screenGC.dispose();
// XXX on mac with SWT4.9 if the screenshot is taken from a HiDpi display and zoom < 0.5 during image painting there is no image available
// see Bug 538487
// therefore we copy the image and create a double size image
// this must be only enabled on HiDpi devices!!
if (HiDpiUtils.getDeviceZoomPercent()!=100){
// HiDPI display, take the full resolution image and store it at 100% to allow access to all pixels
ImageData imData = null;
if (OSAdapter.isMac()){
// work around Mac SWT bug to return full resolution with this call
imData = screenshot.getImageData(); // on SWT 4.9RC1 this returns the full resolution on Mac
}else {
imData = screenshot.getImageData(HiDpiUtils.getDeviceZoomPercent());
}
screenshot.dispose();
screenshot = new Image(mw.display, imData);
}
Hope this helps
(In reply to Tim Mueller from comment #3) > Here is the code that I am using to take the screenshot on all platforms. It > already contains code to work around the issue and obtain a screenshot with > full resolution on all platforms: > > GC screenGC = new GC(mw.display); > Image screenshot = new Image(mw.display, mw.display.getBounds()); > mw.shell.setMinimized(true); > long time = System.currentTimeMillis(); > while(System.currentTimeMillis()-time < millis){ > try { > Thread.sleep(millis - (System.currentTimeMillis()-time)); > } catch (InterruptedException e) {} > } > screenGC.copyArea(screenshot, 0, 0); > mw.shell.setMinimized(false); > screenGC.dispose(); > > // XXX on mac with SWT4.9 if the screenshot is taken from a HiDpi display > and zoom < 0.5 during image painting there is no image available > // see Bug 538487 > // therefore we copy the image and create a double size image > // this must be only enabled on HiDpi devices!! > if (HiDpiUtils.getDeviceZoomPercent()!=100){ > // HiDPI display, take the full resolution image and store it at 100% to > allow access to all pixels > ImageData imData = null; > if (OSAdapter.isMac()){ > // work around Mac SWT bug to return full resolution with this call > imData = screenshot.getImageData(); // on SWT 4.9RC1 this returns the > full resolution on Mac > }else { > imData = screenshot.getImageData(HiDpiUtils.getDeviceZoomPercent()); > } > screenshot.dispose(); > screenshot = new Image(mw.display, imData); > } > > Hope this helps This Problem is reproducible an even the workaround does not work for me.Creating second image with image data creates a empty image Though I am not suer here whether this workaround is foir mac or windows as check with mac does nothing other then getting the imagedata if (OSAdapter.isMac()){ > // work around Mac SWT bug to return full resolution with this call > imData = screenshot.getImageData(); // on SWT 4.9RC1 this returns the Attached the snippets where I could able to reproduce the problem Created attachment 276615 [details]
Snippets To reproduce this issue
Getting imagedata and creating the image out of the imagedata produce white image always
(In reply to Rajesh Dash from comment #4) > > This Problem is reproducible an even the workaround does not work for > me.Creating second image with image data creates a empty image Though I am > not suer here whether this workaround is foir mac or windows as check with > mac does nothing other then getting the imagedata > > if (OSAdapter.isMac()){ > > // work around Mac SWT bug to return full resolution with this call > > imData = screenshot.getImageData(); // on SWT 4.9RC1 this returns the > > Attached the snippets where I could able to reproduce the problem Which version of eclipse are you using? I'm unable to reproduce the empty image problem with your snippet on 4.9 and mac OS 10.13.6. The problem I see is that the captured image is double the size. Sravan, I think the changes to Image.getImageData(int) from https://git.eclipse.org/r/#/c/132283/ will fix the Image doubling problem, can you please verify? New Gerrit change created: https://git.eclipse.org/r/133059 https://git.eclipse.org/r/133059 This is returning a blurry image. which is a no go. Moving to 4.11 I have tested SWT 4.11M1 on MacOS Mojave (10.14) and the behavior is still the same: screenGC.copyArea(screenshot, 0, 0); imData = screenshot.getImageData(); => image width = 3360 screenGC.copyArea(screenshot, 0, 0); imData = imData = screenshot.getImageData(shell.getMonitor().getZoom()); => image width = 6720 (shell.getMonitor().getZoom() = 200) (In reply to Tim Mueller from comment #10) > I have tested SWT 4.11M1 on MacOS Mojave (10.14) and the behavior is still > the same: > > screenGC.copyArea(screenshot, 0, 0); > imData = screenshot.getImageData(); > > => image width = 3360 > > screenGC.copyArea(screenshot, 0, 0); > imData = imData = screenshot.getImageData(shell.getMonitor().getZoom()); > > => image width = 6720 > (shell.getMonitor().getZoom() = 200) This is expected as getImageData() works with 100% image, and getImageData(200) works with 200% image. So you'll find double size I thought screenshot.getImageData() should return an image with a width specified in logical pixels not physical pixels. 3360 is the width of the screen in physical pixels on a 15inch MacBook Pro Retina. 1680 would be the number of logical pixels. As I wrote in the initial bug report, the behavior on windows 10 is different. There it will return the number of logical pixels. (In reply to Tim Mueller from comment #12) > I thought screenshot.getImageData() should return an image with a width > specified in logical pixels not physical pixels. 3360 is the width of the > screen in physical pixels on a 15inch MacBook Pro Retina. 1680 would be the > number of logical pixels. > > As I wrote in the initial bug report, the behavior on windows 10 is > different. There it will return the number of logical pixels. You are right. I will take a look. If you have snippet can you please attach to this bug? @Sravan, Please create a separate patch to handle proper scaling of getImageData(200) on non-retina display. I am pushing a patch today. Please check tomorrow's build and let me know if this fixes you issue Gerrit change https://git.eclipse.org/r/133059 was merged to [master]. Commit: http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/?id=1fdceeecf03490cf104f153703ea774962a5e0a2 (In reply to Lakshmi Shanmugam from comment #14) > @Sravan, > Please create a separate patch to handle proper scaling of getImageData(200) > on non-retina display. Raised bug 544341 to address this (In reply to Eclipse Genie from comment #16) > Gerrit change https://git.eclipse.org/r/133059 was merged to [master]. > Commit: > http://git.eclipse.org/c/platform/eclipse.platform.swt.git/commit/ > ?id=1fdceeecf03490cf104f153703ea774962a5e0a2 Merged to master This is bug is back. On Eclipse 2022-12, the snippet generates white images. As far as I can tell, it's been like this since SWT 4.18. (In reply to Mario Marinato from comment #19) > This is bug is back. On Eclipse 2022-12, the snippet generates white images. > As far as I can tell, it's been like this since SWT 4.18. It might be better if you open a new bug at https://github.com/eclipse-platform/eclipse.platform.swt/issues and reference this one. If you can add a Snippet to the bug as well. I'll sure do, Phil. Thanks for the info. |