From 7fc47a338c196be61b757c7ee50e2d077f0781c1 Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Thu, 26 Sep 2024 11:16:26 +0200 Subject: [PATCH] Add minimal metadata + minor clean-up --- .../imageio/plugins/dds/DDS.java | 6 ++ .../imageio/plugins/dds/DDSHeader.java | 1 + .../imageio/plugins/dds/DDSImageReader.java | 9 +++ .../plugins/dds/DDSImageReaderSpi.java | 2 +- .../imageio/plugins/dds/DDSMetadata.java | 58 +++++++++++++++++++ .../imageio/plugins/dds/DDSReader.java | 13 +++-- 6 files changed, 82 insertions(+), 7 deletions(-) create mode 100755 imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSMetadata.java 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 9b148abd..02282708 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 @@ -30,10 +30,12 @@ package com.twelvemonkeys.imageio.plugins.dds; +@SuppressWarnings("unused") interface DDS { byte[] MAGIC = new byte[]{'D', 'D', 'S', ' '}; int HEADER_SIZE = 124; + // Header Flags int FLAG_CAPS = 0x1; // Required in every .dds file. int FLAG_HEIGHT = 0x2; // Required in every .dds file. int FLAG_WIDTH = 0x4; // Required in every .dds file. @@ -42,4 +44,8 @@ interface DDS { int FLAG_MIPMAPCOUNT = 0x20000; // Required in a mipmapped texture. int FLAG_LINEARSIZE = 0x80000; // Required when pitch is provided for a compressed texture. int FLAG_DEPTH = 0x800000; // Required in a depth texture. + + // Pixel Format Flags + int PIXEL_FORMAT_FLAG_FOURCC = 0x04; + int PIXEL_FORMAT_FLAG_RGB = 0x40; } 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 ef5e6fdb..bc784fda 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 @@ -53,6 +53,7 @@ final class DDSHeader { private int blueMask; private int alphaMask; + @SuppressWarnings("unused") static DDSHeader read(final ImageInputStream imageInput) throws IOException { DDSHeader header = new DDSHeader(); 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 f0f6b3cf..deb77901 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 @@ -38,6 +38,7 @@ import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageReaderSpi; import java.awt.*; @@ -90,6 +91,7 @@ public final class DDSImageReader extends ImageReaderBase { checkBounds(imageIndex); readHeader(); + // TODO: Implement for the specific formats... return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB); } @@ -141,6 +143,13 @@ public final class DDSImageReader extends ImageReaderBase { return destination; } + @Override + public IIOMetadata getImageMetadata(int imageIndex) throws IOException { + ImageTypeSpecifier imageType = getRawImageType(imageIndex); + + return new DDSMetadata(imageType, header); + } + private void readHeader() throws IOException { if (header == null) { imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN); 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 34fb2618..33113c38 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 @@ -65,7 +65,7 @@ public final class DDSImageReaderSpi extends ImageReaderSpiBase { } @Override - public ImageReader createReaderInstance(Object extension) throws IOException { + public ImageReader createReaderInstance(Object extension) { return new DDSImageReader(this); } diff --git a/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSMetadata.java b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSMetadata.java new file mode 100755 index 00000000..ca168751 --- /dev/null +++ b/imageio/imageio-dds/src/main/java/com/twelvemonkeys/imageio/plugins/dds/DDSMetadata.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.twelvemonkeys.imageio.plugins.dds; + +import javax.imageio.ImageTypeSpecifier; + +import com.twelvemonkeys.imageio.StandardImageMetadataSupport; + +final class DDSMetadata extends StandardImageMetadataSupport { + DDSMetadata(ImageTypeSpecifier type, DDSHeader header) { + super(builder(type) + .withCompressionTypeName(compressionName(header)) + .withFormatVersion("1.0") + ); + } + + private static String compressionName(DDSHeader header) { + // If the fourCC is valid, compression is one of the DXTn versions, otherwise None + int flags = header.getPixelFormatFlags(); + + if ((flags & DDS.PIXEL_FORMAT_FLAG_FOURCC) != 0) { + // DXTn + DDSType type = DDSType.valueOf(header.getFourCC()); + + return type.name(); + } + + return "None"; + } +} 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 272e7613..dc8a8dae 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 @@ -134,11 +134,12 @@ final class DDSReader { private DDSType getType() throws IIOException { int flags = header.getPixelFormatFlags(); - if ((flags & 0x04) != 0) { + if ((flags & DDS.PIXEL_FORMAT_FLAG_FOURCC) != 0) { // DXT int type = header.getFourCC(); return DDSType.valueOf(type); - } else if ((flags & 0x40) != 0) { + + } else if ((flags & DDS.PIXEL_FORMAT_FLAG_RGB) != 0) { // RGB int bitCount = header.getBitCount(); int redMask = header.getRedMask(); @@ -240,7 +241,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 + 0] = 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; @@ -270,7 +271,7 @@ final class DDSReader { int a0 = (buffer[index++] & 0xFF); int a1 = (buffer[index++] & 0xFF); // 4bit alpha to 8bit alpha - alphaTable[4 * k + 0] = 17 * ((a0 & 0xF0) >> 4); + alphaTable[4 * k ] = 17 * ((a0 & 0xF0) >> 4); alphaTable[4 * k + 1] = 17 * (a0 & 0x0F); alphaTable[4 * k + 2] = 17 * ((a1 & 0xF0) >> 4); alphaTable[4 * k + 3] = 17 * (a1 & 0x0F); @@ -285,7 +286,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 + 0] = getDXTColor(c0, c1, alphaTable[4 * k + 0], 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; @@ -343,7 +344,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 + 0] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 0]), 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;