@@ -372,7 +372,7 @@ public Image(Device device, ImageData data) {
372372 if (data == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
373373 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
374374 int deviceZoom = getZoom ();
375- data = DPIUtil . scaleImageData (device , new ElementAtZoom <>( data , 100 ), deviceZoom );
375+ data = scaleImageData (data , deviceZoom , 100 );
376376 init (data , deviceZoom );
377377 init ();
378378 this .device .registerResourceWithZoomSupport (this );
@@ -416,8 +416,8 @@ public Image(Device device, ImageData source, ImageData mask) {
416416 SWT .error (SWT .ERROR_INVALID_ARGUMENT );
417417 }
418418 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
419- source = DPIUtil . autoScaleUp ( device , source );
420- mask = DPIUtil . autoScaleUp ( device , mask );
419+ source = scaleImageData ( source , getZoom (), 100 );
420+ mask = scaleImageData ( mask , getZoom (), 100 );
421421 mask = ImageData .convertMask (mask );
422422 initIconHandle (this .device , source , mask , getZoom ());
423423 init ();
@@ -481,7 +481,8 @@ public Image (Device device, InputStream stream) {
481481 super (device );
482482 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
483483 int deviceZoom = getZoom ();
484- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (stream , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
484+ ElementAtZoom <ImageData > imageCandidate = ImageDataLoader .load (stream , FileFormat .DEFAULT_ZOOM , deviceZoom );
485+ ImageData data = scaleImageData (imageCandidate .element (), deviceZoom , imageCandidate .zoom ());
485486 init (data , deviceZoom );
486487 init ();
487488 this .device .registerResourceWithZoomSupport (this );
@@ -524,7 +525,8 @@ public Image (Device device, String filename) {
524525 if (filename == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
525526 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
526527 int deviceZoom = getZoom ();
527- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (filename , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
528+ ElementAtZoom <ImageData > imageCandidate = ImageDataLoader .load (filename , FileFormat .DEFAULT_ZOOM , deviceZoom );
529+ ImageData data = scaleImageData (imageCandidate .element (), deviceZoom , imageCandidate .zoom ());
528530 init (data , deviceZoom );
529531 init ();
530532 this .device .registerResourceWithZoomSupport (this );
@@ -1264,7 +1266,7 @@ private ImageData getScaledImageData (int zoom) {
12641266 }
12651267 TreeSet <Integer > availableZooms = new TreeSet <>(zoomLevelToImageHandle .keySet ());
12661268 int closestZoom = Optional .ofNullable (availableZooms .higher (zoom )).orElse (availableZooms .lower (zoom ));
1267- return DPIUtil . scaleImageData ( device , getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
1269+ return scaleImageData ( getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
12681270}
12691271
12701272
@@ -1854,6 +1856,40 @@ public void setBackground(Color color) {
18541856 zoomLevelToImageHandle .values ().forEach (imageHandle -> imageHandle .setBackground (backgroundColor ));
18551857}
18561858
1859+ private ImageData scaleImageData (final ImageData imageData , int targetZoom , int currentZoom ) {
1860+ if (imageData == null || targetZoom == currentZoom || (device != null && !device .isAutoScalable ())) return imageData ;
1861+ float scaleFactor = (float ) targetZoom / (float ) currentZoom ;
1862+ int width = imageData .width ;
1863+ int height = imageData .height ;
1864+ int scaledWidth = Math .round (width * scaleFactor );
1865+ int scaledHeight = Math .round (height * scaleFactor );
1866+ boolean useSmoothScaling = DPIUtil .isSmoothScalingEnabled () && imageData .getTransparencyType () != SWT .TRANSPARENCY_MASK ;
1867+ if (useSmoothScaling ) {
1868+ return scaleToUsingSmoothScaling (scaledWidth , scaledHeight , imageData );
1869+ }
1870+ return imageData .scaledTo (scaledWidth , scaledHeight );
1871+ }
1872+
1873+ private ImageData scaleToUsingSmoothScaling (int width , int height , ImageData imageData ) {
1874+ Image original = new Image (device , (ImageDataProvider ) zoom -> imageData );
1875+ /* Create a 24 bit image data with alpha channel */
1876+ final ImageData resultData = new ImageData (width , height , 24 , new PaletteData (0xFF , 0xFF00 , 0xFF0000 ));
1877+ resultData .alphaData = new byte [width * height ];
1878+ Image resultImage = new Image (device , (ImageDataProvider ) zoom -> resultData );
1879+ GC gc = new GC (resultImage );
1880+ gc .setAntialias (SWT .ON );
1881+ gc .drawImage (original , 0 , 0 , imageData .width , imageData .height ,
1882+ /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
1883+ * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
1884+ */
1885+ 0 , 0 , width , height , false );
1886+ gc .dispose ();
1887+ original .dispose ();
1888+ ImageData result = resultImage .getImageData (resultImage .getZoom ());
1889+ resultImage .dispose ();
1890+ return result ;
1891+ }
1892+
18571893private int getZoom () {
18581894 return DPIUtil .getZoomForAutoscaleProperty (initialNativeZoom );
18591895}
@@ -2073,7 +2109,7 @@ ImageData getImageData(int zoom) {
20732109
20742110 private ImageData scaleIfNecessary (ElementAtZoom <ImageData > imageDataAtZoom , int zoom ) {
20752111 if (imageDataAtZoom .zoom () != zoom ) {
2076- return DPIUtil . scaleImageData (device , imageDataAtZoom , zoom );
2112+ return scaleImageData (imageDataAtZoom . element (), zoom , imageDataAtZoom . zoom () );
20772113 } else {
20782114 return imageDataAtZoom .element ();
20792115 }
@@ -2298,13 +2334,13 @@ private class ImageDataProviderWrapper extends BaseImageProviderWrapper<ImageDat
22982334 @ Override
22992335 ImageData getImageData (int zoom ) {
23002336 ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2301- return DPIUtil . scaleImageData ( device , data .element (), zoom , data .zoom ());
2337+ return scaleImageData ( data .element (), zoom , data .zoom ());
23022338 }
23032339
23042340 @ Override
23052341 ImageHandle getImageMetadata (int zoom ) {
23062342 ElementAtZoom <ImageData > imageCandidate = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2307- ImageData resizedData = DPIUtil . scaleImageData ( device , imageCandidate .element (), zoom , imageCandidate .zoom ());
2343+ ImageData resizedData = scaleImageData ( imageCandidate .element (), zoom , imageCandidate .zoom ());
23082344 ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
23092345 init (newData , zoom );
23102346 return zoomLevelToImageHandle .get (zoom );
0 commit comments