/*
* Copyright (C) 2016 Patrick Favre-Bulle
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package at.favre.tools.dconvert.util;
import at.favre.tools.dconvert.arg.Arguments;
import at.favre.tools.dconvert.arg.ImageType;
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
import com.twelvemonkeys.imageio.metadata.exif.EXIFReader;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEG;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
/**
* Main Util class containing all
*/
public class ImageUtil {
public static LoadedImage loadImage(File input) throws Exception {
if (input == null) {
throw new IllegalArgumentException("input == null!");
}
if (!input.canRead()) {
throw new IIOException("Can't read input file!");
}
ImageInputStream stream = ImageIO.createImageInputStream(input);
if (stream == null) {
throw new IIOException("Can't create an ImageInputStream!");
}
LoadedImage image = read(stream, Arguments.getImageType(input));
if (image.getImage() == null) {
stream.close();
}
return new LoadedImage(input, image.getImage(), image.getMetadata(), readExif(input));
}
private static CompoundDirectory readExif(File input) throws IOException {
if (Arguments.getImageType(input) == ImageType.JPG) {
try (ImageInputStream stream = ImageIO.createImageInputStream(input)) {
List<JPEGSegment> exifSegment = JPEGSegmentUtil.readSegments(stream, JPEG.APP1, "Exif");
if (!exifSegment.isEmpty()) {
InputStream exifData = exifSegment.get(0).data();
exifData.read(); // Skip 0-pad for Exif in JFIF
try (ImageInputStream exifStream = ImageIO.createImageInputStream(exifData)) {
return (CompoundDirectory) new EXIFReader().read(exifStream);
}
}
} catch (Exception e) {
System.err.println("could not read exif");
e.printStackTrace();
return null;
}
}
return null;
}
private static LoadedImage read(ImageInputStream stream, ImageType imageType) throws IOException {
if (stream == null) {
throw new IllegalArgumentException("stream == null!");
}
Iterator iter = ImageIO.getImageReaders(stream);
if (!iter.hasNext()) {
return null;
}
ImageReader reader = (ImageReader) iter.next();
ImageReadParam param = reader.getDefaultReadParam();
reader.setInput(stream, true, true);
BufferedImage bi;
IIOMetadata metadata;
try {
metadata = reader.getImageMetadata(0);
bi = reader.read(0, param);
} finally {
reader.dispose();
stream.close();
}
return new LoadedImage(null, bi, metadata, null);
}
@Deprecated
public static BufferedImage readSvg(File file, Dimension sourceDimension) throws Exception {
try (ImageInputStream input = ImageIO.createImageInputStream(file)) {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext()) {
throw new IllegalArgumentException("No reader for: " + file);
}
ImageReader reader = readers.next();
try {
reader.setInput(input);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRenderSize(sourceDimension);
return reader.read(0, param);
} finally {
reader.dispose();
}
}
}
/**
* Gets image dimensions for given file
*
* @param imgFile image file
* @return dimensions of image
* @throws IOException if the file is not a known image
*/
public static Dimension getImageDimension(File imgFile) throws IOException {
int pos = imgFile.getName().lastIndexOf(".");
if (pos == -1)
throw new IOException("No extension for file: " + imgFile.getAbsolutePath());
String suffix = imgFile.getName().substring(pos + 1);
Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
if (iter.hasNext()) {
ImageReader reader = iter.next();
try {
ImageInputStream stream = new FileImageInputStream(imgFile);
reader.setInput(stream);
int width = reader.getWidth(reader.getMinIndex());
int height = reader.getHeight(reader.getMinIndex());
return new Dimension(width, height);
} finally {
reader.dispose();
}
}
throw new IOException("Not a known image file: " + imgFile.getAbsolutePath());
}
}