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 a0967762920..25ec987f0ee 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2020 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,11 +16,14 @@ import java.io.*; import java.util.*; +import java.util.function.*; 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.*; /** * Instances of this class are graphics which have been prepared @@ -692,7 +695,7 @@ public Image(Device device, InputStream stream) { NSAutoreleasePool pool = null; if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); try { - init(new ImageData(stream)); + initWithSupplier(zoom -> ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, zoom)); init(); } finally { if (pool != null) pool.release(); @@ -738,7 +741,7 @@ public Image(Device device, String filename) { try { if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initNative(filename); - if (this.handle == null) init(new ImageData(filename)); + if (this.handle == null) initWithSupplier(zoom -> ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, zoom)); init(); } finally { if (pool != null) pool.release(); @@ -784,7 +787,7 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) { if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); try { initNative(filename); - if (this.handle == null) init(new ImageData(filename)); + if (this.handle == null) init(ImageDataLoader.load(filename, 100, 100).element()); init(); String filename2x = imageFileNameProvider.getImagePath(200); if (filename2x != null) { @@ -792,6 +795,15 @@ public Image(Device device, ImageFileNameProvider imageFileNameProvider) { id id = NSImageRep.imageRepWithContentsOfFile(NSString.stringWith(filename2x)); NSImageRep rep = new NSImageRep(id); handle.addRepresentation(rep); + } else { + // 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(); + } } } finally { if (pool != null) pool.release(); @@ -1472,6 +1484,25 @@ 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) { + alphaInfo_200 = new AlphaInfo(); + NSBitmapImageRep rep = createRepresentation (imageData2x, alphaInfo_200); + handle.addRepresentation(rep); + rep.release(); + } +} + + void initAlpha_200(NSBitmapImageRep nativeRep) { NSAutoreleasePool pool = null; if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init(); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java index c268e5caaed..c5515b3fe74 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java @@ -331,9 +331,7 @@ scanlinePad, checkData(data), 0, null, * @see ImageLoader#load(InputStream) */ public ImageData(InputStream stream) { - ImageData[] data = ImageDataLoader.load(stream); - if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE); - ImageData i = data[0]; + ImageData i = ImageDataLoader.load(stream); setAllFields( i.width, i.height, @@ -377,9 +375,7 @@ public ImageData(InputStream stream) { * */ public ImageData(String filename) { - ImageData[] data = ImageDataLoader.load(filename); - if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE); - ImageData i = data[0]; + ImageData i = ImageDataLoader.load(filename); setAllFields( i.width, i.height, 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 b1fe23d2472..c81cc6d27a7 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,6 +14,10 @@ package org.eclipse.swt.graphics; import java.io.*; +import java.util.*; + +import org.eclipse.swt.*; +import org.eclipse.swt.internal.DPIUtil.*; /** * Internal class that separates ImageData from ImageLoader @@ -21,12 +25,28 @@ */ class ImageDataLoader { - public static ImageData[] load(InputStream stream) { - return new ImageLoader().load(stream); + public static ImageData load(InputStream stream) { + ImageData[] data = new ImageLoader().load(stream); + if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE); + return data[0]; + } + + public static ImageData load(String filename) { + ImageData[] data = new ImageLoader().load(filename); + if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE); + return data[0]; + } + + 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 ImageData[] load(String filename) { - return new ImageLoader().load(filename); + 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); + return data.get(0); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java index 5ec0f68edd8..4abc2ec14ed 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -22,6 +22,7 @@ import org.eclipse.swt.internal.DPIUtil.*; import org.eclipse.swt.internal.cairo.*; import org.eclipse.swt.internal.gtk.*; +import org.eclipse.swt.internal.image.*; /** * Instances of this class are graphics which have been prepared @@ -530,9 +531,9 @@ public Image(Device device, ImageData source, ImageData mask) { */ public Image(Device device, InputStream stream) { super(device); - ImageData data = new ImageData(stream); currentDeviceZoom = DPIUtil.getDeviceZoom(); - data = DPIUtil.autoScaleUp (device, data); + ElementAtZoom image = ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, currentDeviceZoom); + ImageData data = DPIUtil.scaleImageData(device, image, currentDeviceZoom); init(data); init(); } @@ -572,10 +573,9 @@ public Image(Device device, InputStream stream) { public Image(Device device, String filename) { super(device); if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - - ImageData data = new ImageData(filename); currentDeviceZoom = DPIUtil.getDeviceZoom(); - data = DPIUtil.autoScaleUp (device, data); + ElementAtZoom image = ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, currentDeviceZoom); + ImageData data = DPIUtil.scaleImageData(device, image, currentDeviceZoom); init(data); init(); } @@ -775,9 +775,10 @@ private void initFromFileNameProvider(int zoom) { initNative(fileForZoom.element()); } if (this.surface == 0) { - ImageData imageData = new ImageData(fileForZoom.element()); - if (fileForZoom.zoom() != zoom) { - imageData = DPIUtil.scaleImageData(device, imageData, zoom, fileForZoom.zoom()); + ElementAtZoom imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom); + ImageData imageData = imageDataAtZoom.element(); + if (imageDataAtZoom.zoom() != zoom) { + imageData = DPIUtil.scaleImageData(device, imageDataAtZoom, zoom); } init(imageData); } 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 997024b723d..e9e19764a58 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2025 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -21,6 +21,7 @@ import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.DPIUtil.*; import org.eclipse.swt.internal.gdip.*; +import org.eclipse.swt.internal.image.*; import org.eclipse.swt.internal.win32.*; /** @@ -473,7 +474,7 @@ public Image (Device device, InputStream stream) { super(device); initialNativeZoom = DPIUtil.getNativeDeviceZoom(); int deviceZoom = getZoom(); - ImageData data = DPIUtil.scaleImageData(device, new ElementAtZoom<>(new ImageData (stream), 100), deviceZoom); + ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(stream, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); init(data, deviceZoom); init(); this.device.registerResourceWithZoomSupport(this); @@ -516,7 +517,7 @@ public Image (Device device, String filename) { if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initialNativeZoom = DPIUtil.getNativeDeviceZoom(); int deviceZoom = getZoom(); - ImageData data = DPIUtil.scaleImageData(device, new ElementAtZoom<>(new ImageData (filename), 100), deviceZoom); + ImageData data = DPIUtil.scaleImageData(device, ImageDataLoader.load(filename, FileFormat.DEFAULT_ZOOM, deviceZoom), deviceZoom); init(data, deviceZoom); init(); this.device.registerResourceWithZoomSupport(this); @@ -2130,7 +2131,8 @@ protected Rectangle getBounds(int zoom) { @Override ImageData getImageData(int zoom) { ElementAtZoom fileName = DPIUtil.validateAndGetImagePathAtZoom (provider, zoom); - return DPIUtil.scaleImageData (device, new ImageData (fileName.element()), zoom, fileName.zoom()); + ElementAtZoom imageData = ImageDataLoader.load(fileName.element(), fileName.zoom(), zoom); + return DPIUtil.scaleImageData (device, imageData, zoom); } @Override @@ -2141,9 +2143,10 @@ ImageHandle getImageMetadata(int zoom) { nativeInitializedImage = initNative(fileForZoom.element(), zoom); } if (nativeInitializedImage == null) { - ImageData imageData = new ImageData (fileForZoom.element()); - if (fileForZoom.zoom() != zoom) { - imageData = DPIUtil.scaleImageData(device, imageData, zoom, fileForZoom.zoom()); + ElementAtZoom imageDataAtZoom = ImageDataLoader.load(fileForZoom.element(), fileForZoom.zoom(), zoom); + ImageData imageData = imageDataAtZoom.element(); + if (imageDataAtZoom.zoom() != zoom) { + imageData = DPIUtil.scaleImageData(device, imageDataAtZoom, zoom); } imageData = adaptImageDataIfDisabledOrGray(imageData); init(imageData, zoom);