Compare commits

...

10 Commits

Author SHA1 Message Date
Harald Kuhr 26d3de45a7 [maven-release-plugin] prepare for next development iteration 2020-01-09 19:40:24 +01:00
Harald Kuhr 13507ce303 [maven-release-plugin] prepare release twelvemonkeys-3.4.3 2020-01-09 19:40:16 +01:00
Harald Kuhr a8508dc234 Stick to the git user, when using ssh
(cherry picked from commit b6aec25f00)
2020-01-09 19:28:35 +01:00
Harald Kuhr b3cf467f0b log4j removal
(cherry picked from commit ae213dcf5e)
2020-01-09 19:25:48 +01:00
Harald Kuhr b0e6fbed9f #510: Fixes possible hang situation
(cherry picked from commit 5501c0e709)
2020-01-09 19:25:48 +01:00
Harald Kuhr c087addb76 #501: Fix for TYPE_USHORT_555/565_RGB, ColorModel now 16 bits
(cherry picked from commit 42e17f2063)
2020-01-09 19:25:48 +01:00
Harald Kuhr 250c58cc2e #289, #493: Finally implemented subsampling for < 8 bit samples
(cherry picked from commit 0c2433dc9f)
2020-01-09 19:25:48 +01:00
Oliver Schmidtmer c33b3a76f4 Test correction for ViewBox based svg sizes
(cherry picked from commit 810b7197ab)
2020-01-09 19:24:58 +01:00
Oliver Schmidtmer f14e6823bd When rescaling SVGs use the ViewBox, if defined, for default sizes
(cherry picked from commit 24a0786d64)
2020-01-09 19:24:58 +01:00
Harald Kuhr cae72336a2 [maven-release-plugin] prepare for next development iteration 2019-08-12 21:05:55 +02:00
40 changed files with 431 additions and 270 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -46,6 +46,7 @@ import org.apache.batik.gvt.renderer.ImageRendererFactory;
import org.apache.batik.transcoder.*;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGSVGElement;
@@ -326,7 +327,7 @@ public class SVGImageReader extends ImageReaderBase {
// get the 'width' and 'height' attributes of the SVG document
Dimension2D docSize = ctx.getDocumentSize();
if (docSize != null) {
if (docSize != null) {
defaultWidth = (float) docSize.getWidth();
defaultHeight = (float) docSize.getHeight();
}
@@ -334,6 +335,14 @@ public class SVGImageReader extends ImageReaderBase {
defaultWidth = 200;
defaultHeight = 200;
}
SVGSVGElement rootElement = svgDoc.getRootElement();
String viewBoxStr = rootElement.getAttributeNS
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
if (viewBoxStr.length() != 0) {
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
defaultWidth = rect[2];
defaultHeight = rect[3];
}
// Hack to work around exception above
if (root != null) {
@@ -35,6 +35,7 @@ import org.junit.Ignore;
import org.junit.Test;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.event.IIOReadWarningListener;
@@ -43,9 +44,12 @@ import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImagingOpException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.Buffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -70,7 +74,7 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
new TestData(getClassLoaderResource("/svg/batikLogo.svg"), new Dimension(450, 500)),
new TestData(getClassLoaderResource("/svg/red-square.svg"), new Dimension(100, 100)),
new TestData(getClassLoaderResource("/svg/blue-square.svg"), new Dimension(100, 100)),
new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(400, 400))
new TestData(getClassLoaderResource("/svg/Android_robot.svg"), new Dimension(294, 345))
);
}
@@ -99,6 +103,57 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
return Collections.singletonList("image/svg+xml");
}
@Test
public void testScaleViewBox() throws IOException {
URL svgUrl = getClassLoaderResource("/svg/quadrants.svg");
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
SVGImageReader reader = createReader();
SVGReadParam param = new SVGReadParam();
int[] sizes = new int[]{16, 32, 64, 128};
for (int size : sizes) {
try (InputStream svgStream = svgUrl.openStream(); ImageInputStream iis = ImageIO.createImageInputStream(svgStream)) {
reader.reset();
reader.setInput(iis);
param.setSourceRenderSize(new Dimension(size, size));
BufferedImage image = reader.read(0, param);
checkQuadrantColors(image);
}
finally {
reader.dispose();
}
}
}
private void checkQuadrantColors(BufferedImage image) {
int quadPoint = image.getWidth() / 2;
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
int current = image.getRGB(x, y);
if (x < quadPoint) {
if (y < quadPoint) {
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF0000FF, current);
}
else {
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFFFF0000, current);
}
}
else {
if (y < quadPoint) {
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF00FF00, current);
}
else {
assertEquals("x=" + x + " y=" + y + " q=" + quadPoint, 0xFF000000, current);
}
}
}
}
}
@Test
@Override
public void testReadWithSizeParam() {
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" id="blue-square" version="1.1">
<g id="layer1">
<rect id="rect2985" width="50" height="50" x="0" y="0"
style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect id="rect2986" width="50" height="50" x="50" y="0"
style="color:#000000;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect id="rect2987" width="50" height="50" x="0" y="50"
style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect id="rect2988" width="50" height="50" x="50" y="50"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-bmp</artifactId>
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>
+80 -7
View File
@@ -31,6 +31,7 @@
package com.twelvemonkeys.imageio.util;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.lang.Validate;
import javax.imageio.IIOParam;
import javax.imageio.ImageIO;
@@ -148,10 +149,9 @@ public final class IIOUtil {
return null;
}
if (pSourceRegion != null) {
if (pSourceRegion.x != 0 || pSourceRegion.y != 0 || pSourceRegion.width != pImage.getWidth() || pSourceRegion.height != pImage.getHeight()) {
return pImage.getSubimage(pSourceRegion.x, pSourceRegion.y, pSourceRegion.width, pSourceRegion.height);
}
if (pSourceRegion != null
&& (pSourceRegion.x != 0 || pSourceRegion.y != 0 || pSourceRegion.width != pImage.getWidth() || pSourceRegion.height != pImage.getHeight())) {
return pImage.getSubimage(pSourceRegion.x, pSourceRegion.y, pSourceRegion.width, pSourceRegion.height);
}
return pImage;
@@ -192,7 +192,7 @@ public final class IIOUtil {
* The names are all upper-case, and contains no duplicates.
*
* @return a normalized array of {@code String}s.
* @see javax.imageio.ImageIO#getReaderFormatNames()
* @see ImageIO#getReaderFormatNames()
*/
public static String[] getNormalizedReaderFormatNames() {
return normalizeNames(ImageIO.getReaderFormatNames());
@@ -203,7 +203,7 @@ public final class IIOUtil {
* The names are all upper-case, and contains no duplicates.
*
* @return a normalized array of {@code String}s.
* @see javax.imageio.ImageIO#getWriterFormatNames()
* @see ImageIO#getWriterFormatNames()
*/
public static String[] getNormalizedWriterFormatNames() {
return normalizeNames(ImageIO.getWriterFormatNames());
@@ -216,6 +216,79 @@ public final class IIOUtil {
normalizedNames.add(name.toUpperCase());
}
return normalizedNames.toArray(new String[normalizedNames.size()]);
return normalizedNames.toArray(new String[0]);
}
// TODO: RasterUtils? Subsampler?
public static void subsampleRow(byte[] srcRow, int srcPos, int srcWidth,
byte[] destRow, int destPos,
int samplesPerPixel, int bitsPerSample, int samplePeriod) {
Validate.isTrue(samplePeriod > 1, "samplePeriod must be > 1"); // Period == 1 could be a no-op...
Validate.isTrue(bitsPerSample > 0 && bitsPerSample <= 8 && (bitsPerSample == 1 || bitsPerSample % 2 == 0),
"bitsPerSample must be > 0 and <= 8 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 8 || samplesPerPixel * bitsPerSample % 8 == 0,
"samplesPerPixel * bitsPerSample must be < 8 or a multiple of 8 ");
if (bitsPerSample * samplesPerPixel % 8 == 0) {
int pixelStride = bitsPerSample * samplesPerPixel / 8;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
// System.arraycopy should be intrinsic, but consider using direct array access for pixelStride == 1
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
}
}
else {
// Start bit fiddling...
int pixelStride = bitsPerSample * samplesPerPixel;
int mask = (1 << pixelStride) - 1;
for (int x = 0; x < srcWidth; x += samplePeriod) {
int dstOff = (destPos + x / samplePeriod) * pixelStride / 8;
int srcOff = (srcPos + x) * pixelStride / 8;
int srcBitPos = 8 - pixelStride - (x * pixelStride) % 8;
int srcMask = mask << srcBitPos;
int dstBitPos = 8 - pixelStride - (x * pixelStride / samplePeriod) % 8;
int dstMask = ~(mask << dstBitPos);
int val = ((srcRow[srcOff] & srcMask) >> srcBitPos);
destRow[dstOff] = (byte) ((destRow[dstOff] & dstMask) | val << dstBitPos);
}
}
}
public static void subsampleRow(short[] srcRow, int srcPos, int srcWidth,
short[] destRow, int destPos,
int samplesPerPixel, int bitsPerSample, int samplePeriod) {
Validate.isTrue(samplePeriod > 1, "samplePeriod must be > 1"); // Period == 1 could be a no-op...
Validate.isTrue(bitsPerSample > 0 && bitsPerSample <= 16 && (bitsPerSample == 1 || bitsPerSample % 2 == 0),
"bitsPerSample must be > 0 and <= 16 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 16 || samplesPerPixel * bitsPerSample % 16 == 0,
"samplesPerPixel * bitsPerSample must be < 16 or a multiple of 16 ");
int pixelStride = bitsPerSample * samplesPerPixel / 16;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
// System.arraycopy should be intrinsic, but consider using direct array access for pixelStride == 1
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
}
}
public static void subsampleRow(int[] srcRow, int srcPos, int srcWidth,
int[] destRow, int destPos,
int samplesPerPixel, int bitsPerSample, int samplePeriod) {
Validate.isTrue(samplePeriod > 1, "samplePeriod must be > 1"); // Period == 1 could be a no-op...
Validate.isTrue(bitsPerSample > 0 && bitsPerSample <= 32 && (bitsPerSample == 1 || bitsPerSample % 2 == 0),
"bitsPerSample must be > 0 and <= 32 and a power of 2");
Validate.isTrue(samplesPerPixel > 0, "samplesPerPixel must be > 0");
Validate.isTrue(samplesPerPixel * bitsPerSample <= 32 || samplesPerPixel * bitsPerSample % 32 == 0,
"samplesPerPixel * bitsPerSample must be < 32 or a multiple of 32 ");
int pixelStride = bitsPerSample * samplesPerPixel / 32;
for (int x = 0; x < srcWidth * pixelStride; x += samplePeriod * pixelStride) {
// System.arraycopy should be intrinsic, but consider using direct array access for pixelStride == 1
System.arraycopy(srcRow, srcPos + x, destRow, destPos + x / samplePeriod, pixelStride);
}
}
}
@@ -54,6 +54,28 @@ public final class ImageTypeSpecifiers {
private ImageTypeSpecifiers() {}
public static ImageTypeSpecifier createFromBufferedImageType(final int bufferedImageType) {
switch (bufferedImageType) {
// ImageTypeSpecifier unconditionally uses bits == 32, we'll use a workaround for the USHORT types
case BufferedImage.TYPE_USHORT_565_RGB:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0xF800,
0x07E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
case BufferedImage.TYPE_USHORT_555_RGB:
return createPacked(ColorSpace.getInstance(ColorSpace.CS_sRGB),
0x7C00,
0x03E0,
0x001F,
0x0,
DataBuffer.TYPE_USHORT,
false);
default:
}
return ImageTypeSpecifier.createFromBufferedImageType(bufferedImageType);
}
@@ -147,21 +169,21 @@ public final class ImageTypeSpecifiers {
int numEntries = 1 << bits;
byte[] arr = new byte[numEntries];
byte[] arg = new byte[numEntries];
byte[] arb = new byte[numEntries];
byte[] r = new byte[numEntries];
byte[] g = new byte[numEntries];
byte[] b = new byte[numEntries];
// Scale array values according to color profile..
for (int i = 0; i < numEntries; i++) {
float[] gray = new float[]{i / (float) (numEntries - 1)};
float[] rgb = colorSpace.toRGB(gray);
arr[i] = (byte) (rgb[0] * 255);
arg[i] = (byte) (rgb[1] * 255);
arb[i] = (byte) (rgb[2]* 255);
r[i] = (byte) (rgb[0] * 255);
g[i] = (byte) (rgb[1] * 255);
b[i] = (byte) (rgb[2] * 255);
}
ColorModel colorModel = new IndexColorModel(bits, numEntries, arr, arg, arb);
ColorModel colorModel = new IndexColorModel(bits, numEntries, r, g, b);
SampleModel sampleModel = new MultiPixelPackedSampleModel(dataType, 1, 1, bits);
return new ImageTypeSpecifier(colorModel, sampleModel);
@@ -0,0 +1,145 @@
package com.twelvemonkeys.imageio.util;
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
/**
* IIOUtilTest
*/
public class IIOUtilTest {
@Test
public void subsampleRowPeriod2Byte() {
int period = 2;
byte[] input = {-1, 0, (byte) 0xAA, 0, -1};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {-1, (byte) 0xAA, -1};
IIOUtil.subsampleRow(input, 0, input.length, output, 0, 1, 8, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2ByteStride3() {
int period = 2;
byte[] input = {-1, -1, -1, 0, 0, 0, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, 0, 0, 0, -1, -1, -1};
byte[] output = new byte[9];
byte[] expected = {-1, -1, -1, (byte) 0xAA, (byte) 0xAA, (byte) 0xAA, -1, -1, -1};
IIOUtil.subsampleRow(input, 0, input.length / 3, output, 0, 3, 8, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2Byte1() {
int period = 2;
byte[] input = {(byte) 0xaa, (byte) 0xaa, (byte) 0xaa};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 0, input.length * 8, output, 0, 1, 1, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod3_1Bit() {
int period = 3;
byte[] input = {(byte) 0x92, (byte) 0x49, (byte) 0x24};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff};
IIOUtil.subsampleRow(input, 0, input.length * 8, output, 0, 1, 1, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_2Bit() {
int period = 2;
byte[] input = {(byte) 0xcc, (byte) 0xcc, (byte) 0xcc};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 0, input.length * 4, output, 0, 1, 2, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_4Bit() {
int period = 2;
byte[] input = {(byte) 0xf0, (byte) 0xf0, (byte) 0xf0};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 0, input.length * 2, output, 0, 1, 4, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_1Bit2Samples() {
int period = 2;
byte[] input = {(byte) 0xcc, (byte) 0xcc, (byte) 0xcc};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 0, input.length * 4, output, 0, 2, 1, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_2Bit2Samples() {
int period = 2;
byte[] input = {(byte) 0xf0, (byte) 0xf0, (byte) 0xf0};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 0, input.length * 2, output, 0, 2, 2, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_4Bit2Samples() {
int period = 2;
byte[] input = {-1, 0, (byte) 0xAA, 0, -1};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {-1, (byte) 0xAA, -1};
IIOUtil.subsampleRow(input, 0, input.length, output, 0, 2, 4, period);
assertArrayEquals(expected, output);
}
@Test
public void subsampleRowPeriod2_1BitOffset1() {
int period = 2;
byte[] input = {(byte) 0xaa, (byte) 0xaa, (byte) 0xaa};
byte[] output = new byte[divCeil(input.length, period)];
byte[] expected = {(byte) 0xff, (byte) 0xf0};
IIOUtil.subsampleRow(input, 1, input.length * 8, output, 0, 1, 1, period);
assertArrayEquals(expected, output);
}
private int divCeil(int numerator, int denominator) {
return (numerator + denominator - 1) / denominator;
}
}
@@ -61,10 +61,21 @@ public class ImageTypeSpecifiersTest {
@Test
public void testCreateFromBufferedImageType() {
for (int type = BufferedImage.TYPE_INT_RGB; type < BufferedImage.TYPE_BYTE_INDEXED; type++) {
assertEquals(
ImageTypeSpecifier.createFromBufferedImageType(type),
ImageTypeSpecifiers.createFromBufferedImageType(type)
);
ImageTypeSpecifier expected;
switch (type) {
// Special handling for USHORT_565 and 555, due to bug in ImageTypeSpecifier for these types (DirectColorModel is 32 bits)
case BufferedImage.TYPE_USHORT_565_RGB:
expected = createPacked(sRGB, DCM_565_RED_MASK, DCM_565_GRN_MASK, DCM_565_BLU_MASK, 0, DataBuffer.TYPE_USHORT, false);
break;
case BufferedImage.TYPE_USHORT_555_RGB:
expected = createPacked(sRGB, DCM_555_RED_MASK, DCM_555_GRN_MASK, DCM_555_BLU_MASK, 0, DataBuffer.TYPE_USHORT, false);
break;
default:
expected = ImageTypeSpecifier.createFromBufferedImageType(type);
}
assertEquals(expected, ImageTypeSpecifiers.createFromBufferedImageType(type));
}
}
@@ -119,7 +130,7 @@ public class ImageTypeSpecifiersTest {
// Extra: Make sure color models bits is actually 16 (ImageTypeSpecifier equivalent returns 32)
assertEquals(16, ImageTypeSpecifiers.createPacked(sRGB, DCM_565_RED_MASK, DCM_565_GRN_MASK, DCM_565_BLU_MASK, 0, DataBuffer.TYPE_USHORT, false).getColorModel().getPixelSize());
}
}
@Test
public void testCreatePacked8() {
@@ -531,6 +542,7 @@ public class ImageTypeSpecifiersTest {
@Test
public void testCreatePackedGrayscale1() {
// TODO: Fails on Java 11, because IndexColorModel now has an overloaded equals that actually tests the color entries
assertEquals(
ImageTypeSpecifier.createGrayscale(1, DataBuffer.TYPE_BYTE, false),
ImageTypeSpecifiers.createPackedGrayscale(GRAY, 1, DataBuffer.TYPE_BYTE)
@@ -539,6 +551,7 @@ public class ImageTypeSpecifiersTest {
@Test
public void testCreatePackedGrayscale2() {
// TODO: Fails on Java 11, because IndexColorModel now has an overloaded equals that actually tests the color entries
assertEquals(
ImageTypeSpecifier.createGrayscale(2, DataBuffer.TYPE_BYTE, false),
ImageTypeSpecifiers.createPackedGrayscale(GRAY, 2, DataBuffer.TYPE_BYTE)
@@ -546,7 +559,8 @@ public class ImageTypeSpecifiersTest {
}
@Test
public void testCreatePackedGrayscale4() {
public void testCreatePackedGrayscale4() throws Exception {
// TODO: Fails on Java 11, because IndexColorModel now has an overloaded equals that actually tests the color entries
assertEquals(
ImageTypeSpecifier.createGrayscale(4, DataBuffer.TYPE_BYTE, false),
ImageTypeSpecifiers.createPackedGrayscale(GRAY, 4, DataBuffer.TYPE_BYTE)
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-hdr</artifactId>
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-icns</artifactId>
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-iff</artifactId>
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
@@ -37,7 +37,7 @@ import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageInputStreamImpl;
import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -58,12 +58,12 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
// TODO: Rewrite JPEGSegment (from metadata) to store stream pos/length, and be able to replay data, and use instead of Segment?
// TODO: Support multiple JPEG streams (SOI...EOI, SOI...EOI, ...) in a single file
final private ImageInputStream stream;
final private JPEGSegmentStreamWarningListener warningListener;
private final ImageInputStream stream;
private final JPEGSegmentStreamWarningListener warningListener;
final private ComponentIdSet componentIds = new ComponentIdSet();
private final ComponentIdSet componentIds = new ComponentIdSet();
private final List<Segment> segments = new ArrayList<Segment>(64);
private final List<Segment> segments = new ArrayList<>(64);
private int currentSegment = -1;
private Segment segment;
@@ -275,7 +275,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
processWarningOccured(String.format("Duplicate component ID %d in SOF", id));
id++;
while (!componentIds.add(id) && componentIds.size() <= 16) {
while (componentIds.size() < 4 && !componentIds.add(id) && id < 255) {
id++;
}
@@ -330,7 +330,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
}
static String asAsciiString(final byte[] data, final int offset, final int length) {
return new String(data, offset, length, Charset.forName("ascii"));
return new String(data, offset, length, StandardCharsets.US_ASCII);
}
private void streamInit() throws IOException {
@@ -443,8 +443,9 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
}
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
@Deprecated
@Override
protected void finalize() throws Throwable {
protected void finalize() {
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
}
@@ -585,7 +586,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
}
static final class ComponentIdSet {
final int[] values = new int[4]; // The native code don't support more than 4 components
final int[] values = new int[4]; // The native code doesn't support more than 4 components
int size;
boolean add(final int value) {
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pdf</artifactId>
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pict</artifactId>
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pnm</artifactId>
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-psd</artifactId>
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-reference</artifactId>
<name>TwelveMonkeys :: ImageIO :: reference test cases</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-sgi</artifactId>
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-tga</artifactId>
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-thumbsdb</artifactId>
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-tiff</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
@@ -48,6 +48,7 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.metadata.xmp.XMPReader;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.IIOUtil;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.io.FastByteArrayOutputStream;
@@ -82,8 +83,7 @@ import java.util.*;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import static com.twelvemonkeys.imageio.util.IIOUtil.createStreamAdapter;
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
import static com.twelvemonkeys.imageio.util.IIOUtil.*;
import static java.util.Arrays.asList;
/**
@@ -502,7 +502,7 @@ public final class TIFFImageReader extends ImageReaderBase {
if (cs == ColorSpace.getInstance(ColorSpace.CS_GRAY) && (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 || bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32)) {
return ImageTypeSpecifiers.createGrayscale(bitsPerSample, dataType);
}
else if (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 ) {
else if (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4) {
// Use packed format for 1/2/4 bits
return ImageTypeSpecifiers.createPackedGrayscale(cs, bitsPerSample, dataType);
}
@@ -1841,6 +1841,7 @@ public final class TIFFImageReader extends ImageReaderBase {
DataBuffer dataBuffer = tileRowRaster.getDataBuffer();
int bands = dataBuffer.getNumBanks();
boolean banded = bands > 1;
int bitsPerSample = getBitsPerSample();
switch (tileRowRaster.getTransferType()) {
case DataBuffer.TYPE_BYTE:
@@ -1870,9 +1871,8 @@ public final class TIFFImageReader extends ImageReaderBase {
// Subsample horizontal
if (xSub != 1) {
for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) {
System.arraycopy(rowDataByte, x * xSub, rowDataByte, x, numBands);
}
IIOUtil.subsampleRow(rowDataByte, srcRegion.x * numBands, colsInTile,
rowDataByte, srcRegion.x * numBands / xSub, numBands, bitsPerSample, xSub);
}
destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel);
@@ -1913,9 +1913,8 @@ public final class TIFFImageReader extends ImageReaderBase {
// Subsample horizontal
if (xSub != 1) {
for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) {
System.arraycopy(rowDataShort, x * xSub, rowDataShort, x, numBands);
}
subsampleRow(rowDataShort, srcRegion.x * numBands, colsInTile,
rowDataShort, srcRegion.x * numBands / xSub, numBands, bitsPerSample, xSub);
}
destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel);
@@ -1950,9 +1949,8 @@ public final class TIFFImageReader extends ImageReaderBase {
// Subsample horizontal
if (xSub != 1) {
for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) {
System.arraycopy(rowDataInt, x * xSub, rowDataInt, x, numBands);
}
subsampleRow(rowDataInt, srcRegion.x * numBands, colsInTile,
rowDataInt, srcRegion.x * numBands / xSub, numBands, bitsPerSample, xSub);
}
destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel);
@@ -1998,6 +1996,9 @@ public final class TIFFImageReader extends ImageReaderBase {
}
break;
default:
throw new AssertionError("Unsupported data type: " + tileRowRaster.getTransferType());
}
}
@@ -2294,7 +2295,7 @@ public final class TIFFImageReader extends ImageReaderBase {
case TIFFBaseline.COMPRESSION_NONE:
return stream;
case TIFFBaseline.COMPRESSION_PACKBITS:
return new DecoderStream(createFillOrderStream(fillOrder, stream), new PackBitsDecoder(), 1024);
return new DecoderStream(createFillOrderStream(fillOrder, stream), new PackBitsDecoder(), 256);
case TIFFExtension.COMPRESSION_LZW:
// NOTE: Needs large buffer for compatibility with certain encoders
return new DecoderStream(createFillOrderStream(fillOrder, stream), LZWDecoder.create(LZWDecoder.isOldBitReversedStream(stream)), Math.max(width * bands, 4096));
@@ -2469,6 +2470,7 @@ public final class TIFFImageReader extends ImageReaderBase {
return null;
}
@Override
public boolean canReadRaster() {
return true;
@@ -708,6 +708,29 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest<TIFFImageReader
}
}
@Test
public void testReadWithSubsampleParamPixelsBinary() throws IOException {
ImageReader reader = createReader();
TestData data = new TestData(getClassLoaderResource("/tiff/ccitt/group3_2d.tif"), new Dimension(6, 4));
reader.setInput(data.getInputStream());
ImageReadParam param = reader.getDefaultReadParam();
BufferedImage image = null;
BufferedImage subsampled = null;
try {
image = reader.read(0, param);
param.setSourceSubsampling(2, 2, 0, 0);
subsampled = reader.read(0, param);
}
catch (IOException e) {
failBecause("Image could not be read", e);
}
assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param);
}
@Test
public void testReadWithSubsampleParamPixelsJPEG() throws IOException {
// Tiled "new style" JPEG
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.twelvemonkeys.imageio</groupId>
+3 -3
View File
@@ -9,7 +9,7 @@
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Twelvemonkeys</name>
@@ -84,9 +84,9 @@
<scm>
<connection>scm:git:https://github.com/haraldk/TwelveMonkeys</connection>
<developerConnection>scm:git:ssh://github.com/haraldk/TwelveMonkeys</developerConnection>
<developerConnection>scm:git:ssh://git@github.com/haraldk/TwelveMonkeys</developerConnection>
<url>https://github.com/haraldk/TwelveMonkeys</url>
<tag>twelvemonkeys-3.4.2</tag>
<tag>twelvemonkeys-3.4</tag>
</scm>
<properties>
-6
View File
@@ -80,11 +80,5 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,183 +0,0 @@
package com.twelvemonkeys.servlet.log4j;
import org.apache.log4j.Logger;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;
/**
* Log4JContextWrapper
* <p/>
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version $Id: log4j/Log4JContextWrapper.java#1 $
*/
final class Log4JContextWrapper implements ServletContext {
// TODO: Move to sandbox
// TODO: This solution sucks...
// How about starting to create some kind of pluggable decorator system,
// something along the lines of AOP mixins/interceptor pattern..
// Probably using a dynamic Proxy, delegating to the mixins and or the
// wrapped object based on configuration.
// This way we could simply call ServletUtil.decorate(ServletContext):ServletContext
// And the context would be decorated with all configured mixins at once,
// requiring less boilerplate delegation code, and less layers of wrapping
// (alternatively we could decorate the Servlet/FilterConfig objects).
// See the ServletUtil.createWrapper methods for some hints..
// Something like this:
public static ServletContext wrap(final ServletContext pContext, final Object[] pDelegates, final ClassLoader pLoader) {
ClassLoader cl = pLoader != null ? pLoader : Thread.currentThread().getContextClassLoader();
// TODO: Create a "static" mapping between methods in the ServletContext
// and the corresponding delegate
// TODO: Resolve super-invokations, to delegate to next delegate in
// chain, and finally invoke pContext
return (ServletContext) Proxy.newProxyInstance(cl, new Class[] {ServletContext.class}, new InvocationHandler() {
public Object invoke(Object pProxy, Method pMethod, Object[] pArgs) throws Throwable {
// TODO: Test if any of the delegates should receive, if so invoke
// Else, invoke on original object
return pMethod.invoke(pContext, pArgs);
}
});
}
private final ServletContext context;
private final Logger logger;
Log4JContextWrapper(ServletContext pContext) {
context = pContext;
// TODO: We want a logger per servlet, not per servlet context, right?
logger = Logger.getLogger(pContext.getServletContextName());
// TODO: Automatic init/config of Log4J using context parameter for log4j.xml?
// See Log4JInit.java
// TODO: Automatic config of properties in the context wrapper?
}
public final void log(final Exception pException, final String pMessage) {
log(pMessage, pException);
}
// TODO: Add more logging methods to interface info/warn/error?
// TODO: Implement these mehtods in GenericFilter/GenericServlet?
public void log(String pMessage) {
// TODO: Get logger for caller..
// Should be possible using some stack peek hack, but that's slow...
// Find a good way...
// Maybe just pass it into the constuctor, and have one wrapper per servlet
logger.info(pMessage);
}
public void log(String pMessage, Throwable pCause) {
// TODO: Get logger for caller..
logger.error(pMessage, pCause);
}
public Object getAttribute(String pMessage) {
return context.getAttribute(pMessage);
}
public Enumeration getAttributeNames() {
return context.getAttributeNames();
}
public ServletContext getContext(String pMessage) {
return context.getContext(pMessage);
}
public String getInitParameter(String pMessage) {
return context.getInitParameter(pMessage);
}
public Enumeration getInitParameterNames() {
return context.getInitParameterNames();
}
public int getMajorVersion() {
return context.getMajorVersion();
}
public String getMimeType(String pMessage) {
return context.getMimeType(pMessage);
}
public int getMinorVersion() {
return context.getMinorVersion();
}
public RequestDispatcher getNamedDispatcher(String pMessage) {
return context.getNamedDispatcher(pMessage);
}
public String getRealPath(String pMessage) {
return context.getRealPath(pMessage);
}
public RequestDispatcher getRequestDispatcher(String pMessage) {
return context.getRequestDispatcher(pMessage);
}
public URL getResource(String pMessage) throws MalformedURLException {
return context.getResource(pMessage);
}
public InputStream getResourceAsStream(String pMessage) {
return context.getResourceAsStream(pMessage);
}
public Set getResourcePaths(String pMessage) {
return context.getResourcePaths(pMessage);
}
public String getServerInfo() {
return context.getServerInfo();
}
public Servlet getServlet(String pMessage) throws ServletException {
//noinspection deprecation
return context.getServlet(pMessage);
}
public String getServletContextName() {
return context.getServletContextName();
}
public Enumeration getServletNames() {
//noinspection deprecation
return context.getServletNames();
}
public Enumeration getServlets() {
//noinspection deprecation
return context.getServlets();
}
public void removeAttribute(String pMessage) {
context.removeAttribute(pMessage);
}
public void setAttribute(String pMessage, Object pExtension) {
context.setAttribute(pMessage, pExtension);
}
}
+1 -8
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.4.2</version>
<version>3.4.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -57,13 +57,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>