Compare commits

...

22 Commits

Author SHA1 Message Date
Harald Kuhr 54dd9b6d7b [maven-release-plugin] prepare release twelvemonkeys-3.6.3 2021-02-26 18:50:59 +01:00
Harald Kuhr 4e10fc019e #588 Clipping path from JPEG with multiple APP13 segments
(cherry picked from commit 970f4f3a7e)
2021-02-26 18:42:42 +01:00
Harald Kuhr 1295951ead Fix SGI source subsampling + test optimizations.
(cherry picked from commit 6d192968d1)
2021-02-26 18:42:38 +01:00
Harald Kuhr d5e664cdcc JPEG Exif/thumbnail fixes.
(cherry picked from commit fbc738f2d4)
2021-02-26 18:39:43 +01:00
Harald Kuhr efe5f3c34a No longer reads thumbnails, as part of the readWithOrientation method.
(cherry picked from commit 80c595cea8)
2021-02-26 18:33:47 +01:00
Harald Kuhr 2488f6f67c JPEG Exif/thumbnail fixes.
(cherry picked from commit fbc738f2d4)
2021-02-26 18:33:46 +01:00
Harald Kuhr 6a66d2e059 More standard key mapping, more correct fit size. Nicer color!
(cherry picked from commit 3e3acf3332)
2021-02-26 18:33:44 +01:00
Koen De Groote ebd5533879 Upgraded the Apache Batik library from 1.12 to 1.14 due to fixed CVEs.
(cherry picked from commit 72cd3aade3)
2021-02-26 18:32:21 +01:00
Harald Kuhr e6e4e96309 Update README.md
Removed JDK 7 from recommended build.

(cherry picked from commit 88bd9cd2ba)
2021-02-26 18:32:20 +01:00
Harald Kuhr aadc62dde9 Removed XWD plugin that will be in 3.7.
Fixed some incorrect code escaping.

