From 05f754f6e57a5d421e93d7b01852f152266584d1 Mon Sep 17 00:00:00 2001 From: Paul Allen Date: Tue, 24 Sep 2024 17:49:58 +0100 Subject: [PATCH] Use imageIndex to calculate height/width and buffer offset. --- .../imageio/plugins/dds/DDSHeader.java | 55 +++++++++++-------- .../imageio/plugins/dds/DDSImageReader.java | 11 +++- .../imageio/plugins/dds/DDSReader.java | 37 ++++--------- 3 files changed, 52 insertions(+), 51 deletions(-) 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 ab6eb0ba..74be65b2 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 @@ -2,18 +2,18 @@ package com.twelvemonkeys.imageio.plugins.dds; import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; +import java.awt.Dimension; import java.io.IOException; import java.math.BigInteger; -import java.nio.ByteOrder; import java.util.Arrays; final class DDSHeader { // https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide private int flags; - private int width; - private int height; - private int mipmap; + + private int mipMapCount; + private Dimension[] dimensions; private int pixelFormatFlags; private int fourCC; @@ -25,7 +25,7 @@ final class DDSHeader { public static DDSHeader read(final ImageInputStream imageInput) throws IOException { DDSHeader header = new DDSHeader(); - + // Read MAGIC bytes [0,3] byte[] magic = new byte[DDS.MAGIC.length]; imageInput.readFully(magic); @@ -50,13 +50,15 @@ final class DDSHeader { } // Read Height & Width - header.height = imageInput.readInt(); // [12,15] - header.width = imageInput.readInt(); // [16,19] - + int dwHeight = imageInput.readInt(); // [12,15] + int dwWidth = imageInput.readInt(); // [16,19] int dwPitchOrLinearSize = imageInput.readInt(); // [20,23] int dwDepth = imageInput.readInt(); // [24,27] - header.mipmap = imageInput.readInt(); // [28,31] + header.mipMapCount = imageInput.readInt(); // [28,31] + + // build dimensions list + header.addDimensions(dwWidth, dwHeight); byte[] dwReserved1 = new byte[11 * 4]; // [32,75] imageInput.readFully(dwReserved1); @@ -82,28 +84,35 @@ final class DDSHeader { return header; } + private void addDimensions(int width, int height) { + dimensions = new Dimension[getMipMapCount()]; + + int w = width; + int h = height; + for (int i = 0; i < getMipMapCount(); i++) { + dimensions[i] = new Dimension(w, h); + w /= 2; + h /= 2; + } + } + private boolean getFlag(int mask) { return (flags & mask) != 0; } - public int getWidth() { - return width; + public int getWidth(int imageIndex) { + int lim = dimensions[imageIndex].width; + return (lim <= 0) ? 1 : lim; } - public void setWidth(int width) { - this.width = width; + public int getHeight(int imageIndex) { + int lim = dimensions[imageIndex].height; + return (lim <= 0) ? 1 : lim; } - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getMipmap() { - return mipmap; + public int getMipMapCount() { + // 0 = (unused) or 1 = (1 level), but still only one 'base' image + return (mipMapCount == 0) ? 1 : mipMapCount; } public int getAlphaMask() { diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReader.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReader.java index ed2d39d9..bacdc733 100644 --- a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReader.java +++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSImageReader.java @@ -34,7 +34,7 @@ public final class DDSImageReader extends ImageReaderBase { checkBounds(imageIndex); readHeader(); - return header.getWidth(); + return header.getWidth(imageIndex); } @Override @@ -42,7 +42,14 @@ public final class DDSImageReader extends ImageReaderBase { checkBounds(imageIndex); readHeader(); - return header.getHeight(); + return header.getHeight(imageIndex); + } + + @Override + public int getNumImages(final boolean allowSearch) throws IOException { + readHeader(); + + return header.getMipMapCount(); } @Override 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 8df75cb6..71ed3536 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 @@ -29,39 +29,21 @@ final class DDSReader { this.header = header; } - public int[] read(ImageInputStream imageInput, int mipmapLevel) throws IOException { - - // header - int width = header.getWidth(); - int height = header.getHeight(); - int mipmap = header.getMipmap(); - - if (mipmapLevel > mipmap) { - throw new IIOException("Invalid mipmap level: " + mipmapLevel); - } + public int[] read(ImageInputStream imageInput, int imageIndex) throws IOException { // type DDSType type = getType(); - // length - int len = getLength(type, width, height); - byte[] buffer = new byte[len]; - imageInput.readFully(buffer); - - for (int i = 1; i < mipmapLevel; i++) { - width /= 2; - height /= 2; - - // length - len = getLength(type, width, height); + // offset buffer to index mipmap image + byte[] buffer = null; + for (int i = 0; i <= imageIndex; i++) { + int len = getLength(type, i); buffer = new byte[len]; imageInput.readFully(buffer); } - if (width <= 0) width = 1; - if (height <= 0) height = 1; - header.setWidth(width); - header.setHeight(height); + int width = header.getWidth(imageIndex); + int height = header.getHeight(imageIndex); switch (type) { case DXT1: @@ -163,7 +145,10 @@ final class DDSReader { } } - private static int getLength(DDSType type, int width, int height) throws IIOException { + private int getLength(DDSType type, int imageIndex) throws IIOException { + int width = header.getWidth(imageIndex); + int height = header.getHeight(imageIndex); + switch (type) { case DXT1: return 8 * ((width + 3) / 4) * ((height + 3) / 4);