diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java index 25ec987f0ee..2c04c23902f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/Image.java @@ -20,7 +20,6 @@ import org.eclipse.swt.*; import org.eclipse.swt.internal.*; -import org.eclipse.swt.internal.DPIUtil.*; import org.eclipse.swt.internal.cocoa.*; import org.eclipse.swt.internal.graphics.*; import org.eclipse.swt.internal.image.*; @@ -692,11 +691,18 @@ public Image(Device device, ImageData source, ImageData mask) { */ public Image(Device device, InputStream stream) { super(device); + if (stream == null) { + SWT.error(SWT.ERROR_NULL_ARGUMENT); + } NSAutoreleasePool pool = null; if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); try { - initWithSupplier(zoom -> ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, zoom)); + byte[] input = stream.readAllBytes(); + initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom), + zoom -> ImageDataLoader.load(new ByteArrayInputStream(input), FileFormat.DEFAULT_ZOOM, zoom).element()); init(); + } catch (IOException e) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT, e); } finally { if (pool != null) pool.release(); } @@ -741,7 +747,10 @@ public Image(Device device, String filename) { try { if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initNative(filename); - if (this.handle == null) initWithSupplier(zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom)); + if (this.handle == null) { + initWithSupplier(zoom -> ImageDataLoader.canLoadAtZoom(filename, FileFormat.DEFAULT_ZOOM, zoom), + zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom).element()); + } init(); } finally { if (pool != null) pool.release(); @@ -795,15 +804,13 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) { id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(filename2x)); NSImageRep rep = new NSImageRep(id); handle.addRepresentation(rep); - } else { + } else if (ImageDataLoader.canLoadAtZoom(filename, 100, 200)) { // Try to natively scale up the image (e.g. possible if it's an SVG) - ElementAtZoom imageData2x = ImageDataLoader.load(filename, 100, 200); - if (imageData2x.zoom() == 200) { - alphaInfo_200 = new AlphaInfo(); - NSBitmapImageRep rep = createRepresentation (imageData2x.element(), alphaInfo_200); - handle.addRepresentation(rep); - rep.release(); - } + ImageData imageData2x = ImageDataLoader.load(filename, 100, 200).element(); + alphaInfo_200 = new AlphaInfo(); + NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200); + handle.addRepresentation(rep); + rep.release(); } } finally { if (pool != null) pool.release(); @@ -1484,17 +1491,11 @@ void init(ImageData image) { handle.setCacheMode(OS.NSImageCacheNever); } -private void initWithSupplier(Function> zoomToImageData) { - ElementAtZoom imageData = zoomToImageData.apply(DPIUtil.getDeviceZoom()); - ImageData imageData2x = null; - if (imageData.zoom() == 200) { - imageData2x = imageData.element(); - } - if (imageData.zoom() != 100) { - imageData = zoomToImageData.apply(100); - } - init(imageData.element()); - if (imageData2x != null) { +private void initWithSupplier(Function canLoadAtZoom, Function zoomToImageData) { + ImageData imageData = zoomToImageData.apply(100); + init(imageData); + if (canLoadAtZoom.apply(200)) { + ImageData imageData2x = zoomToImageData.apply(200); alphaInfo_200 = new AlphaInfo(); NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200); handle.addRepresentation(rep); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDataLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDataLoader.java index c81cc6d27a7..29f517b45c0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDataLoader.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageDataLoader.java @@ -37,12 +37,20 @@ public static ImageData load(String filename) { return data[0]; } + public static boolean canLoadAtZoom(InputStream stream, int fileZoom, int targetZoom) { + return ImageLoader.canLoadAtZoom(stream, fileZoom, targetZoom); + } + public static ElementAtZoom load(InputStream stream, int fileZoom, int targetZoom) { List> data = new ImageLoader().load(stream, fileZoom, targetZoom); if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE); return data.get(0); } + public static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) { + return ImageLoader.canLoadAtZoom(filename, fileZoom, targetZoom); + } + public static ElementAtZoom load(String filename, int fileZoom, int targetZoom) { List> data = new ImageLoader().load(filename, fileZoom, targetZoom); if (data.isEmpty()) SWT.error(SWT.ERROR_INVALID_IMAGE); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java index 3c8a12dbccd..9973b8f06e3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java @@ -163,6 +163,11 @@ List> load(InputStream stream, int fileZoom, int target return images; } +static boolean canLoadAtZoom(InputStream stream, int fileZoom, int targetZoom) { + if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + return FileFormat.canLoadAtZoom(new ElementAtZoom<>(stream, fileZoom), targetZoom); +} + /** * Loads an array of ImageData objects from the * file with the specified name. Throws an error if either @@ -196,6 +201,16 @@ List> load(String filename, int fileZoom, int targetZoo return null; } +static boolean canLoadAtZoom(String filename, int fileZoom, int targetZoom) { + if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); + try (InputStream stream = new FileInputStream(filename)) { + return canLoadAtZoom(stream, fileZoom, targetZoom); + } catch (IOException e) { + SWT.error(SWT.ERROR_IO, e); + } + return false; +} + /** * Saves the image data in this ImageLoader to the specified stream. * The format parameter can have one of the following values: diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java index 491c8c19181..8232d71023d 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java @@ -136,6 +136,10 @@ public static List> load(ElementAtZoom is, return fileFormat.loadFromStream(stream, is.zoom(), targetZoom); } +public static boolean canLoadAtZoom(ElementAtZoom is, int targetZoom) { + return is.zoom() == targetZoom || isDynamicallySizableFormat(is.element()); +} + /** * Write the device independent image array stored in the specified loader * to the specified output stream using the specified file format. diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index 48cd8e27ee7..743af6023c9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -2235,13 +2235,20 @@ private class ImageFileNameProviderWrapper extends BaseImageProviderWrapper loadImageData(int zoom) { ElementAtZoom fileForZoom = DPIUtil.validateAndGetImagePathAtZoom(provider, zoom); + + // Load at appropriate zoom via loader + if (fileForZoom.zoom() != zoom && ImageDataLoader.canLoadAtZoom(fileForZoom.element(), fileForZoom.zoom(), zoom)) { + ElementAtZoom imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom); + return new ElementAtZoom<>(adaptImageDataIfDisabledOrGray(imageDataAtZoom.element()), zoom); + } + + // Load at file zoom (native or via loader) and rescale ImageHandle nativeInitializedImage; if (zoomLevelToImageHandle.containsKey(fileForZoom.zoom())) { nativeInitializedImage = zoomLevelToImageHandle.get(fileForZoom.zoom()); } else { nativeInitializedImage = initNative(fileForZoom.element(), fileForZoom.zoom()); } - ElementAtZoom imageDataAtZoom; if (nativeInitializedImage == null) { imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom);