@@ -361,7 +361,7 @@ public Image(Device device, ImageData data) {
361361 if (data == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
362362 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
363363 int deviceZoom = getZoom ();
364- data = DPIUtil . scaleImageData (device , new ElementAtZoom <>( data , 100 ), deviceZoom );
364+ data = scaleImageData (data , deviceZoom , 100 );
365365 init (data , deviceZoom );
366366 init ();
367367 this .device .registerResourceWithZoomSupport (this );
@@ -405,8 +405,8 @@ public Image(Device device, ImageData source, ImageData mask) {
405405 SWT .error (SWT .ERROR_INVALID_ARGUMENT );
406406 }
407407 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
408- source = DPIUtil . autoScaleUp ( device , source );
409- mask = DPIUtil . autoScaleUp ( device , mask );
408+ source = scaleImageData ( source , getZoom (), 100 );
409+ mask = scaleImageData ( mask , getZoom (), 100 );
410410 mask = ImageData .convertMask (mask );
411411 initIconHandle (this .device , source , mask , getZoom ());
412412 init ();
@@ -470,7 +470,8 @@ public Image (Device device, InputStream stream) {
470470 super (device );
471471 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
472472 int deviceZoom = getZoom ();
473- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (stream , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
473+ ElementAtZoom <ImageData > imageCandidate = ImageDataLoader .load (stream , FileFormat .DEFAULT_ZOOM , deviceZoom );
474+ ImageData data = scaleImageData (imageCandidate .element (), deviceZoom , imageCandidate .zoom ());
474475 init (data , deviceZoom );
475476 init ();
476477 this .device .registerResourceWithZoomSupport (this );
@@ -513,7 +514,8 @@ public Image (Device device, String filename) {
513514 if (filename == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
514515 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
515516 int deviceZoom = getZoom ();
516- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (filename , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
517+ ElementAtZoom <ImageData > imageCandidate = ImageDataLoader .load (filename , FileFormat .DEFAULT_ZOOM , deviceZoom );
518+ ImageData data = scaleImageData (imageCandidate .element (), deviceZoom , imageCandidate .zoom ());
517519 init (data , deviceZoom );
518520 init ();
519521 this .device .registerResourceWithZoomSupport (this );
@@ -1237,7 +1239,7 @@ private ImageData getScaledImageData (int zoom) {
12371239 }
12381240 TreeSet <Integer > availableZooms = new TreeSet <>(zoomLevelToImageHandle .keySet ());
12391241 int closestZoom = Optional .ofNullable (availableZooms .higher (zoom )).orElse (availableZooms .lower (zoom ));
1240- return DPIUtil . scaleImageData ( device , getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
1242+ return scaleImageData ( getImageMetadata (closestZoom ).getImageData (), zoom , closestZoom );
12411243}
12421244
12431245
@@ -1850,6 +1852,40 @@ private void setBackground(Color color, long handle) {
18501852 device .internal_dispose_GC (hDC , null );
18511853}
18521854
1855+ private ImageData scaleImageData (final ImageData imageData , int targetZoom , int currentZoom ) {
1856+ if (imageData == null || targetZoom == currentZoom || (device != null && !device .isAutoScalable ())) return imageData ;
1857+ float scaleFactor = (float ) targetZoom / (float ) currentZoom ;
1858+ int width = imageData .width ;
1859+ int height = imageData .height ;
1860+ int scaledWidth = Math .round (width * scaleFactor );
1861+ int scaledHeight = Math .round (height * scaleFactor );
1862+ boolean useSmoothScaling = DPIUtil .isSmoothScalingEnabled () && imageData .getTransparencyType () != SWT .TRANSPARENCY_MASK ;
1863+ if (useSmoothScaling ) {
1864+ return scaleToUsingSmoothScaling (scaledWidth , scaledHeight , imageData );
1865+ }
1866+ return imageData .scaledTo (scaledWidth , scaledHeight );
1867+ }
1868+
1869+ private ImageData scaleToUsingSmoothScaling (int width , int height , ImageData imageData ) {
1870+ Image original = new Image (device , (ImageDataProvider ) zoom -> imageData );
1871+ /* Create a 24 bit image data with alpha channel */
1872+ final ImageData resultData = new ImageData (width , height , 24 , new PaletteData (0xFF , 0xFF00 , 0xFF0000 ));
1873+ resultData .alphaData = new byte [width * height ];
1874+ Image resultImage = new Image (device , (ImageDataProvider ) zoom -> resultData );
1875+ GC gc = new GC (resultImage );
1876+ gc .setAntialias (SWT .ON );
1877+ gc .drawImage (original , 0 , 0 , imageData .width , imageData .height ,
1878+ /* E.g. destWidth here is effectively DPIUtil.autoScaleDown (scaledWidth), but avoiding rounding errors.
1879+ * Nevertheless, we still have some rounding errors due to the point-based API GC#drawImage(..).
1880+ */
1881+ 0 , 0 , width , height , false );
1882+ gc .dispose ();
1883+ original .dispose ();
1884+ ImageData result = resultImage .getImageData (resultImage .getZoom ());
1885+ resultImage .dispose ();
1886+ return result ;
1887+ }
1888+
18531889private int getZoom () {
18541890 return DPIUtil .getZoomForAutoscaleProperty (initialNativeZoom );
18551891}
@@ -2059,7 +2095,7 @@ ImageData getImageData(int zoom) {
20592095
20602096 private ImageData scaleIfNecessary (ElementAtZoom <ImageData > imageDataAtZoom , int zoom ) {
20612097 if (imageDataAtZoom .zoom () != zoom ) {
2062- return DPIUtil . scaleImageData (device , imageDataAtZoom , zoom );
2098+ return scaleImageData (imageDataAtZoom . element (), zoom , imageDataAtZoom . zoom () );
20632099 } else {
20642100 return imageDataAtZoom .element ();
20652101 }
@@ -2308,13 +2344,13 @@ protected Rectangle getBounds(int zoom) {
23082344 @ Override
23092345 ImageData getImageData (int zoom ) {
23102346 ElementAtZoom <ImageData > data = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2311- return DPIUtil . scaleImageData ( device , data .element (), zoom , data .zoom ());
2347+ return scaleImageData ( data .element (), zoom , data .zoom ());
23122348 }
23132349
23142350 @ Override
23152351 ImageHandle getImageMetadata (int zoom ) {
23162352 ElementAtZoom <ImageData > imageCandidate = DPIUtil .validateAndGetImageDataAtZoom (provider , zoom );
2317- ImageData resizedData = DPIUtil . scaleImageData ( device , imageCandidate .element (), zoom , imageCandidate .zoom ());
2353+ ImageData resizedData = scaleImageData ( imageCandidate .element (), zoom , imageCandidate .zoom ());
23182354 ImageData newData = adaptImageDataIfDisabledOrGray (resizedData );
23192355 init (newData , zoom );
23202356 return zoomLevelToImageHandle .get (zoom );
0 commit comments