diff --git a/imageio/imageio-jpeg/license.txt b/imageio/imageio-jpeg/license.txt index 4913b243..53188f88 100644 --- a/imageio/imageio-jpeg/license.txt +++ b/imageio/imageio-jpeg/license.txt @@ -1,4 +1,6 @@ -Copyright (c) 2013, Harald Kuhr +Copyright (c) 2016, Harald Kuhr +Copyright (C) 2015, Michael Martinez (JPEG Lossless decoder) +Copyright (C) 2004, Helmut Dersch (Java JPEG decoder) All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AdobeDCT.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AdobeDCT.java index 19b6dc06..22cbc6c1 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AdobeDCT.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AdobeDCT.java @@ -40,17 +40,17 @@ import java.io.IOException; * @author last modified by $Author: haraldk$ * @version $Id: AdobeDCTSegment.java,v 1.0 23.04.12 16:55 haraldk Exp$ */ -final class AdobeDCT extends AppSegment { - public static final int Unknown = 0; - public static final int YCC = 1; - public static final int YCCK = 2; +final class AdobeDCT extends Application { + static final int Unknown = 0; + static final int YCC = 1; + static final int YCCK = 2; final int version; final int flags0; final int flags1; final int transform; - AdobeDCT(int version, int flags0, int flags1, int transform) { + private AdobeDCT(int version, int flags0, int flags1, int transform) { super(JPEG.APP14, "Adobe", new byte[]{'A', 'd', 'o', 'b', 'e', 0, (byte) version, (byte) (flags0 >> 8), (byte) (flags0 & 0xff), (byte) (flags1 >> 8), (byte) (flags1 & 0xff), (byte) transform}); this.version = version; // 100 or 101 diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AppSegment.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AppSegment.java deleted file mode 100644 index e77472be..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/AppSegment.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.twelvemonkeys.imageio.plugins.jpeg; - -import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; -import com.twelvemonkeys.lang.Validate; - -import java.io.ByteArrayInputStream; -import java.io.DataInput; -import java.io.IOException; -import java.io.InputStream; - -/** - * AppSegment. - * - * @author Harald Kuhr - * @author last modified by $Author: harald.kuhr$ - * @version $Id: AppSegment.java,v 1.0 22/08/16 harald.kuhr Exp$ - */ -class AppSegment extends Segment { - - final String identifier; - final byte[] data; - - AppSegment(int marker, final String identifier, final byte[] data) { - super(marker); - - this.identifier = Validate.notEmpty(identifier, "identifier"); - this.data = data; - } - - protected AppSegment(int marker, final String identifier) { - this(marker, identifier, null); - } - - InputStream data() { - int offset = identifier.length() + 1; - return new ByteArrayInputStream(data, offset, data.length - offset); - } - - public static AppSegment read(final int marker, final String identifier, final DataInput data, final int length) throws IOException { - switch (marker) { - case JPEG.APP0: - // JFIF - if ("JFIF".equals(identifier)) { - return JFIF.read(data, length); - } - case JPEG.APP1: - // JFXX - if ("JFXX".equals(identifier)) { - return JFXX.read(data, length); - } - // TODO: Exif? - case JPEG.APP2: - // ICC_PROFILE - if ("ICC_PROFILE".equals(identifier)) { - return ICCProfile.read(data, length); - } - case JPEG.APP14: - // Adobe - if ("Adobe".equals(identifier)) { - return AdobeDCT.read(data, length); - } - - default: - // Generic APPn segment - byte[] bytes = new byte[length - 2]; - data.readFully(bytes); - return new AppSegment(marker, identifier, bytes); - } - } -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Application.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Application.java new file mode 100644 index 00000000..2a205ba6 --- /dev/null +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Application.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.twelvemonkeys.imageio.plugins.jpeg; + +import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; +import com.twelvemonkeys.lang.Validate; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.IOException; +import java.io.InputStream; + +/** + * Application. + * + * @author Harald Kuhr + * @author last modified by $Author: harald.kuhr$ + * @version $Id: Application.java,v 1.0 22/08/16 harald.kuhr Exp$ + */ +class Application extends Segment { + + final String identifier; + final byte[] data; + + Application(int marker, final String identifier, final byte[] data) { + super(marker); + + this.identifier = Validate.notEmpty(identifier, "identifier"); + this.data = data; + } + + InputStream data() { + int offset = identifier.length() + 1; + return new ByteArrayInputStream(data, offset, data.length - offset); + } + + @Override + public String toString() { + return "APP" + (marker & 0x0f) + "/" + identifier + "[length: " + data.length + "]"; + } + + public static Application read(final int marker, final String identifier, final DataInput data, final int length) throws IOException { + switch (marker) { + case JPEG.APP0: + // JFIF + if ("JFIF".equals(identifier)) { + return JFIF.read(data, length); + } + case JPEG.APP1: + // JFXX + if ("JFXX".equals(identifier)) { + return JFXX.read(data, length); + } + // TODO: Exif? + case JPEG.APP2: + // ICC_PROFILE + if ("ICC_PROFILE".equals(identifier)) { + return ICCProfile.read(data, length); + } + case JPEG.APP14: + // Adobe + if ("Adobe".equals(identifier)) { + return AdobeDCT.read(data, length); + } + + default: + // Generic APPn segment + byte[] bytes = new byte[length - 2]; + data.readFully(bytes); + return new Application(marker, identifier, bytes); + } + } +} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Comment.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Comment.java index 1b4c5c04..50e9ea69 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Comment.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Comment.java @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; @@ -21,10 +49,15 @@ class Comment extends Segment { this.comment = comment; } + @Override + public String toString() { + return "COM[" + comment + "]"; + } + public static Segment read(final DataInput data, final int length) throws IOException { - byte[] ascii = new byte[length]; + byte[] ascii = new byte[length - 2]; data.readFully(ascii); - return new Comment(new String(ascii, StandardCharsets.UTF_8)); + return new Comment(new String(ascii, StandardCharsets.UTF_8)); // Strictly, it is ASCII, but UTF-8 is compatible } } diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Frame.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Frame.java index b3788669..d72dc5f3 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Frame.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Frame.java @@ -51,7 +51,7 @@ final class Frame extends Segment { final Component[] components; // Components specifications - Frame(final int marker, final int samplePrecision, final int lines, final int samplesPerLine, final Component[] components) { + private Frame(final int marker, final int samplePrecision, final int lines, final int samplesPerLine, final Component[] components) { super(marker); this.samplePrecision = samplePrecision; @@ -116,7 +116,7 @@ final class Frame extends Segment { return read(marker, new SubImageInputStream(data, length), length); } - static final class Component { + public static final class Component { final int id; final int hSub; // Horizontal sampling factor final int vSub; // Vertical sampling factor diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/HuffmanTable.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/HuffmanTable.java index 8bd4b465..bd53c739 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/HuffmanTable.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/HuffmanTable.java @@ -1,37 +1,38 @@ /* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. + * Copyright (c) 2016, Harald Kuhr + * Copyright (C) 2015, Michael Martinez + * Copyright (C) 2004, Helmut Dersch + * All rights reserved. * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; +import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; import java.io.DataInput; import java.io.IOException; @@ -45,7 +46,7 @@ final class HuffmanTable extends Segment { public static final int MSB = 0x80000000; - public HuffmanTable() { + private HuffmanTable() { super(JPEG.DHT); tc[0][0] = 0; @@ -109,7 +110,7 @@ final class HuffmanTable extends Segment { } if (k >= 256) { if (k > 256) { - throw new IOException("Huffman table error"); + throw new IIOException("JPEG Huffman Table error"); } k = 0; @@ -119,9 +120,14 @@ final class HuffmanTable extends Segment { } } - public static Segment read(DataInput data, int length) throws IOException { - int count = 0; - count += 2; + @Override + public String toString() { + // TODO: Id and class for tables + return "DHT[]"; + } + + public static Segment read(final DataInput data, final int length) throws IOException { + int count = 2; HuffmanTable table = new HuffmanTable(); @@ -130,12 +136,12 @@ final class HuffmanTable extends Segment { count++; int t = temp & 0x0F; if (t > 3) { - throw new IOException("Huffman table Id > 3:" + t); + throw new IIOException("Unexpected JPEG Huffman Table Id (> 3):" + t); } int c = temp >> 4; if (c > 2) { - throw new IOException("Huffman table class > 2: " + c); + throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c); } table.th[t] = 1; @@ -149,7 +155,7 @@ final class HuffmanTable extends Segment { for (int i = 0; i < 16; i++) { for (int j = 0; j < table.l[t][c][i]; j++) { if (count > length) { - throw new IOException("Huffman table format error [count>Lh]"); + throw new IIOException("JPEG Huffman Table format error"); } table.v[t][c][i][j] = data.readUnsignedByte(); count++; @@ -158,18 +164,9 @@ final class HuffmanTable extends Segment { } if (count != length) { - throw new IOException("Huffman table format error [count!=Lf]"); + throw new IIOException("JPEG Huffman Table format error, bad segment length: " + length); } -// for (int i = 0; i < 4; i++) { -// for (int j = 0; j < 2; j++) { -// if (tc[i][j] != 0) { -// buildHuffTable(HuffTab[i][j], l[i][j], v[i][j]); -// } -// } -// } -// -// return 1; return table; } } diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/ICCProfile.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/ICCProfile.java index bdea9621..ba0ae44f 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/ICCProfile.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/ICCProfile.java @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; @@ -12,12 +40,18 @@ import java.io.IOException; * @author last modified by $Author: harald.kuhr$ * @version $Id: ICCProfile.java,v 1.0 22/08/16 harald.kuhr Exp$ */ -final class ICCProfile extends AppSegment { - protected ICCProfile(final byte[] data) { +final class ICCProfile extends Application { + private ICCProfile(final byte[] data) { super(JPEG.APP2, "ICC_PROFILE", data); } // TODO: Create util method to concat all ICC segments to one and return ICC_Profile (move from JPEGImageReader) + // If so, how to deal with warnings from the original code? Throw exceptions instead? + + @Override + public String toString() { + return "ICC_PROFILE[" + data[0] + "/" + data[1] + " length: " + data.length + "]"; + } public static ICCProfile read(DataInput data, int length) throws IOException { byte[] bytes = new byte[length - 2]; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFIF.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFIF.java index 832105f2..e20d5289 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFIF.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFIF.java @@ -32,7 +32,6 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; import java.io.*; import java.nio.ByteBuffer; -import java.util.Arrays; /** * JFIFSegment @@ -41,7 +40,7 @@ import java.util.Arrays; * @author last modified by $Author: haraldk$ * @version $Id: JFIFSegment.java,v 1.0 23.04.12 16:52 haraldk Exp$ */ -final class JFIF extends AppSegment { +final class JFIF extends Application { final int majorVersion; final int minorVersion; final int units; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFXX.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFXX.java index 01099fa7..cb19ac87 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFXX.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JFXX.java @@ -29,9 +29,7 @@ package com.twelvemonkeys.imageio.plugins.jpeg; import java.io.DataInput; -import java.io.DataInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.Arrays; /** @@ -41,7 +39,7 @@ import java.util.Arrays; * @author last modified by $Author: haraldk$ * @version $Id: JFXXSegment.java,v 1.0 23.04.12 16:54 haraldk Exp$ */ -final class JFXX extends AppSegment { +final class JFXX extends Application { public static final int JPEG = 0x10; public static final int INDEXED = 0x11; public static final int RGB = 0x13; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10Metadata.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10Metadata.java index 46ebb233..d3a59730 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10Metadata.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10Metadata.java @@ -2,13 +2,9 @@ package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.AbstractMetadata; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; -import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment; import org.w3c.dom.Node; import javax.imageio.metadata.IIOMetadataNode; -import java.io.DataInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -95,10 +91,10 @@ class JPEGImage10Metadata extends AbstractMetadata { Scan scan = (Scan) segment; IIOMetadataNode sos = new IIOMetadataNode("sos"); sos.setAttribute("numScanComponents", String.valueOf(scan.components.length)); - sos.setAttribute("startSpectralSelection", String.valueOf(scan.selection)); - sos.setAttribute("endSpectralSelection", String.valueOf(scan.spectralEnd)); - sos.setAttribute("approxHigh", String.valueOf(scan.ah)); - sos.setAttribute("approxLow", String.valueOf(scan.al)); + sos.setAttribute("startSpectralSelection", String.valueOf(scan.spectralSelStart)); + sos.setAttribute("endSpectralSelection", String.valueOf(scan.spectralSelEnd)); + sos.setAttribute("approxHigh", String.valueOf(scan.approxHigh)); + sos.setAttribute("approxLow", String.valueOf(scan.approxLow)); for (Scan.Component component : scan.components) { IIOMetadataNode spec = new IIOMetadataNode("scanComponentSpec"); @@ -135,7 +131,7 @@ class JPEGImage10Metadata extends AbstractMetadata { default: IIOMetadataNode unknown = new IIOMetadataNode("unknown"); unknown.setAttribute("MarkerTag", String.valueOf(segment.marker & 0xFF)); - unknown.setUserObject(((AppSegment) segment).data); + unknown.setUserObject(((Application) segment).data); markerSequence.appendChild(unknown); break; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10MetadataCleaner.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10MetadataCleaner.java index ca2b3728..ac404c0f 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10MetadataCleaner.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImage10MetadataCleaner.java @@ -10,10 +10,7 @@ import javax.imageio.metadata.IIOInvalidTreeException; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import java.awt.color.ICC_Profile; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; import java.io.IOException; -import java.nio.charset.Charset; import java.util.List; /** @@ -39,7 +36,7 @@ final class JPEGImage10MetadataCleaner { IIOMetadata cleanMetadata(final IIOMetadata imageMetadata) throws IOException { // We filter out pretty much everything from the stream.. // Meaning we have to read get *all APP segments* and re-insert into metadata. - List appSegments = reader.getAppSegments(JPEGImageReader.ALL_APP_MARKERS, null); + List appSegments = reader.getAppSegments(JPEGImageReader.ALL_APP_MARKERS, null); // NOTE: There's a bug in the merging code in JPEGMetadata mergeUnknownNode that makes sure all "unknown" nodes are added twice in certain conditions.... ARGHBL... // DONE: 1: Work around @@ -176,7 +173,7 @@ final class JPEGImage10MetadataCleaner { } Node next = null; - for (AppSegment segment : appSegments) { + for (Application segment : appSegments) { // Except real app0JFIF, app0JFXX, app2ICC and app14Adobe, add all the app segments that we filtered away as "unknown" markers if (segment.marker == JPEG.APP0 && "JFIF".equals(segment.identifier) && hasRealJFIF) { continue; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java index 54a15409..867373f4 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGImageReader.java @@ -39,7 +39,6 @@ import com.twelvemonkeys.imageio.metadata.exif.TIFF; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment; import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil; -import com.twelvemonkeys.imageio.plugins.jpeg.lossless.JPEGLosslessDecoderWrapper; import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; import com.twelvemonkeys.imageio.util.ProgressListenerBase; import com.twelvemonkeys.lang.Validate; @@ -110,7 +109,7 @@ public class JPEGImageReader extends ImageReaderBase { static final int ALL_APP_MARKERS = -1; /** Segment identifiers for the JPEG segments we care about reading. */ - private static final Map> SEGMENT_IDENTIFIERS = createSegmentIds(); + private static final Map> SEGMENT_IDENTIFIERS = JPEGSegmentUtil.ALL_SEGMENTS; //createSegmentIds(); private static Map> createSegmentIds() { Map> map = new LinkedHashMap<>(); @@ -386,7 +385,7 @@ public class JPEGImageReader extends ImageReaderBase { // TODO: What about stream position? // TODO: Param handling: Source region, offset, subsampling, destination, destination type, etc.... // Read image as lossless - return new JPEGLosslessDecoderWrapper().readImage(imageInput); + return new JPEGLosslessDecoderWrapper().readImage(segments, imageInput); } // We need to apply ICC profile unless the profile is sRGB/default gray (whatever that is) @@ -592,25 +591,25 @@ public class JPEGImageReader extends ImageReaderBase { if (adobeDCT != null) { switch (adobeDCT.transform) { case AdobeDCT.YCC: - if (startOfFrame.components.length != 3) { + if (startOfFrame.componentsInFrame() != 3) { // This probably means the Adobe marker is bogus break; } return JPEGColorSpace.YCbCr; case AdobeDCT.YCCK: - if (startOfFrame.components.length != 4) { + if (startOfFrame.componentsInFrame() != 4) { // This probably means the Adobe marker is bogus break; } return JPEGColorSpace.YCCK; case AdobeDCT.Unknown: - if (startOfFrame.components.length == 1) { + if (startOfFrame.componentsInFrame() == 1) { return JPEGColorSpace.Gray; } - else if (startOfFrame.components.length == 3) { + else if (startOfFrame.componentsInFrame() == 3) { return JPEGColorSpace.RGB; } - else if (startOfFrame.components.length == 4) { + else if (startOfFrame.componentsInFrame() == 4) { return JPEGColorSpace.CMYK; } // Else fall through @@ -619,7 +618,7 @@ public class JPEGImageReader extends ImageReaderBase { } // TODO: We should probably allow component ids out of order (ie. BGR or KMCY)... - switch (startOfFrame.components.length) { + switch (startOfFrame.componentsInFrame()) { case 1: return JPEGColorSpace.Gray; case 2: @@ -712,7 +711,7 @@ public class JPEGImageReader extends ImageReaderBase { if (segments == null) { long start = DEBUG ? System.currentTimeMillis() : 0; - // TODO: Consider just reading the segments here, for better performance... + // TODO: Consider just reading the segments directly, for better performance... List jpegSegments = readSegments(); List segments = new ArrayList<>(jpegSegments.size()); @@ -761,20 +760,20 @@ public class JPEGImageReader extends ImageReaderBase { return Collections.emptyList(); } - List getAppSegments(final int marker, final String identifier) throws IOException { + List getAppSegments(final int marker, final String identifier) throws IOException { initHeader(); - List appSegments = Collections.emptyList(); + List appSegments = Collections.emptyList(); for (Segment segment : segments) { - if (segment instanceof AppSegment + if (segment instanceof Application && (marker == ALL_APP_MARKERS || marker == segment.marker) - && (identifier == null || identifier.equals(((AppSegment) segment).identifier))) { + && (identifier == null || identifier.equals(((Application) segment).identifier))) { if (appSegments == Collections.EMPTY_LIST) { appSegments = new ArrayList<>(segments.size()); } - appSegments.add((AppSegment) segment); + appSegments.add((Application) segment); } } @@ -794,26 +793,26 @@ public class JPEGImageReader extends ImageReaderBase { } AdobeDCT getAdobeDCT() throws IOException { - List adobe = getAppSegments(JPEG.APP14, "Adobe"); + List adobe = getAppSegments(JPEG.APP14, "Adobe"); return adobe.isEmpty() ? null : (AdobeDCT) adobe.get(0); } JFIF getJFIF() throws IOException{ - List jfif = getAppSegments(JPEG.APP0, "JFIF"); + List jfif = getAppSegments(JPEG.APP0, "JFIF"); return jfif.isEmpty() ? null : (JFIF) jfif.get(0); } JFXX getJFXX() throws IOException { - List jfxx = getAppSegments(JPEG.APP0, "JFXX"); + List jfxx = getAppSegments(JPEG.APP0, "JFXX"); return jfxx.isEmpty() ? null : (JFXX) jfxx.get(0); } private CompoundDirectory getExif() throws IOException { - List exifSegments = getAppSegments(JPEG.APP1, "Exif"); + List exifSegments = getAppSegments(JPEG.APP1, "Exif"); if (!exifSegments.isEmpty()) { - AppSegment exif = exifSegments.get(0); + Application exif = exifSegments.get(0); InputStream data = exif.data(); if (data.read() == -1) { // Read pad @@ -849,13 +848,13 @@ public class JPEGImageReader extends ImageReaderBase { // TODO: Allow metadata to contain the wrongly indexed profiles, if readable // NOTE: We ignore any profile with wrong index for reading and image types, just to be on the safe side - List segments = getAppSegments(JPEG.APP2, "ICC_PROFILE"); + List segments = getAppSegments(JPEG.APP2, "ICC_PROFILE"); // TODO: Possibly move this logic to the ICCProfile class... if (segments.size() == 1) { // Faster code for the common case - AppSegment segment = segments.get(0); + Application segment = segments.get(0); DataInputStream stream = new DataInputStream(segment.data()); int chunkNumber = stream.readUnsignedByte(); int chunkCount = stream.readUnsignedByte(); @@ -945,7 +944,7 @@ public class JPEGImageReader extends ImageReaderBase { if (isLossless()) { // TODO: What about stream position? // TODO: Param handling: Reading as raster should support source region, subsampling etc. - return new JPEGLosslessDecoderWrapper().readRaster(imageInput); + return new JPEGLosslessDecoderWrapper().readRaster(segments, imageInput); } return delegate.readRaster(imageIndex, param); @@ -1001,9 +1000,9 @@ public class JPEGImageReader extends ImageReaderBase { } // Read Exif thumbnails if present - List exifSegments = getAppSegments(JPEG.APP1, "Exif"); + List exifSegments = getAppSegments(JPEG.APP1, "Exif"); if (!exifSegments.isEmpty()) { - AppSegment exif = exifSegments.get(0); + Application exif = exifSegments.get(0); InputStream data = exif.data(); if (data.read() == -1) { diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoder.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoder.java similarity index 66% rename from imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoder.java rename to imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoder.java index 2fe8d16e..776c6aef 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoder.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoder.java @@ -1,50 +1,51 @@ -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - /* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. + * Copyright (c) 2016, Harald Kuhr + * Copyright (C) 2015, Michael Martinez + * Copyright (C) 2004, Helmut Dersch + * All rights reserved. * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; +import com.twelvemonkeys.lang.Validate; +import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; import java.io.IOException; +import java.util.List; -public class JPEGLosslessDecoder { +final class JPEGLosslessDecoder { private final ImageInputStream input; - // TODO: Merge these classes with similar classes from the main package - // (FrameHeader == Frame, ComponentSpec == Frame.Component, ScanHeader == Scan etc) - private final FrameHeader frame; + private final Frame frame; private final HuffmanTable huffTable; private final QuantizationTable quantTable; - private final ScanHeader scan; + private Scan scan; private final int HuffTab[][][] = new int[4][2][MAX_HUFFMAN_SUBTREE * 256]; private final int IDCT_Source[] = new int[64]; @@ -69,36 +70,65 @@ public class JPEGLosslessDecoder { private int[] outputBlueData; private static final int IDCT_P[] = { - 0, 5, 40, 16, 45, 2, 7, 42, 21, 56, 8, 61, 18, 47, 1, 4, 41, 23, 58, 13, 32, 24, 37, 10, 63, 17, 44, 3, 6, 43, 20, - 57, 15, 34, 29, 48, 53, 26, 39, 9, 60, 19, 46, 22, 59, 12, 33, 31, 50, 55, 25, 36, 11, 62, 14, 35, 28, 49, 52, 27, 38, 30, 51, 54 + 0, 5, 40, 16, 45, 2, 7, 42, + 21, 56, 8, 61, 18, 47, 1, 4, + 41, 23, 58, 13, 32, 24, 37, 10, + 63, 17, 44, 3, 6, 43, 20, 57, + 15, 34, 29, 48, 53, 26, 39, 9, + 60, 19, 46, 22, 59, 12, 33, 31, + 50, 55, 25, 36, 11, 62, 14, 35, + 28, 49, 52, 27, 38, 30, 51, 54 }; private static final int TABLE[] = { - 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, - 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 }; - public static final int RESTART_MARKER_BEGIN = 0xFFD0; - public static final int RESTART_MARKER_END = 0xFFD7; - public static final int MAX_HUFFMAN_SUBTREE = 50; - public static final int MSB = 0x80000000; + private static final int RESTART_MARKER_BEGIN = 0xFFD0; + private static final int RESTART_MARKER_END = 0xFFD7; + private static final int MAX_HUFFMAN_SUBTREE = 50; + private static final int MSB = 0x80000000; - public int getDimX() { + int getDimX() { return xDim; } - public int getDimY() { + int getDimY() { return yDim; } - public JPEGLosslessDecoder(final ImageInputStream data) { + JPEGLosslessDecoder(final List segments, final ImageInputStream data) { + Validate.notNull(segments); + + frame = get(segments, Frame.class); + scan = get(segments, Scan.class); + + QuantizationTable qt = get(segments, QuantizationTable.class); + quantTable = qt != null ? qt : new QuantizationTable(); // For lossless there are no DQTs + huffTable = get(segments, HuffmanTable.class); // For non-lossless there can be multiple of DHTs + RestartInterval dri = get(segments, RestartInterval.class); + restartInterval = dri != null ? dri.interval : 0; + input = data; - frame = new FrameHeader(); - scan = new ScanHeader(); - quantTable = new QuantizationTable(); - huffTable = new HuffmanTable(); } - public int[][] decode() throws IOException { + private T get(final List segments, final Class type) { + for (Segment segment : segments) { + if (type.isInstance(segment)) { + return type.cast(segment); + } + } + + return null; + } + + int[][] decode() throws IOException { int current, scanNum = 0; final int pred[] = new int[10]; int[][] outputRef; @@ -108,108 +138,22 @@ public class JPEGLosslessDecoder { current = input.readUnsignedShort(); if (current != JPEG.SOI) { // SOI - throw new IOException("Not a JPEG file"); + throw new IIOException("Not a JPEG file"); } - // TODO: Why the two loops?! + huffTable.buildHuffTables(HuffTab); + quantTable.enhanceTables(TABLE); current = input.readUnsignedShort(); - while (((current >> 4) != 0x0FFC) || (current == JPEG.DHT)) { // SOF 0~15 - switch (current) { - case JPEG.DHT: // DHT - huffTable.read(input, HuffTab); - break; - case JPEG.DAC: // DAC - throw new IOException("Program doesn't support arithmetic coding."); - case JPEG.DQT: - quantTable.read(input, TABLE); - break; - case JPEG.DRI: - restartInterval = readNumber(); - break; - case JPEG.APP0: - case JPEG.APP1: - case JPEG.APP2: - case JPEG.APP3: - case JPEG.APP4: - case JPEG.APP5: - case JPEG.APP6: - case JPEG.APP7: - case JPEG.APP8: - case JPEG.APP9: - case JPEG.APP10: - case JPEG.APP11: - case JPEG.APP12: - case JPEG.APP13: - case JPEG.APP14: - case JPEG.APP15: - readApp(); - break; - case JPEG.COM: - readComment(); - break; - default: - if ((current >> 8) != 0xFF) { - throw new IOException("JPEG Segment marker expected."); - } - } - - current = input.readUnsignedShort(); - } - - if ((current < 0xFFC0) || (current > 0xFFC7)) { - throw new IOException("ERROR: could not handle arithmetic code!"); - } - - frame.read(input); - current = input.readUnsignedShort(); - do { - while (current != 0x0FFDA) { //SOS - switch (current) { - case 0xFFC4: //DHT - huffTable.read(input, HuffTab); - break; - case 0xFFCC: //DAC - throw new IOException("Program doesn't support arithmetic coding. (format throw new IOException)"); - case 0xFFDB: - quantTable.read(input, TABLE); - break; - case 0xFFDD: - restartInterval = readNumber(); - break; - case 0xFFE0: - case 0xFFE1: - case 0xFFE2: - case 0xFFE3: - case 0xFFE4: - case 0xFFE5: - case 0xFFE6: - case 0xFFE7: - case 0xFFE8: - case 0xFFE9: - case 0xFFEA: - case 0xFFEB: - case 0xFFEC: - case 0xFFED: - case 0xFFEE: - case 0xFFEF: - readApp(); - break; - case 0xFFFE: - readComment(); - break; - default: - if ((current >> 8) != 0xFF) { - throw new IOException("ERROR: format throw new IOException! (Parser.decode)"); - } - } - + // Skip until first SOS + while (current != JPEG.SOS) { + input.skipBytes(input.readUnsignedShort() - 2); current = input.readUnsignedShort(); } - final int precision = frame.getPrecision(); + int precision = frame.samplePrecision; if (precision == 8) { mask = 0xFF; @@ -218,28 +162,29 @@ public class JPEGLosslessDecoder { mask = 0xFFFF; } - final ComponentSpec[] components = frame.getComponents(); + Frame.Component[] components = frame.components; - readScan(); - numComp = scan.getNumComponents(); - selection = scan.getSelection(); + scan = readScan(); + numComp = scan.components.length; + selection = scan.spectralSelStart; - final ScanComponent[] scanComps = scan.components; + final Scan.Component[] scanComps = scan.components; final int[][] quantTables = quantTable.quantTables; for (int i = 0; i < numComp; i++) { - ComponentSpec component = getComponentSpec(components, scanComps[i].getScanCompSel()); - qTab[i] = quantTables[component.quantTableSel]; - nBlock[i] = component.vSamp * component.hSamp; - dcTab[i] = HuffTab[scanComps[i].getDcTabSel()][0]; - acTab[i] = HuffTab[scanComps[i].getAcTabSel()][1]; + Frame.Component component = getComponentSpec(components, scanComps[i].scanCompSel); + qTab[i] = quantTables[component.qtSel]; + nBlock[i] = component.vSub * component.hSub; + dcTab[i] = HuffTab[scanComps[i].dcTabSel][0]; + acTab[i] = HuffTab[scanComps[i].acTabSel][1]; } - xDim = frame.getDimX(); - yDim = frame.getDimY(); + xDim = frame.samplesPerLine; + yDim = frame.lines; outputRef = new int[numComp][]; + // TODO: Support 4 components (RGBA/YCCA/CMYK/YCCK), others? if (numComp == 1) { outputData = new int[xDim * yDim]; outputRef[0] = outputData; @@ -314,8 +259,8 @@ public class JPEGLosslessDecoder { return outputRef; } - private ComponentSpec getComponentSpec(ComponentSpec[] components, int sel) { - for (ComponentSpec component : components) { + private Frame.Component getComponentSpec(Frame.Component[] components, int sel) { + for (Frame.Component component : components) { if (component.id == sel) { return component; } @@ -324,8 +269,9 @@ public class JPEGLosslessDecoder { throw new IllegalArgumentException("No such component id: " + sel); } - private int readScan() throws IOException { - return scan.read(input); + private Scan readScan() throws IOException { + int length = input.readUnsignedShort(); + return Scan.read(input, length); } private int decode(final int prev[], final int temp[], final int index[]) throws IOException { @@ -341,11 +287,11 @@ public class JPEGLosslessDecoder { } private int decodeSingle(final int prev[], final int temp[], final int index[]) throws IOException { - // At the beginning of the first line and - // at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision. + // At the beginning of the first line and + // at the beginning of each restart interval the prediction value of 2P – 1 is used, where P is the input precision. if (restarting) { restarting = false; - prev[0] = (1 << (frame.getPrecision() - 1)); + prev[0] = (1 << (frame.samplePrecision - 1)); } else { switch (selection) { @@ -554,7 +500,7 @@ public class JPEGLosslessDecoder { index[0] += 8 - (code >> 8); if (index[0] < 0) { - throw new IOException("index=" + index[0] + " temp=" + temp[0] + " code=" + code + " in HuffmanValue()"); + throw new IIOException("index=" + index[0] + " temp=" + temp[0] + " code=" + code + " in HuffmanValue()"); } if (index[0] < markerIndex) { @@ -566,7 +512,7 @@ public class JPEGLosslessDecoder { return code & 0xFF; } - private int getn(final int[] PRED, final int n, final int temp[], final int index[]) throws IOException { + private int getn(final int[] pred, final int n, final int temp[], final int index[]) throws IOException { int result; final int one = 1; final int n_one = -1; @@ -578,7 +524,7 @@ public class JPEGLosslessDecoder { } if (n == 16) { - if (PRED[0] >= 0) { + if (pred[0] >= 0) { return -32768; } else { @@ -659,7 +605,7 @@ public class JPEGLosslessDecoder { return getPreviousY(data); } else { - return (1 << (frame.getPrecision() - 1)); + return (1 << (frame.samplePrecision - 1)); } } @@ -685,18 +631,18 @@ public class JPEGLosslessDecoder { return (xLoc == (xDim - 1)) && (yLoc == (yDim - 1)); } - private void output(final int PRED[]) { + private void output(final int pred[]) { if (numComp == 1) { - outputSingle(PRED); + outputSingle(pred); } else { - outputRGB(PRED); + outputRGB(pred); } } - private void outputSingle(final int PRED[]) { + private void outputSingle(final int pred[]) { if ((xLoc < xDim) && (yLoc < yDim)) { - outputData[(yLoc * xDim) + xLoc] = mask & PRED[0]; + outputData[(yLoc * xDim) + xLoc] = mask & pred[0]; xLoc++; if (xLoc >= xDim) { @@ -706,11 +652,11 @@ public class JPEGLosslessDecoder { } } - private void outputRGB(final int PRED[]) { + private void outputRGB(final int pred[]) { if ((xLoc < xDim) && (yLoc < yDim)) { - outputRedData[(yLoc * xDim) + xLoc] = PRED[0]; - outputGreenData[(yLoc * xDim) + xLoc] = PRED[1]; - outputBlueData[(yLoc * xDim) + xLoc] = PRED[2]; + outputRedData[(yLoc * xDim) + xLoc] = pred[0]; + outputGreenData[(yLoc * xDim) + xLoc] = pred[1]; + outputBlueData[(yLoc * xDim) + xLoc] = pred[2]; xLoc++; if (xLoc >= xDim) { @@ -720,34 +666,6 @@ public class JPEGLosslessDecoder { } } - private int readApp() throws IOException { - int count = 0; - final int length = input.readUnsignedShort(); - count += 2; - - while (count < length) { - input.readUnsignedByte(); - count++; - } - - return length; - } - - private String readComment() throws IOException { - final StringBuffer sb = new StringBuffer(); - int count = 0; - - final int length = input.readUnsignedShort(); - count += 2; - - while (count < length) { - sb.append((char) input.readUnsignedByte()); - count++; - } - - return sb.toString(); - } - private int readNumber() throws IOException { final int Ld = input.readUnsignedShort(); @@ -758,11 +676,11 @@ public class JPEGLosslessDecoder { return input.readUnsignedShort(); } - public int getNumComponents() { + int getNumComponents() { return numComp; } - public int getPrecision() { - return frame.getPrecision(); + int getPrecision() { + return frame.samplePrecision; } } diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoderWrapper.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoderWrapper.java similarity index 68% rename from imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoderWrapper.java rename to imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoderWrapper.java index 2a554fdd..6fc0d9c8 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/JPEGLosslessDecoderWrapper.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGLosslessDecoderWrapper.java @@ -1,4 +1,33 @@ -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; +/* + * Copyright (c) 2016, Harald Kuhr + * Copyright (c) 2016, Herman Kroll + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.twelvemonkeys.imageio.plugins.jpeg; import javax.imageio.stream.ImageInputStream; import java.awt.image.BufferedImage; @@ -6,6 +35,7 @@ import java.awt.image.DataBufferByte; import java.awt.image.DataBufferUShort; import java.awt.image.Raster; import java.io.IOException; +import java.util.List; /** * This class provides the conversion of input data @@ -22,7 +52,7 @@ import java.io.IOException; * * @author Hermann Kroll */ -public class JPEGLosslessDecoderWrapper { +final class JPEGLosslessDecoderWrapper { /** * Decodes a JPEG Lossless stream to a {@code BufferedImage}. @@ -31,17 +61,19 @@ public class JPEGLosslessDecoderWrapper { * - 8Bit, Grayscale -> BufferedImage.TYPE_BYTE_GRAY * - 16Bit, Grayscale -> BufferedImage.TYPE_USHORT_GRAY * + * @param segments * @param input input stream which contains a jpeg lossless data * @return if successfully a BufferedImage is returned * @throws IOException is thrown if the decoder failed or a conversion is not supported */ - public BufferedImage readImage(final ImageInputStream input) throws IOException { - JPEGLosslessDecoder decoder = new JPEGLosslessDecoder(input); + BufferedImage readImage(final List segments, final ImageInputStream input) throws IOException { + JPEGLosslessDecoder decoder = new JPEGLosslessDecoder(segments, input); int[][] decoded = decoder.decode(); int width = decoder.getDimX(); int height = decoder.getDimY(); + // Single component, assumed to be Gray if (decoder.getNumComponents() == 1) { switch (decoder.getPrecision()) { case 8: @@ -52,7 +84,8 @@ public class JPEGLosslessDecoderWrapper { throw new IOException("JPEG Lossless with " + decoder.getPrecision() + " bit precision and 1 component cannot be decoded"); } } - //rgb + + // 3 components, assumed to be RGB if (decoder.getNumComponents() == 3) { switch (decoder.getPrecision()) { case 8: @@ -66,9 +99,9 @@ public class JPEGLosslessDecoderWrapper { throw new IOException("JPEG Lossless with " + decoder.getPrecision() + " bit precision and " + decoder.getNumComponents() + " component(s) cannot be decoded"); } - public Raster readRaster(final ImageInputStream input) throws IOException { + Raster readRaster(final List segments, final ImageInputStream input) throws IOException { // TODO: Can perhaps be implemented faster - return readImage(input).getRaster(); + return readImage(segments, input).getRaster(); } /** diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGProviderInfo.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGProviderInfo.java index 2865efaf..b571071a 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGProviderInfo.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/JPEGProviderInfo.java @@ -38,7 +38,7 @@ import com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfo; * @version $Id: JPEGProviderInfo.java,v 1.0 20/03/15 harald.kuhr Exp$ */ final class JPEGProviderInfo extends ReaderWriterProviderInfo { - protected JPEGProviderInfo() { + JPEGProviderInfo() { super( JPEGProviderInfo.class, new String[] {"JPEG", "jpeg", "JPG", "jpg"}, diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/QuantizationTable.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/QuantizationTable.java index 2d3a53d5..6b3dacd9 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/QuantizationTable.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/QuantizationTable.java @@ -1,38 +1,38 @@ /* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. + * Copyright (c) 2016, Harald Kuhr + * Copyright (C) 2015, Michael Martinez + * Copyright (C) 2004, Helmut Dersch + * All rights reserved. * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; -import javax.imageio.stream.ImageInputStream; +import javax.imageio.IIOException; import java.io.DataInput; import java.io.IOException; @@ -41,7 +41,7 @@ final class QuantizationTable extends Segment { private final int precision[] = new int[4]; // Quantization precision 8 or 16 private final int[] tq = new int[4]; // 1: this table is presented - protected final int quantTables[][] = new int[4][64]; // Tables + final int quantTables[][] = new int[4][64]; // Tables QuantizationTable() { super(JPEG.DQT); @@ -53,7 +53,7 @@ final class QuantizationTable extends Segment { } // TODO: Get rid of table param, make it a member? - protected void enhanceTables(final int[] table) throws IOException { + void enhanceTables(final int[] table) throws IOException { for (int t = 0; t < 4; t++) { if (tq[t] != 0) { enhanceQuantizationTable(quantTables[t], table); @@ -63,24 +63,24 @@ final class QuantizationTable extends Segment { private void enhanceQuantizationTable(final int qtab[], final int[] table) { for (int i = 0; i < 8; i++) { - qtab[table[(0 * 8) + i]] *= 90; - qtab[table[(4 * 8) + i]] *= 90; + qtab[table[ i]] *= 90; + qtab[table[(4 * 8) + i]] *= 90; qtab[table[(2 * 8) + i]] *= 118; - qtab[table[(6 * 8) + i]] *= 49; - qtab[table[(5 * 8) + i]] *= 71; - qtab[table[(1 * 8) + i]] *= 126; - qtab[table[(7 * 8) + i]] *= 25; + qtab[table[(6 * 8) + i]] *= 49; + qtab[table[(5 * 8) + i]] *= 71; + qtab[table[( 8) + i]] *= 126; + qtab[table[(7 * 8) + i]] *= 25; qtab[table[(3 * 8) + i]] *= 106; } for (int i = 0; i < 8; i++) { - qtab[table[0 + (8 * i)]] *= 90; - qtab[table[4 + (8 * i)]] *= 90; + qtab[table[( 8 * i)]] *= 90; + qtab[table[4 + (8 * i)]] *= 90; qtab[table[2 + (8 * i)]] *= 118; - qtab[table[6 + (8 * i)]] *= 49; - qtab[table[5 + (8 * i)]] *= 71; + qtab[table[6 + (8 * i)]] *= 49; + qtab[table[5 + (8 * i)]] *= 71; qtab[table[1 + (8 * i)]] *= 126; - qtab[table[7 + (8 * i)]] *= 25; + qtab[table[7 + (8 * i)]] *= 25; qtab[table[3 + (8 * i)]] *= 106; } @@ -89,8 +89,14 @@ final class QuantizationTable extends Segment { } } + @Override + public String toString() { + // TODO: Tables... + return "DQT[]"; + } + public static QuantizationTable read(final DataInput data, final int length) throws IOException { - int count = 0; // TODO: Could probably use data.getPosition for this + int count = 2; QuantizationTable table = new QuantizationTable(); while (count < length) { @@ -99,7 +105,7 @@ final class QuantizationTable extends Segment { final int t = temp & 0x0F; if (t > 3) { - throw new IOException("ERROR: Quantization table ID > 3"); + throw new IIOException("Unexpected JPEG Quantization Table Id (> 3): " + t); } table.precision[t] = temp >> 4; @@ -111,7 +117,7 @@ final class QuantizationTable extends Segment { table.precision[t] = 16; } else { - throw new IOException("ERROR: Quantization table precision error"); + throw new IIOException("Unexpected JPEG Quantization Table precision: " + table.precision[t]); } table.tq[t] = 1; @@ -119,31 +125,27 @@ final class QuantizationTable extends Segment { if (table.precision[t] == 8) { for (int i = 0; i < 64; i++) { if (count > length) { - throw new IOException("ERROR: Quantization table format error"); + throw new IIOException("JPEG Quantization Table format error"); } table.quantTables[t][i] = data.readUnsignedByte(); count++; } - -// table.enhanceQuantizationTable(table.quantTables[t], table); } else { for (int i = 0; i < 64; i++) { if (count > length) { - throw new IOException("ERROR: Quantization table format error"); + throw new IIOException("JPEG Quantization Table format error"); } table.quantTables[t][i] = data.readUnsignedShort(); count += 2; } - -// table.enhanceQuantizationTable(table.quantTables[t], table); } } if (count != length) { - throw new IOException("ERROR: Quantization table error [count!=Lq]"); + throw new IIOException("JPEG Quantization Table error, bad segment length: " + length); } return table; diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/RestartInterval.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/RestartInterval.java new file mode 100644 index 00000000..b4e73a2b --- /dev/null +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/RestartInterval.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.twelvemonkeys.imageio.plugins.jpeg; + +import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; + +import javax.imageio.IIOException; +import java.io.DataInput; +import java.io.IOException; + +/** + * RestartInterval. + * + * @author Harald Kuhr + * @author last modified by $Author: harald.kuhr$ + * @version $Id: RestartInterval.java,v 1.0 24/08/16 harald.kuhr Exp$ + */ +class RestartInterval extends Segment { + final int interval; + + private RestartInterval(int interval) { + super(JPEG.DRI); + this.interval = interval; + } + + @Override + public String toString() { + return "DRI[" + interval + "]"; + } + + public static RestartInterval read(final DataInput data, final int length) throws IOException { + if (length != 4) { + throw new IIOException("Unexpected length of DRI segment: " + length); + } + + return new RestartInterval(data.readUnsignedShort()); + } +} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Scan.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Scan.java index 5e3612e6..0de93192 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Scan.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Scan.java @@ -38,28 +38,28 @@ import java.io.IOException; import java.util.Arrays; final class Scan extends Segment { - final int selection; // Start of spectral or predictor selection - final int spectralEnd; // End of spectral selection - final int ah; - final int al; + final int spectralSelStart; // Start of spectral or predictor selection + final int spectralSelEnd; // End of spectral selection + final int approxHigh; + final int approxLow; final Component[] components; - Scan(final Component[] components, final int selection, final int spectralEnd, final int ah, final int al) { + Scan(final Component[] components, final int spectralStart, final int spectralSelEnd, final int approxHigh, final int approxLow) { super(JPEG.SOS); this.components = components; - this.selection = selection; - this.spectralEnd = spectralEnd; - this.ah = ah; - this.al = al; + this.spectralSelStart = spectralStart; + this.spectralSelEnd = spectralSelEnd; + this.approxHigh = approxHigh; + this.approxLow = approxLow; } @Override public String toString() { return String.format( - "SOS[selection: %d, spectralEnd: %d, ah: %d, al: %d, components: %s]", - selection, spectralEnd, ah, al, Arrays.toString(components) + "SOS[spectralSelStart: %d, spectralSelEnd: %d, approxHigh: %d, approxLow: %d, components: %s]", + spectralSelStart, spectralSelEnd, approxHigh, approxLow, Arrays.toString(components) ); } @@ -93,7 +93,7 @@ final class Scan extends Segment { return new Scan(components, selection, spectralEnd, temp >> 4, temp & 0x0F); } - final static class Component { + public final static class Component { final int scanCompSel; // Scan component selector final int acTabSel; // AC table selector final int dcTabSel; // DC table selector diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Segment.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Segment.java index bb57b22d..0a0d2b93 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Segment.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Segment.java @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package com.twelvemonkeys.imageio.plugins.jpeg; import com.twelvemonkeys.imageio.metadata.jpeg.JPEG; @@ -20,15 +48,12 @@ abstract class Segment { this.marker = Validate.isTrue(marker >> 8 == 0xFF, marker, "Unknown JPEG marker: 0x%04x"); } - public static Segment read(int marker, String identifier, int length, DataInput data) throws IOException { - // TODO: Fix length inconsistencies... -// System.err.print("marker: " + marker); -// System.err.println(" length: " + length); + static Segment read(int marker, String identifier, int length, DataInput data) throws IOException { switch (marker) { case JPEG.DHT: return HuffmanTable.read(data, length); case JPEG.DQT: - return QuantizationTable.read(data, length - 2); + return QuantizationTable.read(data, length); case JPEG.SOF0: case JPEG.SOF1: case JPEG.SOF2: @@ -47,6 +72,9 @@ abstract class Segment { return Scan.read(data, length); case JPEG.COM: return Comment.read(data, length); + // TODO: JPEG.DAC + case JPEG.DRI: + return RestartInterval.read(data, length); case JPEG.APP0: case JPEG.APP1: case JPEG.APP2: @@ -63,8 +91,7 @@ abstract class Segment { case JPEG.APP13: case JPEG.APP14: case JPEG.APP15: - return AppSegment.read(marker, identifier, data, length); - // TODO: JPEG.DRI? + return Application.read(marker, identifier, data, length); default: return Unknown.read(marker, length, data); } diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Unknown.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Unknown.java index 9c59e504..012eddfd 100644 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Unknown.java +++ b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/Unknown.java @@ -1,10 +1,38 @@ +/* + * Copyright (c) 2016, Harald Kuhr + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name "TwelveMonkeys" nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package com.twelvemonkeys.imageio.plugins.jpeg; import java.io.DataInput; import java.io.IOException; /** - * Unknown. + * Represents an unknown segment in the JPEG stream. * * @author Harald Kuhr * @author last modified by $Author: harald.kuhr$ @@ -19,9 +47,15 @@ final class Unknown extends Segment { this.data = data; } + @Override + public String toString() { + return String.format("Unknown[%04x, length: %d]", marker, data.length); + } + public static Segment read(int marker, int length, DataInput data) throws IOException { byte[] bytes = new byte[length - 2]; data.readFully(bytes); + return new Unknown(marker, bytes); } } diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ComponentSpec.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ComponentSpec.java deleted file mode 100644 index 3df58427..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ComponentSpec.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -public class ComponentSpec { - - protected int id; - protected int hSamp; // Horizontal sampling factor - protected int quantTableSel; // Quantization table destination selector - protected int vSamp; // Vertical -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/FrameHeader.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/FrameHeader.java deleted file mode 100644 index 2443426b..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/FrameHeader.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -import javax.imageio.stream.ImageInputStream; -import java.io.IOException; - -public class FrameHeader { - - private ComponentSpec components[]; // Components - private int dimX; // Number of samples per line - private int dimY; // Number of lines - private int numComp; // Number of component in the frame - private int precision; // Sample Precision (from the original image) - - public ComponentSpec[] getComponents() { - return components.clone(); - } - - public int getDimX() { - return dimX; - } - - public int getDimY() { - return dimY; - } - - public int getNumComponents() { - return numComp; - } - - public int getPrecision() { - return precision; - } - - protected int read(final ImageInputStream data) throws IOException { - int count = 0; - - int length = data.readUnsignedShort(); - count += 2; - - precision = data.readUnsignedByte(); - count++; - - dimY = data.readUnsignedShort(); - count += 2; - - dimX = data.readUnsignedShort(); - count += 2; - - numComp = data.readUnsignedByte(); - count++; - - components = new ComponentSpec[numComp]; - - for (int i = 0; i < numComp; i++) { - if (count > length) { - throw new IOException("ERROR: frame format error"); - } - - int cid = data.readUnsignedByte(); - count++; - - if (count >= length) { - throw new IOException("ERROR: frame format error [c>=Lf]"); - } - - int temp = data.readUnsignedByte(); - count++; - - if (components[i] == null) { - components[i] = new ComponentSpec(); - } - - components[i].id = cid; - components[i].hSamp = temp >> 4; - components[i].vSamp = temp & 0x0F; - components[i].quantTableSel = data.readUnsignedByte(); - count++; - } - - if (count != length) { - throw new IOException("ERROR: frame format error [Lf!=count]"); - } - - return 1; - } -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/HuffmanTable.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/HuffmanTable.java deleted file mode 100644 index e6517403..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/HuffmanTable.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -import javax.imageio.stream.ImageInputStream; -import java.io.IOException; - -public class HuffmanTable { - - private final int l[][][] = new int[4][2][16]; - private final int th[] = new int[4]; // 1: this table is presented - private final int v[][][][] = new int[4][2][16][200]; // tables - private final int[][] tc = new int[4][2]; // 1: this table is presented - - public static final int MSB = 0x80000000; - - public HuffmanTable() { - tc[0][0] = 0; - tc[1][0] = 0; - tc[2][0] = 0; - tc[3][0] = 0; - tc[0][1] = 0; - tc[1][1] = 0; - tc[2][1] = 0; - tc[3][1] = 0; - th[0] = 0; - th[1] = 0; - th[2] = 0; - th[3] = 0; - } - - protected int read(final ImageInputStream data, final int[][][] HuffTab) throws IOException { - int count = 0; - final int length = data.readUnsignedShort(); - count += 2; - - while (count < length) { - final int temp = data.readUnsignedByte(); - count++; - final int t = temp & 0x0F; - if (t > 3) { - throw new IOException("ERROR: Huffman table ID > 3"); - } - - final int c = temp >> 4; - if (c > 2) { - throw new IOException("ERROR: Huffman table [Table class > 2 ]"); - } - - th[t] = 1; - tc[t][c] = 1; - - for (int i = 0; i < 16; i++) { - l[t][c][i] = data.readUnsignedByte(); - count++; - } - - for (int i = 0; i < 16; i++) { - for (int j = 0; j < l[t][c][i]; j++) { - if (count > length) { - throw new IOException("ERROR: Huffman table format error [count>Lh]"); - } - v[t][c][i][j] = data.readUnsignedByte(); - count++; - } - } - } - - if (count != length) { - throw new IOException("ERROR: Huffman table format error [count!=Lf]"); - } - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 2; j++) { - if (tc[i][j] != 0) { - buildHuffTable(HuffTab[i][j], l[i][j], v[i][j]); - } - } - } - - return 1; - } - - // Build_HuffTab() - // Parameter: t table ID - // c table class ( 0 for DC, 1 for AC ) - // L[i] # of codewords which length is i - // V[i][j] Huffman Value (length=i) - // Effect: - // build up HuffTab[t][c] using L and V. - private void buildHuffTable(final int tab[], final int L[], final int V[][]) throws IOException { - int currentTable, temp; - int k; - temp = 256; - k = 0; - - for (int i = 0; i < 8; i++) { // i+1 is Code length - for (int j = 0; j < L[i]; j++) { - for (int n = 0; n < (temp >> (i + 1)); n++) { - tab[k] = V[i][j] | ((i + 1) << 8); - k++; - } - } - } - - for (int i = 1; k < 256; i++, k++) { - tab[k] = i | MSB; - } - - currentTable = 1; - k = 0; - - for (int i = 8; i < 16; i++) { // i+1 is Code length - for (int j = 0; j < L[i]; j++) { - for (int n = 0; n < (temp >> (i - 7)); n++) { - tab[(currentTable * 256) + k] = V[i][j] | ((i + 1) << 8); - k++; - } - if (k >= 256) { - if (k > 256) { - throw new IOException("ERROR: Huffman table error(1)!"); - } - k = 0; - currentTable++; - } - } - } - } -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/QuantizationTable.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/QuantizationTable.java deleted file mode 100644 index dbad4683..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/QuantizationTable.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -import javax.imageio.stream.ImageInputStream; -import java.io.IOException; - -public class QuantizationTable { - - private final int precision[] = new int[4]; // Quantization precision 8 or 16 - private final int[] tq = new int[4]; // 1: this table is presented - - protected final int quantTables[][] = new int[4][64]; // Tables - - public QuantizationTable() { - tq[0] = 0; - tq[1] = 0; - tq[2] = 0; - tq[3] = 0; - } - - protected int read(final ImageInputStream data, final int[] table) throws IOException { - int count = 0; - final int length = data.readUnsignedShort(); - count += 2; - - while (count < length) { - final int temp = data.readUnsignedByte(); - count++; - final int t = temp & 0x0F; - - if (t > 3) { - throw new IOException("ERROR: Quantization table ID > 3"); - } - - precision[t] = temp >> 4; - - if (precision[t] == 0) { - precision[t] = 8; - } - else if (precision[t] == 1) { - precision[t] = 16; - } - else { - throw new IOException("ERROR: Quantization table precision error"); - } - - tq[t] = 1; - - if (precision[t] == 8) { - for (int i = 0; i < 64; i++) { - if (count > length) { - throw new IOException("ERROR: Quantization table format error"); - } - - quantTables[t][i] = data.readUnsignedByte(); - count++; - } - - enhanceQuantizationTable(quantTables[t], table); - } - else { - for (int i = 0; i < 64; i++) { - if (count > length) { - throw new IOException("ERROR: Quantization table format error"); - } - - quantTables[t][i] = data.readUnsignedShort(); - count += 2; - } - - enhanceQuantizationTable(quantTables[t], table); - } - } - - if (count != length) { - throw new IOException("ERROR: Quantization table error [count!=Lq]"); - } - - return 1; - } - - private void enhanceQuantizationTable(final int qtab[], final int[] table) { - for (int i = 0; i < 8; i++) { - qtab[table[(0 * 8) + i]] *= 90; - qtab[table[(4 * 8) + i]] *= 90; - qtab[table[(2 * 8) + i]] *= 118; - qtab[table[(6 * 8) + i]] *= 49; - qtab[table[(5 * 8) + i]] *= 71; - qtab[table[(1 * 8) + i]] *= 126; - qtab[table[(7 * 8) + i]] *= 25; - qtab[table[(3 * 8) + i]] *= 106; - } - - for (int i = 0; i < 8; i++) { - qtab[table[0 + (8 * i)]] *= 90; - qtab[table[4 + (8 * i)]] *= 90; - qtab[table[2 + (8 * i)]] *= 118; - qtab[table[6 + (8 * i)]] *= 49; - qtab[table[5 + (8 * i)]] *= 71; - qtab[table[1 + (8 * i)]] *= 126; - qtab[table[7 + (8 * i)]] *= 25; - qtab[table[3 + (8 * i)]] *= 106; - } - - for (int i = 0; i < 64; i++) { - qtab[i] >>= 6; - } - } -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanComponent.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanComponent.java deleted file mode 100644 index 94fc6cf9..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanComponent.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -public class ScanComponent { - - private int acTabSel; // AC table selector - private int dcTabSel; // DC table selector - private int scanCompSel; // Scan component selector - - public int getAcTabSel() { - return acTabSel; - } - - public int getDcTabSel() { - return dcTabSel; - } - - public int getScanCompSel() { - return scanCompSel; - } - - public void setAcTabSel(final int acTabSel) { - this.acTabSel = acTabSel; - } - - public void setDcTabSel(final int dcTabSel) { - this.dcTabSel = dcTabSel; - } - - public void setScanCompSel(final int scanCompSel) { - this.scanCompSel = scanCompSel; - } -} diff --git a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanHeader.java b/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanHeader.java deleted file mode 100644 index be52e20b..00000000 --- a/imageio/imageio-jpeg/src/main/java/com/twelvemonkeys/imageio/plugins/jpeg/lossless/ScanHeader.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2015 Michael Martinez - * Changes: Added support for selection values 2-7, fixed minor bugs & - * warnings, split into multiple class files, and general clean up. - * - * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT. - */ - -/* - * Copyright (C) Helmut Dersch - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package com.twelvemonkeys.imageio.plugins.jpeg.lossless; - -import javax.imageio.stream.ImageInputStream; -import java.io.IOException; - -public class ScanHeader { - - private int ah; - private int al; - private int numComp; // Number of components in the scan - private int selection; // Start of spectral or predictor selection - private int spectralEnd; // End of spectral selection - - protected ScanComponent components[]; - - public int getAh() { - return ah; - } - - public int getAl() { - return al; - } - - public int getNumComponents() { - return numComp; - } - - public int getSelection() { - return selection; - } - - public int getSpectralEnd() { - return spectralEnd; - } - - public void setAh(final int ah) { - this.ah = ah; - } - - public void setAl(final int al) { - this.al = al; - } - - public void setSelection(final int selection) { - this.selection = selection; - } - - public void setSpectralEnd(final int spectralEnd) { - this.spectralEnd = spectralEnd; - } - - protected int read(final ImageInputStream data) throws IOException { - int count = 0; - final int length = data.readUnsignedShort(); - count += 2; - - numComp = data.readUnsignedByte(); - count++; - - components = new ScanComponent[numComp]; - - for (int i = 0; i < numComp; i++) { - components[i] = new ScanComponent(); - - if (count > length) { - throw new IOException("ERROR: scan header format error"); - } - - components[i].setScanCompSel(data.readUnsignedByte()); - count++; - - final int temp = data.readUnsignedByte(); - count++; - - components[i].setDcTabSel(temp >> 4); - components[i].setAcTabSel(temp & 0x0F); - } - - setSelection(data.readUnsignedByte()); - count++; - - setSpectralEnd(data.readUnsignedByte()); - count++; - - final int temp = data.readUnsignedByte(); - setAh(temp >> 4); - setAl(temp & 0x0F); - count++; - - if (count != length) { - throw new IOException("ERROR: scan header format error [count!=Ns]"); - } - - return 1; - } -}