(cherry picked from commit 5ee8678a29)
2021-02-26 18:32:20 +01:00
Harald Kuhr 24cbe57240 Updated README with latest version numbers.
(cherry picked from commit fb1937ae63)
2021-02-26 18:32:20 +01:00
Harald Kuhr f7d8ae0cd2 [maven-release-plugin] prepare for next development iteration 2021-01-23 17:09:08 +01:00
Harald Kuhr 5da934e11b [maven-release-plugin] prepare release twelvemonkeys-3.6.2 2021-01-23 17:08:59 +01:00
Harald Kuhr 51297ad496 #582: Fix for missing Exif thumbnail, now only issues warning.
(cherry picked from commit de02e3d7e0)
2021-01-23 17:01:14 +01:00
Harald Kuhr 80a534cd62 Fix some corner cases in BufferedImageInputStream.
(cherry picked from commit 8a1a90dafd)
2021-01-23 17:01:08 +01:00
Harald Kuhr 24130d466d #579 More reliable CCITT compression type detection
(cherry picked from commit 253f04066b)
2021-01-23 17:01:05 +01:00
Harald Kuhr 7559686782 StandardCharsets.US_ASCII instead of Charset.forName("ascii")
(cherry picked from commit 74902b3fb4)
2021-01-23 17:00:58 +01:00
Harald Kuhr b6988c37a7 #577 Fix TGA subsampling + bonus metadata fix and palette conversion.
(cherry picked from commit af1a6492d4)
2021-01-23 17:00:48 +01:00
Harald Kuhr bbffb1d416 BufferedImageInputStream performance optimizations.
(cherry picked from commit c7d2f422b8)
2021-01-23 17:00:31 +01:00
Harald Kuhr c68de3bc92 Updated links to latest version.
(cherry picked from commit 25150b421c)
2021-01-23 16:59:58 +01:00
Harald Kuhr a12b6044c6 Add XWD to BOM.
(cherry picked from commit 94031a2913)
2021-01-23 16:59:48 +01:00
Harald Kuhr 9a0e2d9659 [maven-release-plugin] prepare for next development iteration 2020-11-19 22:40:02 +01:00
48 changed files with 614 additions and 225 deletions
+35 -35
View File
@@ -237,7 +237,7 @@ Build the project (using [Maven](http://maven.apache.org/download.cgi)):
$ mvn package
Currently, the recommended JDK for making a build is Oracle JDK 7.x or 8.x.
Currently, the recommended JDK for making a build is Oracle JDK 8.x.
It's possible to build using OpenJDK, but some tests might fail due to some minor differences between the color management systems used. You will need to either disable the tests in question, or build without tests altogether.
@@ -280,22 +280,22 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.6</version>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.6</version>
<version>3.6.2</version>
</dependency>
<!--
Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
Optional dependency. Needed only if you deploy ImageIO plugins as part of a web app.
Make sure you add the IIOProviderContextListener to your web.xml, see above.
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.6</version>
<version>3.6.2</version>
</dependency>
</dependencies>
```
@@ -304,13 +304,13 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
twelvemonkeys-common-lang-3.6.jar
twelvemonkeys-common-io-3.6.jar
twelvemonkeys-common-image-3.6.jar
twelvemonkeys-imageio-core-3.6.jar
twelvemonkeys-imageio-metadata-3.6.jar
twelvemonkeys-imageio-jpeg-3.6.jar
twelvemonkeys-imageio-tiff-3.6.jar
twelvemonkeys-common-lang-3.6.2.jar
twelvemonkeys-common-io-3.6.2.jar
twelvemonkeys-common-image-3.6.2.jar
twelvemonkeys-imageio-core-3.6.2.jar
twelvemonkeys-imageio-metadata-3.6.2.jar
twelvemonkeys-imageio-jpeg-3.6.2.jar
twelvemonkeys-imageio-tiff-3.6.2.jar
#### Deploying the plugins in a web app
@@ -376,42 +376,42 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
### Links to prebuilt binaries
##### Latest version (3.6)
##### Latest version (3.6.2)
Requires Java 7 or later.
Common dependencies
* [common-lang-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.6/common-lang-3.6.jar)
* [common-io-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.6/common-io-3.6.jar)
* [common-image-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.6/common-image-3.6.jar)
* [common-lang-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.6.2/common-lang-3.6.2.jar)
* [common-io-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.6.2/common-io-3.6.2.jar)
* [common-image-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.6.2/common-image-3.6.2.jar)
ImageIO dependencies
* [imageio-core-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.6/imageio-core-3.6.jar)
* [imageio-metadata-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.6/imageio-metadata-3.6.jar)
* [imageio-core-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.6.2/imageio-core-3.6.2.jar)
* [imageio-metadata-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.6.2/imageio-metadata-3.6.2.jar)
ImageIO plugins
* [imageio-bmp-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.6/imageio-bmp-3.6.jar)
* [imageio-jpeg-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.6/imageio-jpeg-3.6.jar)
* [imageio-tiff-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.6/imageio-tiff-3.6.jar)
* [imageio-pnm-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.6/imageio-pnm-3.6.jar)
* [imageio-psd-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.6/imageio-psd-3.6.jar)
* [imageio-hdr-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.6/imageio-hdr-3.6.jar)
* [imageio-iff-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.6/imageio-iff-3.6.jar)
* [imageio-pcx-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.6/imageio-pcx-3.6.jar)
* [imageio-pict-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.6/imageio-pict-3.6.jar)
* [imageio-sgi-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.6/imageio-sgi-3.6.jar)
* [imageio-tga-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.6/imageio-tga-3.6.jar)
* [imageio-icns-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.6/imageio-icns-3.6.jar)
* [imageio-thumbsdb-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.6/imageio-thumbsdb-3.6.jar)
* [imageio-bmp-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.6.2/imageio-bmp-3.6.2.jar)
* [imageio-hdr-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.6.2/imageio-hdr-3.6.2.jar)
* [imageio-icns-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.6.2/imageio-icns-3.6.2.jar)
* [imageio-iff-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.6.2/imageio-iff-3.6.2.jar)
* [imageio-jpeg-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.6.2/imageio-jpeg-3.6.2.jar)
* [imageio-pcx-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.6.2/imageio-pcx-3.6.2.jar)
* [imageio-pict-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.6.2/imageio-pict-3.6.2.jar)
* [imageio-pnm-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.6.2/imageio-pnm-3.6.2.jar)
* [imageio-psd-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.6.2/imageio-psd-3.6.2.jar)
* [imageio-sgi-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.6.2/imageio-sgi-3.6.2.jar)
* [imageio-tga-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.6.2/imageio-tga-3.6.2.jar)
* [imageio-thumbsdb-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.6.2/imageio-thumbsdb-3.6.2.jar)
* [imageio-tiff-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.6.2/imageio-tiff-3.6.2.jar)
ImageIO plugins requiring 3rd party libs
* [imageio-batik-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.6/imageio-batik-3.6.jar)
* [imageio-batik-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.6.2/imageio-batik-3.6.2.jar)
Photoshop Path support for ImageIO
* [imageio-clippath-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.6/imageio-clippath-3.6.jar)
* [imageio-clippath-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.6.2/imageio-clippath-3.6.2.jar)
Servlet support
* [servlet-3.6.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.6/servlet-3.6.jar)
* [servlet-3.6.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.6.2/servlet-3.6.2.jar)
##### Old version (3.0.x)
+6 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>
@@ -123,6 +123,11 @@
<artifactId>imageio-tiff</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-xwd</artifactId>
<version>${project.version}</version>
</dependency>
<!-- ImageIO 3rd party dependent plugins -->
<dependency>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>
@@ -2,6 +2,7 @@ package com.twelvemonkeys.contrib.exif;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.ImageReaderBase;
import org.w3c.dom.NodeList;
import javax.imageio.IIOImage;
@@ -82,12 +83,11 @@ public class EXIFUtilities {
ImageReader reader = readers.next();
try {
reader.setInput(input, true, false);
IIOImage image = reader.readAll(0, reader.getDefaultReadParam());
BufferedImage bufferedImage = ImageUtil.toBuffered(image.getRenderedImage());
image.setRenderedImage(applyOrientation(bufferedImage, findImageOrientation(image.getMetadata()).value()));
IIOMetadata metadata = reader.getImageMetadata(0);
BufferedImage bufferedImage = applyOrientation(reader.read(0), findImageOrientation(metadata).value());
return image;
return new IIOImage(bufferedImage, null, metadata);
}
finally {
reader.dispose();
@@ -123,9 +123,15 @@ public class EXIFUtilities {
for (String arg : args) {
File input = new File(arg);
// Read everything (similar to ImageReader.readAll(0, null)), but applies the correct image orientation
// Read everything but thumbnails (similar to ImageReader.readAll(0, null)),
// and applies the correct image orientation
IIOImage image = readWithOrientation(input);
if (image == null) {
System.err.printf("No reader for %s%n", input);
continue;
}
// Finds the orientation as defined by the javax_imageio_1.0 format
Orientation orientation = findImageOrientation(image.getMetadata());
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
@@ -104,6 +104,6 @@
</dependencies>
<properties>
<batik.version>1.12</batik.version>
<batik.version>1.14</batik.version>
</properties>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
@@ -56,6 +56,8 @@ import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;
@@ -131,7 +133,13 @@ public final class Paths {
List<JPEGSegment> photoshop = JPEGSegmentUtil.readSegments(stream, segmentIdentifiers);
if (!photoshop.isEmpty()) {
return readPathFromPhotoshopResources(new MemoryCacheImageInputStream(photoshop.get(0).data()));
InputStream data = null;
for (JPEGSegment ps : photoshop) {
data = data == null ? ps.data() : new SequenceInputStream(data, ps.data());
}
return readPathFromPhotoshopResources(new MemoryCacheImageInputStream(data));
}
}
else if (magic >>> 16 == TIFF.BYTE_ORDER_MARK_BIG_ENDIAN && (magic & 0xffff) == TIFF.TIFF_MAGIC
@@ -350,10 +358,10 @@ public final class Paths {
IIOMetadataNode unknown = new IIOMetadataNode("unknown");
unknown.setAttribute("MarkerTag", Integer.toString(JPEG.APP13 & 0xFF));
byte[] identfier = "Photoshop 3.0".getBytes(StandardCharsets.US_ASCII);
byte[] data = new byte[identfier.length + 1 + pathResource.length];
System.arraycopy(identfier, 0, data, 0, identfier.length);
System.arraycopy(pathResource, 0, data, identfier.length + 1, pathResource.length);
byte[] identifier = "Photoshop 3.0".getBytes(StandardCharsets.US_ASCII);
byte[] data = new byte[identifier.length + 1 + pathResource.length];
System.arraycopy(identifier, 0, data, 0, identifier.length);
System.arraycopy(pathResource, 0, data, identifier.length + 1, pathResource.length);
unknown.setUserObject(data);
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>
@@ -30,16 +30,20 @@
package com.twelvemonkeys.imageio;
import com.twelvemonkeys.image.BufferedImageIcon;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.util.IIOUtil;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
@@ -48,20 +52,6 @@ import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Iterator;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
import com.twelvemonkeys.image.BufferedImageIcon;
import com.twelvemonkeys.image.ImageUtil;
import com.twelvemonkeys.imageio.util.IIOUtil;
/**
* Abstract base class for image readers.
*
@@ -450,6 +440,7 @@ public abstract class ImageReaderBase extends ImageReader {
static final String ZOOM_IN = "zoom-in";
static final String ZOOM_OUT = "zoom-out";
static final String ZOOM_ACTUAL = "zoom-actual";
static final String ZOOM_FIT = "zoom-fit";
private BufferedImage image;
@@ -525,9 +516,20 @@ public abstract class ImageReaderBase extends ImageReader {
private void setupActions() {
// Mac weirdness... VK_MINUS/VK_PLUS seems to map to english key map always...
bindAction(new ZoomAction("Zoom in", 2), ZOOM_IN, KeyStroke.getKeyStroke('+'), KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0));
bindAction(new ZoomAction("Zoom out", .5), ZOOM_OUT, KeyStroke.getKeyStroke('-'), KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0));
bindAction(new ZoomAction("Zoom actual"), ZOOM_ACTUAL, KeyStroke.getKeyStroke('0'), KeyStroke.getKeyStroke(KeyEvent.VK_0, 0));
bindAction(new ZoomAction("Zoom in", 2), ZOOM_IN,
KeyStroke.getKeyStroke('+'),
KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
KeyStroke.getKeyStroke(KeyEvent.VK_ADD, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
bindAction(new ZoomAction("Zoom out", .5), ZOOM_OUT,
KeyStroke.getKeyStroke('-'),
KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()),
KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
bindAction(new ZoomAction("Zoom actual"), ZOOM_ACTUAL,
KeyStroke.getKeyStroke('0'),
KeyStroke.getKeyStroke(KeyEvent.VK_0, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
bindAction(new ZoomToFitAction("Zoom fit"), ZOOM_FIT,
KeyStroke.getKeyStroke('9'),
KeyStroke.getKeyStroke(KeyEvent.VK_9, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
bindAction(TransferHandler.getCopyAction(), (String) TransferHandler.getCopyAction().getValue(Action.NAME), KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
bindAction(TransferHandler.getPasteAction(), (String) TransferHandler.getPasteAction().getValue(Action.NAME), KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
@@ -544,6 +546,7 @@ public abstract class ImageReaderBase extends ImageReader {
private JPopupMenu createPopupMenu() {
JPopupMenu popup = new JPopupMenu();
popup.add(getActionMap().get(ZOOM_FIT));
popup.add(getActionMap().get(ZOOM_ACTUAL));
popup.add(getActionMap().get(ZOOM_IN));
popup.add(getActionMap().get(ZOOM_OUT));
@@ -564,7 +567,7 @@ public abstract class ImageReaderBase extends ImageReader {
addCheckBoxItem(new ChangeBackgroundAction("Dark", Color.DARK_GRAY), background, group);
addCheckBoxItem(new ChangeBackgroundAction("Black", Color.BLACK), background, group);
background.addSeparator();
ChooseBackgroundAction chooseBackgroundAction = new ChooseBackgroundAction("Choose...", defaultBG != null ? defaultBG : Color.BLUE);
ChooseBackgroundAction chooseBackgroundAction = new ChooseBackgroundAction("Choose...", defaultBG != null ? defaultBG : new Color(0xFF6600));
chooseBackgroundAction.putValue(Action.SELECTED_KEY, backgroundPaint == defaultBG);
addCheckBoxItem(chooseBackgroundAction, background, group);
@@ -678,14 +681,41 @@ public abstract class ImageReaderBase extends ImageReader {
}
else {
Icon current = getIcon();
int w = (int) Math.max(Math.min(current.getIconWidth() * zoomFactor, image.getWidth() * 16), image.getWidth() / 16);
int h = (int) Math.max(Math.min(current.getIconHeight() * zoomFactor, image.getHeight() * 16), image.getHeight() / 16);
int w = Math.max(Math.min((int) (current.getIconWidth() * zoomFactor), image.getWidth() * 16), image.getWidth() / 16);
int h = Math.max(Math.min((int) (current.getIconHeight() * zoomFactor), image.getHeight() * 16), image.getHeight() / 16);
setIcon(new BufferedImageIcon(image, Math.max(w, 2), Math.max(h, 2), w > image.getWidth() || h > image.getHeight()));
}
}
}
private class ZoomToFitAction extends ZoomAction {
public ZoomToFitAction(final String name) {
super(name, -1);
}
public void actionPerformed(final ActionEvent e) {
JComponent source = (JComponent) e.getSource();
if (source instanceof JMenuItem) {
JPopupMenu menu = (JPopupMenu) SwingUtilities.getAncestorOfClass(JPopupMenu.class, source);
source = (JComponent) menu.getInvoker();
}
Container container = SwingUtilities.getAncestorOfClass(JViewport.class, source);
double ratioX = container.getWidth() / (double) image.getWidth();
double ratioY = container.getHeight() / (double) image.getHeight();
double zoomFactor = Math.min(ratioX, ratioY);
int w = Math.max(Math.min((int) (image.getWidth() * zoomFactor), image.getWidth() * 16), image.getWidth() / 16);
int h = Math.max(Math.min((int) (image.getHeight() * zoomFactor), image.getHeight() * 16), image.getHeight() / 16);
setIcon(new BufferedImageIcon(image, w, h, zoomFactor > 1));
}
}
private static class ImageTransferable implements Transferable {
private final BufferedImage image;
@@ -704,7 +734,7 @@ public abstract class ImageReaderBase extends ImageReader {
}
@Override
public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException {
public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException {
if (isDataFlavorSupported(flavor)) {
return image;
}
@@ -57,8 +57,10 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
private ImageInputStream stream;
private ByteBuffer buffer;
private ByteBuffer integralCache = ByteBuffer.allocate(8);
private ByteBuffer buffer;
private final ByteBuffer integralCache = ByteBuffer.allocate(8);
private final byte[] integralCacheArray = integralCache.array();
public BufferedImageInputStream(final ImageInputStream pStream) throws IOException {
this(pStream, DEFAULT_BUFFER_SIZE);
@@ -97,10 +99,10 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
if (!buffer.hasRemaining()) {
fillBuffer();
}
if (!buffer.hasRemaining()) {
return -1;
if (!buffer.hasRemaining()) {
return -1;
}
}
bitOffset = 0;
@@ -172,21 +174,21 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
@Override
public short readShort() throws IOException {
readFully(integralCache.array(), 0, 2);
readFully(integralCacheArray, 0, 2);
return integralCache.getShort(0);
}
@Override
public int readInt() throws IOException {
readFully(integralCache.array(), 0, 4);
readFully(integralCacheArray, 0, 4);
return integralCache.getInt(0);
}
@Override
public long readLong() throws IOException {
readFully(integralCache.array(), 0, 8);
readFully(integralCacheArray, 0, 8);
return integralCache.getLong(0);
}
@@ -253,6 +255,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
}
int val = buffer.get() & 0xff;
streamPos++;
accum <<= 8;
accum |= val;
@@ -262,9 +265,7 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
// Move byte position back if in the middle of a byte
if (newBitOffset != 0) {
buffer.position(buffer.position() - 1);
}
else {
streamPos++;
streamPos--;
}
this.bitOffset = newBitOffset;
@@ -279,26 +280,26 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
}
@Override
public void seek(long pPosition) throws IOException {
public void seek(long position) throws IOException {
checkClosed();
bitOffset = 0;
if (streamPos == pPosition) {
if (streamPos == position) {
return;
}
// Optimized to not invalidate buffer if new position is within current buffer
long newBufferPos = buffer.position() + pPosition - streamPos;
long newBufferPos = buffer.position() + position - streamPos;
if (newBufferPos >= 0 && newBufferPos <= buffer.limit()) {
buffer.position((int) newBufferPos);
}
else {
// Will invalidate buffer
buffer.limit(0);
stream.seek(pPosition);
stream.seek(position);
}
streamPos = pPosition;
streamPos = position;
}
@Override
@@ -330,7 +331,9 @@ public final class BufferedImageInputStream extends ImageInputStreamImpl impleme
@Override
public void close() throws IOException {
if (stream != null) {
//stream.close();
// TODO: FixMe: Need to close underlying stream here!
// For call sites that relies on not closing, we should instead not close the buffered stream.
// stream.close();
stream = null;
buffer = null;
}
@@ -32,16 +32,19 @@ package com.twelvemonkeys.imageio.stream;
import com.twelvemonkeys.io.ole2.CompoundDocument;
import com.twelvemonkeys.io.ole2.Entry;
import org.junit.Test;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Random;
import static java.util.Arrays.fill;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
/**
* BufferedImageInputStreamTest
@@ -72,6 +75,257 @@ public class BufferedImageInputStreamTest {
}
}
@Test
public void testReadBit() throws IOException {
byte[] bytes = new byte[] {(byte) 0xF0, (byte) 0x0F};
// Create wrapper stream
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
// Read all bits
assertEquals(1, stream.readBit());
assertEquals(1, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(2, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(3, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(4, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(5, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(6, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(7, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBit()); // last bit
assertEquals(0, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
// Full reset, read same sequence again
stream.seek(0);
assertEquals(0, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(0, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
// Full reset, read partial
stream.seek(0);
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
// Byte reset, read same sequence again
stream.setBitOffset(0);
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(1, stream.readBit());
assertEquals(0, stream.readBit());
// Byte reset, read partial sequence again
stream.setBitOffset(3);
assertEquals(1, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(0, stream.getStreamPosition());
// Byte reset, read partial sequence again
stream.setBitOffset(6);
assertEquals(0, stream.readBit());
assertEquals(0, stream.readBit());
assertEquals(1, stream.getStreamPosition());
// Read all bits, second byte
assertEquals(0, stream.readBit());
assertEquals(1, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(2, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(3, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0, stream.readBit());
assertEquals(4, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(5, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(6, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(1, stream.readBit());
assertEquals(7, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(1, stream.readBit()); // last bit
assertEquals(0, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
}
@Test
public void testReadBits() throws IOException {
byte[] bytes = new byte[] {(byte) 0xF0, (byte) 0xCC, (byte) 0xAA};
// Create wrapper stream
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
// Read all bits, first byte
assertEquals(3, stream.readBits(2));
assertEquals(2, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(3, stream.readBits(2));
assertEquals(4, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBits(2));
assertEquals(6, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0, stream.readBits(2));
assertEquals(0, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
// Read all bits, second byte
assertEquals(3, stream.readBits(2));
assertEquals(2, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0, stream.readBits(2));
assertEquals(4, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(3, stream.readBits(2));
assertEquals(6, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0, stream.readBits(2));
assertEquals(0, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
// Read all bits, third byte
assertEquals(2, stream.readBits(2));
assertEquals(2, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
assertEquals(2, stream.readBits(2));
assertEquals(4, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
assertEquals(2, stream.readBits(2));
assertEquals(6, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
assertEquals(2, stream.readBits(2));
assertEquals(0, stream.getBitOffset());
assertEquals(3, stream.getStreamPosition());
// Full reset, read same sequence again
stream.seek(0);
assertEquals(0, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
// Read all bits, increasing size
assertEquals(7, stream.readBits(3)); // 111
assertEquals(3, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(8, stream.readBits(4)); // 1000
assertEquals(7, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(12, stream.readBits(5)); // 01100
assertEquals(4, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(50, stream.readBits(6)); // 110010
assertEquals(2, stream.getBitOffset());
assertEquals(2, stream.getStreamPosition());
assertEquals(42, stream.readBits(6)); // 101010
assertEquals(0, stream.getBitOffset());
assertEquals(3, stream.getStreamPosition());
// Full reset, read same sequence again
stream.seek(0);
assertEquals(0, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
// Read all bits multi-byte
assertEquals(0xF0C, stream.readBits(12)); // 111100001100
assertEquals(4, stream.getBitOffset());
assertEquals(1, stream.getStreamPosition());
assertEquals(0xCAA, stream.readBits(12)); // 110010101010
assertEquals(0, stream.getBitOffset());
assertEquals(3, stream.getStreamPosition());
// Full reset, read same sequence again, all bits in one go
stream.seek(0);
assertEquals(0, stream.getBitOffset());
assertEquals(0, stream.getStreamPosition());
assertEquals(0xF0CCAA, stream.readBits(24));
}
@Test
public void testReadBitsRandom() throws IOException {
long value = random.nextLong();
byte[] bytes = new byte[8];
ByteBuffer.wrap(bytes).putLong(value);
// Create wrapper stream
BufferedImageInputStream stream = new BufferedImageInputStream(new ByteArrayImageInputStream(bytes));
for (int i = 1; i < 64; i++) {
stream.seek(0);
assertEquals(i + " bits differ", value >>> (64L - i), stream.readBits(i));
}
}
@Test
public void testClose() throws IOException {
// Create wrapper stream
ImageInputStream mock = mock(ImageInputStream.class);
BufferedImageInputStream stream = new BufferedImageInputStream(mock);
stream.close();
verify(mock, never()).close();
}
// TODO: Write other tests
// TODO: Create test that exposes read += -1 (eof) bug
@@ -553,10 +553,10 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
int actualRGB = actual.getRGB(x, y);
try {
assertEquals(String.format("%s alpha at (%d, %d)", message, x, y), (expectedRGB >>> 24) & 0xff, (actualRGB >>> 24) & 0xff, 5);
assertEquals(String.format("%s red at (%d, %d)", message, x, y), (expectedRGB >> 16) & 0xff, (actualRGB >> 16) & 0xff, 5);
assertEquals(String.format("%s green at (%d, %d)", message, x, y), (expectedRGB >> 8) & 0xff, (actualRGB >> 8) & 0xff, 5);
assertEquals(String.format("%s blue at (%d, %d)", message, x, y), expectedRGB & 0xff, actualRGB & 0xff, 5);
assertEquals((expectedRGB >>> 24) & 0xff, (actualRGB >>> 24) & 0xff, 5);
assertEquals((expectedRGB >> 16) & 0xff, (actualRGB >> 16) & 0xff, 5);
assertEquals((expectedRGB >> 8) & 0xff, (actualRGB >> 8) & 0xff, 5);
assertEquals(expectedRGB & 0xff, actualRGB & 0xff, 5);
}
catch (AssertionError e) {
File tempExpected = File.createTempFile("junit-expected-", ".png");
@@ -566,7 +566,6 @@ public abstract class ImageReaderAbstractTest<T extends ImageReader> {
System.err.println("tempActual.getAbsolutePath(): " + tempActual.getAbsolutePath());
ImageIO.write(actual, "PNG", tempActual);
assertEquals(String.format("%s ARGB at (%d, %d)", message, x, y), String.format("#%08x", expectedRGB), String.format("#%08x", actualRGB));
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
@@ -30,37 +30,6 @@
package com.twelvemonkeys.imageio.plugins.jpeg;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.*;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.event.IIOReadUpdateListener;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import com.twelvemonkeys.imageio.ImageReaderBase;
import com.twelvemonkeys.imageio.color.ColorSpaces;
import com.twelvemonkeys.imageio.color.YCbCrConverter;
@@ -72,7 +41,6 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
@@ -80,6 +48,24 @@ import com.twelvemonkeys.imageio.util.ProgressListenerBase;
import com.twelvemonkeys.lang.Validate;
import com.twelvemonkeys.xml.XMLSerializer;
import javax.imageio.*;
import javax.imageio.event.IIOReadUpdateListener;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.*;
import java.io.*;
import java.nio.ByteOrder;
import java.util.List;
import java.util.*;
/**
* A JPEG {@code ImageReader} implementation based on the JRE {@code JPEGImageReader},
* that adds support and properly handles cases where the JRE version throws exceptions.
@@ -140,7 +126,7 @@ public final class JPEGImageReader extends ImageReaderBase {
private List<Segment> segments;
private int currentStreamIndex = 0;
private List<Long> streamOffsets = new ArrayList<>();
private final List<Long> streamOffsets = new ArrayList<>();
protected JPEGImageReader(final ImageReaderSpi provider, final ImageReader delegate) {
super(provider);
@@ -197,10 +183,10 @@ public final class JPEGImageReader extends ImageReaderBase {
return true;
}
}
catch (IIOException ignore) {
catch (IIOException e) {
// May happen if no SOF is found, in case we'll just fall through
if (DEBUG) {
ignore.printStackTrace();
e.printStackTrace();
}
}
@@ -747,26 +733,26 @@ public final class JPEGImageReader extends ImageReaderBase {
long lastKnownSOIOffset = streamOffsets.get(streamOffsets.size() - 1);
imageInput.seek(lastKnownSOIOffset);
try (ImageInputStream stream = new BufferedImageInputStream(imageInput)) { // Extreme (10s -> 50ms) speedup if imageInput is FileIIS
try {
for (int i = streamOffsets.size() - 1; i < imageIndex; i++) {
long start = 0;
if (DEBUG) {
start = System.currentTimeMillis();
System.out.println(String.format("Start seeking for image index %d", i + 1));
System.out.printf("Start seeking for image index %d%n", i + 1);
}
// Need to skip over segments, as they may contain JPEG markers (eg. JFXX or EXIF thumbnail)
JPEGSegmentUtil.readSegments(stream, Collections.<Integer, List<String>>emptyMap());
JPEGSegmentUtil.readSegments(imageInput, Collections.<Integer, List<String>>emptyMap());
// Now, search for EOI and following SOI...
int marker;
while ((marker = stream.read()) != -1) {
if (marker == 0xFF && (0xFF00 | stream.readUnsignedByte()) == JPEG.EOI) {
while ((marker = imageInput.read()) != -1) {
if (marker == 0xFF && (0xFF00 | imageInput.readUnsignedByte()) == JPEG.EOI) {
// Found EOI, now the SOI should be nearby...
while ((marker = stream.read()) != -1) {
if (marker == 0xFF && (0xFF00 | stream.readUnsignedByte()) == JPEG.SOI) {
long nextSOIOffset = stream.getStreamPosition() - 2;
while ((marker = imageInput.read()) != -1) {
if (marker == 0xFF && (0xFF00 | imageInput.readUnsignedByte()) == JPEG.SOI) {
long nextSOIOffset = imageInput.getStreamPosition() - 2;
imageInput.seek(nextSOIOffset);
streamOffsets.add(nextSOIOffset);
@@ -780,10 +766,9 @@ public final class JPEGImageReader extends ImageReaderBase {
}
if (DEBUG) {
System.out.println(String.format("Seek in %d ms", System.currentTimeMillis() - start));
System.out.printf("Seek in %d ms%n", System.currentTimeMillis() - start);
}
}
}
catch (EOFException eof) {
IndexOutOfBoundsException ioobe = new IndexOutOfBoundsException("Image index " + imageIndex + " not found in stream");
@@ -843,9 +828,9 @@ public final class JPEGImageReader extends ImageReaderBase {
return JPEGSegmentUtil.readSegments(imageInput, JPEGSegmentUtil.ALL_SEGMENTS);
}
catch (IIOException | IllegalArgumentException ignore) {
catch (IIOException | IllegalArgumentException e) {
if (DEBUG) {
ignore.printStackTrace();
e.printStackTrace();
}
}
finally {
@@ -919,6 +904,9 @@ public final class JPEGImageReader extends ImageReaderBase {
try (ImageInputStream stream = new ByteArrayImageInputStream(exif.data, offset, exif.data.length - offset)) {
return (CompoundDirectory) new TIFFReader().read(stream);
}
catch (IIOException e) {
processWarningOccurred("Exif chunk is present, but can't be read: " + e.getMessage());
}
}
}
@@ -1106,6 +1094,7 @@ public final class JPEGImageReader extends ImageReaderBase {
// Read JFIF thumbnails if present
JFIF jfif = getJFIF();
if (jfif != null && jfif.thumbnail != null) {
// TODO: Check if the JFIF segment really has room for this thumbnail?
thumbnails.add(new JFIFThumbnailReader(thumbnailProgressDelegator, imageIndex, thumbnails.size(), jfif));
}
@@ -1116,6 +1105,7 @@ public final class JPEGImageReader extends ImageReaderBase {
case JFXX.JPEG:
case JFXX.INDEXED:
case JFXX.RGB:
// TODO: Check if the JFXX segment really has room for this thumbnail?
thumbnails.add(new JFXXThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), imageIndex, thumbnails.size(), jfxx));
break;
default:
@@ -1129,48 +1119,77 @@ public final class JPEGImageReader extends ImageReaderBase {
Application exif = exifSegments.get(0);
// Identifier is "Exif\0" + 1 byte pad
int offset = exif.identifier.length() + 2;
int dataOffset = exif.identifier.length() + 2;
if (exif.data.length <= offset) {
if (exif.data.length <= dataOffset) {
processWarningOccurred("Exif chunk has no data.");
}
else {
ImageInputStream stream = new ByteArrayImageInputStream(exif.data, offset, exif.data.length - offset);
CompoundDirectory exifMetadata = (CompoundDirectory) new TIFFReader().read(stream);
ImageInputStream stream = new ByteArrayImageInputStream(exif.data, dataOffset, exif.data.length - dataOffset);
try {
CompoundDirectory exifMetadata = (CompoundDirectory) new TIFFReader().read(stream);
if (exifMetadata.directoryCount() == 2) {
Directory ifd1 = exifMetadata.getDirectory(1);
if (exifMetadata.directoryCount() == 2) {
Directory ifd1 = exifMetadata.getDirectory(1);
// Compression: 1 = no compression, 6 = JPEG compression (default)
Entry compressionEntry = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
// Compression: 1 = no compression, 6 = JPEG compression (default)
Entry compressionEntry = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
if (compression == 6) {
if (ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT) != null) {
Entry jpegLength = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
if (compression == 6) {
Entry jpegOffEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
if (jpegOffEntry != null) {
Entry jpegLenEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
if ((jpegLength == null || ((Number) jpegLength.getValue()).longValue() > 0)) {
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
// Test if Exif thumbnail is contained within the Exif segment (offset + length <= segment.length)
long jpegOffset = ((Number) jpegOffEntry.getValue()).longValue();
long jpegLength = jpegLenEntry != null ? ((Number) jpegLenEntry.getValue()).longValue() : -1;
if (jpegLength > 0 && jpegOffset + jpegLength <= stream.length()) {
// Verify first bytes are FFD8
stream.seek(jpegOffset);
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
if (stream.readUnsignedShort() == JPEG.SOI) {
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
}
// TODO: Simplify this warning fallback stuff...
else {
processWarningOccurred("EXIF IFD with empty or incomplete JPEG thumbnail");
}
}
else {
processWarningOccurred("EXIF IFD with empty or incomplete JPEG thumbnail");
}
}
else {
processWarningOccurred("EXIF IFD with empty (zero-length) thumbnail");
processWarningOccurred("EXIF IFD with JPEG thumbnail missing JPEGInterchangeFormat tag");
}
}
else if (compression == 1) {
Entry stripOffEntry = ifd1.getEntryById(TIFF.TAG_STRIP_OFFSETS);
if (stripOffEntry != null) {
long stripOffset = ((Number) stripOffEntry.getValue()).longValue();
if (stripOffset < stream.length()) {
// TODO: Verify length of Exif thumbnail vs length of segment like in JPEG
// ...but this requires so many extra values... Instead move this logic to the
// EXIFThumbnailReader?
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
}
else {
processWarningOccurred("EXIF IFD with empty or incomplete uncompressed thumbnail");
}
}
else {
processWarningOccurred("EXIF IFD with uncompressed thumbnail missing StripOffsets tag");
}
}
else {
processWarningOccurred("EXIF IFD with JPEG thumbnail missing JPEGInterchangeFormat tag");
processWarningOccurred("EXIF IFD with unknown compression (expected 1 or 6): " + compression);
}
}
else if (compression == 1) {
if (ifd1.getEntryById(TIFF.TAG_STRIP_OFFSETS) != null) {
thumbnails.add(new EXIFThumbnailReader(thumbnailProgressDelegator, getThumbnailReader(), 0, thumbnails.size(), ifd1, stream));
}
else {
processWarningOccurred("EXIF IFD with uncompressed thumbnail missing StripOffsets tag");
}
}
else {
processWarningOccurred("EXIF IFD with unknown compression (expected 1 or 6): " + compression);
}
}
catch (IIOException e) {
processWarningOccurred("Exif chunk present, but can't be read: " + e.getMessage());
}
}
}
@@ -1215,7 +1234,15 @@ public final class JPEGImageReader extends ImageReaderBase {
public BufferedImage readThumbnail(int imageIndex, int thumbnailIndex) throws IOException {
checkThumbnailBounds(imageIndex, thumbnailIndex);
return thumbnails.get(thumbnailIndex).read();
// processThumbnailStarted(imageIndex, thumbnailIndex);
// processThumbnailProgress(0f);
BufferedImage thumbnail = thumbnails.get(thumbnailIndex).read();;
// processThumbnailProgress(100f);
// processThumbnailComplete();
return thumbnail;
}
// Metadata
@@ -1392,7 +1419,7 @@ public final class JPEGImageReader extends ImageReaderBase {
final String arg = args[argIdx];
if (arg.charAt(0) == '-') {
if (arg.equals("-s") || arg.equals("--subsample") && args.length > argIdx) {
if (arg.equals("-s") || arg.equals("--subsample") && args.length > argIdx + 1) {
String[] sub = args[++argIdx].split(",");
try {
@@ -1411,7 +1438,7 @@ public final class JPEGImageReader extends ImageReaderBase {
System.err.println("Bad sub sampling (x,y): '" + args[argIdx] + "'");
}
}
else if (arg.equals("-r") || arg.equals("--roi") && args.length > argIdx) {
else if (arg.equals("-r") || arg.equals("--roi") && args.length > argIdx + 1) {
String[] region = args[++argIdx].split(",");
try {
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId>
@@ -48,7 +48,7 @@ import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static com.twelvemonkeys.lang.Validate.notNull;
@@ -154,7 +154,7 @@ public final class JPEGSegmentUtil {
}
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);
}
static void readSOI(final ImageInputStream stream) throws IOException {
@@ -348,6 +348,7 @@ public final class JPEGSegmentUtil {
else if ("Photoshop 3.0".equals(segment.identifier())) {
// TODO: The "Photoshop 3.0" segment contains several image resources, of which one might contain
// IPTC metadata. Probably duplicated in the XMP though...
// TODO: Merge multiple APP13 segments to single resource block
ImageInputStream stream = new ByteArrayImageInputStream(segment.data, segment.offset(), segment.length());
Directory psd = new PSDReader().read(stream);
Entry iccEntry = psd.getEntryById(PSD.RES_ICC_PROFILE);
@@ -359,6 +360,7 @@ public final class JPEGSegmentUtil {
System.err.println(TIFFReader.HexDump.dump(segment.data));
}
else if ("ICC_PROFILE".equals(segment.identifier())) {
// TODO: Merge multiple APP2 segments to single ICC Profile
// Skip
}
else {
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
@@ -64,7 +64,7 @@ public class PCXImageReaderTest extends ImageReaderAbstractTest<PCXImageReader>
@Override
protected List<TestData> getTestData() {
return Arrays.asList(
new TestData(getClassLoaderResource("/pcx/MARBLES.PCX"), new Dimension(1419, 1001)), // RLE encoded RGB
new TestData(getClassLoaderResource("/pcx/input.pcx"), new Dimension(70, 46)), // RLE encoded RGB
new TestData(getClassLoaderResource("/pcx/lena.pcx"), new Dimension(512, 512)), // RLE encoded RGB
new TestData(getClassLoaderResource("/pcx/lena2.pcx"), new Dimension(512, 512)), // RLE encoded, 256 color indexed (8 bps/1 channel)
new TestData(getClassLoaderResource("/pcx/lena3.pcx"), new Dimension(512, 512)), // RLE encoded, 16 color indexed (4 bps/1 channel)
@@ -76,6 +76,7 @@ public class PCXImageReaderTest extends ImageReaderAbstractTest<PCXImageReader>
new TestData(getClassLoaderResource("/pcx/lena9.pcx"), new Dimension(512, 512)), // RLE encoded, 2 color indexed (1 bps/1 channel)
new TestData(getClassLoaderResource("/pcx/lena10.pcx"), new Dimension(512, 512)), // RLE encoded, 16 color indexed (4 bps/1 channel) (uses only 8 colors)
new TestData(getClassLoaderResource("/pcx/DARKSTAR.PCX"), new Dimension(88, 52)), // RLE encoded monochrome (1 bps/1 channel)
new TestData(getClassLoaderResource("/pcx/MARBLES.PCX"), new Dimension(1419, 1001)), // RLE encoded RGB
new TestData(getClassLoaderResource("/pcx/no-palette-monochrome.pcx"), new Dimension(128, 152)), // RLE encoded monochrome (1 bps/1 channel)
// See cga-pcx.txt, however, the text seems to be in error, the bits can not not as described
new TestData(getClassLoaderResource("/pcx/CGA_BW.PCX"), new Dimension(640, 200)), // RLE encoded indexed (CGA mode)
Binary file not shown.
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-sgi</artifactId>
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
@@ -218,7 +218,8 @@ public final class SGIImageReader extends ImageReaderBase {
private void readRowByte(int height, Rectangle srcRegion, int[] scanlineOffsets, int[] scanlineLengths, int compression, int xSub, int ySub, int c, 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) {
int destY = height - 1 - y;
if (destY % ySub != 0 || destY < srcRegion.y || destY >= srcRegion.y + srcRegion.height) {
if (compression == SGI.COMPRESSION_NONE) {
imageInput.skipBytes(rowDataByte.length);
}
@@ -245,16 +246,17 @@ public final class SGIImageReader extends ImageReaderBase {
}
}
normalize(rowDataByte, 9, srcRegion.width / xSub);
normalize(rowDataByte, 0, srcRegion.width / xSub);
// Flip into position (SGI images are stored bottom/up)
int dstY = (height - 1 - y - srcRegion.y) / ySub;
int dstY = (destY - srcRegion.y) / ySub;
destChannel.setDataElements(0, dstY, srcChannel);
}
private void readRowUShort(int height, Rectangle srcRegion, int[] scanlineOffsets, int[] scanlineLengths, int compression, int xSub, int ySub, int c, short[] rowDataUShort, 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) {
int destY = height - 1 - y;
if (destY % ySub != 0 || destY < srcRegion.y || destY >= srcRegion.y + srcRegion.height) {
if (compression == SGI.COMPRESSION_NONE) {
imageInput.skipBytes(rowDataUShort.length * 2);
}
@@ -281,10 +283,10 @@ public final class SGIImageReader extends ImageReaderBase {
}
}
normalize(rowDataUShort, 9, srcRegion.width / xSub);
normalize(rowDataUShort, 0, srcRegion.width / xSub);
// Flip into position (SGI images are stored bottom/up)
int dstY = (height - 1 - y - srcRegion.y) / ySub;
int dstY = (destY - srcRegion.y) / ySub;
destChannel.setDataElements(0, dstY, srcChannel);
}
@@ -53,7 +53,8 @@ public class SGIImageReaderTest extends ImageReaderAbstractTest<SGIImageReader>
@Override
protected List<TestData> getTestData() {
return Collections.singletonList(
return Arrays.asList(
new TestData(getClassLoaderResource("/sgi/input.sgi"), new Dimension(70, 46)), // RLE encoded RGB
new TestData(getClassLoaderResource("/sgi/MARBLES.SGI"), new Dimension(1419, 1001)) // RLE encoded RGB
);
}
Binary file not shown.
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-tga</artifactId>
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
@@ -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:
@@ -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);
@@ -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");
@@ -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<TGAImageReader>
"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();
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.6.1</version>
<version>3.6.3</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.6.1</version>
<version>3.6.3</version>
</parent>
<artifactId>imageio-tiff</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
@@ -152,7 +152,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
static int findCompressionType(final int type, final InputStream in) throws IOException {
// Discover possible incorrect type, revert to RLE
if (type == TIFFExtension.COMPRESSION_CCITT_T4 && in.markSupported()) {
byte[] streamData = new byte[20];
byte[] streamData = new byte[32];
try {
in.mark(streamData.length);
@@ -173,8 +173,9 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
if (streamData[0] != 0 || (streamData[1] >> 4 != 1 && streamData[1] != 1)) {
// Leading EOL (0b000000000001) not found, search further and try RLE if not found
int numBits = streamData.length * 8;
short b = (short) (((streamData[0] << 8) + streamData[1]) >> 4);
for (int i = 12; i < 160; i++) {
for (int i = 12; i < numBits; i++) {
b = (short) ((b << 1) + ((streamData[(i / 8)] >> (7 - (i % 8))) & 0x01));
if ((b & 0xFFF) == 1) {
@@ -68,14 +68,19 @@ public class CCITTFaxDecoderStreamTest {
};
// group3_2d.tif: EOL|k=1|3W|1B|2W|EOL|k=0|V|V|V|EOL|k=1|3W|1B|2W|EOL|k=0|V-1|V|V|6*F
static final byte[] DATA_G3_2D = { 0x00, 0x1C, 0x27, 0x00, 0x17, 0x00, 0x1C, 0x27, 0x00, 0x12, (byte) 0xC0 };
static final byte[] DATA_G3_2D = {0x00, 0x1C, 0x27, 0x00, 0x17, 0x00, 0x1C, 0x27, 0x00, 0x12, (byte) 0xC0};
// group3_2d_fill.tif
static final byte[] DATA_G3_2D_FILL = { 0x00, 0x01, (byte) 0xC2, 0x70, 0x01, 0x70, 0x01, (byte) 0xC2, 0x70, 0x01,
0x2C };
static final byte[] DATA_G3_2D_FILL = {0x00, 0x01, (byte) 0xC2, 0x70, 0x01, 0x70, 0x01, (byte) 0xC2,
0x70, 0x01, 0x2C};
static final byte[] DATA_G3_2D_lsb2msb = { 0x00, 0x38, (byte) 0xE4, 0x00, (byte) 0xE8, 0x00, 0x38, (byte) 0xE4,
0x00, 0x48, 0x03 };
static final byte[] DATA_G3_2D_lsb2msb = {0x00, 0x38, (byte) 0xE4, 0x00, (byte) 0xE8, 0x00, 0x38, (byte) 0xE4,
0x00, 0x48, 0x03};
static final byte[] DATA_G3_LONG = {0x00, 0x68, 0x0A, (byte) 0xC9, 0x3A, 0x3A, 0x00, 0x68,
(byte) 0x8A, (byte) 0xD8, 0x3A, 0x35, 0x00, 0x68, 0x0A, 0x06,
(byte) 0xDD, 0x3A, 0x19, 0x00, 0x68, (byte) 0x8A, (byte) 0x9E, 0x75,
0x08, 0x00, 0x68};
// group4.tif:
// Line 1: V-3, V-2, V0
@@ -189,6 +194,7 @@ public class CCITTFaxDecoderStreamTest {
assertEquals(TIFFExtension.COMPRESSION_CCITT_T4, CCITTFaxDecoderStream.findCompressionType(TIFFExtension.COMPRESSION_CCITT_T4, new ByteArrayInputStream(DATA_G3_2D)));
assertEquals(TIFFExtension.COMPRESSION_CCITT_T4, CCITTFaxDecoderStream.findCompressionType(TIFFExtension.COMPRESSION_CCITT_T4, new ByteArrayInputStream(DATA_G3_2D_FILL)));
assertEquals(TIFFExtension.COMPRESSION_CCITT_T4, CCITTFaxDecoderStream.findCompressionType(TIFFExtension.COMPRESSION_CCITT_T4, new ByteArrayInputStream(DATA_G3_2D_lsb2msb)));
assertEquals(TIFFExtension.COMPRESSION_CCITT_T4, CCITTFaxDecoderStream.findCompressionType(TIFFExtension.COMPRESSION_CCITT_T4, new ByteArrayInputStream(DATA_G3_LONG)));
// Group 4/CCITT_T6
assertEquals(TIFFExtension.COMPRESSION_CCITT_T6, CCITTFaxDecoderStream.findCompressionType(TIFFExtension.COMPRESSION_CCITT_T6, new ByteArrayInputStream(DATA_G4)));
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.twelvemonkeys.imageio</groupId>
+2 -2
View File
@@ -9,7 +9,7 @@
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
<packaging>pom</packaging>
<name>Twelvemonkeys</name>
@@ -86,7 +86,7 @@
<connection>scm:git:https://github.com/haraldk/TwelveMonkeys</connection>
<developerConnection>scm:git:ssh://git@github.com/haraldk/TwelveMonkeys</developerConnection>
<url>https://github.com/haraldk/TwelveMonkeys</url>
<tag>twelvemonkeys-3.6.1</tag>
<tag>twelvemonkeys-3.6.3</tag>
</scm>
<properties>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>