Merge branch 'master' into camera-raw
@@ -6,22 +6,24 @@ 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.
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
* 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 of the copyright holder 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 HOLDER 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.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.4-SNAPSHOT</version>
|
||||
<version>3.8.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
||||
@@ -12,6 +12,10 @@
|
||||
ImageIO plugin for Joint Photographer Expert Group images (JPEG/JFIF).
|
||||
</description>
|
||||
|
||||
<properties>
|
||||
<project.jpms.module.name>com.twelvemonkeys.imageio.jpeg</project.jpms.module.name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
@@ -21,6 +25,7 @@
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio-core</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -36,7 +38,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Application.
|
||||
* An application (APPn) segment in the JPEG stream.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: harald.kuhr$
|
||||
@@ -76,7 +78,9 @@ class Application extends Segment {
|
||||
if ("JFXX".equals(identifier)) {
|
||||
return JFXX.read(data, length);
|
||||
}
|
||||
// TODO: Exif?
|
||||
if ("Exif".equals(identifier)) {
|
||||
return EXIF.read(data, length);
|
||||
}
|
||||
case JPEG.APP2:
|
||||
// ICC_PROFILE
|
||||
if ("ICC_PROFILE".equals(identifier)) {
|
||||
@@ -90,7 +94,7 @@ class Application extends Segment {
|
||||
|
||||
default:
|
||||
// Generic APPn segment
|
||||
byte[] bytes = new byte[length - 2];
|
||||
byte[] bytes = new byte[Math.max(0, length - 2)];
|
||||
data.readFully(bytes);
|
||||
return new Application(marker, identifier, bytes);
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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 of the copyright holder 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 HOLDER 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.imageio.stream.ByteArrayImageInputStream;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* An EXIF segment.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JFIFSegment.java,v 1.0 23.04.12 16:52 haraldk Exp$
|
||||
*/
|
||||
final class EXIF extends Application {
|
||||
EXIF(byte[] data) {
|
||||
super(JPEG.APP1, "Exif", data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("APP1/Exif, length: %d", data.length);
|
||||
}
|
||||
|
||||
ImageInputStream exifData() {
|
||||
// Identifier is "Exif\0" + 1 byte pad
|
||||
int offset = identifier.length() + 2;
|
||||
return new ByteArrayImageInputStream(data, offset, data.length - offset);
|
||||
}
|
||||
|
||||
public static EXIF read(final DataInput data, int length) throws IOException {
|
||||
if (length < 2 + 6) {
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[length - 2];
|
||||
data.readFully(bytes);
|
||||
|
||||
return new EXIF(bytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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 of the copyright holder 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 HOLDER 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.color.YCbCrConverter;
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.JPEGThumbnailReader;
|
||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* EXIFThumbnail
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: EXIFThumbnail.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class EXIFThumbnail {
|
||||
private EXIFThumbnail() {
|
||||
}
|
||||
|
||||
static ThumbnailReader from(final EXIF segment, final CompoundDirectory exif, final ImageReader jpegThumbnailReader) throws IOException {
|
||||
if (segment != null && exif != null && exif.directoryCount() >= 2) {
|
||||
ImageInputStream stream = segment.exifData(); // NOTE This is an in-memory stream and must not be closed...
|
||||
|
||||
Directory ifd1 = exif.getDirectory(1);
|
||||
|
||||
// Compression: 1 = no compression, 6 = JPEG compression (default)
|
||||
Entry compressionEntry = ifd1.getEntryById(TIFF.TAG_COMPRESSION);
|
||||
int compression = compressionEntry == null ? 6 : ((Number) compressionEntry.getValue()).intValue();
|
||||
|
||||
switch (compression) {
|
||||
case 1:
|
||||
return createUncompressedThumbnailReader(stream, ifd1);
|
||||
case 6:
|
||||
return createJPEGThumbnailReader(segment, jpegThumbnailReader, stream, ifd1);
|
||||
default:
|
||||
throw new IIOException("EXIF IFD with unknown thumbnail compression (expected 1 or 6): " + compression);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static UncompressedThumbnailReader createUncompressedThumbnailReader(ImageInputStream stream, Directory ifd1) throws IOException {
|
||||
Entry stripOffEntry = ifd1.getEntryById(TIFF.TAG_STRIP_OFFSETS);
|
||||
Entry width = ifd1.getEntryById(TIFF.TAG_IMAGE_WIDTH);
|
||||
Entry height = ifd1.getEntryById(TIFF.TAG_IMAGE_HEIGHT);
|
||||
|
||||
if (stripOffEntry != null && width != null && height != null) {
|
||||
Entry bitsPerSample = ifd1.getEntryById(TIFF.TAG_BITS_PER_SAMPLE);
|
||||
Entry samplesPerPixel = ifd1.getEntryById(TIFF.TAG_SAMPLES_PER_PIXEL);
|
||||
Entry photometricInterpretation = ifd1.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION);
|
||||
|
||||
// Required
|
||||
int w = ((Number) width.getValue()).intValue();
|
||||
int h = ((Number) height.getValue()).intValue();
|
||||
|
||||
if (bitsPerSample != null && !Arrays.equals((int[]) bitsPerSample.getValue(), new int[] {8, 8, 8})) {
|
||||
throw new IIOException("Unknown BitsPerSample value for uncompressed EXIF thumbnail (expected [8, 8, 8]): " + bitsPerSample.getValueAsString());
|
||||
}
|
||||
|
||||
if (samplesPerPixel != null && ((Number) samplesPerPixel.getValue()).intValue() != 3) {
|
||||
throw new IIOException("Unknown SamplesPerPixel value for uncompressed EXIF thumbnail (expected 3): " + samplesPerPixel.getValueAsString());
|
||||
}
|
||||
|
||||
int interpretation = photometricInterpretation != null ? ((Number) photometricInterpretation.getValue()).intValue() : 2;
|
||||
long stripOffset = ((Number) stripOffEntry.getValue()).longValue();
|
||||
|
||||
int thumbLength = w * h * 3;
|
||||
if (stripOffset >= 0 && stripOffset + thumbLength <= stream.length()) {
|
||||
// Read raw image data, either RGB or YCbCr
|
||||
stream.seek(stripOffset);
|
||||
byte[] thumbData = new byte[thumbLength];
|
||||
stream.readFully(thumbData);
|
||||
|
||||
switch (interpretation) {
|
||||
case 2:
|
||||
// RGB
|
||||
break;
|
||||
case 6:
|
||||
// YCbCr
|
||||
for (int i = 0; i < thumbLength; i += 3) {
|
||||
YCbCrConverter.convertYCbCr2RGB(thumbData, thumbData, i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IIOException("Unknown PhotometricInterpretation value for uncompressed EXIF thumbnail (expected 2 or 6): " + interpretation);
|
||||
}
|
||||
|
||||
return new UncompressedThumbnailReader(w, h, thumbData);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IIOException("EXIF IFD with empty or incomplete uncompressed thumbnail");
|
||||
}
|
||||
|
||||
private static JPEGThumbnailReader createJPEGThumbnailReader(EXIF exif, ImageReader jpegThumbnailReader, ImageInputStream stream, Directory ifd1) throws IOException {
|
||||
Entry jpegOffEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
|
||||
if (jpegOffEntry != null) {
|
||||
Entry jpegLenEntry = ifd1.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
|
||||
|
||||
// Test if Exif thumbnail is contained within the Exif segment (offset + length <= segment.length)
|
||||
long jpegOffset = ((Number) jpegOffEntry.getValue()).longValue();
|
||||
long jpegLength = jpegLenEntry != null ? ((Number) jpegLenEntry.getValue()).longValue() : -1;
|
||||
|
||||
if (jpegLength > 0 && jpegOffset + jpegLength <= exif.data.length) {
|
||||
// Verify first bytes are FFD8
|
||||
stream.seek(jpegOffset);
|
||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
if (stream.readUnsignedShort() == JPEG.SOI) {
|
||||
return new JPEGThumbnailReader(jpegThumbnailReader, stream, jpegOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IIOException("EXIF IFD with empty or incomplete JPEG thumbnail");
|
||||
}
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.color.YCbCrConverter;
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.SequenceInputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* EXIFThumbnail
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: EXIFThumbnail.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class EXIFThumbnailReader extends ThumbnailReader {
|
||||
private final ImageReader reader;
|
||||
private final Directory ifd;
|
||||
private final ImageInputStream stream;
|
||||
private final int compression;
|
||||
|
||||
private transient SoftReference<BufferedImage> cachedThumbnail;
|
||||
|
||||
EXIFThumbnailReader(final ThumbnailReadProgressListener progressListener, final ImageReader jpegReader, final int imageIndex, final int thumbnailIndex, final Directory ifd, final ImageInputStream stream) {
|
||||
super(progressListener, imageIndex, thumbnailIndex);
|
||||
this.reader = Validate.notNull(jpegReader);
|
||||
this.ifd = ifd;
|
||||
this.stream = stream;
|
||||
|
||||
Entry compression = ifd.getEntryById(TIFF.TAG_COMPRESSION);
|
||||
|
||||
this.compression = compression != null ? ((Number) compression.getValue()).intValue() : 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage read() throws IOException {
|
||||
if (compression == 1) { // 1 = no compression
|
||||
processThumbnailStarted();
|
||||
BufferedImage thumbnail = readUncompressed();
|
||||
processThumbnailProgress(100f);
|
||||
processThumbnailComplete();
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
else if (compression == 6) { // 6 = JPEG compression
|
||||
processThumbnailStarted();
|
||||
BufferedImage thumbnail = readJPEGCached(true);
|
||||
processThumbnailProgress(100f);
|
||||
processThumbnailComplete();
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
else {
|
||||
throw new IIOException("Unsupported EXIF thumbnail compression: " + compression);
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage readJPEGCached(final boolean pixelsExposed) throws IOException {
|
||||
BufferedImage thumbnail = cachedThumbnail != null ? cachedThumbnail.get() : null;
|
||||
|
||||
if (thumbnail == null) {
|
||||
thumbnail = readJPEG();
|
||||
}
|
||||
|
||||
cachedThumbnail = pixelsExposed ? null : new SoftReference<>(thumbnail);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
private BufferedImage readJPEG() throws IOException {
|
||||
// IFD1 should contain JPEG offset for JPEG thumbnail
|
||||
Entry jpegOffset = ifd.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT);
|
||||
|
||||
if (jpegOffset != null) {
|
||||
stream.seek(((Number) jpegOffset.getValue()).longValue());
|
||||
InputStream input = IIOUtil.createStreamAdapter(stream);
|
||||
|
||||
// For certain EXIF files (encoded with TIFF.TAG_YCBCR_POSITIONING = 2?), we need
|
||||
// EXIF information to read the thumbnail correctly (otherwise the colors are messed up).
|
||||
// Probably related to: http://bugs.sun.com/view_bug.do?bug_id=4881314
|
||||
|
||||
// HACK: Splice empty EXIF information into the thumbnail stream
|
||||
byte[] fakeEmptyExif = {
|
||||
// SOI (from original data)
|
||||
(byte) input.read(), (byte) input.read(),
|
||||
// APP1 + len (016) + 'Exif' + 0-term + pad
|
||||
(byte) 0xFF, (byte) 0xE1, 0, 16, 'E', 'x', 'i', 'f', 0, 0,
|
||||
// Big-endian BOM (MM), TIFF magic (042), offset (0000)
|
||||
'M', 'M', 0, 42, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
input = new SequenceInputStream(new ByteArrayInputStream(fakeEmptyExif), input);
|
||||
|
||||
try {
|
||||
|
||||
try (MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input)) {
|
||||
return readJPEGThumbnail(reader, stream);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IIOException("Missing JPEGInterchangeFormat tag for JPEG compressed EXIF thumbnail");
|
||||
}
|
||||
|
||||
private BufferedImage readUncompressed() throws IOException {
|
||||
// Read ImageWidth, ImageLength (height) and BitsPerSample (=8 8 8, always)
|
||||
// PhotometricInterpretation (2=RGB, 6=YCbCr), SamplesPerPixel (=3, always),
|
||||
Entry width = ifd.getEntryById(TIFF.TAG_IMAGE_WIDTH);
|
||||
Entry height = ifd.getEntryById(TIFF.TAG_IMAGE_HEIGHT);
|
||||
|
||||
if (width == null || height == null) {
|
||||
throw new IIOException("Missing dimensions for uncompressed EXIF thumbnail");
|
||||
}
|
||||
|
||||
Entry bitsPerSample = ifd.getEntryById(TIFF.TAG_BITS_PER_SAMPLE);
|
||||
Entry samplesPerPixel = ifd.getEntryById(TIFF.TAG_SAMPLES_PER_PIXEL);
|
||||
Entry photometricInterpretation = ifd.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION);
|
||||
|
||||
// Required
|
||||
int w = ((Number) width.getValue()).intValue();
|
||||
int h = ((Number) height.getValue()).intValue();
|
||||
|
||||
if (bitsPerSample != null) {
|
||||
int[] bpp = (int[]) bitsPerSample.getValue();
|
||||
if (!Arrays.equals(bpp, new int[] {8, 8, 8})) {
|
||||
throw new IIOException("Unknown BitsPerSample value for uncompressed EXIF thumbnail (expected [8, 8, 8]): " + bitsPerSample.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
if (samplesPerPixel != null && (Integer) samplesPerPixel.getValue() != 3) {
|
||||
throw new IIOException("Unknown SamplesPerPixel value for uncompressed EXIF thumbnail (expected 3): " + samplesPerPixel.getValueAsString());
|
||||
}
|
||||
|
||||
int interpretation = photometricInterpretation != null ? ((Number) photometricInterpretation.getValue()).intValue() : 2;
|
||||
|
||||
// IFD1 should contain strip offsets for uncompressed images
|
||||
Entry offset = ifd.getEntryById(TIFF.TAG_STRIP_OFFSETS);
|
||||
if (offset != null) {
|
||||
stream.seek(((Number) offset.getValue()).longValue());
|
||||
|
||||
// Read raw image data, either RGB or YCbCr
|
||||
int thumbSize = w * h * 3;
|
||||
byte[] thumbData = JPEGImageReader.readFully(stream, thumbSize);
|
||||
|
||||
switch (interpretation) {
|
||||
case 2:
|
||||
// RGB
|
||||
break;
|
||||
case 6:
|
||||
// YCbCr
|
||||
for (int i = 0; i < thumbSize; i += 3) {
|
||||
YCbCrConverter.convertYCbCr2RGB(thumbData, thumbData, i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IIOException("Unknown PhotometricInterpretation value for uncompressed EXIF thumbnail (expected 2 or 6): " + interpretation);
|
||||
}
|
||||
|
||||
return ThumbnailReader.readRawThumbnail(thumbData, thumbSize, 0, w, h);
|
||||
}
|
||||
|
||||
throw new IIOException("Missing StripOffsets tag for uncompressed EXIF thumbnail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() throws IOException {
|
||||
if (compression == 1) { // 1 = no compression
|
||||
Entry width = ifd.getEntryById(TIFF.TAG_IMAGE_WIDTH);
|
||||
|
||||
if (width == null) {
|
||||
throw new IIOException("Missing dimensions for uncompressed EXIF thumbnail");
|
||||
}
|
||||
|
||||
return ((Number) width.getValue()).intValue();
|
||||
}
|
||||
else if (compression == 6) { // 6 = JPEG compression
|
||||
return readJPEGCached(false).getWidth();
|
||||
}
|
||||
else {
|
||||
throw new IIOException("Unsupported EXIF thumbnail compression (expected 1 or 6): " + compression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
if (compression == 1) { // 1 = no compression
|
||||
Entry height = ifd.getEntryById(TIFF.TAG_IMAGE_HEIGHT);
|
||||
|
||||
if (height == null) {
|
||||
throw new IIOException("Missing dimensions for uncompressed EXIF thumbnail");
|
||||
}
|
||||
|
||||
return ((Number) height.getValue()).intValue();
|
||||
}
|
||||
else if (compression == 6) { // 6 = JPEG compression
|
||||
return readJPEGCached(false).getHeight();
|
||||
}
|
||||
else {
|
||||
throw new IIOException("Unsupported EXIF thumbnail compression (expected 1 or 6): " + compression);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -37,8 +39,9 @@ import java.awt.image.*;
|
||||
|
||||
/**
|
||||
* This class performs a pixel by pixel conversion of the source image, from CMYK to RGB.
|
||||
* <p/>
|
||||
* <p>
|
||||
* The conversion is fast, but performed without any color space conversion.
|
||||
*</p>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
@@ -59,6 +62,7 @@ class FastCMYKToRGB implements /*BufferedImageOp,*/ RasterOp {
|
||||
* @return {@code dest}, or a new {@link WritableRaster} if {@code dest} is {@code null}.
|
||||
* @throws IllegalArgumentException if {@code src} and {@code dest} refer to the same object
|
||||
*/
|
||||
@Override
|
||||
public WritableRaster filter(Raster src, WritableRaster dest) {
|
||||
Validate.notNull(src, "src may not be null");
|
||||
// TODO: Why not allow same raster, if converting to 4 byte ABGR?
|
||||
@@ -139,10 +143,12 @@ class FastCMYKToRGB implements /*BufferedImageOp,*/ RasterOp {
|
||||
rgb[2] = (byte) (255 - (((cmyk[2] & 0xFF) * (255 - k) / 255) + k));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBounds2D(Raster src) {
|
||||
return src.getBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WritableRaster createCompatibleDestRaster(final Raster src) {
|
||||
// WHAT?? This code no longer work for JRE 7u45+... JRE bug?!
|
||||
// Raster child = src.createChild(0, 0, src.getWidth(), src.getHeight(), 0, 0, new int[] {0, 1, 2});
|
||||
@@ -150,10 +156,11 @@ class FastCMYKToRGB implements /*BufferedImageOp,*/ RasterOp {
|
||||
|
||||
// This is a workaround for the above code that no longer works.
|
||||
// It wil use 25% more memory, but it seems to work...
|
||||
WritableRaster raster = src.createCompatibleWritableRaster();
|
||||
return raster.createWritableChild(0, 0, src.getWidth(), src.getHeight(), 0, 0, new int[] {0, 1, 2});
|
||||
return src.createCompatibleWritableRaster()
|
||||
.createWritableChild(0, 0, src.getWidth(), src.getHeight(), 0, 0, new int[] {0, 1, 2});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
|
||||
if (dstPt == null) {
|
||||
dstPt = new Point2D.Double(srcPt.getX(), srcPt.getY());
|
||||
@@ -165,6 +172,7 @@ class FastCMYKToRGB implements /*BufferedImageOp,*/ RasterOp {
|
||||
return dstPt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -6,26 +6,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -33,27 +35,27 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
|
||||
final class HuffmanTable extends Segment {
|
||||
|
||||
private final int l[][][] = new int[4][2][16];
|
||||
private final int th[] = new int[4]; // 1: this table is present
|
||||
final int v[][][][] = new int[4][2][16][200]; // tables
|
||||
final int[][] tc = new int[4][2]; // 1: this table is present
|
||||
private final short[][][] l = new short[4][2][16];
|
||||
private final short[][][][] v = new short[4][2][16][200]; // tables
|
||||
private final boolean[][] tc = new boolean[4][2]; // 1: this table is present
|
||||
|
||||
static final int MSB = 0x80000000;
|
||||
private static final int MSB = 0x80000000;
|
||||
|
||||
private HuffmanTable() {
|
||||
super(JPEG.DHT);
|
||||
}
|
||||
|
||||
void buildHuffTables(final int[][][] HuffTab) throws IOException {
|
||||
void buildHuffTables(final int[][][] huffTab) throws IOException {
|
||||
for (int t = 0; t < 4; t++) {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
if (tc[t][c] != 0) {
|
||||
buildHuffTable(HuffTab[t][c], l[t][c], v[t][c]);
|
||||
if (tc[t][c]) {
|
||||
buildHuffTable(huffTab[t][c], l[t][c], v[t][c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +68,7 @@ final class HuffmanTable extends Segment {
|
||||
// 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 {
|
||||
private void buildHuffTable(final int[] tab, final short[] L, final short[][] V) throws IOException {
|
||||
int temp = 256;
|
||||
int k = 0;
|
||||
|
||||
@@ -110,7 +112,7 @@ final class HuffmanTable extends Segment {
|
||||
|
||||
for (int t = 0; t < tc.length; t++) {
|
||||
for (int c = 0; c < tc[t].length; c++) {
|
||||
if (tc[t][c] != 0) {
|
||||
if (tc[t][c]) {
|
||||
if (builder.length() > 4) {
|
||||
builder.append(", ");
|
||||
}
|
||||
@@ -147,11 +149,10 @@ final class HuffmanTable extends Segment {
|
||||
throw new IIOException("Unexpected JPEG Huffman Table class (> 2): " + c);
|
||||
}
|
||||
|
||||
table.th[t] = 1;
|
||||
table.tc[t][c] = 1;
|
||||
table.tc[t][c] = true;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
table.l[t][c][i] = data.readUnsignedByte();
|
||||
table.l[t][c][i] = (short) data.readUnsignedByte();
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -160,7 +161,7 @@ final class HuffmanTable extends Segment {
|
||||
if (count > length) {
|
||||
throw new IIOException("JPEG Huffman Table format error");
|
||||
}
|
||||
table.v[t][c][i][j] = data.readUnsignedByte();
|
||||
table.v[t][c][i][j] = (short) data.readUnsignedByte();
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -172,4 +173,41 @@ final class HuffmanTable extends Segment {
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
public boolean isPresent(int tableId, int tableClass) {
|
||||
return tc[tableId][tableClass];
|
||||
}
|
||||
|
||||
private short[] lengths(int tableId, int tableClass) {
|
||||
// TODO: Consider stripping the 0s?
|
||||
return l[tableId][tableClass];
|
||||
}
|
||||
|
||||
private short[] tables(int tableId, int tableClass) {
|
||||
// Find sum of lengths
|
||||
short[] lengths = lengths(tableId, tableClass);
|
||||
|
||||
int sumOfLengths = 0;
|
||||
for (int length : lengths) {
|
||||
sumOfLengths += length;
|
||||
}
|
||||
|
||||
// Flatten the tables
|
||||
short[] tables = new short[sumOfLengths];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
short[] table = v[tableId][tableClass][i];
|
||||
short length = lengths[i];
|
||||
|
||||
System.arraycopy(table, 0, tables, pos, length);
|
||||
pos += length;
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
JPEGHuffmanTable toNativeTable(int tableId, int tableClass) {
|
||||
return new JPEGHuffmanTable(lengths(tableId, tableClass), tables(tableId, tableClass));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -36,7 +38,7 @@ import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* JFIFSegment
|
||||
* A JFIF segment.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
@@ -52,8 +54,8 @@ final class JFIF extends Application {
|
||||
final int yThumbnail;
|
||||
final byte[] thumbnail;
|
||||
|
||||
private JFIF(int majorVersion, int minorVersion, int units, int xDensity, int yDensity, int xThumbnail, int yThumbnail, byte[] thumbnail, byte[] data) {
|
||||
super(JPEG.APP0, "JFIF", data);
|
||||
JFIF(int majorVersion, int minorVersion, int units, int xDensity, int yDensity, int xThumbnail, int yThumbnail, byte[] thumbnail) {
|
||||
super(JPEG.APP0, "JFIF", new byte[5 + 9 + (thumbnail != null ? thumbnail.length : 0)]);
|
||||
|
||||
this.majorVersion = majorVersion;
|
||||
this.minorVersion = minorVersion;
|
||||
@@ -96,7 +98,7 @@ final class JFIF extends Application {
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
data.readFully(new byte[5]);
|
||||
data.readFully(new byte[5]); // Skip "JFIF\0"
|
||||
|
||||
byte[] bytes = new byte[length - 2 - 5];
|
||||
data.readFully(bytes);
|
||||
@@ -113,8 +115,7 @@ final class JFIF extends Application {
|
||||
buffer.getShort() & 0xffff,
|
||||
x = buffer.get() & 0xff,
|
||||
y = buffer.get() & 0xff,
|
||||
getBytes(buffer, Math.min(buffer.remaining(), x * y * 3)),
|
||||
bytes
|
||||
getBytes(buffer, Math.min(buffer.remaining(), x * y * 3))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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 of the copyright holder 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 HOLDER 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.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JFIFThumbnail
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JFIFThumbnail.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class JFIFThumbnail {
|
||||
private JFIFThumbnail() {
|
||||
}
|
||||
|
||||
static ThumbnailReader from(final JFIF segment) throws IOException {
|
||||
if (segment != null && segment.xThumbnail > 0 && segment.yThumbnail > 0) {
|
||||
if (segment.thumbnail == null || segment.thumbnail.length < segment.xThumbnail * segment.yThumbnail) {
|
||||
throw new IIOException("Truncated JFIF thumbnail");
|
||||
}
|
||||
|
||||
return new UncompressedThumbnailReader(segment.xThumbnail, segment.yThumbnail, segment.thumbnail);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JFIFThumbnailReader
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JFIFThumbnailReader.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class JFIFThumbnailReader extends ThumbnailReader {
|
||||
private final JFIF segment;
|
||||
|
||||
JFIFThumbnailReader(final ThumbnailReadProgressListener progressListener, final int imageIndex, final int thumbnailIndex, final JFIF segment) {
|
||||
super(progressListener, imageIndex, thumbnailIndex);
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage read() {
|
||||
processThumbnailStarted();
|
||||
BufferedImage thumbnail = readRawThumbnail(segment.thumbnail, segment.thumbnail.length, 0, segment.xThumbnail, segment.yThumbnail);
|
||||
processThumbnailProgress(100f);
|
||||
processThumbnailComplete();
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() throws IOException {
|
||||
return segment.xThumbnail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
return segment.yThumbnail;
|
||||
}
|
||||
}
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -33,7 +35,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* JFXXSegment
|
||||
* A JFXX segment (aka JFIF extension segment).
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
@@ -47,8 +49,8 @@ final class JFXX extends Application {
|
||||
final int extensionCode;
|
||||
final byte[] thumbnail;
|
||||
|
||||
private JFXX(final int extensionCode, final byte[] thumbnail, final byte[] data) {
|
||||
super(com.twelvemonkeys.imageio.metadata.jpeg.JPEG.APP0, "JFXX", data);
|
||||
JFXX(final int extensionCode, final byte[] thumbnail) {
|
||||
super(com.twelvemonkeys.imageio.metadata.jpeg.JPEG.APP0, "JFXX", new byte[1 + (thumbnail != null ? thumbnail.length : 0)]);
|
||||
|
||||
this.extensionCode = extensionCode;
|
||||
this.thumbnail = thumbnail;
|
||||
@@ -80,8 +82,7 @@ final class JFXX extends Application {
|
||||
|
||||
return new JFXX(
|
||||
bytes[0] & 0xff,
|
||||
bytes.length - 1 > 0 ? Arrays.copyOfRange(bytes, 1, bytes.length - 1) : null,
|
||||
bytes
|
||||
bytes.length - 1 > 0 ? Arrays.copyOfRange(bytes, 1, bytes.length - 1) : null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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 of the copyright holder 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 HOLDER 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.imageio.plugins.jpeg.ThumbnailReader.IndexedThumbnailReader;
|
||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.JPEGThumbnailReader;
|
||||
import com.twelvemonkeys.imageio.plugins.jpeg.ThumbnailReader.UncompressedThumbnailReader;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* JFXXThumbnailReader
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JFXXThumbnailReader.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class JFXXThumbnail {
|
||||
|
||||
private JFXXThumbnail() {
|
||||
}
|
||||
|
||||
static ThumbnailReader from(final JFXX segment, final ImageReader thumbnailReader) throws IOException {
|
||||
if (segment != null) {
|
||||
if (segment.thumbnail != null && segment.thumbnail.length > 2) {
|
||||
switch (segment.extensionCode) {
|
||||
case JFXX.JPEG:
|
||||
if (((segment.thumbnail[0] & 0xff) << 8 | segment.thumbnail[1] & 0xff) == JPEG.SOI) {
|
||||
return new JPEGThumbnailReader(thumbnailReader, new ByteArrayImageInputStream(segment.thumbnail), 0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case JFXX.INDEXED:
|
||||
int w = segment.thumbnail[0] & 0xff;
|
||||
int h = segment.thumbnail[1] & 0xff;
|
||||
|
||||
if (segment.thumbnail.length >= 2 + 768 + w * h) {
|
||||
return new IndexedThumbnailReader(w, h, segment.thumbnail, 2, segment.thumbnail, 2 + 768);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case JFXX.RGB:
|
||||
w = segment.thumbnail[0] & 0xff;
|
||||
h = segment.thumbnail[1] & 0xff;
|
||||
|
||||
if (segment.thumbnail.length >= 2 + w * h * 3) {
|
||||
return new UncompressedThumbnailReader(w, h, segment.thumbnail, 2);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IIOException(String.format("Unknown JFXX extension code: %d, ignoring thumbnail", segment.extensionCode));
|
||||
}
|
||||
}
|
||||
|
||||
throw new IIOException("JFXX segment truncated, ignoring thumbnail");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.image.InverseColorMapIndexColorModel;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
/**
|
||||
* JFXXThumbnailReader
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JFXXThumbnailReader.java,v 1.0 18.04.12 12:19 haraldk Exp$
|
||||
*/
|
||||
final class JFXXThumbnailReader extends ThumbnailReader {
|
||||
|
||||
private final ImageReader reader;
|
||||
private final JFXX segment;
|
||||
|
||||
private transient SoftReference<BufferedImage> cachedThumbnail;
|
||||
|
||||
JFXXThumbnailReader(final ThumbnailReadProgressListener progressListener, final ImageReader jpegReader, final int imageIndex, final int thumbnailIndex, final JFXX segment) {
|
||||
super(progressListener, imageIndex, thumbnailIndex);
|
||||
this.reader = Validate.notNull(jpegReader);
|
||||
this.segment = segment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage read() throws IOException {
|
||||
processThumbnailStarted();
|
||||
|
||||
BufferedImage thumbnail;
|
||||
switch (segment.extensionCode) {
|
||||
case JFXX.JPEG:
|
||||
thumbnail = readJPEGCached(true);
|
||||
break;
|
||||
case JFXX.INDEXED:
|
||||
thumbnail = readIndexed();
|
||||
break;
|
||||
case JFXX.RGB:
|
||||
thumbnail = readRGB();
|
||||
break;
|
||||
default:
|
||||
throw new IIOException(String.format("Unsupported JFXX extension code: %d", segment.extensionCode));
|
||||
}
|
||||
|
||||
processThumbnailProgress(100f);
|
||||
processThumbnailComplete();
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
IIOMetadata readMetadata() throws IOException {
|
||||
ImageInputStream input = new ByteArrayImageInputStream(segment.thumbnail);
|
||||
|
||||
try {
|
||||
reader.setInput(input);
|
||||
|
||||
return reader.getImageMetadata(0);
|
||||
}
|
||||
finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage readJPEGCached(boolean pixelsExposed) throws IOException {
|
||||
BufferedImage thumbnail = cachedThumbnail != null ? cachedThumbnail.get() : null;
|
||||
|
||||
if (thumbnail == null) {
|
||||
ImageInputStream stream = new ByteArrayImageInputStream(segment.thumbnail);
|
||||
try {
|
||||
thumbnail = readJPEGThumbnail(reader, stream);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
cachedThumbnail = pixelsExposed ? null : new SoftReference<BufferedImage>(thumbnail);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() throws IOException {
|
||||
switch (segment.extensionCode) {
|
||||
case JFXX.RGB:
|
||||
case JFXX.INDEXED:
|
||||
return segment.thumbnail[0] & 0xff;
|
||||
case JFXX.JPEG:
|
||||
return readJPEGCached(false).getWidth();
|
||||
default:
|
||||
throw new IIOException(String.format("Unsupported JFXX extension code: %d", segment.extensionCode));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
switch (segment.extensionCode) {
|
||||
case JFXX.RGB:
|
||||
case JFXX.INDEXED:
|
||||
return segment.thumbnail[1] & 0xff;
|
||||
case JFXX.JPEG:
|
||||
return readJPEGCached(false).getHeight();
|
||||
default:
|
||||
throw new IIOException(String.format("Unsupported JFXX extension code: %d", segment.extensionCode));
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage readIndexed() {
|
||||
// 1 byte: xThumb
|
||||
// 1 byte: yThumb
|
||||
// 768 bytes: palette
|
||||
// x * y bytes: 8 bit indexed pixels
|
||||
int w = segment.thumbnail[0] & 0xff;
|
||||
int h = segment.thumbnail[1] & 0xff;
|
||||
|
||||
int[] rgbs = new int[256];
|
||||
for (int i = 0; i < rgbs.length; i++) {
|
||||
rgbs[i] = (segment.thumbnail[3 * i + 2] & 0xff) << 16
|
||||
| (segment.thumbnail[3 * i + 3] & 0xff) << 8
|
||||
| (segment.thumbnail[3 * i + 4] & 0xff);
|
||||
}
|
||||
|
||||
IndexColorModel icm = new InverseColorMapIndexColorModel(8, rgbs.length, rgbs, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
DataBufferByte buffer = new DataBufferByte(segment.thumbnail, segment.thumbnail.length - 770, 770);
|
||||
WritableRaster raster = Raster.createPackedRaster(buffer, w, h, 8, null);
|
||||
|
||||
return new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
private BufferedImage readRGB() {
|
||||
// 1 byte: xThumb
|
||||
// 1 byte: yThumb
|
||||
// 3 * x * y bytes: 24 bit RGB pixels
|
||||
int w = segment.thumbnail[0] & 0xff;
|
||||
int h = segment.thumbnail[1] & 0xff;
|
||||
|
||||
return ThumbnailReader.readRawThumbnail(segment.thumbnail, segment.thumbnail.length - 2, 2, w, h);
|
||||
}
|
||||
}
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -1,10 +1,45 @@
|
||||
/*
|
||||
* 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 of the copyright holder 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 HOLDER 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.AbstractMetadata;
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -16,31 +51,89 @@ import java.util.List;
|
||||
*/
|
||||
class JPEGImage10Metadata extends AbstractMetadata {
|
||||
|
||||
// TODO: Clean up. Consider just making the meta data classes we were trying to avoid in the first place....
|
||||
/**
|
||||
* Native metadata format name
|
||||
*/
|
||||
static final String JAVAX_IMAGEIO_JPEG_IMAGE_1_0 = "javax_imageio_jpeg_image_1.0";
|
||||
|
||||
// TODO: Create our own native format, which is simply markerSequence from the Sun format, with the segments as-is, in sequence...
|
||||
// + add special case for app segments, containing appXX + identifier (ie. <app0JFIF /> to <app0 identifier="JFIF" /> or <app app="0" identifier="JFIF" />
|
||||
|
||||
private final List<Segment> segments;
|
||||
|
||||
JPEGImage10Metadata(List<Segment> segments) {
|
||||
super(true, JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0, null, null, null);
|
||||
private final Frame frame;
|
||||
private final JFIF jfif;
|
||||
private final AdobeDCT adobeDCT;
|
||||
private final JFXX jfxx;
|
||||
private final ICC_Profile embeddedICCProfile;
|
||||
|
||||
private final CompoundDirectory exif;
|
||||
|
||||
// TODO: Consider moving all the metadata stuff from the reader, over here...
|
||||
JPEGImage10Metadata(final List<Segment> segments, Frame frame, JFIF jfif, JFXX jfxx, ICC_Profile embeddedICCProfile, AdobeDCT adobeDCT, final CompoundDirectory exif) {
|
||||
super(true, JAVAX_IMAGEIO_JPEG_IMAGE_1_0, null, null, null);
|
||||
|
||||
this.segments = segments;
|
||||
this.frame = frame;
|
||||
this.jfif = jfif;
|
||||
this.adobeDCT = adobeDCT;
|
||||
this.jfxx = jfxx;
|
||||
this.embeddedICCProfile = embeddedICCProfile;
|
||||
this.exif = exif;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getNativeTree() {
|
||||
IIOMetadataNode root = new IIOMetadataNode(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
IIOMetadataNode root = new IIOMetadataNode(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
|
||||
IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety");
|
||||
root.appendChild(jpegVariety);
|
||||
// TODO: If we have JFIF, append in JPEGvariety, but can't happen for lossless
|
||||
boolean isJFIF = jfif != null;
|
||||
if (isJFIF) {
|
||||
IIOMetadataNode app0JFIF = new IIOMetadataNode("app0JFIF");
|
||||
app0JFIF.setAttribute("majorVersion", Integer.toString(jfif.majorVersion));
|
||||
app0JFIF.setAttribute("minorVersion", Integer.toString(jfif.minorVersion));
|
||||
|
||||
app0JFIF.setAttribute("resUnits", Integer.toString(jfif.units));
|
||||
app0JFIF.setAttribute("Xdensity", Integer.toString(jfif.xDensity));
|
||||
app0JFIF.setAttribute("Ydensity", Integer.toString(jfif.yDensity));
|
||||
|
||||
app0JFIF.setAttribute("thumbWidth", Integer.toString(jfif.xThumbnail));
|
||||
app0JFIF.setAttribute("thumbHeight", Integer.toString(jfif.yThumbnail));
|
||||
|
||||
jpegVariety.appendChild(app0JFIF);
|
||||
|
||||
// Due to format oddity, add JFXX and app2ICC as subnodes here...
|
||||
// ...and ignore them below, if added...
|
||||
apendJFXX(app0JFIF);
|
||||
appendICCProfile(app0JFIF);
|
||||
}
|
||||
|
||||
root.appendChild(jpegVariety);
|
||||
|
||||
appendMarkerSequence(root, segments, isJFIF);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void appendMarkerSequence(IIOMetadataNode root, List<Segment> segments, boolean isJFIF) {
|
||||
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
|
||||
root.appendChild(markerSequence);
|
||||
|
||||
for (Segment segment : segments)
|
||||
switch (segment.marker) {
|
||||
// SOF3 is the only one supported by now
|
||||
case JPEG.SOF0:
|
||||
case JPEG.SOF1:
|
||||
case JPEG.SOF2:
|
||||
case JPEG.SOF3:
|
||||
case JPEG.SOF5:
|
||||
case JPEG.SOF6:
|
||||
case JPEG.SOF7:
|
||||
case JPEG.SOF9:
|
||||
case JPEG.SOF10:
|
||||
case JPEG.SOF11:
|
||||
case JPEG.SOF13:
|
||||
case JPEG.SOF14:
|
||||
case JPEG.SOF15:
|
||||
Frame sofSegment = (Frame) segment;
|
||||
|
||||
IIOMetadataNode sof = new IIOMetadataNode("sof");
|
||||
@@ -67,13 +160,13 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
HuffmanTable huffmanTable = (HuffmanTable) segment;
|
||||
IIOMetadataNode dht = new IIOMetadataNode("dht");
|
||||
|
||||
// Uses fixed tables...
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (huffmanTable.tc[i][j] != 0) {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
if (huffmanTable.isPresent(i, c)) {
|
||||
IIOMetadataNode dhtable = new IIOMetadataNode("dhtable");
|
||||
dhtable.setAttribute("class", String.valueOf(j));
|
||||
dhtable.setAttribute("class", String.valueOf(c));
|
||||
dhtable.setAttribute("htableId", String.valueOf(i));
|
||||
dhtable.setUserObject(huffmanTable.toNativeTable(i, c));
|
||||
dht.appendChild(dhtable);
|
||||
}
|
||||
}
|
||||
@@ -83,8 +176,28 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
break;
|
||||
|
||||
case JPEG.DQT:
|
||||
markerSequence.appendChild(new IIOMetadataNode("dqt"));
|
||||
// TODO:
|
||||
QuantizationTable quantizationTable = (QuantizationTable) segment;
|
||||
IIOMetadataNode dqt = new IIOMetadataNode("dqt");
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (quantizationTable.isPresent(i)) {
|
||||
IIOMetadataNode dqtable = new IIOMetadataNode("dqtable");
|
||||
dqtable.setAttribute("elementPrecision", quantizationTable.precision(i) != 16 ? "0" : "1"); // 0 = 8 bits, 1 = 16 bits
|
||||
dqtable.setAttribute("qtableId", Integer.toString(i));
|
||||
dqtable.setUserObject(quantizationTable.toNativeTable(i));
|
||||
dqt.appendChild(dqtable);
|
||||
}
|
||||
}
|
||||
markerSequence.appendChild(dqt);
|
||||
|
||||
break;
|
||||
|
||||
case JPEG.DRI:
|
||||
RestartInterval restartInterval = (RestartInterval) segment;
|
||||
IIOMetadataNode dri = new IIOMetadataNode("dri");
|
||||
dri.setAttribute("interval", Integer.toString(restartInterval.interval));
|
||||
markerSequence.appendChild(dri);
|
||||
|
||||
break;
|
||||
|
||||
case JPEG.SOS:
|
||||
@@ -115,6 +228,25 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
|
||||
break;
|
||||
|
||||
case JPEG.APP0:
|
||||
if (segment instanceof JFIF) {
|
||||
// Either already added, or we'll ignore it anyway...
|
||||
break;
|
||||
}
|
||||
else if (isJFIF && segment instanceof JFXX) {
|
||||
// Already added
|
||||
break;
|
||||
}
|
||||
|
||||
// Else, fall through to unknown segment
|
||||
|
||||
case JPEG.APP2:
|
||||
if (isJFIF && segment instanceof ICCProfile) {
|
||||
// Already added
|
||||
break;
|
||||
}
|
||||
// Else, fall through to unknown segment
|
||||
|
||||
case JPEG.APP14:
|
||||
if (segment instanceof AdobeDCT) {
|
||||
AdobeDCT adobe = (AdobeDCT) segment;
|
||||
@@ -136,32 +268,149 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
private void appendICCProfile(IIOMetadataNode app0JFIF) {
|
||||
if (embeddedICCProfile != null) {
|
||||
IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC");
|
||||
app2ICC.setUserObject(embeddedICCProfile);
|
||||
|
||||
app0JFIF.appendChild(app2ICC);
|
||||
}
|
||||
}
|
||||
|
||||
private void apendJFXX(IIOMetadataNode app0JFIF) {
|
||||
if (jfxx != null) {
|
||||
IIOMetadataNode jfxxNode = new IIOMetadataNode("JFXX");
|
||||
app0JFIF.appendChild(jfxxNode);
|
||||
|
||||
IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
|
||||
app0JFXX.setAttribute("extensionCode", Integer.toString(jfxx.extensionCode));
|
||||
jfxxNode.appendChild(app0JFXX);
|
||||
|
||||
switch (jfxx.extensionCode) {
|
||||
case JFXX.JPEG:
|
||||
IIOMetadataNode thumbJPEG = new IIOMetadataNode("JFIFthumbJPEG");
|
||||
thumbJPEG.appendChild(new IIOMetadataNode("markerSequence"));
|
||||
// TODO: Insert segments in marker sequence...
|
||||
// List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(new ByteArrayImageInputStream(jfxx.thumbnail), JPEGSegmentUtil.ALL_SEGMENTS);
|
||||
// Convert to Segment as in JPEGImageReader...
|
||||
// appendMarkerSequence(thumbJPEG, segments, false);
|
||||
|
||||
app0JFXX.appendChild(thumbJPEG);
|
||||
|
||||
break;
|
||||
|
||||
case JFXX.INDEXED:
|
||||
IIOMetadataNode thumbPalette = new IIOMetadataNode("JFIFthumbPalette");
|
||||
thumbPalette.setAttribute("thumbWidth", Integer.toString(jfxx.thumbnail[0] & 0xFF));
|
||||
thumbPalette.setAttribute("thumbHeight", Integer.toString(jfxx.thumbnail[1] & 0xFF));
|
||||
app0JFXX.appendChild(thumbPalette);
|
||||
break;
|
||||
|
||||
case JFXX.RGB:
|
||||
IIOMetadataNode thumbRGB = new IIOMetadataNode("JFIFthumbRGB");
|
||||
thumbRGB.setAttribute("thumbWidth", Integer.toString(jfxx.thumbnail[0] & 0xFF));
|
||||
thumbRGB.setAttribute("thumbHeight", Integer.toString(jfxx.thumbnail[1] & 0xFF));
|
||||
app0JFXX.appendChild(thumbRGB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IIOMetadataNode getStandardChromaNode() {
|
||||
IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
|
||||
|
||||
for (Segment segment : segments) {
|
||||
if (segment instanceof Frame) {
|
||||
Frame sofSegment = (Frame) segment;
|
||||
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
||||
colorSpaceType.setAttribute("name", sofSegment.componentsInFrame() == 1 ? "GRAY" : "RGB"); // TODO YCC, YCCK, CMYK etc
|
||||
chroma.appendChild(colorSpaceType);
|
||||
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
||||
colorSpaceType.setAttribute("name", getColorSpaceType());
|
||||
chroma.appendChild(colorSpaceType);
|
||||
|
||||
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
||||
numChannels.setAttribute("value", String.valueOf(sofSegment.componentsInFrame()));
|
||||
chroma.appendChild(numChannels);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
||||
numChannels.setAttribute("value", String.valueOf(frame.componentsInFrame()));
|
||||
chroma.appendChild(numChannels);
|
||||
|
||||
return chroma;
|
||||
}
|
||||
|
||||
private String getColorSpaceType() {
|
||||
try {
|
||||
JPEGColorSpace csType = JPEGImageReader.getSourceCSType(jfif, adobeDCT, frame);
|
||||
|
||||
switch (csType) {
|
||||
case Gray:
|
||||
case GrayA:
|
||||
return "GRAY";
|
||||
case YCbCr:
|
||||
case YCbCrA:
|
||||
return "YCbCr";
|
||||
case RGB:
|
||||
case RGBA:
|
||||
return "RGB";
|
||||
case PhotoYCC:
|
||||
case PhotoYCCA:
|
||||
return "PhotoYCC";
|
||||
case YCCK:
|
||||
return "YCCK";
|
||||
case CMYK:
|
||||
return "CMYK";
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
catch (IIOException ignore) {
|
||||
}
|
||||
|
||||
return Integer.toString(frame.componentsInFrame(), 16) + "CLR";
|
||||
}
|
||||
|
||||
private boolean hasAlpha() {
|
||||
try {
|
||||
JPEGColorSpace csType = JPEGImageReader.getSourceCSType(jfif, adobeDCT, frame);
|
||||
|
||||
switch (csType) {
|
||||
case GrayA:
|
||||
case YCbCrA:
|
||||
case RGBA:
|
||||
case PhotoYCCA:
|
||||
return true;
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
catch (IIOException ignore) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isLossess() {
|
||||
switch (frame.marker) {
|
||||
case JPEG.SOF3:
|
||||
case JPEG.SOF7:
|
||||
case JPEG.SOF11:
|
||||
case JPEG.SOF15:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IIOMetadataNode getStandardTransparencyNode() {
|
||||
if (hasAlpha()) {
|
||||
IIOMetadataNode transparency = new IIOMetadataNode("Transparency");
|
||||
|
||||
IIOMetadataNode alpha = new IIOMetadataNode("Alpha");
|
||||
alpha.setAttribute("value", "nonpremultipled");
|
||||
transparency.appendChild(alpha);
|
||||
|
||||
return transparency;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IIOMetadataNode getStandardCompressionNode() {
|
||||
IIOMetadataNode compression = new IIOMetadataNode("Compression");
|
||||
@@ -171,7 +420,7 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
compression.appendChild(compressionTypeName);
|
||||
|
||||
IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
|
||||
lossless.setAttribute("value", "TRUE"); // TODO: For lossless only
|
||||
lossless.setAttribute("value", isLossess() ? "TRUE" : "FALSE");
|
||||
compression.appendChild(lossless);
|
||||
|
||||
IIOMetadataNode numProgressiveScans = new IIOMetadataNode("NumProgressiveScans");
|
||||
@@ -186,12 +435,67 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
IIOMetadataNode dimension = new IIOMetadataNode("Dimension");
|
||||
|
||||
IIOMetadataNode imageOrientation = new IIOMetadataNode("ImageOrientation");
|
||||
imageOrientation.setAttribute("value", "normal"); // TODO
|
||||
imageOrientation.setAttribute("value", getExifOrientation(exif));
|
||||
dimension.appendChild(imageOrientation);
|
||||
|
||||
if (jfif != null) {
|
||||
// Aspect ratio
|
||||
float xDensity = Math.max(1, jfif.xDensity);
|
||||
float yDensity = Math.max(1, jfif.yDensity);
|
||||
float aspectRatio = jfif.units == 0 ? xDensity / yDensity : yDensity / xDensity;
|
||||
|
||||
IIOMetadataNode pixelAspectRatio = new IIOMetadataNode("PixelAspectRatio");
|
||||
pixelAspectRatio.setAttribute("value", Float.toString(aspectRatio));
|
||||
dimension.insertBefore(pixelAspectRatio, imageOrientation); // Keep order
|
||||
|
||||
if (jfif.units != 0) {
|
||||
// Pixel size
|
||||
float scale = jfif.units == 1 ? 25.4F : 10.0F; // DPI or DPcm
|
||||
|
||||
IIOMetadataNode horizontalPixelSize = new IIOMetadataNode("HorizontalPixelSize");
|
||||
horizontalPixelSize.setAttribute("value", Float.toString(scale / xDensity));
|
||||
dimension.appendChild(horizontalPixelSize);
|
||||
|
||||
IIOMetadataNode verticalPixelSize = new IIOMetadataNode("VerticalPixelSize");
|
||||
verticalPixelSize.setAttribute("value", Float.toString(scale / yDensity));
|
||||
dimension.appendChild(verticalPixelSize);
|
||||
}
|
||||
}
|
||||
|
||||
return dimension;
|
||||
}
|
||||
|
||||
private String getExifOrientation(Directory exif) {
|
||||
if (exif != null) {
|
||||
Entry orientationEntry = exif.getEntryById(TIFF.TAG_ORIENTATION);
|
||||
|
||||
if (orientationEntry != null) {
|
||||
switch (((Number) orientationEntry.getValue()).intValue()) {
|
||||
case 2:
|
||||
return "FlipH";
|
||||
case 3:
|
||||
return "Rotate180";
|
||||
case 4:
|
||||
return "FlipV";
|
||||
case 5:
|
||||
return "FlipVRotate90";
|
||||
case 6:
|
||||
return "Rotate270";
|
||||
case 7:
|
||||
return "FlipHRotate90";
|
||||
case 8:
|
||||
return "Rotate90";
|
||||
case 0:
|
||||
case 1:
|
||||
default:
|
||||
// Fall-through
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "Normal";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IIOMetadataNode getStandardTextNode() {
|
||||
IIOMetadataNode text = new IIOMetadataNode("Text");
|
||||
@@ -206,6 +510,10 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add the following from Exif (as in TIFFMetadata)
|
||||
// DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright:
|
||||
// /Text/TextEntry@keyword = field name, /Text/TextEntry@value = field value.
|
||||
|
||||
return text.hasChildNodes() ? text : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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 of the copyright holder 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 HOLDER 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.xml.XMLSerializer;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
@@ -22,11 +53,6 @@ import java.util.List;
|
||||
*/
|
||||
final class JPEGImage10MetadataCleaner {
|
||||
|
||||
/**
|
||||
* Native metadata format name
|
||||
*/
|
||||
static final String JAVAX_IMAGEIO_JPEG_IMAGE_1_0 = "javax_imageio_jpeg_image_1.0";
|
||||
|
||||
private final JPEGImageReader reader;
|
||||
|
||||
JPEGImage10MetadataCleaner(final JPEGImageReader reader) {
|
||||
@@ -63,7 +89,7 @@ final class JPEGImage10MetadataCleaner {
|
||||
the version to the method/constructor used to obtain an IIOMetadata object.)
|
||||
*/
|
||||
|
||||
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
IIOMetadataNode tree = (IIOMetadataNode) imageMetadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
IIOMetadataNode jpegVariety = (IIOMetadataNode) tree.getElementsByTagName("JPEGvariety").item(0);
|
||||
IIOMetadataNode markerSequence = (IIOMetadataNode) tree.getElementsByTagName("markerSequence").item(0);
|
||||
|
||||
@@ -107,7 +133,7 @@ final class JPEGImage10MetadataCleaner {
|
||||
IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
|
||||
app0JFXX.setAttribute("extensionCode", String.valueOf(jfxx.extensionCode));
|
||||
|
||||
JFXXThumbnailReader thumbnailReader = new JFXXThumbnailReader(null, reader.getThumbnailReader(), 0, 0, jfxx);
|
||||
ThumbnailReader thumbnailReader = JFXXThumbnail.from(jfxx, reader.getThumbnailReader());
|
||||
IIOMetadataNode jfifThumb;
|
||||
|
||||
switch (jfxx.extensionCode) {
|
||||
@@ -115,7 +141,7 @@ final class JPEGImage10MetadataCleaner {
|
||||
jfifThumb = new IIOMetadataNode("JFIFthumbJPEG");
|
||||
// Contains it's own "markerSequence" with full DHT, DQT, SOF etc...
|
||||
IIOMetadata thumbMeta = thumbnailReader.readMetadata();
|
||||
Node thumbTree = thumbMeta.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
Node thumbTree = thumbMeta.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
jfifThumb.appendChild(thumbTree.getLastChild());
|
||||
app0JFXX.appendChild(jfifThumb);
|
||||
break;
|
||||
@@ -277,11 +303,11 @@ final class JPEGImage10MetadataCleaner {
|
||||
}
|
||||
|
||||
try {
|
||||
imageMetadata.setFromTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0, tree);
|
||||
imageMetadata.setFromTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0, tree);
|
||||
}
|
||||
catch (IIOInvalidTreeException e) {
|
||||
if (JPEGImageReader.DEBUG) {
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(JAVAX_IMAGEIO_JPEG_IMAGE_1_0), false);
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0), false);
|
||||
System.out.println("-- 8< --");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(tree, false);
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -49,7 +51,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static com.twelvemonkeys.imageio.plugins.jpeg.JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0;
|
||||
import static com.twelvemonkeys.imageio.plugins.jpeg.JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0;
|
||||
|
||||
/**
|
||||
* JPEGImageWriter
|
||||
@@ -157,6 +159,17 @@ public final class JPEGImageWriter extends ImageWriterBase {
|
||||
writeCMYK(streamMetadata, image, param);
|
||||
}
|
||||
else {
|
||||
// If the image metadata is our substitute, convert it back to native com.sun format
|
||||
if (image.getMetadata() instanceof JPEGImage10Metadata) {
|
||||
ImageTypeSpecifier type = image.hasRaster() ? null : ImageTypeSpecifier.createFromRenderedImage(image.getRenderedImage());
|
||||
IIOMetadata nativeMetadata = delegate.getDefaultImageMetadata(type, param);
|
||||
|
||||
JPEGImage10Metadata metadata = (JPEGImage10Metadata) image.getMetadata();
|
||||
nativeMetadata.setFromTree(metadata.getNativeMetadataFormatName(), metadata.getNativeTree());
|
||||
|
||||
image.setMetadata(nativeMetadata);
|
||||
}
|
||||
|
||||
delegate.write(streamMetadata, image, param);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -6,26 +6,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -37,6 +39,7 @@ import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
final class JPEGLosslessDecoder {
|
||||
@@ -49,12 +52,12 @@ final class JPEGLosslessDecoder {
|
||||
private final QuantizationTable quantTable;
|
||||
private Scan scan;
|
||||
|
||||
private final int HuffTab[][][] = new int[4][2][MAX_HUFFMAN_SUBTREE * 256];
|
||||
private final int IDCT_Source[] = new int[64];
|
||||
private final int nBlock[] = new int[10]; // number of blocks in the i-th Comp in a scan
|
||||
private final int[] acTab[] = new int[10][]; // ac HuffTab for the i-th Comp in a scan
|
||||
private final int[] dcTab[] = new int[10][]; // dc HuffTab for the i-th Comp in a scan
|
||||
private final int[] qTab[] = new int[10][]; // quantization table for the i-th Comp in a scan
|
||||
private final int[][][] HuffTab = new int[4][2][MAX_HUFFMAN_SUBTREE * 256];
|
||||
private final int[] IDCT_Source = new int[64];
|
||||
private final int[] nBlock = new int[10]; // number of blocks in the i-th Comp in a scan
|
||||
private final int[][] acTab = new int[10][]; // ac HuffTab for the i-th Comp in a scan
|
||||
private final int[][] dcTab = new int[10][]; // dc HuffTab for the i-th Comp in a scan
|
||||
private final int[][] qTab = new int[10][]; // quantization table for the i-th Comp in a scan
|
||||
|
||||
private boolean restarting;
|
||||
private int marker;
|
||||
@@ -68,7 +71,7 @@ final class JPEGLosslessDecoder {
|
||||
private int mask;
|
||||
private int[][] outputData;
|
||||
|
||||
private static final int IDCT_P[] = {
|
||||
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,
|
||||
@@ -78,16 +81,6 @@ final class JPEGLosslessDecoder {
|
||||
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
|
||||
};
|
||||
|
||||
private static final int RESTART_MARKER_BEGIN = 0xFFD0;
|
||||
private static final int RESTART_MARKER_END = 0xFFD7;
|
||||
@@ -156,7 +149,7 @@ final class JPEGLosslessDecoder {
|
||||
huffTable.buildHuffTables(HuffTab);
|
||||
}
|
||||
|
||||
quantTable.enhanceTables(TABLE);
|
||||
quantTable.enhanceTables();
|
||||
|
||||
current = input.readUnsignedShort();
|
||||
|
||||
@@ -183,11 +176,10 @@ final class JPEGLosslessDecoder {
|
||||
selection = scan.spectralSelStart;
|
||||
|
||||
final Scan.Component[] scanComps = scan.components;
|
||||
final int[][] quantTables = quantTable.quantTables;
|
||||
|
||||
for (int i = 0; i < numComp; i++) {
|
||||
Frame.Component component = getComponentSpec(components, scanComps[i].scanCompSel);
|
||||
qTab[i] = quantTables[component.qtSel];
|
||||
qTab[i] = quantTable.qTable(component.qtSel);
|
||||
nBlock[i] = component.vSub * component.hSub;
|
||||
|
||||
int dcTabSel = scanComps[i].dcTabSel;
|
||||
@@ -218,18 +210,18 @@ final class JPEGLosslessDecoder {
|
||||
outputData[componentIndex] = new int[xDim * yDim];
|
||||
}
|
||||
|
||||
final int firstValue[] = new int[numComp];
|
||||
final int[] firstValue = new int[numComp];
|
||||
for (int i = 0; i < numComp; i++) {
|
||||
firstValue[i] = (1 << (precision - 1));
|
||||
}
|
||||
|
||||
final int pred[] = new int[numComp];
|
||||
final int[] pred = new int[numComp];
|
||||
|
||||
scanNum++;
|
||||
|
||||
while (true) { // Decode one scan
|
||||
int temp[] = new int[1]; // to store remainder bits
|
||||
int index[] = new int[1];
|
||||
int[] temp = new int[1]; // to store remainder bits
|
||||
int[] index = new int[1];
|
||||
|
||||
System.arraycopy(firstValue, 0, pred, 0, numComp);
|
||||
|
||||
@@ -286,7 +278,7 @@ final class JPEGLosslessDecoder {
|
||||
private boolean useACForDC(final int dcTabSel) {
|
||||
if (isLossless()) {
|
||||
for (HuffmanTable huffTable : huffTables) {
|
||||
if (huffTable.tc[dcTabSel][0] == 0 && huffTable.tc[dcTabSel][1] != 0) {
|
||||
if (!huffTable.isPresent(dcTabSel, 0) && huffTable.isPresent(dcTabSel, 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -322,7 +314,7 @@ final class JPEGLosslessDecoder {
|
||||
return Scan.read(input, length);
|
||||
}
|
||||
|
||||
private int decode(final int prev[], final int temp[], final int index[]) throws IOException {
|
||||
private int decode(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||
if (numComp == 1) {
|
||||
return decodeSingle(prev, temp, index);
|
||||
}
|
||||
@@ -334,7 +326,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private int decodeSingle(final int prev[], final int temp[], final int index[]) throws IOException {
|
||||
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.
|
||||
if (restarting) {
|
||||
@@ -388,7 +380,7 @@ final class JPEGLosslessDecoder {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int decodeRGB(final int prev[], final int temp[], final int index[]) throws IOException {
|
||||
private int decodeRGB(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||
final int[] outputRedData = outputData[0];
|
||||
final int[] outputGreenData = outputData[1];
|
||||
final int[] outputBlueData = outputData[2];
|
||||
@@ -433,7 +425,7 @@ final class JPEGLosslessDecoder {
|
||||
return decode0(prev, temp, index);
|
||||
}
|
||||
|
||||
private int decodeAny(final int prev[], final int temp[], final int index[]) throws IOException {
|
||||
private int decodeAny(final int[] prev, final int[] temp, final int[] index) throws IOException {
|
||||
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
||||
final int[] outputData = this.outputData[componentIndex];
|
||||
final int previous;
|
||||
@@ -467,17 +459,17 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
|
||||
private int decode0(int[] prev, int[] temp, int[] index) throws IOException {
|
||||
int value, actab[], dctab[];
|
||||
int qtab[];
|
||||
int value;
|
||||
int[] actab;
|
||||
int[] dctab;
|
||||
int[] qtab;
|
||||
|
||||
for (int ctrC = 0; ctrC < numComp; ctrC++) {
|
||||
qtab = qTab[ctrC];
|
||||
actab = acTab[ctrC];
|
||||
dctab = dcTab[ctrC];
|
||||
for (int i = 0; i < nBlock[ctrC]; i++) {
|
||||
for (int k = 0; k < IDCT_Source.length; k++) {
|
||||
IDCT_Source[k] = 0;
|
||||
}
|
||||
Arrays.fill(IDCT_Source, 0);
|
||||
|
||||
value = getHuffmanValue(dctab, temp, index);
|
||||
|
||||
@@ -543,7 +535,7 @@ final class JPEGLosslessDecoder {
|
||||
// and marker_index=9
|
||||
// If marker_index=9 then index is always > 8, or HuffmanValue()
|
||||
// will not be called
|
||||
private int getHuffmanValue(final int table[], final int temp[], final int index[]) throws IOException {
|
||||
private int getHuffmanValue(final int[] table, final int[] temp, final int[] index) throws IOException {
|
||||
int code, input;
|
||||
final int mask = 0xFFFF;
|
||||
|
||||
@@ -601,7 +593,7 @@ final 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;
|
||||
@@ -686,7 +678,7 @@ final class JPEGLosslessDecoder {
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getPreviousX(final int data[]) {
|
||||
private int getPreviousX(final int[] data) {
|
||||
if (xLoc > 0) {
|
||||
return data[((yLoc * xDim) + xLoc) - 1];
|
||||
}
|
||||
@@ -698,7 +690,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private int getPreviousXY(final int data[]) {
|
||||
private int getPreviousXY(final int[] data) {
|
||||
if ((xLoc > 0) && (yLoc > 0)) {
|
||||
return data[(((yLoc - 1) * xDim) + xLoc) - 1];
|
||||
}
|
||||
@@ -707,7 +699,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private int getPreviousY(final int data[]) {
|
||||
private int getPreviousY(final int[] data) {
|
||||
if (yLoc > 0) {
|
||||
return data[((yLoc - 1) * xDim) + xLoc];
|
||||
}
|
||||
@@ -720,7 +712,7 @@ final 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);
|
||||
}
|
||||
@@ -732,7 +724,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void outputSingle(final int pred[]) {
|
||||
private void outputSingle(final int[] pred) {
|
||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||
outputData[0][(yLoc * xDim) + xLoc] = mask & pred[0];
|
||||
xLoc++;
|
||||
@@ -744,7 +736,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void outputRGB(final int pred[]) {
|
||||
private void outputRGB(final int[] pred) {
|
||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||
final int index = (yLoc * xDim) + xLoc;
|
||||
outputData[0][index] = pred[0];
|
||||
@@ -759,7 +751,7 @@ final class JPEGLosslessDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void outputAny(final int pred[]) {
|
||||
private void outputAny(final int[] pred) {
|
||||
if ((xLoc < xDim) && (yLoc < yDim)) {
|
||||
final int index = (yLoc * xDim) + xLoc;
|
||||
for (int componentIndex = 0; componentIndex < outputData.length; ++componentIndex) {
|
||||
|
||||
@@ -5,32 +5,32 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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.stream.BufferedImageInputStream;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.*;
|
||||
@@ -75,7 +75,7 @@ final class JPEGLosslessDecoderWrapper {
|
||||
* @throws IOException is thrown if the decoder failed or a conversion is not supported
|
||||
*/
|
||||
BufferedImage readImage(final List<Segment> segments, final ImageInputStream input) throws IOException {
|
||||
JPEGLosslessDecoder decoder = new JPEGLosslessDecoder(segments, createBufferedInput(input), listenerDelegate);
|
||||
JPEGLosslessDecoder decoder = new JPEGLosslessDecoder(segments, input, listenerDelegate);
|
||||
|
||||
// TODO: Allow 10/12/14 bit (using a ComponentColorModel with correct bits, as in TIFF)
|
||||
// TODO: Rewrite this to pass a pre-allocated buffer of correct type (byte/short)/correct bands
|
||||
@@ -125,10 +125,6 @@ final class JPEGLosslessDecoderWrapper {
|
||||
throw new IIOException("JPEG Lossless with " + decoder.getPrecision() + " bit precision and " + decoder.getNumComponents() + " component(s) not supported");
|
||||
}
|
||||
|
||||
private ImageInputStream createBufferedInput(final ImageInputStream input) throws IOException {
|
||||
return input instanceof BufferedImageInputStream ? input : new BufferedImageInputStream(input);
|
||||
}
|
||||
|
||||
Raster readRaster(final List<Segment> segments, final ImageInputStream input) throws IOException {
|
||||
// TODO: Can perhaps be implemented faster
|
||||
return readImage(segments, input).getRaster();
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -48,8 +50,8 @@ final class JPEGProviderInfo extends ReaderWriterProviderInfo {
|
||||
new String[] {"com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageReaderSpi"},
|
||||
"com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter",
|
||||
new String[] {"com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriterSpi"},
|
||||
false, null, null, null, null,
|
||||
true, null, null, null, null
|
||||
false, "javax_imageio_jpeg_stream_1.0", null, null, null,
|
||||
true, "javax_imageio_jpeg_image_1.0", null, null, null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -35,11 +37,12 @@ import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageInputStreamImpl;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil.isKnownJPEGMarker;
|
||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||
import static java.util.Arrays.copyOf;
|
||||
|
||||
@@ -55,23 +58,22 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
// TODO: Rewrite JPEGSegment (from metadata) to store stream pos/length, and be able to replay data, and use instead of Segment?
|
||||
// TODO: Support multiple JPEG streams (SOI...EOI, SOI...EOI, ...) in a single file
|
||||
|
||||
final private ImageInputStream stream;
|
||||
final private JPEGSegmentStreamWarningListener warningListener;
|
||||
private final ImageInputStream stream;
|
||||
private final JPEGSegmentWarningListener warningListener;
|
||||
|
||||
final private ComponentIdSet componentIds = new ComponentIdSet();
|
||||
private final ComponentIdSet componentIds = new ComponentIdSet();
|
||||
|
||||
private final List<Segment> segments = new ArrayList<Segment>(64);
|
||||
private final List<Segment> segments = new ArrayList<>(64);
|
||||
private int currentSegment = -1;
|
||||
private Segment segment;
|
||||
|
||||
|
||||
JPEGSegmentImageInputStream(final ImageInputStream stream, final JPEGSegmentStreamWarningListener warningListener) {
|
||||
JPEGSegmentImageInputStream(final ImageInputStream stream, final JPEGSegmentWarningListener warningListener) {
|
||||
this.stream = notNull(stream, "stream");
|
||||
this.warningListener = notNull(warningListener, "warningListener");
|
||||
}
|
||||
|
||||
JPEGSegmentImageInputStream(final ImageInputStream stream) {
|
||||
this(stream, JPEGSegmentStreamWarningListener.NULL_LISTENER);
|
||||
this(stream, JPEGSegmentWarningListener.NULL_LISTENER);
|
||||
}
|
||||
|
||||
private void processWarningOccured(final String warning) {
|
||||
@@ -105,24 +107,25 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
|
||||
// Scan forward
|
||||
while (true) {
|
||||
long realPosition = stream.getStreamPosition();
|
||||
|
||||
int trash = 0;
|
||||
int marker = stream.readUnsignedByte();
|
||||
|
||||
// Skip bad padding before the marker
|
||||
while (marker != 0xff) {
|
||||
marker = stream.readUnsignedByte();
|
||||
trash++;
|
||||
realPosition++;
|
||||
}
|
||||
while (!isKnownJPEGMarker(marker)) {
|
||||
marker &= 0xff;
|
||||
|
||||
marker = 0xff00 | stream.readUnsignedByte();
|
||||
// Skip bad padding before the marker
|
||||
while (marker != 0xff) {
|
||||
marker = stream.readUnsignedByte();
|
||||
trash++;
|
||||
}
|
||||
|
||||
// Skip over 0xff padding between markers
|
||||
while (marker == 0xffff) {
|
||||
realPosition++;
|
||||
marker = 0xff00 | stream.readUnsignedByte();
|
||||
|
||||
// Skip over 0xff padding between markers
|
||||
while (marker == 0xffff) {
|
||||
marker = 0xff00 | stream.readUnsignedByte();
|
||||
trash++;
|
||||
}
|
||||
}
|
||||
|
||||
if (trash != 0) {
|
||||
@@ -131,6 +134,8 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
processWarningOccured(String.format("Corrupt JPEG data: %d extraneous bytes before marker 0x%02x", trash, marker & 0xff));
|
||||
}
|
||||
|
||||
long realPosition = stream.getStreamPosition() - 2;
|
||||
|
||||
// We are now handling all important segments ourselves, except APP1/Exif and APP14/Adobe,
|
||||
// as these segments affects image decoding.
|
||||
boolean appSegmentMarker = isAppSegmentMarker(marker);
|
||||
@@ -144,7 +149,6 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
else {
|
||||
if (marker == JPEG.EOI) {
|
||||
segment = new Segment(marker, realPosition, segment.end(), 2);
|
||||
segments.add(segment);
|
||||
}
|
||||
else {
|
||||
// Length including length field itself
|
||||
@@ -159,6 +163,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
// Inspect segment, see if we have 16 bit precision (assuming segments will not contain
|
||||
// multiple quality tables with varying precision)
|
||||
int qtInfo = stream.read();
|
||||
|
||||
if ((qtInfo & 0x10) == 0x10) {
|
||||
processWarningOccured("16 bit DQT encountered");
|
||||
segment = new DownsampledDQTReplacement(realPosition, segment.end(), length, qtInfo, stream);
|
||||
@@ -168,6 +173,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
}
|
||||
}
|
||||
else if (isSOFMarker(marker)) {
|
||||
// TODO: Warning + ignore if we already have a SOF
|
||||
// Replace duplicate SOFn component ids
|
||||
byte[] data = readReplaceDuplicateSOFnComponentIds(marker, length);
|
||||
segment = new ReplacementSegment(marker, realPosition, segment.end(), length, data);
|
||||
@@ -181,10 +187,9 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
else {
|
||||
segment = new Segment(marker, realPosition, segment.end(), length);
|
||||
}
|
||||
|
||||
segments.add(segment);
|
||||
}
|
||||
|
||||
segments.add(segment);
|
||||
currentSegment = segments.size() - 1;
|
||||
|
||||
if (marker == JPEG.SOS) {
|
||||
@@ -268,7 +273,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
processWarningOccured(String.format("Duplicate component ID %d in SOF", id));
|
||||
|
||||
id++;
|
||||
while (!componentIds.add(id)) {
|
||||
while (componentIds.size() < 4 && !componentIds.add(id) && id < 255) {
|
||||
id++;
|
||||
}
|
||||
|
||||
@@ -323,11 +328,11 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
}
|
||||
|
||||
static String asAsciiString(final byte[] data, final int offset, final int length) {
|
||||
return new String(data, offset, length, Charset.forName("ascii"));
|
||||
return new String(data, offset, length, StandardCharsets.US_ASCII);
|
||||
}
|
||||
|
||||
private void streamInit() throws IOException {
|
||||
stream.seek(0);
|
||||
long position = stream.getStreamPosition();
|
||||
|
||||
try {
|
||||
int soi = stream.readUnsignedShort();
|
||||
@@ -336,7 +341,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
throw new IIOException(String.format("Not a JPEG stream (starts with: 0x%04x, expected SOI: 0x%04x)", soi, JPEG.SOI));
|
||||
}
|
||||
|
||||
segment = new Segment(soi, 0, 0, 2);
|
||||
segment = new Segment(soi, position, 0, 2);
|
||||
|
||||
segments.add(segment);
|
||||
currentSegment = segments.size() - 1; // 0
|
||||
@@ -380,6 +385,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
fetchSegment();
|
||||
}
|
||||
catch (EOFException ignore) {
|
||||
segments.add(new Segment(0, segment.realEnd(), segment.end(), Integer.MAX_VALUE * 2L - segment.realEnd()));
|
||||
// This might happen if the segment lengths in the stream are bad.
|
||||
// We MUST leave internal state untouched in this case.
|
||||
// We ignore this exception here, but client code will get
|
||||
@@ -415,7 +421,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
repositionAsNecessary();
|
||||
|
||||
long bytesLeft = segment.end() - streamPos; // If no more bytes after reposition, we're at EOF
|
||||
int count = bytesLeft == 0 ? -1 : segment.read(stream, b, off + total, (int) Math.min(len - total, bytesLeft));
|
||||
int count = bytesLeft <= 0 ? -1 : segment.read(stream, b, off + total, (int) Math.min(len - total, bytesLeft));
|
||||
|
||||
if (count == -1) {
|
||||
// EOF
|
||||
@@ -435,8 +441,9 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
|
||||
@Deprecated
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
protected void finalize() {
|
||||
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
||||
}
|
||||
|
||||
@@ -563,12 +570,17 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
|
||||
@Override
|
||||
public int read(final ImageInputStream stream) {
|
||||
return data[pos++] & 0xff;
|
||||
return data.length > pos ? data[pos++] & 0xff : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final ImageInputStream stream, byte[] b, int off, int len) {
|
||||
int length = Math.min(data.length - pos, len);
|
||||
int dataLeft = data.length - pos;
|
||||
if (dataLeft <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int length = Math.min(dataLeft, len);
|
||||
System.arraycopy(data, pos, b, off, length);
|
||||
pos += length;
|
||||
|
||||
@@ -577,7 +589,7 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
|
||||
}
|
||||
|
||||
static final class ComponentIdSet {
|
||||
final int[] values = new int[4]; // The native code don't support more than 4 components
|
||||
final int[] values = new int[4]; // The native code doesn't support more than 4 components
|
||||
int size;
|
||||
|
||||
boolean add(final int value) {
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
|
||||
/**
|
||||
* JPEGSegmentStreamWarningListener
|
||||
*/
|
||||
interface JPEGSegmentStreamWarningListener {
|
||||
void warningOccurred(String warning);
|
||||
|
||||
JPEGSegmentStreamWarningListener NULL_LISTENER = new JPEGSegmentStreamWarningListener() {
|
||||
@Override
|
||||
public void warningOccurred(final String warning) {}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
/**
|
||||
* JPEGSegmentStreamWarningListener
|
||||
*/
|
||||
interface JPEGSegmentWarningListener {
|
||||
void warningOccurred(String warning);
|
||||
|
||||
JPEGSegmentWarningListener NULL_LISTENER = new JPEGSegmentWarningListener() {
|
||||
@Override
|
||||
public void warningOccurred(final String warning) {}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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 of the copyright holder 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 HOLDER 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.lang.Validate;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.RasterOp;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* LuminanceToGray.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: LuminanceToGray.java,v 1.0 10/04/2021 haraldk Exp$
|
||||
*/
|
||||
final class LuminanceToGray implements RasterOp {
|
||||
|
||||
@Override
|
||||
public WritableRaster filter(final Raster src, WritableRaster dest) {
|
||||
Validate.notNull(src, "src may not be null");
|
||||
Validate.isTrue(src != dest, "src and dest raster may not be same");
|
||||
Validate.isTrue(src.getNumDataElements() >= 3, src.getNumDataElements(), "luminance raster must have at least 3 data elements: %s");
|
||||
|
||||
if (dest == null) {
|
||||
dest = createCompatibleDestRaster(src);
|
||||
}
|
||||
|
||||
// If src and dest have alpha component, keep it, otherwise extract luminance only
|
||||
int[] bandList = src.getNumBands() > 3 && dest.getNumBands() > 1 ? new int[] {0, 3} : new int[] {0};
|
||||
dest.setRect(0, 0, src.createChild(0, 0, src.getWidth(), src.getHeight(), 0, 0, bandList));
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getBounds2D(final Raster src) {
|
||||
return src.getBounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WritableRaster createCompatibleDestRaster(final Raster src) {
|
||||
return src.createCompatibleWritableRaster()
|
||||
.createWritableChild(0, 0, src.getWidth(), src.getHeight(), 0, 0, new int[] {0});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2D getPoint2D(final Point2D srcPt, Point2D dstPt) {
|
||||
if (dstPt == null) {
|
||||
dstPt = new Point2D.Double(srcPt.getX(), srcPt.getY());
|
||||
}
|
||||
else {
|
||||
dstPt.setLocation(srcPt);
|
||||
}
|
||||
|
||||
return dstPt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -6,26 +6,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -33,35 +35,42 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.plugins.jpeg.JPEGQTable;
|
||||
import java.io.DataInput;
|
||||
import java.io.IOException;
|
||||
|
||||
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
|
||||
private static final int[] ZIGZAG = {
|
||||
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
|
||||
};
|
||||
|
||||
final int quantTables[][] = new int[4][64]; // Tables
|
||||
private final int[] precision = new int[4]; // Quantization precision 8 or 16
|
||||
private final boolean[] tq = new boolean[4]; // 1: this table is present
|
||||
|
||||
private final int[][] quantTables = new int[4][64]; // Tables
|
||||
|
||||
QuantizationTable() {
|
||||
super(JPEG.DQT);
|
||||
|
||||
tq[0] = 0;
|
||||
tq[1] = 0;
|
||||
tq[2] = 0;
|
||||
tq[3] = 0;
|
||||
}
|
||||
|
||||
// TODO: Get rid of table param, make it a member?
|
||||
void enhanceTables(final int[] table) throws IOException {
|
||||
// TODO: Consider creating a copy for the decoder here, as we need to keep the original values for the metadata
|
||||
void enhanceTables() {
|
||||
for (int t = 0; t < 4; t++) {
|
||||
if (tq[t] != 0) {
|
||||
enhanceQuantizationTable(quantTables[t], table);
|
||||
if (tq[t]) {
|
||||
enhanceQuantizationTable(quantTables[t], ZIGZAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enhanceQuantizationTable(final int qtab[], final int[] table) {
|
||||
private void enhanceQuantizationTable(final int[] qtab, final int[] table) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
qtab[table[ i]] *= 90;
|
||||
qtab[table[(4 * 8) + i]] *= 90;
|
||||
@@ -120,7 +129,7 @@ final class QuantizationTable extends Segment {
|
||||
throw new IIOException("Unexpected JPEG Quantization Table precision: " + table.precision[t]);
|
||||
}
|
||||
|
||||
table.tq[t] = 1;
|
||||
table.tq[t] = true;
|
||||
|
||||
if (table.precision[t] == 8) {
|
||||
for (int i = 0; i < 64; i++) {
|
||||
@@ -150,4 +159,28 @@ final class QuantizationTable extends Segment {
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
public boolean isPresent(int tabelId) {
|
||||
return tq[tabelId];
|
||||
}
|
||||
|
||||
int precision(int tableId) {
|
||||
return precision[tableId];
|
||||
}
|
||||
|
||||
int[] qTable(int tabelId) {
|
||||
return quantTables[tabelId];
|
||||
}
|
||||
|
||||
JPEGQTable toNativeTable(int tableId) {
|
||||
// TODO: Should de-zigzag (ie. "natural order") while reading
|
||||
// TODO: ...and make sure the table isn't "enhanced"...
|
||||
int[] qTable = new int[quantTables[tableId].length];
|
||||
|
||||
for (int i = 0; i < qTable.length; i++) {
|
||||
qTable[i] = quantTables[tableId][ZIGZAG[i]];
|
||||
}
|
||||
|
||||
return new JPEGQTable(qTable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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;
|
||||
|
||||
/**
|
||||
* ThumbnailReadProgressListener
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ThumbnailReadProgressListener.java,v 1.0 07.05.12 10:15 haraldk Exp$
|
||||
*/
|
||||
interface ThumbnailReadProgressListener {
|
||||
void thumbnailStarted(int imageIndex, int thumbnailIndex);
|
||||
|
||||
void thumbnailProgress(float percentageDone);
|
||||
|
||||
void thumbnailComplete();
|
||||
}
|
||||
@@ -4,37 +4,43 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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.ImageReader;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.twelvemonkeys.lang.Validate.isTrue;
|
||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||
|
||||
/**
|
||||
* ThumbnailReader
|
||||
*
|
||||
@@ -44,68 +50,156 @@ import java.io.IOException;
|
||||
*/
|
||||
abstract class ThumbnailReader {
|
||||
|
||||
private final ThumbnailReadProgressListener progressListener;
|
||||
protected final int imageIndex;
|
||||
protected final int thumbnailIndex;
|
||||
|
||||
protected ThumbnailReader(final ThumbnailReadProgressListener progressListener, final int imageIndex, final int thumbnailIndex) {
|
||||
this.progressListener = progressListener != null ? progressListener : new NullProgressListener();
|
||||
this.imageIndex = imageIndex;
|
||||
this.thumbnailIndex = thumbnailIndex;
|
||||
}
|
||||
|
||||
protected final void processThumbnailStarted() {
|
||||
progressListener.thumbnailStarted(imageIndex, thumbnailIndex);
|
||||
}
|
||||
|
||||
protected final void processThumbnailProgress(float percentageDone) {
|
||||
progressListener.thumbnailProgress(percentageDone);
|
||||
}
|
||||
|
||||
protected final void processThumbnailComplete() {
|
||||
progressListener.thumbnailComplete();
|
||||
}
|
||||
|
||||
static protected BufferedImage readJPEGThumbnail(final ImageReader reader, final ImageInputStream stream) throws IOException {
|
||||
reader.setInput(stream);
|
||||
|
||||
return reader.read(0);
|
||||
}
|
||||
|
||||
static protected BufferedImage readRawThumbnail(final byte[] thumbnail, final int size, final int offset, int w, int h) {
|
||||
DataBufferByte buffer = new DataBufferByte(thumbnail, size, offset);
|
||||
WritableRaster raster;
|
||||
ColorModel cm;
|
||||
|
||||
if (thumbnail.length == w * h) {
|
||||
raster = Raster.createInterleavedRaster(buffer, w, h, w, 1, new int[] {0}, null);
|
||||
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
}
|
||||
else {
|
||||
raster = Raster.createInterleavedRaster(buffer, w, h, w * 3, 3, new int[] {0, 1, 2}, null);
|
||||
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
}
|
||||
|
||||
return new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
public abstract BufferedImage read() throws IOException;
|
||||
|
||||
public abstract int getWidth() throws IOException;
|
||||
|
||||
public abstract int getHeight() throws IOException;
|
||||
|
||||
private static class NullProgressListener implements ThumbnailReadProgressListener {
|
||||
@Override
|
||||
public void thumbnailStarted(int imageIndex, int thumbnailIndex) {
|
||||
public IIOMetadata readMetadata() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
static class UncompressedThumbnailReader extends ThumbnailReader {
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final byte[] data;
|
||||
private final int offset;
|
||||
|
||||
public UncompressedThumbnailReader(int width, int height, byte[] data) {
|
||||
this(width, height, data, 0);
|
||||
}
|
||||
|
||||
public UncompressedThumbnailReader(int width, int height, byte[] data, int offset) {
|
||||
this.width = isTrue(width > 0, width, "width");
|
||||
this.height = isTrue(height > 0, height, "height");;
|
||||
this.data = notNull(data, "data");
|
||||
this.offset = isTrue(offset >= 0 && offset < data.length, offset, "offset");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void thumbnailProgress(float percentageDone) {
|
||||
public BufferedImage read() throws IOException {
|
||||
DataBufferByte buffer = new DataBufferByte(data, data.length, offset);
|
||||
WritableRaster raster;
|
||||
ColorModel cm;
|
||||
|
||||
if (data.length == width * height) {
|
||||
raster = Raster.createInterleavedRaster(buffer, width, height, width, 1, new int[] {0}, null);
|
||||
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
}
|
||||
else {
|
||||
raster = Raster.createInterleavedRaster(buffer, width, height, width * 3, 3, new int[] {0, 1, 2}, null);
|
||||
cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
}
|
||||
|
||||
return new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void thumbnailComplete() {
|
||||
public int getWidth() throws IOException {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
static class IndexedThumbnailReader extends ThumbnailReader {
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final byte[] palette;
|
||||
private final int paletteOff;
|
||||
private final byte[] data;
|
||||
private final int dataOff;
|
||||
|
||||
public IndexedThumbnailReader(final int width, int height, final byte[] palette, final int paletteOff, final byte[] data, final int dataOff) {
|
||||
this.width = isTrue(width > 0, width, "width");
|
||||
this.height = isTrue(height > 0, height, "height");;
|
||||
this.palette = notNull(palette, "palette");
|
||||
this.paletteOff = isTrue(paletteOff >= 0 && paletteOff < palette.length, paletteOff, "paletteOff");
|
||||
this.data = notNull(data, "data");
|
||||
this.dataOff = isTrue(dataOff >= 0 && dataOff < data.length, dataOff, "dataOff");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage read() throws IOException {
|
||||
// 256 RGB triplets
|
||||
int[] rgbs = new int[256];
|
||||
for (int i = 0; i < rgbs.length; i++) {
|
||||
rgbs[i] = (palette[paletteOff + 3 * i ] & 0xff) << 16
|
||||
| (palette[paletteOff + 3 * i + 1] & 0xff) << 8
|
||||
| (palette[paletteOff + 3 * i + 2] & 0xff);
|
||||
}
|
||||
|
||||
IndexColorModel icm = new IndexColorModel(8, rgbs.length, rgbs, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
DataBufferByte buffer = new DataBufferByte(data, data.length - dataOff, dataOff);
|
||||
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, 8, null);
|
||||
|
||||
return new BufferedImage(icm, raster, icm.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() throws IOException {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
static class JPEGThumbnailReader extends ThumbnailReader {
|
||||
private final ImageReader reader;
|
||||
private final ImageInputStream input;
|
||||
private final long offset;
|
||||
|
||||
private Dimension dimension;
|
||||
|
||||
public JPEGThumbnailReader(final ImageReader reader, final ImageInputStream input, final long offset) {
|
||||
this.reader = notNull(reader, "reader");
|
||||
this.input = notNull(input, "input");
|
||||
this.offset = isTrue(offset >= 0, offset, "offset");
|
||||
}
|
||||
|
||||
private void initReader() throws IOException {
|
||||
if (reader.getInput() != input) {
|
||||
input.seek(offset);
|
||||
reader.setInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage read() throws IOException {
|
||||
initReader();
|
||||
return reader.read(0, null);
|
||||
}
|
||||
|
||||
private Dimension readDimensions() throws IOException {
|
||||
if (dimension == null) {
|
||||
initReader();
|
||||
dimension = new Dimension(reader.getWidth(0), reader.getHeight(0));
|
||||
}
|
||||
|
||||
return dimension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() throws IOException {
|
||||
return readDimensions().width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() throws IOException {
|
||||
return readDimensions().height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata readMetadata() throws IOException {
|
||||
initReader();
|
||||
return reader.getImageMetadata(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Harald Kuhr
|
||||
* Copyright (c) 2012, 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -50,9 +52,7 @@ public abstract class AbstractThumbnailReaderTest {
|
||||
IIORegistry.getDefaultInstance().registerServiceProvider(new URLImageInputStreamSpi());
|
||||
}
|
||||
|
||||
protected abstract ThumbnailReader createReader(
|
||||
ThumbnailReadProgressListener progressListener, int imageIndex, int thumbnailIndex, ImageInputStream stream
|
||||
) throws IOException;
|
||||
protected abstract ThumbnailReader createReader(ImageInputStream stream) throws IOException;
|
||||
|
||||
protected final ImageInputStream createStream(final String name) throws IOException {
|
||||
URL resource = getClass().getResource(name);
|
||||
|
||||
@@ -4,47 +4,59 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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.AbstractCompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
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.metadata.tiff.IFD;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* EXIFThumbnailReaderTest
|
||||
@@ -55,31 +67,175 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
|
||||
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
thumbnailReader.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromNullSegment() throws IOException {
|
||||
assertNull(EXIFThumbnail.from(null, null, thumbnailReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromNullIFD() throws IOException {
|
||||
assertNull(EXIFThumbnail.from(new EXIF(new byte[0]), null, thumbnailReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromEmptyIFD() throws IOException {
|
||||
assertNull(EXIFThumbnail.from(new EXIF(new byte[0]), new EXIFDirectory(), thumbnailReader));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromSingleIFD() throws IOException {
|
||||
assertNull(EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList())), thumbnailReader));
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromMissingThumbnail() throws IOException {
|
||||
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(Collections.<Entry>emptyList())), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromUnsupportedThumbnailCompression() throws IOException {
|
||||
List<TIFFEntry> entries = Collections.singletonList(new TIFFEntry(TIFF.TAG_COMPRESSION, 42));
|
||||
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromMissingOffsetUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromMissingWidthUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromMissingHeightUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromUnsupportedPhotometricUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9),
|
||||
new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, 42)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromUnsupportedBitsPerSampleUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9),
|
||||
new TIFFEntry(TIFF.TAG_BITS_PER_SAMPLE, new int[]{5, 6, 5})
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromUnsupportedSamplesPerPixelUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 160),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 90),
|
||||
new TIFFEntry(TIFF.TAG_SAMPLES_PER_PIXEL, 1)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncatedUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 160),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 90)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidUncompressed() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 1),
|
||||
new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, 0),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, 16),
|
||||
new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, 9)
|
||||
);
|
||||
|
||||
ThumbnailReader reader = EXIFThumbnail.from(new EXIF(new byte[6 + 16 * 9 * 3]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
assertNotNull(reader);
|
||||
|
||||
// Sanity check below
|
||||
assertEquals(16, reader.getWidth());
|
||||
assertEquals(9, reader.getHeight());
|
||||
assertNotNull(reader.read());
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromMissingOffsetJPEG() throws IOException {
|
||||
List<TIFFEntry> entries = Collections.singletonList(new TIFFEntry(TIFF.TAG_COMPRESSION, 6));
|
||||
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncatedJPEG() throws IOException {
|
||||
List<TIFFEntry> entries = Arrays.asList(
|
||||
new TIFFEntry(TIFF.TAG_COMPRESSION, 6),
|
||||
new TIFFEntry(TIFF.TAG_JPEG_INTERCHANGE_FORMAT, 0)
|
||||
);
|
||||
EXIFThumbnail.from(new EXIF(new byte[42]), new EXIFDirectory(new IFD(Collections.<Entry>emptyList()), new IFD(entries)), thumbnailReader);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected EXIFThumbnailReader createReader(final ThumbnailReadProgressListener progressListener, final int imageIndex, final int thumbnailIndex, final ImageInputStream stream) throws IOException {
|
||||
protected ThumbnailReader createReader(final ImageInputStream stream) throws IOException {
|
||||
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP1, "Exif");
|
||||
stream.close();
|
||||
|
||||
assertNotNull(segments);
|
||||
assertFalse(segments.isEmpty());
|
||||
|
||||
TIFFReader reader = new TIFFReader();
|
||||
InputStream data = segments.get(0).data();
|
||||
if (data.read() < 0) {
|
||||
throw new AssertionError("EOF!");
|
||||
}
|
||||
JPEGSegment exifSegment = segments.get(0);
|
||||
InputStream data = exifSegment.segmentData();
|
||||
byte[] exifData = new byte[exifSegment.segmentLength() - 2];
|
||||
new DataInputStream(data).readFully(exifData);
|
||||
|
||||
ImageInputStream exifStream = ImageIO.createImageInputStream(data);
|
||||
CompoundDirectory ifds = (CompoundDirectory) reader.read(exifStream);
|
||||
|
||||
assertEquals(2, ifds.directoryCount());
|
||||
|
||||
return new EXIFThumbnailReader(progressListener, ImageIO.getImageReadersByFormatName("JPEG").next(), imageIndex, thumbnailIndex, ifds.getDirectory(1), exifStream);
|
||||
EXIF exif = new EXIF(exifData);
|
||||
return EXIFThumbnail.from(exif, (CompoundDirectory) new TIFFReader().read(exif.exifData()), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadJPEG() throws IOException {
|
||||
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"));
|
||||
ThumbnailReader reader = createReader(createStream("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"));
|
||||
|
||||
assertEquals(114, reader.getWidth());
|
||||
assertEquals(160, reader.getHeight());
|
||||
@@ -92,7 +248,7 @@ public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
|
||||
@Test
|
||||
public void testReadRaw() throws IOException {
|
||||
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/exif-rgb-thumbnail-sony-d700.jpg"));
|
||||
ThumbnailReader reader = createReader(createStream("/jpeg/exif-rgb-thumbnail-sony-d700.jpg"));
|
||||
|
||||
assertEquals(80, reader.getWidth());
|
||||
assertEquals(60, reader.getHeight());
|
||||
@@ -103,27 +259,9 @@ public class EXIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
assertEquals(60, thumbnail.getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressListenerJPEG() throws IOException {
|
||||
ThumbnailReadProgressListener listener = mock(ThumbnailReadProgressListener.class);
|
||||
|
||||
createReader(listener, 42, 43, createStream("/jpeg/cmyk-sample-multiple-chunk-icc.jpg")).read();
|
||||
|
||||
InOrder order = inOrder(listener);
|
||||
order.verify(listener).thumbnailStarted(42, 43);
|
||||
order.verify(listener, atLeastOnce()).thumbnailProgress(100f);
|
||||
order.verify(listener).thumbnailComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressListenerRaw() throws IOException {
|
||||
ThumbnailReadProgressListener listener = mock(ThumbnailReadProgressListener.class);
|
||||
|
||||
createReader(listener, 0, 99, createStream("/jpeg/exif-rgb-thumbnail-sony-d700.jpg")).read();
|
||||
|
||||
InOrder order = inOrder(listener);
|
||||
order.verify(listener).thumbnailStarted(0, 99);
|
||||
order.verify(listener, atLeastOnce()).thumbnailProgress(100f);
|
||||
order.verify(listener).thumbnailComplete();
|
||||
private static class EXIFDirectory extends AbstractCompoundDirectory {
|
||||
public EXIFDirectory(IFD... ifds) {
|
||||
super(Arrays.asList(ifds));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -61,7 +63,7 @@ public class FastCMYKToRGBTest {
|
||||
assertNotNull(pixel);
|
||||
assertEquals(3, pixel.length);
|
||||
byte[] expected = {(byte) 255, (byte) 255, (byte) 255};
|
||||
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,7 +95,7 @@ public class FastCMYKToRGBTest {
|
||||
assertNotNull(pixel);
|
||||
assertEquals(3, pixel.length);
|
||||
byte[] expected = {(byte) 0, (byte) 0, (byte) 0};
|
||||
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +134,7 @@ public class FastCMYKToRGBTest {
|
||||
assertNotNull(pixel);
|
||||
assertEquals(3, pixel.length);
|
||||
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i)};
|
||||
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +153,7 @@ public class FastCMYKToRGBTest {
|
||||
assertNotNull(pixel);
|
||||
assertEquals(3, pixel.length);
|
||||
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i)};
|
||||
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +172,7 @@ public class FastCMYKToRGBTest {
|
||||
assertNotNull(pixel);
|
||||
assertEquals(4, pixel.length);
|
||||
byte[] expected = {(byte) (255 - i), (byte) i, (byte) (127 - i), (byte) 0xff};
|
||||
assertTrue(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), Arrays.equals(expected, pixel));
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -31,9 +33,10 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.DataInputStream;
|
||||
@@ -41,7 +44,6 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* JFIFThumbnailReaderTest
|
||||
@@ -51,8 +53,9 @@ import static org.mockito.Mockito.*;
|
||||
* @version $Id: JFIFThumbnailReaderTest.java,v 1.0 04.05.12 15:56 haraldk Exp$
|
||||
*/
|
||||
public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
|
||||
@Override
|
||||
protected JFIFThumbnailReader createReader(ThumbnailReadProgressListener progressListener, int imageIndex, int thumbnailIndex, ImageInputStream stream) throws IOException {
|
||||
protected ThumbnailReader createReader(ImageInputStream stream) throws IOException {
|
||||
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP0, "JFIF");
|
||||
stream.close();
|
||||
|
||||
@@ -60,12 +63,44 @@ public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
assertFalse(segments.isEmpty());
|
||||
|
||||
JPEGSegment segment = segments.get(0);
|
||||
return new JFIFThumbnailReader(progressListener, imageIndex, thumbnailIndex, JFIF.read(new DataInputStream(segment.segmentData()), segment.segmentLength()));
|
||||
|
||||
return JFIFThumbnail.from(JFIF.read(new DataInputStream(segment.segmentData()), segment.segmentLength()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromNull() throws IOException {
|
||||
assertNull(JFIFThumbnail.from(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromNullThumbnail() throws IOException {
|
||||
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromEmpty() throws IOException {
|
||||
assertNull(JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 0, 0, new byte[0])));
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncated() throws IOException {
|
||||
JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 255, 170, new byte[99]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromValid() throws IOException {
|
||||
ThumbnailReader reader = JFIFThumbnail.from(new JFIF(1, 1, 0, 1, 1, 30, 20, new byte[30 * 20 * 3]));
|
||||
assertNotNull(reader);
|
||||
|
||||
// Sanity check below
|
||||
assertEquals(30, reader.getWidth());
|
||||
assertEquals(20, reader.getHeight());
|
||||
assertNotNull(reader.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadRaw() throws IOException {
|
||||
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/jfif-jfif-and-exif-thumbnail-sharpshot-iphone.jpg"));
|
||||
ThumbnailReader reader = createReader(createStream("/jpeg/jfif-jfif-and-exif-thumbnail-sharpshot-iphone.jpg"));
|
||||
|
||||
assertEquals(131, reader.getWidth());
|
||||
assertEquals(122, reader.getHeight());
|
||||
@@ -78,7 +113,7 @@ public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
|
||||
@Test
|
||||
public void testReadNonSpecGray() throws IOException {
|
||||
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/jfif-grayscale-thumbnail.jpg"));
|
||||
ThumbnailReader reader = createReader(createStream("/jpeg/jfif-grayscale-thumbnail.jpg"));
|
||||
|
||||
assertEquals(127, reader.getWidth());
|
||||
assertEquals(76, reader.getHeight());
|
||||
@@ -89,16 +124,4 @@ public class JFIFThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
assertEquals(127, thumbnail.getWidth());
|
||||
assertEquals(76, thumbnail.getHeight());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgressListenerRaw() throws IOException {
|
||||
ThumbnailReadProgressListener listener = mock(ThumbnailReadProgressListener.class);
|
||||
|
||||
createReader(listener, 0, 99, createStream("/jpeg/jfif-jfif-and-exif-thumbnail-sharpshot-iphone.jpg")).read();
|
||||
|
||||
InOrder order = inOrder(listener);
|
||||
order.verify(listener).thumbnailStarted(0, 99);
|
||||
order.verify(listener, atLeastOnce()).thumbnailProgress(100f);
|
||||
order.verify(listener).thumbnailComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -31,10 +33,13 @@ package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.DataInputStream;
|
||||
@@ -42,7 +47,6 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* JFXXThumbnailReaderTest
|
||||
@@ -52,8 +56,10 @@ import static org.mockito.Mockito.*;
|
||||
* @version $Id: JFXXThumbnailReaderTest.java,v 1.0 04.05.12 15:56 haraldk Exp$
|
||||
*/
|
||||
public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
private final ImageReader thumbnailReader = ImageIO.getImageReadersByFormatName("jpeg").next();
|
||||
|
||||
@Override
|
||||
protected JFXXThumbnailReader createReader(ThumbnailReadProgressListener progressListener, int imageIndex, int thumbnailIndex, ImageInputStream stream) throws IOException {
|
||||
protected ThumbnailReader createReader(final ImageInputStream stream) throws IOException {
|
||||
List<JPEGSegment> segments = JPEGSegmentUtil.readSegments(stream, JPEG.APP0, "JFXX");
|
||||
stream.close();
|
||||
|
||||
@@ -61,12 +67,69 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
assertFalse(segments.isEmpty());
|
||||
|
||||
JPEGSegment jfxx = segments.get(0);
|
||||
return new JFXXThumbnailReader(progressListener, ImageIO.getImageReadersByFormatName("jpeg").next(), imageIndex, thumbnailIndex, JFXX.read(new DataInputStream(jfxx.segmentData()), jfxx.length()));
|
||||
return JFXXThumbnail.from(JFXX.read(new DataInputStream(jfxx.segmentData()), jfxx.length()), thumbnailReader);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
thumbnailReader.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromNull() throws IOException {
|
||||
assertNull(JFXXThumbnail.from(null, thumbnailReader));
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromNullThumbnail() throws IOException {
|
||||
JFXXThumbnail.from(new JFXX(JFXX.JPEG, null), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromEmpty() throws IOException {
|
||||
JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[0]), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncatedJPEG() throws IOException {
|
||||
JFXXThumbnail.from(new JFXX(JFXX.JPEG, new byte[99]), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncatedRGB() throws IOException {
|
||||
byte[] thumbnail = new byte[765];
|
||||
thumbnail[0] = (byte) 160;
|
||||
thumbnail[1] = 90;
|
||||
|
||||
JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test(expected = IIOException.class)
|
||||
public void testFromTruncatedIndexed() throws IOException {
|
||||
byte[] thumbnail = new byte[365];
|
||||
thumbnail[0] = (byte) 160;
|
||||
thumbnail[1] = 90;
|
||||
|
||||
JFXXThumbnail.from(new JFXX(JFXX.INDEXED, thumbnail), thumbnailReader);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromValid() throws IOException {
|
||||
byte[] thumbnail = new byte[14];
|
||||
thumbnail[0] = 2;
|
||||
thumbnail[1] = 2;
|
||||
ThumbnailReader reader = JFXXThumbnail.from(new JFXX(JFXX.RGB, thumbnail), thumbnailReader);
|
||||
assertNotNull(reader);
|
||||
|
||||
// Sanity check below
|
||||
assertEquals(2, reader.getWidth());
|
||||
assertEquals(2, reader.getHeight());
|
||||
assertNotNull(reader.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadJPEG() throws IOException {
|
||||
ThumbnailReader reader = createReader(mock(ThumbnailReadProgressListener.class), 0, 0, createStream("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg"));
|
||||
ThumbnailReader reader = createReader(createStream("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg"));
|
||||
|
||||
assertEquals(80, reader.getWidth());
|
||||
assertEquals(60, reader.getHeight());
|
||||
@@ -79,16 +142,4 @@ public class JFXXThumbnailReaderTest extends AbstractThumbnailReaderTest {
|
||||
|
||||
// TODO: Test JFXX indexed thumbnail
|
||||
// TODO: Test JFXX RGB thumbnail
|
||||
|
||||
@Test
|
||||
public void testProgressListenerRaw() throws IOException {
|
||||
ThumbnailReadProgressListener listener = mock(ThumbnailReadProgressListener.class);
|
||||
|
||||
createReader(listener, 0, 99, createStream("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg")).read();
|
||||
|
||||
InOrder order = inOrder(listener);
|
||||
order.verify(listener).thumbnailStarted(0, 99);
|
||||
order.verify(listener, atLeastOnce()).thumbnailProgress(100f);
|
||||
order.verify(listener).thumbnailComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
/*
|
||||
* 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 of the copyright holder 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 HOLDER 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.stream.URLImageInputStreamSpi;
|
||||
@@ -55,12 +85,12 @@ public class JPEGImage10MetadataCleanerTest {
|
||||
reader.setInput(input);
|
||||
|
||||
IIOMetadata original = origReader.getImageMetadata(0);
|
||||
IIOMetadataNode origTree = (IIOMetadataNode) original.getAsTree(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
IIOMetadataNode origTree = (IIOMetadataNode) original.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
|
||||
JPEGImage10MetadataCleaner cleaner = new JPEGImage10MetadataCleaner((JPEGImageReader) reader);
|
||||
IIOMetadata cleaned = cleaner.cleanMetadata(origReader.getImageMetadata(0));
|
||||
|
||||
IIOMetadataNode cleanTree = (IIOMetadataNode) cleaned.getAsTree(JPEGImage10MetadataCleaner.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
IIOMetadataNode cleanTree = (IIOMetadataNode) cleaned.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
|
||||
NodeList origDHT = origTree.getElementsByTagName("dht");
|
||||
assertEquals(1, origDHT.getLength());
|
||||
|
||||
@@ -4,37 +4,60 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTestCase;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.NodeList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import javax.imageio.*;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
@@ -43,19 +66,14 @@ import javax.imageio.spi.ImageWriterSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest;
|
||||
|
||||
/**
|
||||
* JPEGImageWriterTest
|
||||
@@ -64,45 +82,44 @@ import static org.junit.Assert.assertNotNull;
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JPEGImageWriterTest.java,v 1.0 06.02.12 17:05 haraldk Exp$
|
||||
*/
|
||||
public class JPEGImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
|
||||
private static final JPEGImageWriterSpi SPI = new JPEGImageWriterSpi(lookupDelegateProvider());
|
||||
|
||||
public class JPEGImageWriterTest extends ImageWriterAbstractTest<JPEGImageWriter> {
|
||||
private static ImageWriterSpi lookupDelegateProvider() {
|
||||
return IIOUtil.lookupProviderByName(IIORegistry.getDefaultInstance(), "com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi", ImageWriterSpi.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImageWriter createImageWriter() {
|
||||
try {
|
||||
return SPI.createWriterInstance();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
protected ImageWriterSpi createProvider() {
|
||||
return new JPEGImageWriterSpi(lookupDelegateProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<? extends RenderedImage> getTestData() {
|
||||
ColorModel cmyk = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
||||
return Arrays.asList(
|
||||
new BufferedImage(320, 200, BufferedImage.TYPE_3BYTE_BGR),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_INT_RGB),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_INT_BGR),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_INT_ARGB),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_4BYTE_ABGR),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_BYTE_GRAY)
|
||||
// Java 11+ no longer supports RGBA JPEG
|
||||
// new BufferedImage(32, 20, BufferedImage.TYPE_INT_ARGB),
|
||||
// new BufferedImage(32, 20, BufferedImage.TYPE_4BYTE_ABGR),
|
||||
new BufferedImage(32, 20, BufferedImage.TYPE_BYTE_GRAY),
|
||||
new BufferedImage(cmyk, cmyk.createCompatibleWritableRaster(32, 20), cmyk.isAlphaPremultiplied(), null)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReaderForWriter() {
|
||||
ImageWriter writer = createImageWriter();
|
||||
public void testReaderForWriter() throws IOException {
|
||||
ImageWriter writer = createWriter();
|
||||
ImageReader reader = ImageIO.getImageReader(writer);
|
||||
assertNotNull(reader);
|
||||
assertEquals(writer.getClass().getPackage(), reader.getClass().getPackage());
|
||||
}
|
||||
|
||||
private ByteArrayOutputStream transcode(final ImageReader reader, final URL resource, final ImageWriter writer, int outCSType) throws IOException {
|
||||
return transcode(reader, resource, writer, outCSType, true);
|
||||
}
|
||||
|
||||
private ByteArrayOutputStream transcode(final ImageReader reader, final URL resource, final ImageWriter writer, int outCSType, boolean embedICCProfile) throws IOException {
|
||||
try (ImageInputStream input = ImageIO.createImageInputStream(resource)) {
|
||||
reader.setInput(input);
|
||||
ImageTypeSpecifier specifier = null;
|
||||
@@ -123,6 +140,14 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
readParam.setDestinationType(specifier);
|
||||
IIOImage image = reader.readAll(0, readParam);
|
||||
|
||||
if (!embedICCProfile) {
|
||||
// Get rid of the color model/icc profile
|
||||
ColorSpace fakeCS = mock(ColorSpace.class);
|
||||
when(fakeCS.getType()).thenReturn(ColorSpace.TYPE_CMYK);
|
||||
when(fakeCS.getNumComponents()).thenReturn(4);
|
||||
specifier = new ImageTypeSpecifier(new ComponentColorModel(fakeCS, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE), image.getRenderedImage().getSampleModel());
|
||||
}
|
||||
|
||||
// Write it back
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
|
||||
try (ImageOutputStream output = new MemoryCacheImageOutputStream(bytes)) {
|
||||
@@ -138,7 +163,7 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
|
||||
@Test
|
||||
public void testTranscodeWithMetadataRGBtoRGB() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ImageWriter writer = createWriter();
|
||||
ImageReader reader = ImageIO.getImageReader(writer);
|
||||
|
||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/jfif-jfxx-thumbnail-olympus-d320l.jpg"), writer, ColorSpace.TYPE_RGB);
|
||||
@@ -149,11 +174,18 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
reader.setInput(new ByteArrayImageInputStream(stream.toByteArray()));
|
||||
BufferedImage image = reader.read(0);
|
||||
assertNotNull(image);
|
||||
|
||||
// Test color space type RGB (encoded as YCbCr) in standard metadata
|
||||
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||
assertEquals(1, colorSpaceType.getLength());
|
||||
assertEquals("YCbCr", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTranscodeWithMetadataCMYKtoCMYK() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
ImageWriter writer = createWriter();
|
||||
ImageReader reader = ImageIO.getImageReader(writer);
|
||||
|
||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK);
|
||||
@@ -166,11 +198,65 @@ public class JPEGImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
assertEquals(100, image.getWidth());
|
||||
assertEquals(100, image.getHeight());
|
||||
|
||||
// Test color space type CMYK in standard metadata
|
||||
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||
assertEquals(1, colorSpaceType.getLength());
|
||||
assertEquals("CMYK", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||
|
||||
// Test APP2/ICC_PROFILE segments form native metadata
|
||||
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||
assertEquals(11, unknown.getLength()); // We write longer segments than the original, so we get less segments
|
||||
|
||||
ByteArrayOutputStream iccSegments = new ByteArrayOutputStream(1024 * 1024);
|
||||
|
||||
for (int i = 0; i < unknown.getLength(); i++) {
|
||||
IIOMetadataNode node = (IIOMetadataNode) unknown.item(i);
|
||||
byte[] data = (byte[]) node.getUserObject();
|
||||
|
||||
// 226 -> E2, FFE2 -> APP2 marker, ICC_PROFILE
|
||||
String markerId = "ICC_PROFILE";
|
||||
if (node.getAttribute("MarkerTag").equals("226")
|
||||
&& markerId.equals(new String(data, 0, markerId.length(), StandardCharsets.US_ASCII))) {
|
||||
int offset = markerId.length() + 3; // ICC_PROFILE + null + index + count
|
||||
iccSegments.write(Arrays.copyOfRange(data, offset, data.length));
|
||||
}
|
||||
}
|
||||
|
||||
ICC_Profile profile = ICC_Profile.getInstance(iccSegments.toByteArray());
|
||||
assertNotNull(profile); // Assumption, we either have a valid profile, or getInstance blew up...
|
||||
assertEquals(ColorSpace.TYPE_CMYK, profile.getColorSpaceType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTranscodeWithMetadataCMYKtoCMYKNoProfile() throws IOException {
|
||||
ImageWriter writer = createWriter();
|
||||
ImageReader reader = ImageIO.getImageReader(writer);
|
||||
|
||||
// TODO: Add flag to allow removing the ICC profile from image
|
||||
ByteArrayOutputStream stream = transcode(reader, getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), writer, ColorSpace.TYPE_CMYK, false);
|
||||
|
||||
reader.reset();
|
||||
reader.setInput(new ByteArrayImageInputStream(stream.toByteArray()));
|
||||
|
||||
BufferedImage image = reader.read(0);
|
||||
assertNotNull(image);
|
||||
assertEquals(100, image.getWidth());
|
||||
assertEquals(100, image.getHeight());
|
||||
|
||||
// Test color space type CMYK in standard metadata
|
||||
IIOMetadata metadata = reader.getImageMetadata(0);
|
||||
IIOMetadataNode standard = (IIOMetadataNode) metadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
|
||||
NodeList colorSpaceType = standard.getElementsByTagName("ColorSpaceType");
|
||||
assertEquals(1, colorSpaceType.getLength());
|
||||
assertEquals("CMYK", ((IIOMetadataNode) colorSpaceType.item(0)).getAttribute("name"));
|
||||
|
||||
// Test APP2/ICC_PROFILE segments form native metadata
|
||||
IIOMetadataNode nativeMeta = (IIOMetadataNode) metadata.getAsTree(JPEGImage10Metadata.JAVAX_IMAGEIO_JPEG_IMAGE_1_0);
|
||||
NodeList unknown = nativeMeta.getElementsByTagName("unknown");
|
||||
assertEquals(0, unknown.getLength());
|
||||
}
|
||||
|
||||
// TODO: YCCK
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
/*
|
||||
* 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 of the copyright holder 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 HOLDER 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.spi.ReaderWriterProviderInfo;
|
||||
|
||||
@@ -4,26 +4,28 @@
|
||||
*
|
||||
* 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.
|
||||
* * 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 of the copyright holder 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 HOLDER 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;
|
||||
@@ -32,6 +34,7 @@ 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.stream.URLImageInputStreamSpi;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.internal.matchers.LessOrEqual;
|
||||
|
||||
@@ -44,7 +47,9 @@ import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* JPEGSegmentImageInputStreamTest
|
||||
@@ -172,6 +177,32 @@ public class JPEGSegmentImageInputStreamTest {
|
||||
assertEquals(1061L, length); // Sanity check: same as file size, except padding and the filtered ICC_PROFILE segment
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEOFExceptionInSegmentParsingShouldNotCreateBadState2() throws IOException {
|
||||
ImageInputStream iis = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/51432b02-02a8-11e7-9203-b42b1c43c0c3.jpg")));
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
|
||||
// NOTE: This is a simulation of how the native parts of com.sun...JPEGImageReader would read the image...
|
||||
assertEquals(2, iis.read(buffer, 0, buffer.length));
|
||||
assertEquals(2, iis.getStreamPosition());
|
||||
|
||||
iis.seek(2000); // Just a random position beyond EOF
|
||||
assertEquals(2000, iis.getStreamPosition());
|
||||
|
||||
// So far, so good (but stream position is now really beyond EOF)...
|
||||
|
||||
// This however, will blow up with an EOFException internally (but we'll return -1 to be good)
|
||||
assertEquals(-1, iis.read(buffer, 0, buffer.length));
|
||||
assertEquals(-1, iis.read());
|
||||
assertEquals(2000, iis.getStreamPosition());
|
||||
|
||||
// Again, should just continue returning -1 for ever
|
||||
assertEquals(-1, iis.read());
|
||||
assertEquals(-1, iis.read(buffer, 0, buffer.length));
|
||||
assertEquals(2000, iis.getStreamPosition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEOFExceptionInSegmentParsingShouldNotCreateBadState() throws IOException {
|
||||
ImageInputStream iis = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/broken-no-sof-ascii-transfer-mode.jpg")));
|
||||
@@ -189,10 +220,37 @@ public class JPEGSegmentImageInputStreamTest {
|
||||
|
||||
// This however, will blow up with an EOFException internally (but we'll return -1 to be good)
|
||||
assertEquals(-1, iis.read(buffer, 0, buffer.length));
|
||||
assertEquals(-1, iis.read());
|
||||
assertEquals(0x2012, iis.getStreamPosition());
|
||||
|
||||
// Again, should just continue returning -1 for ever
|
||||
assertEquals(-1, iis.read(buffer, 0, buffer.length));
|
||||
assertEquals(-1, iis.read());
|
||||
assertEquals(0x2012, iis.getStreamPosition());
|
||||
}
|
||||
|
||||
|
||||
@Test(timeout = 1000L)
|
||||
public void testInfiniteLoopCorrupt() throws IOException {
|
||||
try (ImageInputStream stream = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg")))) {
|
||||
long length = 0;
|
||||
while (stream.read() != -1) {
|
||||
length++;
|
||||
}
|
||||
|
||||
assertEquals(25504L, length); // Sanity check: same as file size, except..?
|
||||
}
|
||||
|
||||
try (ImageInputStream stream = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg")))) {
|
||||
long length = 0;
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = stream.read(buffer)) != -1) {
|
||||
length += read;
|
||||
}
|
||||
|
||||
assertEquals(25504L, length); // Sanity check: same as file size, except..?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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 of the copyright holder 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 HOLDER 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 org.junit.Test;
|
||||
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class LuminanceToGrayTest {
|
||||
@Test
|
||||
public void testConvertByteYcc() {
|
||||
LuminanceToGray convert = new LuminanceToGray();
|
||||
|
||||
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 3, null);
|
||||
WritableRaster result = null;
|
||||
|
||||
byte[] pixel = null;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) (255 - i), (byte) (127 + i)});
|
||||
result = convert.filter(input, result);
|
||||
pixel = (byte[]) result.getDataElements(0, 0, pixel);
|
||||
|
||||
assertNotNull(pixel);
|
||||
assertEquals(1, pixel.length);
|
||||
byte[] expected = {(byte) i};
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertByteYccK() {
|
||||
LuminanceToGray convert = new LuminanceToGray();
|
||||
|
||||
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 4, null);
|
||||
WritableRaster result = null;
|
||||
|
||||
byte[] pixel = null;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) (255 - i), (byte) (127 + i), (byte) 255});
|
||||
result = convert.filter(input, result);
|
||||
pixel = (byte[]) result.getDataElements(0, 0, pixel);
|
||||
|
||||
assertNotNull(pixel);
|
||||
assertEquals(1, pixel.length);
|
||||
byte[] expected = {(byte) i};
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertByteYccA() {
|
||||
LuminanceToGray convert = new LuminanceToGray();
|
||||
|
||||
WritableRaster input = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 4, null);
|
||||
WritableRaster result = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 1, 1, 2, null);
|
||||
|
||||
byte[] pixel = null;
|
||||
for (int i = 0; i < 255; i++) {
|
||||
input.setDataElements(0, 0, new byte[] {(byte) i, (byte) 255, (byte) (127 + i), (byte) (255 - i)});
|
||||
result = convert.filter(input, result);
|
||||
pixel = (byte[]) result.getDataElements(0, 0, pixel);
|
||||
|
||||
assertNotNull(pixel);
|
||||
assertEquals(2, pixel.length);
|
||||
byte[] expected = {(byte) i, (byte) (255 - i)};
|
||||
assertArrayEquals(String.format("Was: %s, expected: %s", Arrays.toString(pixel), Arrays.toString(expected)), expected, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
|
||||
|
||||
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.
|
||||
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 341 KiB |
|
After Width: | Height: | Size: 341 KiB |
|
After Width: | Height: | Size: 340 KiB |
|
After Width: | Height: | Size: 343 KiB |
|
After Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 344 KiB |
|
After Width: | Height: | Size: 243 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 242 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 246 KiB |
|
After Width: | Height: | Size: 245 KiB |
|
After Width: | Height: | Size: 246 KiB |
@@ -0,0 +1,82 @@
|
||||
EXIF Orientation-flag example images
|
||||
====================================
|
||||
|
||||
Example images using each of the EXIF orientation flags (0-to-8), in both landscape and portrait orientations.
|
||||
|
||||
[See here](http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/) for more information.
|
||||
|
||||
|
||||
Generating your own images
|
||||
--------------------------
|
||||
|
||||
If you would like to generate test images based on your own photos, you can use the `generate.rb` script included in the `generator` folder.
|
||||
|
||||
The instructions below assume you are running on macOS - if not, you will need to install the Ghostscript fonts (`brew install gs`) some other way.
|
||||
|
||||
To install the dependencies:
|
||||
|
||||
```
|
||||
> brew install gs exiftool imagemagick@6
|
||||
> cd generator
|
||||
> gem install bundler
|
||||
> bundle install
|
||||
```
|
||||
|
||||
To generate test images:
|
||||
|
||||
```
|
||||
> cd generator
|
||||
> ./generate.rb path/to/image.jpg
|
||||
```
|
||||
|
||||
This will create images `image_0.jpg` through to `image_8.jpg`.
|
||||
|
||||
|
||||
Re-generating sample images
|
||||
---------------------------
|
||||
|
||||
Simply run `make` to regenerate the included sample images. This will download random portrait and landscape orientation images from [unsplash.com](https://unsplash.com/) and generate sample images for each of them.
|
||||
|
||||
Generating these images depends on having the generator dependencies installed - see the *Generating your own images* section for instructions on installing dependencies.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
* The sample landscape image is by [Pierre Bouillot](https://unsplash.com/photos/v15iOM6pWgI).
|
||||
* The sample portrait image is by [John Salvino](https://unsplash.com/photos/1PPpwrTNkJI).
|
||||
|
||||
|
||||
Change history
|
||||
--------------
|
||||
|
||||
* **Version 2.0.0 (2017-08-05)** : Add a script to generate example images from the command line.
|
||||
* **Version 1.0.2 (2017-03-06)** : Remove Apple Copyrighted ICC profile from orientations 2-8 (thanks @mans0954!).
|
||||
* **Version 1.0.1 (2013-03-10)** : Add MIT license and some contact details.
|
||||
* **Version 1.0.0 (2012-07-28)** : 1.0 release.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Once you've made your commits:
|
||||
|
||||
1. [Fork](http://help.github.com/fork-a-repo/) exif-orientation-examples
|
||||
2. Create a topic branch - `git checkout -b my_branch`
|
||||
3. Push to your branch - `git push origin my_branch`
|
||||
4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch
|
||||
5. That's it!
|
||||
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
Dave Perrett :: hello@daveperrett.com :: [@daveperrett](http://twitter.com/daveperrett)
|
||||
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
These images are licensed under the [MIT License](http://opensource.org/licenses/MIT).
|
||||
|
||||
Copyright (c) 2010 Dave Perrett. See [License](https://github.com/recurser/exif-orientation-examples/blob/master/LICENSE) for details.
|
||||
@@ -0,0 +1 @@
|
||||
2.0.1
|
||||
|
After Width: | Height: | Size: 172 KiB |
|
After Width: | Height: | Size: 2.7 MiB |