Skip to content

Commit 18ac3b4

Browse files
Prepare the implementation of dynamically sized image file-formats
Co-authored-by: Heiko Klare <[email protected]>
1 parent 2974864 commit 18ac3b4

File tree

12 files changed

+146
-92
lines changed

12 files changed

+146
-92
lines changed

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/InternalImageLoader.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
package org.eclipse.swt.graphics;
1515

1616
import java.io.*;
17+
import java.util.*;
1718

19+
import org.eclipse.swt.internal.DPIUtil.*;
1820
import org.eclipse.swt.internal.image.*;
1921

2022
class InternalImageLoader {
2123

22-
static ImageData[] load(InputStream stream, ImageLoader imageLoader) {
23-
return FileFormat.load(stream, imageLoader);
24+
static List<ElementAtZoom<ImageData>> load(InputStream stream, ImageLoader imageLoader, int fileZoom, int targetZoom) {
25+
return FileFormat.load(stream, imageLoader, fileZoom, targetZoom);
2426
}
2527

2628
static void save(OutputStream stream, int format, ImageLoader imageLoader) {

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/ImageLoader.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.util.*;
1919

2020
import org.eclipse.swt.*;
21+
import org.eclipse.swt.internal.DPIUtil.*;
22+
import org.eclipse.swt.internal.image.*;
2123

2224
/**
2325
* Instances of this class are used to load images from,
@@ -148,10 +150,16 @@ void reset() {
148150
* </ul>
149151
*/
150152
public ImageData[] load(InputStream stream) {
153+
load(stream, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM);
154+
return data;
155+
}
156+
157+
List<ElementAtZoom<ImageData>> load(InputStream stream, int fileZoom, int targetZoom) {
151158
if (stream == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
152159
reset();
153-
data = InternalImageLoader.load(stream, this);
154-
return data;
160+
List<ElementAtZoom<ImageData>> images = InternalImageLoader.load(stream, this, fileZoom, targetZoom);
161+
data = images.stream().map(ElementAtZoom::element).toArray(ImageData[]::new);
162+
return images;
155163
}
156164

157165
/**
@@ -173,9 +181,14 @@ public ImageData[] load(InputStream stream) {
173181
* </ul>
174182
*/
175183
public ImageData[] load(String filename) {
184+
load(filename, FileFormat.DEFAULT_ZOOM, FileFormat.DEFAULT_ZOOM);
185+
return data;
186+
}
187+
188+
List<ElementAtZoom<ImageData>> load(String filename, int fileZoom, int targetZoom) {
176189
if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
177190
try (InputStream stream = new FileInputStream(filename)) {
178-
return load(stream);
191+
return load(stream, fileZoom, targetZoom);
179192
} catch (IOException e) {
180193
SWT.error(SWT.ERROR_IO, e);
181194
}

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/FileFormat.java

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.eclipse.swt.*;
2222
import org.eclipse.swt.graphics.*;
23+
import org.eclipse.swt.internal.DPIUtil.*;
2324

2425
/**
2526
* Abstract factory class for loading/unloading images from files or streams
@@ -54,27 +55,60 @@ public abstract class FileFormat {
5455
} catch (NoClassDefFoundError e) { } // ignore format
5556
}
5657

58+
public static final int DEFAULT_ZOOM = 100;
59+
60+
private static Optional<FileFormat> determineFileFormat(LEDataInputStream stream) {
61+
return FORMAT_FACTORIES.stream().skip(1).map(Supplier::get).filter(f -> {
62+
try {
63+
return f.isFileFormat(stream);
64+
} catch (IOException e) {
65+
return false;
66+
}
67+
}).findFirst();
68+
}
69+
70+
private static final int MAX_SIGNATURE_BYTES = 18 + 2; // e.g. Win-BMP or OS2-BMP plus a safety-margin
71+
72+
public static boolean isDynamicallySizableFormat(InputStream is) {
73+
Optional<FileFormat> format = determineFileFormat(new LEDataInputStream(is, MAX_SIGNATURE_BYTES));
74+
return format.isPresent() && !(format.get() instanceof StaticImageFileFormat);
75+
}
76+
77+
static abstract class StaticImageFileFormat extends FileFormat {
78+
79+
abstract ImageData[] loadFromByteStream();
80+
81+
@Override
82+
List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom) {
83+
return Arrays.stream(loadFromByteStream()).map(d -> new ElementAtZoom<>(d, fileZoom)).toList();
84+
}
85+
}
86+
5787
LEDataInputStream inputStream;
5888
LEDataOutputStream outputStream;
5989
ImageLoader loader;
6090
int compression;
6191

62-
/**
63-
* Return whether or not the specified input stream
64-
* represents a supported file format.
65-
*/
66-
abstract boolean isFileFormat(LEDataInputStream stream);
92+
/**
93+
* Return whether or not the specified input stream represents a supported file
94+
* format.
95+
*/
96+
abstract boolean isFileFormat(LEDataInputStream stream) throws IOException;
6797

68-
abstract ImageData[] loadFromByteStream();
98+
/**
99+
* Format that do not implement {@link StaticImageFileFormat} MUST return
100+
* {@link ImageData} with the specified {@code targetZoom}.
101+
*/
102+
abstract List<ElementAtZoom<ImageData>> loadFromByteStream(int fileZoom, int targetZoom);
69103

70104
/**
71105
* Read the specified input stream, and return the
72106
* device independent image array represented by the stream.
73107
*/
74-
public ImageData[] loadFromStream(LEDataInputStream stream) {
108+
public List<ElementAtZoom<ImageData>> loadFromStream(LEDataInputStream stream, int fileZoom, int targetZoom) {
75109
try {
76110
inputStream = stream;
77-
return loadFromByteStream();
111+
return loadFromByteStream(fileZoom, targetZoom);
78112
} catch (Exception e) {
79113
if (e instanceof IOException) {
80114
SWT.error(SWT.ERROR_IO, e);
@@ -89,14 +123,14 @@ public ImageData[] loadFromStream(LEDataInputStream stream) {
89123
* Read the specified input stream using the specified loader, and
90124
* return the device independent image array represented by the stream.
91125
*/
92-
public static ImageData[] load(InputStream is, ImageLoader loader) {
126+
public static List<ElementAtZoom<ImageData>> load(InputStream is, ImageLoader loader, int fileZoom, int targetZoom) {
93127
LEDataInputStream stream = new LEDataInputStream(is);
94-
FileFormat fileFormat = FORMAT_FACTORIES.stream().skip(1) //
95-
.map(Supplier::get).filter(f -> f.isFileFormat(stream)) //
96-
.findFirst().orElse(null);
97-
if (fileFormat == null) SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
128+
FileFormat fileFormat = determineFileFormat(stream).orElseGet(() -> {
129+
SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
130+
return null;
131+
});
98132
fileFormat.loader = loader;
99-
return fileFormat.loadFromStream(stream);
133+
return fileFormat.loadFromStream(stream, fileZoom, targetZoom);
100134
}
101135

102136
/**

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/GIFFileFormat.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2012 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,11 +14,13 @@
1414
package org.eclipse.swt.internal.image;
1515

1616

17+
import java.io.*;
18+
1719
import org.eclipse.swt.*;
1820
import org.eclipse.swt.graphics.*;
19-
import java.io.*;
21+
import org.eclipse.swt.internal.image.FileFormat.*;
2022

21-
public final class GIFFileFormat extends FileFormat {
23+
public final class GIFFileFormat extends StaticImageFileFormat {
2224
String signature;
2325
int screenWidth, screenHeight, backgroundPixel, bitsPerPixel, defaultDepth;
2426
int disposalMethod = 0;
@@ -51,15 +53,11 @@ static PaletteData grayRamp(int numGrays) {
5153
}
5254

5355
@Override
54-
boolean isFileFormat(LEDataInputStream stream) {
55-
try {
56-
byte[] signature = new byte[3];
57-
stream.read(signature);
58-
stream.unread(signature);
59-
return signature[0] == 'G' && signature[1] == 'I' && signature[2] == 'F';
60-
} catch (Exception e) {
61-
return false;
62-
}
56+
boolean isFileFormat(LEDataInputStream stream) throws IOException {
57+
byte[] signature = new byte[3];
58+
stream.read(signature);
59+
stream.unread(signature);
60+
return signature[0] == 'G' && signature[1] == 'I' && signature[2] == 'F';
6361
}
6462

6563
/**

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/JPEGFileFormat.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2014 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -18,11 +18,13 @@
1818
package org.eclipse.swt.internal.image;
1919

2020

21+
import java.io.*;
22+
2123
import org.eclipse.swt.*;
2224
import org.eclipse.swt.graphics.*;
23-
import java.io.*;
25+
import org.eclipse.swt.internal.image.FileFormat.*;
2426

25-
public final class JPEGFileFormat extends FileFormat {
27+
public final class JPEGFileFormat extends StaticImageFileFormat {
2628
int restartInterval;
2729
JPEGFrameHeader frameHeader;
2830
int imageWidth, imageHeight;
@@ -1362,16 +1364,14 @@ void inverseDCT(int[] dataUnit) {
13621364
}
13631365
}
13641366
}
1365-
@Override
1366-
boolean isFileFormat(LEDataInputStream stream) {
1367-
try {
1367+
1368+
@Override
1369+
boolean isFileFormat(LEDataInputStream stream) throws IOException {
13681370
JPEGStartOfImage soi = new JPEGStartOfImage(stream);
13691371
stream.unread(soi.reference);
1370-
return soi.verify(); // we no longer check for appN
1371-
} catch (Exception e) {
1372-
return false;
1372+
return soi.verify(); // we no longer check for appN
13731373
}
1374-
}
1374+
13751375
boolean isZeroInColumn(int[] dataUnit, int col) {
13761376
return dataUnit[col + 8] == 0 && dataUnit[col + 16] == 0
13771377
&& dataUnit[col + 24] == 0 && dataUnit[col + 32] == 0

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/OS2BMPFileFormat.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2008 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,27 +14,26 @@
1414
package org.eclipse.swt.internal.image;
1515

1616

17+
import java.io.*;
18+
1719
import org.eclipse.swt.*;
1820
import org.eclipse.swt.graphics.*;
19-
import java.io.*;
21+
import org.eclipse.swt.internal.image.FileFormat.*;
2022

21-
public final class OS2BMPFileFormat extends FileFormat {
23+
public final class OS2BMPFileFormat extends StaticImageFileFormat {
2224
static final int BMPFileHeaderSize = 14;
2325
static final int BMPHeaderFixedSize = 12;
2426
int width, height, bitCount;
2527

26-
@Override
27-
boolean isFileFormat(LEDataInputStream stream) {
28-
try {
28+
@Override
29+
boolean isFileFormat(LEDataInputStream stream) throws IOException {
2930
byte[] header = new byte[18];
3031
stream.read(header);
3132
stream.unread(header);
3233
int infoHeaderSize = (header[14] & 0xFF) | ((header[15] & 0xFF) << 8) | ((header[16] & 0xFF) << 16) | ((header[17] & 0xFF) << 24);
3334
return header[0] == 0x42 && header[1] == 0x4D && infoHeaderSize == BMPHeaderFixedSize;
34-
} catch (Exception e) {
35-
return false;
3635
}
37-
}
36+
3837
byte[] loadData(byte[] infoHeader) {
3938
int stride = (width * bitCount + 7) / 8;
4039
stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/PNGFileFormat.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2011 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -19,8 +19,9 @@
1919

2020
import org.eclipse.swt.*;
2121
import org.eclipse.swt.graphics.*;
22+
import org.eclipse.swt.internal.image.FileFormat.*;
2223

23-
public final class PNGFileFormat extends FileFormat {
24+
public final class PNGFileFormat extends StaticImageFileFormat {
2425
static final int SIGNATURE_LENGTH = 8;
2526
static final int PRIME = 65521;
2627
PngIhdrChunk headerChunk;
@@ -151,9 +152,9 @@ void unloadIntoByteStream(ImageLoader loader) {
151152
PngEncoder encoder = new PngEncoder(loader);
152153
encoder.encode(outputStream);
153154
}
154-
@Override
155-
boolean isFileFormat(LEDataInputStream stream) {
156-
try {
155+
156+
@Override
157+
boolean isFileFormat(LEDataInputStream stream) throws IOException {
157158
byte[] signature = new byte[SIGNATURE_LENGTH];
158159
stream.read(signature);
159160
stream.unread(signature);
@@ -166,10 +167,8 @@ boolean isFileFormat(LEDataInputStream stream) {
166167
if ((signature[6] & 0xFF) != 26) return false; //<CTRL/Z>
167168
if ((signature[7] & 0xFF) != 10) return false; //<LINEFEED>
168169
return true;
169-
} catch (Exception e) {
170-
return false;
171170
}
172-
}
171+
173172
/**
174173
* SWT does not support 16-bit depths. If this image uses
175174
* 16-bit depths, convert the data to an 8-bit depth.

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/image/TIFFFileFormat.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2009 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,19 +14,20 @@
1414
package org.eclipse.swt.internal.image;
1515

1616

17+
import java.io.*;
18+
1719
import org.eclipse.swt.*;
1820
import org.eclipse.swt.graphics.*;
19-
import java.io.*;
21+
import org.eclipse.swt.internal.image.FileFormat.*;
2022

2123
/**
2224
* Baseline TIFF decoder revision 6.0
2325
* Extension T4-encoding CCITT T.4 1D
2426
*/
25-
public final class TIFFFileFormat extends FileFormat {
27+
public final class TIFFFileFormat extends StaticImageFileFormat {
2628

27-
@Override
28-
boolean isFileFormat(LEDataInputStream stream) {
29-
try {
29+
@Override
30+
boolean isFileFormat(LEDataInputStream stream) throws IOException {
3031
byte[] header = new byte[4];
3132
stream.read(header);
3233
stream.unread(header);
@@ -36,10 +37,7 @@ boolean isFileFormat(LEDataInputStream stream) {
3637
return false;
3738
}
3839
return true;
39-
} catch (Exception e) {
40-
return false;
4140
}
42-
}
4341

4442
@Override
4543
ImageData[] loadFromByteStream() {

0 commit comments

Comments
 (0)