@@ -360,9 +360,7 @@ public Image(Device device, ImageData data) {
360360 super (device );
361361 if (data == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
362362 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
363- int deviceZoom = getZoom ();
364- data = DPIUtil .scaleImageData (device , new ElementAtZoom <>(data , 100 ), deviceZoom );
365- init (data , deviceZoom );
363+ this .imageProvider = new PlainImageDataProviderWrapper (data );
366364 init ();
367365 this .device .registerResourceWithZoomSupport (this );
368366}
@@ -405,10 +403,7 @@ public Image(Device device, ImageData source, ImageData mask) {
405403 SWT .error (SWT .ERROR_INVALID_ARGUMENT );
406404 }
407405 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
408- source = DPIUtil .autoScaleUp (device , source );
409- mask = DPIUtil .autoScaleUp (device , mask );
410- mask = ImageData .convertMask (mask );
411- initIconHandle (this .device , source , mask , getZoom ());
406+ this .imageProvider = new MaskedImageDataProviderWrapper (source , mask );
412407 init ();
413408 this .device .registerResourceWithZoomSupport (this );
414409}
@@ -468,10 +463,12 @@ public Image(Device device, ImageData source, ImageData mask) {
468463 */
469464public Image (Device device , InputStream stream ) {
470465 super (device );
466+ if (stream == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
471467 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
472- int deviceZoom = getZoom ();
473- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (stream , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
474- init (data , deviceZoom );
468+ this .imageProvider = new ImageDataLoaderStreamProviderWrapper (stream );
469+ if (this .imageProvider .getImageData (100 ) == null ) {
470+ SWT .error (SWT .ERROR_INVALID_ARGUMENT , null , ": InputStream returns null ImageData at 100% zoom." );
471+ }
475472 init ();
476473 this .device .registerResourceWithZoomSupport (this );
477474}
@@ -512,9 +509,10 @@ public Image (Device device, String filename) {
512509 super (device );
513510 if (filename == null ) SWT .error (SWT .ERROR_NULL_ARGUMENT );
514511 initialNativeZoom = DPIUtil .getNativeDeviceZoom ();
515- int deviceZoom = getZoom ();
516- ImageData data = DPIUtil .scaleImageData (device , ImageDataLoader .load (filename , FileFormat .DEFAULT_ZOOM , deviceZoom ), deviceZoom );
517- init (data , deviceZoom );
512+ this .imageProvider = new ImageDataLoaderFileProviderWrapper (filename );
513+ if (this .imageProvider .getImageData (100 ) == null ) {
514+ SWT .error (SWT .ERROR_INVALID_ARGUMENT , null , ": Input filename returns null ImageData at 100% zoom." );
515+ }
518516 init ();
519517 this .device .registerResourceWithZoomSupport (this );
520518}
@@ -1901,6 +1899,146 @@ protected void destroy() {
19011899 }
19021900}
19031901
1902+ private abstract class ImageFromImageDataProviderWrapper extends AbstractImageProviderWrapper {
1903+ private boolean isDestroyed ;
1904+
1905+ protected abstract ElementAtZoom <ImageData > loadImageData (int zoom );
1906+
1907+ @ Override
1908+ ImageData getImageData (int zoom ) {
1909+ if (zoomLevelToImageHandle .containsKey (zoom )) {
1910+ return zoomLevelToImageHandle .get (zoom ).getImageData ();
1911+ }
1912+ ElementAtZoom <ImageData > loadedImageData = loadImageData (zoom );
1913+ return DPIUtil .scaleImageData (device , loadedImageData , zoom );
1914+ }
1915+
1916+ @ Override
1917+ ImageHandle getImageMetadata (int zoom ) {
1918+ if (zoomLevelToImageHandle .containsKey (zoom )) {
1919+ return zoomLevelToImageHandle .get (zoom );
1920+ } else {
1921+ ImageData scaledImageData = getImageData (zoom );
1922+ ImageHandle imageHandle = init (scaledImageData , zoom );
1923+ return imageHandle ;
1924+ }
1925+ }
1926+
1927+ @ Override
1928+ protected void destroy () {
1929+ this .isDestroyed = true ;
1930+ }
1931+
1932+ @ Override
1933+ boolean isDisposed () {
1934+ return isDestroyed ;
1935+ }
1936+ }
1937+
1938+
1939+ private class MaskedImageDataProviderWrapper extends ImageFromImageDataProviderWrapper {
1940+ private final ImageData srcAt100 ;
1941+ private final ImageData maskAt100 ;
1942+
1943+ MaskedImageDataProviderWrapper (ImageData srcAt100 , ImageData maskAt100 ) {
1944+ this .srcAt100 = (ImageData ) srcAt100 .clone ();
1945+ this .maskAt100 = (ImageData ) maskAt100 .clone ();
1946+ }
1947+
1948+ @ Override
1949+ protected Rectangle getBounds (int zoom ) {
1950+ Rectangle rectangle = new Rectangle (0 , 0 , srcAt100 .width , srcAt100 .height );
1951+ return DPIUtil .scaleUp (rectangle , zoom );
1952+ }
1953+
1954+ @ Override
1955+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
1956+ ImageData scaledSource = DPIUtil .scaleImageData (device , srcAt100 , zoom , 100 );
1957+ ImageData mask = ImageData .convertMask (maskAt100 );
1958+ ImageData scaledMask = DPIUtil .scaleImageData (device , mask , zoom , 100 );
1959+ ImageData mergedData = applyMask (scaledSource , scaledMask );
1960+ return new ElementAtZoom <>(mergedData , zoom );
1961+ }
1962+
1963+ @ Override
1964+ AbstractImageProviderWrapper createCopy (Image image ) {
1965+ return image .new MaskedImageDataProviderWrapper (this .srcAt100 , this .maskAt100 );
1966+ }
1967+ }
1968+
1969+
1970+ private class PlainImageDataProviderWrapper extends ImageFromImageDataProviderWrapper {
1971+ private ImageData imageDataAt100 ;
1972+
1973+ PlainImageDataProviderWrapper (ImageData imageData ) {
1974+ this .imageDataAt100 = (ImageData ) imageData .clone ();
1975+ }
1976+
1977+ @ Override
1978+ protected Rectangle getBounds (int zoom ) {
1979+ Rectangle rectangle = new Rectangle (0 , 0 , imageDataAt100 .width , imageDataAt100 .height );
1980+ return DPIUtil .scaleUp (rectangle , zoom );
1981+ }
1982+
1983+ @ Override
1984+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
1985+ return new ElementAtZoom <>(imageDataAt100 , 100 );
1986+ }
1987+
1988+ @ Override
1989+ AbstractImageProviderWrapper createCopy (Image image ) {
1990+ return image .new PlainImageDataProviderWrapper (this .imageDataAt100 );
1991+ }
1992+ }
1993+
1994+ private class ImageDataLoaderStreamProviderWrapper extends ImageFromImageDataProviderWrapper {
1995+ private InputStream inputStream ;
1996+
1997+ ImageDataLoaderStreamProviderWrapper (InputStream inputStream ) {
1998+ this .inputStream = inputStream ;
1999+ }
2000+
2001+ @ Override
2002+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
2003+ return ImageDataLoader .load (inputStream , FileFormat .DEFAULT_ZOOM , zoom );
2004+ }
2005+
2006+ @ Override
2007+ protected Rectangle getBounds (int zoom ) {
2008+ ImageData scaledImageData = getImageData (zoom );
2009+ return new Rectangle (0 , 0 , scaledImageData .width , scaledImageData .height );
2010+ }
2011+
2012+ @ Override
2013+ AbstractImageProviderWrapper createCopy (Image image ) {
2014+ return new ImageDataLoaderStreamProviderWrapper (inputStream );
2015+ }
2016+ }
2017+
2018+ private class ImageDataLoaderFileProviderWrapper extends ImageFromImageDataProviderWrapper {
2019+ private String fileName ;
2020+
2021+ ImageDataLoaderFileProviderWrapper (String fileName ) {
2022+ this .fileName = fileName ;
2023+ }
2024+
2025+ @ Override
2026+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
2027+ return ImageDataLoader .load (fileName , FileFormat .DEFAULT_ZOOM , zoom );
2028+ }
2029+
2030+ @ Override
2031+ protected Rectangle getBounds (int zoom ) {
2032+ ImageData scaledImageData = getImageData (zoom );
2033+ return new Rectangle (0 , 0 , scaledImageData .width , scaledImageData .height );
2034+ }
2035+
2036+ @ Override
2037+ AbstractImageProviderWrapper createCopy (Image image ) {
2038+ return new ImageDataLoaderFileProviderWrapper (fileName );
2039+ }
2040+ }
2041+
19042042private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
19052043 private boolean isDestroyed ;
19062044 private final int width ;
0 commit comments