More clean-up: Now keeps stream byte order consistent (LE), support for Raster, more tests

This commit is contained in:
Harald Kuhr
2026-03-11 15:59:48 +01:00
parent dc59c66209
commit 3f356a8197
12 changed files with 184 additions and 58 deletions
@@ -33,7 +33,8 @@ package com.twelvemonkeys.imageio.plugins.dds;
@SuppressWarnings("unused") @SuppressWarnings("unused")
interface DDS { interface DDS {
int MAGIC = ('D' << 24) + ('D' << 16) + ('S' << 8) + ' '; // Big-Endian int MAGIC = 'D' + ('D' << 8) + ('S' << 16) + (' ' << 24); // Little-Endian
int HEADER_SIZE = 124; int HEADER_SIZE = 124;
int PIXELFORMAT_SIZE = 32; int PIXELFORMAT_SIZE = 32;
@@ -48,7 +49,6 @@ interface DDS {
int FLAG_DEPTH = 1 << 23; // Required in a depth texture. int FLAG_DEPTH = 1 << 23; // Required in a depth texture.
// Pixel Format Flags // Pixel Format Flags
int DDSPF_SIZE = 32;
int PIXEL_FORMAT_FLAG_ALPHAPIXELS = 0x1; int PIXEL_FORMAT_FLAG_ALPHAPIXELS = 0x1;
int PIXEL_FORMAT_FLAG_ALPHA = 0x2; int PIXEL_FORMAT_FLAG_ALPHA = 0x2;
int PIXEL_FORMAT_FLAG_FOURCC = 0x04; int PIXEL_FORMAT_FLAG_FOURCC = 0x04;
@@ -71,12 +71,10 @@ final class DDSHeader {
DDSHeader header = new DDSHeader(); DDSHeader header = new DDSHeader();
// Read MAGIC bytes [0,3] // Read MAGIC bytes [0,3]
imageInput.setByteOrder(ByteOrder.BIG_ENDIAN);
int magic = imageInput.readInt(); int magic = imageInput.readInt();
if (magic != DDS.MAGIC) { if (magic != DDS.MAGIC) {
throw new IIOException(String.format("Not a DDS file. Expected DDS magic 0x%8x', read 0x%8x", DDS.MAGIC, 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 // DDS_HEADER structure
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header // https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
@@ -1,5 +1,6 @@
package com.twelvemonkeys.imageio.plugins.dds; package com.twelvemonkeys.imageio.plugins.dds;
import javax.imageio.IIOException;
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
import java.awt.Color; import java.awt.Color;
import java.awt.image.Raster; import java.awt.image.Raster;
@@ -27,24 +28,24 @@ class DDSImageDataEncoder {
private static final int BC4_CHANNEL_ALPHA = 3; //BC3 reuses algorithm from BC4 but uses alpha channelIndex for sampling. private static final int BC4_CHANNEL_ALPHA = 3; //BC3 reuses algorithm from BC4 but uses alpha channelIndex for sampling.
private static final int BC4_CHANNEL_GREEN = 1; //same re-usage as BC3 but for green channel BC5 uses private static final int BC4_CHANNEL_GREEN = 1; //same re-usage as BC3 but for green channel BC5 uses
static void writeImageData(ImageOutputStream imageOutput, RenderedImage renderedImage, BlockCompression compression) throws IOException { static void writeImageData(ImageOutputStream imageOutput, Raster raster, BlockCompression compression) throws IOException {
// TODO: Support compression == null for uncompressed RGB(A/X) data? // TODO: Support compression == null for uncompressed RGB(A/X) data?
switch (compression) { switch (compression) {
case BC1: case BC1:
new BlockCompressor1(false).encode(imageOutput, renderedImage); new BlockCompressor1(false).encode(imageOutput, raster);
break; break;
case BC2: case BC2:
new BlockCompressor2().encode(imageOutput, renderedImage); new BlockCompressor2().encode(imageOutput, raster);
break; break;
case BC3: case BC3:
new BlockCompressor3().encode(imageOutput, renderedImage); new BlockCompressor3().encode(imageOutput, raster);
break; break;
case BC4: case BC4:
new BlockCompressor4(BC4_CHANNEL_RED).encode(imageOutput, renderedImage); new BlockCompressor4(BC4_CHANNEL_RED).encode(imageOutput, raster);
break; break;
case BC5: case BC5:
new BlockCompressor5().encode(imageOutput, renderedImage); new BlockCompressor5().encode(imageOutput, raster);
break; break;
default: default:
throw new IllegalArgumentException("DDS block compression is not supported yet: " + compression); throw new IllegalArgumentException("DDS block compression is not supported yet: " + compression);
@@ -418,14 +419,9 @@ class DDSImageDataEncoder {
} }
} }
void encode(ImageOutputStream imageOutput, RenderedImage image) throws IOException { void encode(ImageOutputStream imageOutput, Raster raster) throws IOException {
int blocksXCount = (image.getWidth() + 3) / 4; int blocksXCount = (raster.getWidth() + 3) / 4;
int blocksYCount = (image.getHeight() + 3) / 4; int blocksYCount = (raster.getHeight() + 3) / 4;
if (image.getNumXTiles() != 1 || image.getNumYTiles() != 1) {
throw new IllegalArgumentException("Only single tile images supported");
}
Raster raster = image.getTile(0, 0);
for (int blockY = 0; blockY < blocksYCount; blockY++) { for (int blockY = 0; blockY < blocksYCount; blockY++) {
for (int blockX = 0; blockX < blocksXCount; blockX++) { for (int blockX = 0; blockX < blocksXCount; blockX++) {
@@ -166,11 +166,9 @@ public final class DDSImageReader extends ImageReaderBase {
private void readHeader() throws IOException { private void readHeader() throws IOException {
if (header == null) { if (header == null) {
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN); // TODO: Move to setInput? imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
header = DDSHeader.read(imageInput); header = DDSHeader.read(imageInput);
imageInput.flushBefore(imageInput.getStreamPosition()); imageInput.flushBefore(imageInput.getStreamPosition());
System.out.println("header = " + header);
} }
imageInput.seek(imageInput.getFlushedPosition()); imageInput.seek(imageInput.getFlushedPosition());
@@ -35,6 +35,7 @@ import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
import javax.imageio.ImageReader; import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteOrder;
import java.util.Locale; import java.util.Locale;
public final class DDSImageReaderSpi extends ImageReaderSpiBase { public final class DDSImageReaderSpi extends ImageReaderSpiBase {
@@ -52,11 +53,15 @@ public final class DDSImageReaderSpi extends ImageReaderSpiBase {
ImageInputStream stream = (ImageInputStream) source; ImageInputStream stream = (ImageInputStream) source;
stream.mark(); stream.mark();
ByteOrder byteOrder = stream.getByteOrder();
try { try {
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
return stream.readInt() == DDS.MAGIC; return stream.readInt() == DDS.MAGIC;
} }
finally { finally {
stream.setByteOrder(byteOrder);
stream.reset(); stream.reset();
} }
} }
@@ -3,6 +3,7 @@ package com.twelvemonkeys.imageio.plugins.dds;
import com.twelvemonkeys.imageio.ImageWriterBase; import com.twelvemonkeys.imageio.ImageWriterBase;
import com.twelvemonkeys.imageio.util.IIOUtil; import com.twelvemonkeys.imageio.util.IIOUtil;
import javax.imageio.IIOException;
import javax.imageio.IIOImage; import javax.imageio.IIOImage;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageTypeSpecifier;
@@ -39,51 +40,74 @@ class DDSImageWriter extends ImageWriterBase {
// This involves seeking backwards, updating the mipmap flag and mipmapcount in the header... :-/ // This involves seeking backwards, updating the mipmap flag and mipmapcount in the header... :-/
// + ensuring that each level is half the size of the previous, but still a multiple of 4... // + ensuring that each level is half the size of the previous, but still a multiple of 4...
@Override
public boolean canWriteRasters() {
return true;
}
@Override @Override
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException {
assertOutput(); assertOutput();
RenderedImage renderedImage = image.getRenderedImage(); // TODO: Support raster? Raster raster = getRaster(image);
ensureTextureSize(renderedImage); ensureTextureSize(raster);
ensureImageChannels(renderedImage); ensureImageChannels(raster);
DDSImageWriteParam ddsParam = param instanceof DDSImageWriteParam DDSImageWriteParam ddsParam = param instanceof DDSImageWriteParam
? ((DDSImageWriteParam) param) ? ((DDSImageWriteParam) param)
: IIOUtil.copyStandardParams(param, getDefaultWriteParam()); : IIOUtil.copyStandardParams(param, getDefaultWriteParam());
processImageStarted(0); if (ddsParam.compression() == null) {
imageOutput.setByteOrder(ByteOrder.BIG_ENDIAN); throw new IIOException("Only compressed DDS using DXT1-5 or DXT10 with block compression is currently supported");
imageOutput.writeInt(DDS.MAGIC); }
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
writeHeader(image, ddsParam.type(), ddsParam.isWriteDXT10()); imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
imageOutput.writeInt(DDS.MAGIC);
writeHeader(raster.getWidth(), raster.getHeight(), ddsParam.type(), ddsParam.isWriteDXT10());
if (ddsParam.isWriteDXT10()) { if (ddsParam.isWriteDXT10()) {
writeDXT10Header(ddsParam.getDxgiFormat()); writeDXT10Header(ddsParam.getDxgiFormat());
} }
processImageStarted(0);
processImageProgress(0f); processImageProgress(0f);
DDSImageDataEncoder.writeImageData(imageOutput, renderedImage, ddsParam.compression()); DDSImageDataEncoder.writeImageData(imageOutput, raster, ddsParam.compression());
processImageProgress(100f); processImageProgress(100f);
imageOutput.flush(); imageOutput.flush();
processImageComplete(); processImageComplete();
} }
private static Raster getRaster(IIOImage image) throws IIOException {
if (image.hasRaster()) {
return image.getRaster();
}
else {
RenderedImage renderedImage = image.getRenderedImage();
if (renderedImage.getNumXTiles() != 1 || renderedImage.getNumYTiles() != 1) {
throw new IIOException("Only single tile images supported");
}
return renderedImage.getTile(0, 0);
}
}
/** /**
* Checking if the image has 3 channels (RGB) or 4 channels (RGBA) and if image has 8 bits/channel. * Checking if the image has 3 channels (RGB) or 4 channels (RGBA) and if image has 8 bits/channel.
*
* @see DDSImageWriterSpi#canEncodeImage(ImageTypeSpecifier)
*/ */
private void ensureImageChannels(RenderedImage renderedImage) { private void ensureImageChannels(Raster data) throws IIOException {
Raster data = renderedImage.getTile(0, 0);
int numBands = data.getNumBands(); int numBands = data.getNumBands();
if (numBands < 3) { if (numBands < 3 || numBands > 4) {
throw new IllegalStateException( throw new IIOException(
"Only image with 3 channels (RGB) or 4 channels (RGBA) is supported, got " + numBands + " channels"); "Only image with 3 channels (RGB) or 4 channels (RGBA) is supported, got " + numBands + " channels");
} }
int sampleSize = data.getSampleModel().getSampleSize(0); int sampleSize = data.getSampleModel().getSampleSize(0);
if (sampleSize != 8) { if (sampleSize != 8) {
throw new IllegalStateException("Only image with 8 bits/channel is supported, got " + sampleSize); throw new IIOException("Only image with 8 bits/channel is supported, got " + sampleSize);
} }
} }
@@ -91,24 +115,21 @@ class DDSImageWriter extends ImageWriterBase {
* Checking if an image can be evenly divided into blocks of 4x4, ideally a power of 2. * Checking if an image can be evenly divided into blocks of 4x4, ideally a power of 2.
* e.g. 16x16, 32x32, 512x128, 512x512, 1024x512, 1024x1024, 2048x1024, ... * e.g. 16x16, 32x32, 512x128, 512x512, 1024x512, 1024x1024, 2048x1024, ...
*/ */
private void ensureTextureSize(RenderedImage renderedImage) { private void ensureTextureSize(Raster raster) throws IIOException {
int w = renderedImage.getWidth(); int width = raster.getWidth();
int h = renderedImage.getHeight(); int height = raster.getHeight();
if (w % 4 != 0 || h % 4 != 0) { // Should also allow mipmaps 2x2 and 1x1?
throw new IllegalStateException(String.format("Image size must be dividable by 4, ideally a power of 2; got (%d x %d)", w, h)); if (width % 4 != 0 || height % 4 != 0) {
throw new IIOException(String.format("Image dimensions must be dividable by 4, ideally a power of 2; got %dx%d", width, height));
} }
} }
private void writeHeader(IIOImage image, DDSType type, boolean writeDXT10) throws IOException { private void writeHeader(int width, int height, DDSType type, boolean writeDXT10) throws IOException {
imageOutput.writeInt(DDS.HEADER_SIZE); imageOutput.writeInt(DDS.HEADER_SIZE);
int linearSizeOrPitch = type.isBlockCompression() ? DDS.FLAG_LINEARSIZE : DDS.FLAG_PITCH; int linearSizeOrPitch = type.isBlockCompression() ? DDS.FLAG_LINEARSIZE : DDS.FLAG_PITCH;
imageOutput.writeInt(DDS.FLAG_CAPS | DDS.FLAG_HEIGHT | DDS.FLAG_WIDTH | DDS.FLAG_PIXELFORMAT | linearSizeOrPitch); imageOutput.writeInt(DDS.FLAG_CAPS | DDS.FLAG_HEIGHT | DDS.FLAG_WIDTH | DDS.FLAG_PIXELFORMAT | linearSizeOrPitch);
RenderedImage renderedImage = image.getRenderedImage();
int height = renderedImage.getHeight();
int width = renderedImage.getWidth();
imageOutput.writeInt(height); imageOutput.writeInt(height);
imageOutput.writeInt(width); imageOutput.writeInt(width);
writePitchOrLinearSize(height, width, type); writePitchOrLinearSize(height, width, type);
@@ -126,12 +147,11 @@ class DDSImageWriter extends ImageWriterBase {
imageOutput.writeInt(0); imageOutput.writeInt(0);
//dwCaps3, dwCaps4, dwReserved2 : 3 unused integers //dwCaps3, dwCaps4, dwReserved2 : 3 unused integers
imageOutput.write(new byte[12]); imageOutput.write(new byte[12]);
} }
//https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-pixelformat //https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-pixelformat
private void writePixelFormat(DDSType type, boolean writeDXT10) throws IOException { private void writePixelFormat(DDSType type, boolean writeDXT10) throws IOException {
imageOutput.writeInt(DDS.DDSPF_SIZE); imageOutput.writeInt(DDS.PIXELFORMAT_SIZE);
writePixelFormatFlags(type, writeDXT10); writePixelFormatFlags(type, writeDXT10);
writeFourCC(type, writeDXT10); writeFourCC(type, writeDXT10);
writeRGBAData(type, writeDXT10); writeRGBAData(type, writeDXT10);
@@ -4,6 +4,8 @@ import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase;
import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter; import javax.imageio.ImageWriter;
import java.awt.image.Raster;
import java.util.Locale; import java.util.Locale;
public final class DDSImageWriterSpi extends ImageWriterSpiBase { public final class DDSImageWriterSpi extends ImageWriterSpiBase {
@@ -13,7 +15,12 @@ public final class DDSImageWriterSpi extends ImageWriterSpiBase {
@Override @Override
public boolean canEncodeImage(ImageTypeSpecifier type) { public boolean canEncodeImage(ImageTypeSpecifier type) {
return true; int numBands = type.getNumBands();
if (numBands < 3 || numBands > 4) {
return false;
}
return type.getSampleModel().getSampleSize(0) == 8;
} }
@Override @Override
@@ -166,14 +166,14 @@ enum DDSType {
case DXGI.DXGI_FORMAT_BC4_TYPELESS: case DXGI.DXGI_FORMAT_BC4_TYPELESS:
case DXGI.DXGI_FORMAT_BC4_UNORM: case DXGI.DXGI_FORMAT_BC4_UNORM:
return ATI1; return BC4U;
case DXGI.DXGI_FORMAT_BC4_SNORM: case DXGI.DXGI_FORMAT_BC4_SNORM:
return BC4S; return BC4S;
case DXGI.DXGI_FORMAT_BC5_TYPELESS: case DXGI.DXGI_FORMAT_BC5_TYPELESS:
case DXGI.DXGI_FORMAT_BC5_UNORM: case DXGI.DXGI_FORMAT_BC5_UNORM:
return ATI2; return BC5U;
case DXGI.DXGI_FORMAT_BC5_SNORM: case DXGI.DXGI_FORMAT_BC5_SNORM:
return BC5S; return BC5S;
@@ -27,6 +27,11 @@ class DDSImageMetadataTest {
IIOMetadataNode lossless = (IIOMetadataNode) losslesses.item(0); IIOMetadataNode lossless = (IIOMetadataNode) losslesses.item(0);
assertEquals("FALSE", lossless.getAttribute("value")); assertEquals("FALSE", lossless.getAttribute("value"));
NodeList bitsPerSamples = tree.getElementsByTagName("BitsPerSample");
assertEquals(1, bitsPerSamples.getLength());
IIOMetadataNode bitsPerSample = (IIOMetadataNode) bitsPerSamples.item(0);
assertEquals("8 8 8 8", bitsPerSample.getAttribute("value"));
NodeList alphas = tree.getElementsByTagName("Alpha"); NodeList alphas = tree.getElementsByTagName("Alpha");
assertEquals(1, alphas.getLength()); assertEquals(1, alphas.getLength());
IIOMetadataNode alpha = (IIOMetadataNode) alphas.item(0); IIOMetadataNode alpha = (IIOMetadataNode) alphas.item(0);
@@ -30,14 +30,27 @@
package com.twelvemonkeys.imageio.plugins.dds; package com.twelvemonkeys.imageio.plugins.dds;
import static org.junit.jupiter.api.Assertions.assertEquals;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.Dimension; import java.awt.Dimension;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.Test;
import org.w3c.dom.NodeList;
public class DDSImageReaderTest extends ImageReaderAbstractTest<DDSImageReader> { public class DDSImageReaderTest extends ImageReaderAbstractTest<DDSImageReader> {
@Override @Override
protected ImageReaderSpi createProvider() { protected ImageReaderSpi createProvider() {
@@ -111,5 +124,66 @@ public class DDSImageReaderTest extends ImageReaderAbstractTest<DDSImageReader>
return Collections.singletonList("image/vnd-ms.dds"); return Collections.singletonList("image/vnd-ms.dds");
} }
@Test
void metadataDXT5() throws IOException {
ImageReader reader = createReader();
try (ImageInputStream inputStream = ImageIO.createImageInputStream(getClassLoaderResource("/dds/dds_DXT5.dds"))) {
reader.setInput(inputStream);
IIOMetadata metadata = reader.getImageMetadata(0);
IIOMetadataNode tree = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
NodeList compressionTypeNames = tree.getElementsByTagName("CompressionTypeName");
assertEquals(1, compressionTypeNames.getLength());
IIOMetadataNode compressionTypeName = (IIOMetadataNode) compressionTypeNames.item(0);
assertEquals("DXT5", compressionTypeName.getAttribute("value"));
NodeList losslesses = tree.getElementsByTagName("Lossless");
assertEquals(1, losslesses.getLength());
IIOMetadataNode lossless = (IIOMetadataNode) losslesses.item(0);
assertEquals("FALSE", lossless.getAttribute("value"));
NodeList bitsPerSamples = tree.getElementsByTagName("BitsPerSample");
assertEquals(1, bitsPerSamples.getLength());
IIOMetadataNode bitsPerSample = (IIOMetadataNode) bitsPerSamples.item(0);
assertEquals("8 8 8 8", bitsPerSample.getAttribute("value"));
NodeList alphas = tree.getElementsByTagName("Alpha");
assertEquals(1, alphas.getLength());
IIOMetadataNode alpha = (IIOMetadataNode) alphas.item(0);
assertEquals("nonpremultiplied", alpha.getAttribute("value"));
}
finally {
reader.dispose();
}
}
@Test
void metadataRGB565() throws IOException {
ImageReader reader = createReader();
try (ImageInputStream inputStream = ImageIO.createImageInputStream(getClassLoaderResource("/dds/dds_R5G6B5.dds"))) {
reader.setInput(inputStream);
IIOMetadata metadata = reader.getImageMetadata(0);
IIOMetadataNode tree = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
NodeList compressions = tree.getElementsByTagName("Compression");
assertEquals(0, compressions.getLength());
NodeList bitsPerSamples = tree.getElementsByTagName("BitsPerSample");
assertEquals(1, bitsPerSamples.getLength());
IIOMetadataNode bitsPerSample = (IIOMetadataNode) bitsPerSamples.item(0);
assertEquals("5 6 5 0", bitsPerSample.getAttribute("value")); // or "5 6 5"
NodeList alphas = tree.getElementsByTagName("Alpha");
assertEquals(1, alphas.getLength());
IIOMetadataNode alpha = (IIOMetadataNode) alphas.item(0);
assertEquals("none", alpha.getAttribute("value"));
}
finally {
reader.dispose();
}
}
} }
@@ -4,9 +4,17 @@ import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays; import java.util.Arrays;
import javax.imageio.ImageWriteParam;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
class DDSImageWriteParamTest { class DDSImageWriteParamTest {
@Test
void defaultParam() {
DDSImageWriteParam param = new DDSImageWriteParam();
assertEquals(DDSImageWriteParam.DEFAULT_TYPE, param.type());
}
@Test @Test
void compressionTypes() { void compressionTypes() {
DDSImageWriteParam param = new DDSImageWriteParam(); DDSImageWriteParam param = new DDSImageWriteParam();
@@ -27,11 +35,22 @@ class DDSImageWriteParamTest {
} }
@Test @Test
void defaultParam() { void setCompression() {
DDSImageWriteParam param = new DDSImageWriteParam(); DDSImageWriteParam param = new DDSImageWriteParam();
// param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // Meh...
assertEquals(DDSImageWriteParam.DEFAULT_TYPE, param.type()); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// assertEquals(DDSImageWriterParam.DEFAULT_TYPE.name(), param.getCompressionType());
String[] compressionTypes = param.getCompressionTypes();
for (String compressionType : compressionTypes) {
param.setCompressionType(compressionType);
assertEquals(compressionType, param.getCompressionType());
if (!"None".equals(compressionType)) {
DDSType type = DDSType.valueOf(compressionType);
assertEquals(type, param.type());
assertEquals(type.compression, param.compression());
}
}
} }
} }
@@ -4,7 +4,7 @@ import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ImageWriterSpi;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.Collections; import java.util.Arrays;
import java.util.List; import java.util.List;
public class DDSImageWriterTest extends ImageWriterAbstractTest<DDSImageWriter> { public class DDSImageWriterTest extends ImageWriterAbstractTest<DDSImageWriter> {
@@ -15,8 +15,12 @@ public class DDSImageWriterTest extends ImageWriterAbstractTest<DDSImageWriter>
@Override @Override
protected List<BufferedImage> getTestData() { protected List<BufferedImage> getTestData() {
return Collections.singletonList( return Arrays.asList(
new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB_PRE) new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB_PRE),
new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB),
new BufferedImage(64, 64, BufferedImage.TYPE_INT_RGB),
new BufferedImage(32, 32, BufferedImage.TYPE_4BYTE_ABGR),
new BufferedImage(16, 16, BufferedImage.TYPE_3BYTE_BGR)
); );
} }
} }