#577 Fix TGA subsampling + bonus metadata fix and palette conversion.

This commit is contained in:
Harald Kuhr 2020-12-15 22:19:04 +01:00
parent 0da007ec8c
commit af1a6492d4
4 changed files with 51 additions and 7 deletions

View File

@ -200,12 +200,12 @@ final class TGAHeader {
int components = colorMap.hasAlpha() ? 4 : 3; int components = colorMap.hasAlpha() ? 4 : 3;
byte[] cmap = new byte[rgb.length * components]; byte[] cmap = new byte[rgb.length * components];
for (int i = 0; i < rgb.length; i++) { for (int i = 0; i < rgb.length; i++) {
cmap[i * components ] = (byte) ((rgb[i] >> 16) & 0xff); cmap[i * components ] = (byte) ((rgb[i] ) & 0xff); // B
cmap[i * components + 1] = (byte) ((rgb[i] >> 8) & 0xff); cmap[i * components + 1] = (byte) ((rgb[i] >> 8) & 0xff); // G
cmap[i * components + 2] = (byte) ((rgb[i] ) & 0xff); cmap[i * components + 2] = (byte) ((rgb[i] >> 16) & 0xff); // R
if (components == 4) { 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; hasAlpha = false;
break; break;
case 24: 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; hasAlpha = false;
break; break;
case 32: 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; hasAlpha = true;
break; break;
default: default:

View File

@ -224,7 +224,7 @@ final class TGAImageReader extends ImageReaderBase {
byte[] rowDataByte, WritableRaster destChannel, Raster srcChannel, int y) throws IOException { byte[] rowDataByte, WritableRaster destChannel, Raster srcChannel, int y) throws IOException {
// If subsampled or outside source region, skip entire row // 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) { 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; return;
} }
@ -251,7 +251,8 @@ final class TGAImageReader extends ImageReaderBase {
destChannel.setDataElements(0, dstY, srcChannel); destChannel.setDataElements(0, dstY, srcChannel);
break; break;
case TGA.ORIGIN_UPPER_LEFT: case TGA.ORIGIN_UPPER_LEFT:
destChannel.setDataElements(0, y, srcChannel); dstY = y / ySub;
destChannel.setDataElements(0, dstY, srcChannel);
break; break;
default: default:
throw new IIOException("Unsupported origin: " + origin); throw new IIOException("Unsupported origin: " + origin);
@ -289,7 +290,8 @@ final class TGAImageReader extends ImageReaderBase {
destChannel.setDataElements(0, dstY, srcChannel); destChannel.setDataElements(0, dstY, srcChannel);
break; break;
case TGA.ORIGIN_UPPER_LEFT: case TGA.ORIGIN_UPPER_LEFT:
destChannel.setDataElements(0, y, srcChannel); dstY = y / ySub;
destChannel.setDataElements(0, dstY, srcChannel);
break; break;
default: default:
throw new IIOException("Unsupported origin: " + origin); throw new IIOException("Unsupported origin: " + origin);

View File

@ -189,6 +189,7 @@ final class TGAMetadata extends AbstractMetadata {
switch (header.getPixelDepth()) { switch (header.getPixelDepth()) {
case 8: case 8:
bitsPerSample.setAttribute("value", createListValue(1, Integer.toString(header.getPixelDepth()))); bitsPerSample.setAttribute("value", createListValue(1, Integer.toString(header.getPixelDepth())));
break;
case 16: case 16:
if (header.getAttributeBits() > 0 && extensions != null && extensions.hasAlpha()) { if (header.getAttributeBits() > 0 && extensions != null && extensions.hasAlpha()) {
bitsPerSample.setAttribute("value", "5, 5, 5, 1"); bitsPerSample.setAttribute("value", "5, 5, 5, 1");

View File

@ -32,11 +32,19 @@ package com.twelvemonkeys.imageio.plugins.tga;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; 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.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*; import java.awt.*;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.junit.Assert.assertNotNull;
/** /**
* TGAImageReaderTest * TGAImageReaderTest
* *
@ -104,4 +112,23 @@ public class TGAImageReaderTest extends ImageReaderAbstractTest<TGAImageReader>
"image/targa", "image/x-targa" "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();
}
} }