From b6988c37a7286ebe2912372b81132a70bec3406a Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Tue, 15 Dec 2020 22:19:04 +0100 Subject: [PATCH] #577 Fix TGA subsampling + bonus metadata fix and palette conversion. (cherry picked from commit af1a6492d400e0dfc19a419a751899850799d726) --- .../imageio/plugins/tga/TGAHeader.java | 22 ++++++++++++--- .../imageio/plugins/tga/TGAImageReader.java | 8 +++--- .../imageio/plugins/tga/TGAMetadata.java | 1 + .../plugins/tga/TGAImageReaderTest.java | 27 +++++++++++++++++++ 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAHeader.java b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAHeader.java index 32980eb5..8b58fb23 100755 --- a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAHeader.java +++ b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAHeader.java @@ -200,12 +200,12 @@ final class TGAHeader { int components = colorMap.hasAlpha() ? 4 : 3; byte[] cmap = new byte[rgb.length * components]; for (int i = 0; i < rgb.length; i++) { - cmap[i * components ] = (byte) ((rgb[i] >> 16) & 0xff); - cmap[i * components + 1] = (byte) ((rgb[i] >> 8) & 0xff); - cmap[i * components + 2] = (byte) ((rgb[i] ) & 0xff); + cmap[i * components ] = (byte) ((rgb[i] ) & 0xff); // B + cmap[i * components + 1] = (byte) ((rgb[i] >> 8) & 0xff); // G + cmap[i * components + 2] = (byte) ((rgb[i] >> 16) & 0xff); // R if (components == 4) { - cmap[i * components + 3] = (byte) ((rgb[i] >>> 24) & 0xff); + cmap[i * components + 3] = (byte) ((rgb[i] >>> 24) & 0xff); // A } } @@ -298,9 +298,23 @@ final class TGAHeader { hasAlpha = false; break; case 24: + // BGR -> RGB + for (int i = 0; i < cmap.length; i += 3) { + byte b = cmap[i]; + cmap[i ] = cmap[i + 2]; + cmap[i + 2] = b; + } + hasAlpha = false; break; case 32: + // BGRA -> RGBA + for (int i = 0; i < cmap.length; i += 4) { + byte b = cmap[i]; + cmap[i ] = cmap[i + 2]; + cmap[i + 2] = b; + } + hasAlpha = true; break; default: diff --git a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java index 76b0c98d..9c0671b3 100755 --- a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java +++ b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java @@ -224,7 +224,7 @@ final class TGAImageReader extends ImageReaderBase { byte[] rowDataByte, WritableRaster destChannel, Raster srcChannel, int y) throws IOException { // If subsampled or outside source region, skip entire row if (y % ySub != 0 || height - 1 - y < srcRegion.y || height - 1 - y >= srcRegion.y + srcRegion.height) { - imageInput.skipBytes(rowDataByte.length); + input.skipBytes(rowDataByte.length); return; } @@ -251,7 +251,8 @@ final class TGAImageReader extends ImageReaderBase { destChannel.setDataElements(0, dstY, srcChannel); break; case TGA.ORIGIN_UPPER_LEFT: - destChannel.setDataElements(0, y, srcChannel); + dstY = y / ySub; + destChannel.setDataElements(0, dstY, srcChannel); break; default: throw new IIOException("Unsupported origin: " + origin); @@ -289,7 +290,8 @@ final class TGAImageReader extends ImageReaderBase { destChannel.setDataElements(0, dstY, srcChannel); break; case TGA.ORIGIN_UPPER_LEFT: - destChannel.setDataElements(0, y, srcChannel); + dstY = y / ySub; + destChannel.setDataElements(0, dstY, srcChannel); break; default: throw new IIOException("Unsupported origin: " + origin); diff --git a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAMetadata.java b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAMetadata.java index 3932b230..241a800a 100755 --- a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAMetadata.java +++ b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAMetadata.java @@ -189,6 +189,7 @@ final class TGAMetadata extends AbstractMetadata { switch (header.getPixelDepth()) { case 8: bitsPerSample.setAttribute("value", createListValue(1, Integer.toString(header.getPixelDepth()))); + break; case 16: if (header.getAttributeBits() > 0 && extensions != null && extensions.hasAlpha()) { bitsPerSample.setAttribute("value", "5, 5, 5, 1"); diff --git a/imageio/imageio-tga/src/test/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReaderTest.java b/imageio/imageio-tga/src/test/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReaderTest.java index 657bc992..0b3d1f71 100755 --- a/imageio/imageio-tga/src/test/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReaderTest.java +++ b/imageio/imageio-tga/src/test/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReaderTest.java @@ -32,11 +32,19 @@ package com.twelvemonkeys.imageio.plugins.tga; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; +import org.junit.Test; + +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; import javax.imageio.spi.ImageReaderSpi; +import javax.imageio.stream.ImageInputStream; import java.awt.*; +import java.io.IOException; import java.util.Arrays; import java.util.List; +import static org.junit.Assert.assertNotNull; + /** * TGAImageReaderTest * @@ -104,4 +112,23 @@ public class TGAImageReaderTest extends ImageReaderAbstractTest "image/targa", "image/x-targa" ); } + + @Test + public void testSubsampling() throws IOException { + ImageReader reader = createReader(); + ImageReadParam param = reader.getDefaultReadParam(); + param.setSourceSubsampling(3, 5, 0, 0); + + for (TestData testData : getTestData()) { + try (ImageInputStream input = testData.getInputStream()) { + reader.setInput(input); + assertNotNull(reader.read(0, param)); + } + finally { + reader.reset(); + } + } + + reader.dispose(); + } }