diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDS.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDS.java
index 02282708..5ed74509 100644
--- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDS.java
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDS.java
@@ -32,7 +32,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
@SuppressWarnings("unused")
interface DDS {
- byte[] MAGIC = new byte[]{'D', 'D', 'S', ' '};
+ int MAGIC = ('D' << 24) + ('D' << 16) + ('S' << 8) + ' '; //Big-Endian
int HEADER_SIZE = 124;
// Header Flags
@@ -48,4 +48,7 @@ interface DDS {
// Pixel Format Flags
int PIXEL_FORMAT_FLAG_FOURCC = 0x04;
int PIXEL_FORMAT_FLAG_RGB = 0x40;
+
+ //DX10 Resource Dimensions
+ int D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3;
}
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java
index bc784fda..23d7b55a 100644
--- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSHeader.java
@@ -34,8 +34,7 @@ import javax.imageio.IIOException;
import javax.imageio.stream.ImageInputStream;
import java.awt.Dimension;
import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Arrays;
+import java.nio.ByteOrder;
final class DDSHeader {
@@ -58,11 +57,12 @@ final class DDSHeader {
DDSHeader header = new DDSHeader();
// Read MAGIC bytes [0,3]
- byte[] magic = new byte[DDS.MAGIC.length];
- imageInput.readFully(magic);
- if (!Arrays.equals(DDS.MAGIC, magic)) {
- throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%08x', read 0x%08x", new BigInteger(DDS.MAGIC), new BigInteger(magic)));
+ imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
+ int magic = imageInput.readInt();
+ if (magic != DDS.MAGIC) {
+ throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, magic));
}
+ imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
// DDS_HEADER structure
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
@@ -93,8 +93,7 @@ final class DDSHeader {
// build dimensions list
header.addDimensions(dwWidth, dwHeight);
- byte[] dwReserved1 = new byte[11 * 4]; // [32,75]
- imageInput.readFully(dwReserved1);
+ imageInput.skipBytes(44);
// DDS_PIXELFORMAT structure
int px_dwSize = imageInput.readInt(); // [76,79]
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderSpi.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderSpi.java
index 33113c38..28af3768 100644
--- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderSpi.java
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderSpi.java
@@ -35,7 +35,6 @@ import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Locale;
public final class DDSImageReaderSpi extends ImageReaderSpiBase {
@@ -55,10 +54,7 @@ public final class DDSImageReaderSpi extends ImageReaderSpiBase {
stream.mark();
try {
- byte[] magic = new byte[DDS.MAGIC.length];
- stream.readFully(magic);
-
- return Arrays.equals(DDS.MAGIC, magic);
+ return stream.readInt() == DDS.MAGIC;
} finally {
stream.reset();
}
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSReader.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSReader.java
index dc8a8dae..8b40f963 100644
--- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSReader.java
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSReader.java
@@ -74,15 +74,19 @@ final class DDSReader {
static final Order ARGB_ORDER = new Order(16, 8, 0, 24);
private final DDSHeader header;
+ private DX10Header dxt10Header;
DDSReader(DDSHeader header) {
this.header = header;
}
int[] read(ImageInputStream imageInput, int imageIndex) throws IOException {
-
// type
DDSType type = getType();
+ if (type == DDSType.DXT10) {
+ dxt10Header = DX10Header.read(imageInput);
+ type = dxt10Header.getDDSType();
+ }
// offset buffer to index mipmap image
byte[] buffer = null;
@@ -138,7 +142,6 @@ final class DDSReader {
// DXT
int type = header.getFourCC();
return DDSType.valueOf(type);
-
} else if ((flags & DDS.PIXEL_FORMAT_FLAG_RGB) != 0) {
// RGB
int bitCount = header.getBitCount();
@@ -224,6 +227,7 @@ final class DDSReader {
}
}
+
private static int[] decodeDXT1(int width, int height, byte[] buffer) {
int[] pixels = new int[width * height];
int index = 0;
@@ -241,7 +245,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6;
- pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, 0xFF, t0);
+ pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, 0xFF, t0);
if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1);
if (4 * j + 2 >= width) continue;
@@ -286,7 +290,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6;
- pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, alphaTable[4 * k ], t0);
+ pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, alphaTable[4 * k], t0);
if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1);
if (4 * j + 2 >= width) continue;
@@ -344,7 +348,7 @@ final class DDSReader {
int t1 = (buffer[index] & 0x0C) >> 2;
int t2 = (buffer[index] & 0x30) >> 4;
int t3 = (buffer[index++] & 0xC0) >> 6;
- pixels[4 * width * i + 4 * j + width * k ] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k ]), t0);
+ pixels[4 * width * i + 4 * j + width * k] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k]), t0);
if (4 * j + 1 >= width) continue;
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1);
if (4 * j + 2 >= width) continue;
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSType.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSType.java
index 370e37e4..da552c85 100644
--- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSType.java
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSType.java
@@ -31,12 +31,12 @@
package com.twelvemonkeys.imageio.plugins.dds;
enum DDSType {
-
DXT1(0x31545844),
DXT2(0x32545844),
DXT3(0x33545844),
DXT4(0x34545844),
DXT5(0x35545844),
+ DXT10(0x30315844),
A1R5G5B5((1 << 16) | 2),
X1R5G5B5((2 << 16) | 2),
A4R4G4B4((3 << 16) | 2),
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10DXGIFormat.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10DXGIFormat.java
new file mode 100644
index 00000000..a08efdb6
--- /dev/null
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10DXGIFormat.java
@@ -0,0 +1,51 @@
+package com.twelvemonkeys.imageio.plugins.dds;
+
+import java.util.Arrays;
+import java.util.function.IntPredicate;
+import java.util.stream.IntStream;
+
+/**
+ * Enum that lists a certain types of DXGI Format this reader supports to read.
+ *
+ * @link DXGI Format List
+ */
+public enum DX10DXGIFormat {
+ BC1(DDSType.DXT1, rangeInclusive(70, 72)),
+ BC2(DDSType.DXT2, rangeInclusive(73, 75)),
+ BC3(DDSType.DXT5, rangeInclusive(76, 78)),
+ //BC7(99),
+ B8G8R8A8(DDSType.A8B8G8R8, exactly(87, 90, 91)),
+ B8G8R8X8(DDSType.X8B8G8R8, exactly(88, 92, 93)),
+ R8G8B8A8(DDSType.A8R8G8B8, rangeInclusive(27, 32));
+ private final DDSType ddsType;
+ private final IntPredicate dxgiFormat;
+
+ DX10DXGIFormat(DDSType ddsType, IntPredicate dxgiFormat) {
+ this.ddsType = ddsType;
+ this.dxgiFormat = dxgiFormat;
+ }
+
+ DDSType getCorrespondingType() {
+ return ddsType;
+ }
+
+ static DX10DXGIFormat getFormat(int value) {
+ for (DX10DXGIFormat format : values()) {
+ if (format.dxgiFormat.test(value)) return format;
+ }
+
+ throw new IllegalArgumentException("Unsupported DXGI_FORMAT : " + value);
+ }
+
+
+ /**
+ * @param acceptedValues values in DXGI Formats List, passed values are expected to be in ascending order
+ */
+ private static IntPredicate exactly(int ... acceptedValues) {
+ return test -> Arrays.binarySearch(acceptedValues, test) >= 0;
+ }
+
+ private static IntPredicate rangeInclusive(int from, int to) {
+ return test -> from <= test && test <= to;
+ }
+}
diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10Header.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10Header.java
new file mode 100644
index 00000000..d599d7f8
--- /dev/null
+++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DX10Header.java
@@ -0,0 +1,33 @@
+package com.twelvemonkeys.imageio.plugins.dds;
+
+import javax.imageio.stream.ImageInputStream;
+import java.io.IOException;
+
+//https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header-dxt10
+public final class DX10Header {
+ final DX10DXGIFormat dxgiFormat;
+ final int resourceDimension, miscFlag, arraySize, miscFlags2;
+
+ private DX10Header(int dxgiFormat, int resourceDimension, int miscFlag, int arraySize, int miscFlags2) {
+ this.dxgiFormat = DX10DXGIFormat.getFormat(dxgiFormat);
+ this.resourceDimension = resourceDimension;
+ if (this.resourceDimension != DDS.D3D10_RESOURCE_DIMENSION_TEXTURE2D)
+ throw new IllegalArgumentException("Resource dimension " + resourceDimension + " is not supported, expected 3.");
+ this.miscFlag = miscFlag;
+ this.arraySize = arraySize;
+ this.miscFlags2 = miscFlags2;
+ }
+
+ static DX10Header read(ImageInputStream inputStream) throws IOException {
+ int dxgiFormat = inputStream.readInt();
+ int resourceDimension = inputStream.readInt();
+ int miscFlag = inputStream.readInt();
+ int arraySize = inputStream.readInt();
+ int miscFlags2 = inputStream.readInt();
+ return new DX10Header(dxgiFormat, resourceDimension, miscFlag, arraySize, miscFlags2);
+ }
+
+ DDSType getDDSType() {
+ return dxgiFormat.getCorrespondingType();
+ }
+}
diff --git a/imageio/imageio-dds/src/test/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderTest.java b/imageio/imageio-dds/src/test/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderTest.java
index a9c7a52e..5b4c347b 100644
--- a/imageio/imageio-dds/src/test/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderTest.java
+++ b/imageio/imageio-dds/src/test/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReaderTest.java
@@ -86,7 +86,13 @@ public class DDSImageReaderTest extends ImageReaderAbstractTest
new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8.dds"), dim256),
new TestData(getClassLoaderResource("/dds/dds_X8B8G8R8_mipmap.dds"), dim256, dim128, dim64),
new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8.dds"), dim256),
- new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8_mipmap.dds"), dim256, dim128, dim64)
+ new TestData(getClassLoaderResource("/dds/dds_X8R8G8B8_mipmap.dds"), dim256, dim128, dim64),
+ new TestData(getClassLoaderResource("/dds/dxt10_BC1_sRGB.dds"), dim256),
+ new TestData(getClassLoaderResource("/dds/dxt10_BC2_sRGB.dds"), dim256),
+ new TestData(getClassLoaderResource("/dds/dxt10_BC3_sRGB.dds"), dim256),
+ new TestData(getClassLoaderResource("/dds/dxt10_B8G8R8A8.dds"), dim256),
+ new TestData(getClassLoaderResource("/dds/dxt10_B8G8R8X8.dds"), dim256),
+ new TestData(getClassLoaderResource("/dds/dxt10_R8G8B8A8.dds"), dim256)
);
}
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8A8.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8A8.dds
new file mode 100644
index 00000000..0b9ffcdd
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8A8.dds differ
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8X8.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8X8.dds
new file mode 100644
index 00000000..fb5f27e4
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_B8G8R8X8.dds differ
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_BC1_sRGB.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC1_sRGB.dds
new file mode 100644
index 00000000..339213a4
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC1_sRGB.dds differ
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_BC2_sRGB.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC2_sRGB.dds
new file mode 100644
index 00000000..e0fd8b66
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC2_sRGB.dds differ
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_BC3_sRGB.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC3_sRGB.dds
new file mode 100644
index 00000000..6460ed3c
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_BC3_sRGB.dds differ
diff --git a/imageio/imageio-dds/src/test/resources/dds/dxt10_R8G8B8A8.dds b/imageio/imageio-dds/src/test/resources/dds/dxt10_R8G8B8A8.dds
new file mode 100644
index 00000000..70e076f4
Binary files /dev/null and b/imageio/imageio-dds/src/test/resources/dds/dxt10_R8G8B8A8.dds differ