mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-01 00:00:02 -04:00
Major ImageMetadata refactor for more consistent standard metadata support.
Fixes a few related bugs as a bonus.
This commit is contained in:
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.icns;
|
||||
|
||||
import com.twelvemonkeys.imageio.StandardImageMetadataSupport;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
|
||||
final class ICNSImageMetadata extends StandardImageMetadataSupport {
|
||||
ICNSImageMetadata(ImageTypeSpecifier type, String compressionName) {
|
||||
super(builder(type).withCompressionName(compressionName));
|
||||
}
|
||||
}
|
||||
+29
-15
@@ -35,11 +35,16 @@ import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
@@ -61,10 +66,9 @@ import java.util.List;
|
||||
* @see <a href="http://en.wikipedia.org/wiki/Apple_Icon_Image_format">Apple Icon Image format (Wikipedia)</a>
|
||||
*/
|
||||
public final class ICNSImageReader extends ImageReaderBase {
|
||||
// TODO: Support ToC resource for faster parsing/faster determine number of icons?
|
||||
// TODO: Subsampled reading for completeness, even if never used?
|
||||
private List<IconResource> icons = new ArrayList<IconResource>();
|
||||
private List<IconResource> masks = new ArrayList<IconResource>();
|
||||
private final List<IconResource> icons = new ArrayList<>();
|
||||
private final List<IconResource> masks = new ArrayList<>();
|
||||
private IconResource lastResourceRead;
|
||||
|
||||
private int length;
|
||||
@@ -136,7 +140,7 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
ImageTypeSpecifier rawType = getRawImageType(imageIndex);
|
||||
IconResource resource = readIconResource(imageIndex);
|
||||
|
||||
List<ImageTypeSpecifier> specifiers = new ArrayList<ImageTypeSpecifier>();
|
||||
List<ImageTypeSpecifier> specifiers = new ArrayList<>();
|
||||
|
||||
switch (resource.depth()) {
|
||||
case 1:
|
||||
@@ -230,14 +234,9 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
packedSize -= 4;
|
||||
}
|
||||
|
||||
InputStream input = IIOUtil.createStreamAdapter(imageInput, packedSize);
|
||||
|
||||
try {
|
||||
try (InputStream input = IIOUtil.createStreamAdapter(imageInput, packedSize)) {
|
||||
ICNSUtil.decompress(new DataInputStream(input), data, 0, (data.length * 24) / 32); // 24 bit data
|
||||
}
|
||||
finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
data = new byte[resource.length - ICNS.RESOURCE_HEADER_SIZE];
|
||||
@@ -491,7 +490,7 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
|
||||
String format;
|
||||
|
||||
if (Arrays.equals(ICNS.PNG_MAGIC, magic)) {
|
||||
if (Arrays.equals(ICNS.PNG_MAGIC, Arrays.copyOfRange(magic, 0, ICNS.PNG_MAGIC.length))) {
|
||||
format = "PNG";
|
||||
}
|
||||
else if (Arrays.equals(ICNS.JPEG_2000_MAGIC, magic)) {
|
||||
@@ -527,7 +526,6 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
IconResource resource = IconResource.read(imageInput);
|
||||
|
||||
if (resource.isTOC()) {
|
||||
// TODO: IconResource.readTOC()?
|
||||
int resourceCount = (resource.length - ICNS.RESOURCE_HEADER_SIZE) / ICNS.RESOURCE_HEADER_SIZE;
|
||||
long pos = resource.start + resource.length;
|
||||
|
||||
@@ -570,6 +568,23 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
|
||||
IconResource resource = readIconResource(imageIndex);
|
||||
|
||||
String compressionName;
|
||||
if (resource.isForeignFormat()) {
|
||||
// Special handling of PNG/JPEG 2000 icons
|
||||
imageInput.seek(resource.start + ICNS.RESOURCE_HEADER_SIZE);
|
||||
compressionName = getForeignFormat(imageInput);
|
||||
}
|
||||
else {
|
||||
compressionName = resource.isCompressed() ? "RLE" : "None";
|
||||
}
|
||||
|
||||
return new ICNSImageMetadata(getRawImageType(imageIndex), compressionName);
|
||||
}
|
||||
|
||||
private static final class ICNSBitMaskColorModel extends IndexColorModel {
|
||||
static final IndexColorModel INSTANCE = new ICNSBitMaskColorModel();
|
||||
|
||||
@@ -578,7 +593,6 @@ public final class ICNSImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedAssignment"})
|
||||
public static void main(String[] args) throws IOException {
|
||||
int argIndex = 0;
|
||||
|
||||
|
||||
+8
-1
@@ -34,7 +34,13 @@ import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||
|
||||
import javax.imageio.*;
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.event.IIOWriteWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
@@ -104,6 +110,7 @@ public final class ICNSImageWriter extends ImageWriterBase {
|
||||
sequenceIndex = 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
@Override
|
||||
public void endWriteSequence() throws IOException {
|
||||
assertOutput();
|
||||
|
||||
+9
-15
@@ -38,8 +38,13 @@ import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
@@ -140,17 +145,12 @@ final class SipsJP2Reader {
|
||||
}
|
||||
|
||||
private static String checkErrorMessage(final Process process) throws IOException {
|
||||
InputStream stream = process.getErrorStream();
|
||||
|
||||
try {
|
||||
try (InputStream stream = process.getErrorStream()) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||
String message = reader.readLine();
|
||||
|
||||
return message != null && message.startsWith("Error: ") ? message.substring(7) : null;
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] buildCommand(final File sipsCommand, final File tempFile) {
|
||||
@@ -159,19 +159,13 @@ final class SipsJP2Reader {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static File dumpToFile(final ImageInputStream stream) throws IOException {
|
||||
File tempFile = File.createTempFile("imageio-icns-", ".png");
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
FileOutputStream out = new FileOutputStream(tempFile);
|
||||
|
||||
try {
|
||||
try (FileOutputStream out = new FileOutputStream(tempFile)) {
|
||||
FileUtil.copy(IIOUtil.createStreamAdapter(stream), out);
|
||||
}
|
||||
finally {
|
||||
out.close();
|
||||
}
|
||||
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user