@@ -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,154 @@ 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 byte [] inputStreamData ;
1996+
1997+ ImageDataLoaderStreamProviderWrapper (InputStream inputStream ) {
1998+ try {
1999+ this .inputStreamData = inputStream .readAllBytes ();
2000+ } catch (IOException e ) {
2001+ SWT .error (SWT .ERROR_INVALID_ARGUMENT , e );
2002+ }
2003+ }
2004+
2005+ private ImageDataLoaderStreamProviderWrapper (byte [] inputStreamData ) {
2006+ this .inputStreamData = inputStreamData ;
2007+ }
2008+
2009+ @ Override
2010+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
2011+ return ImageDataLoader .load (new ByteArrayInputStream (inputStreamData ), FileFormat .DEFAULT_ZOOM , zoom );
2012+ }
2013+
2014+ @ Override
2015+ protected Rectangle getBounds (int zoom ) {
2016+ ImageData scaledImageData = getImageData (zoom );
2017+ return new Rectangle (0 , 0 , scaledImageData .width , scaledImageData .height );
2018+ }
2019+
2020+ @ Override
2021+ AbstractImageProviderWrapper createCopy (Image image ) {
2022+ return new ImageDataLoaderStreamProviderWrapper (inputStreamData );
2023+ }
2024+ }
2025+
2026+ private class ImageDataLoaderFileProviderWrapper extends ImageFromImageDataProviderWrapper {
2027+ private String fileName ;
2028+
2029+ ImageDataLoaderFileProviderWrapper (String fileName ) {
2030+ this .fileName = fileName ;
2031+ }
2032+
2033+ @ Override
2034+ protected ElementAtZoom <ImageData > loadImageData (int zoom ) {
2035+ return ImageDataLoader .load (fileName , FileFormat .DEFAULT_ZOOM , zoom );
2036+ }
2037+
2038+ @ Override
2039+ protected Rectangle getBounds (int zoom ) {
2040+ ImageData scaledImageData = getImageData (zoom );
2041+ return new Rectangle (0 , 0 , scaledImageData .width , scaledImageData .height );
2042+ }
2043+
2044+ @ Override
2045+ AbstractImageProviderWrapper createCopy (Image image ) {
2046+ return new ImageDataLoaderFileProviderWrapper (fileName );
2047+ }
2048+ }
2049+
19042050private class PlainImageProviderWrapper extends AbstractImageProviderWrapper {
19052051 private boolean isDestroyed ;
19062052 private final int width ;
0 commit comments