summaryrefslogtreecommitdiff
path: root/pdf-over-signator
diff options
context:
space:
mode:
authorTobias Kellner <tobias.kellner@iaik.tugraz.at>2016-11-15 16:06:18 +0100
committerTobias Kellner <tobias.kellner@iaik.tugraz.at>2016-11-15 16:06:18 +0100
commit2390462418facd6c323143c06cc30c1ba6051c97 (patch)
tree5c81a608d5cc5adb627a7f696d02078f30ed9ac8 /pdf-over-signator
parent7cd102ad6924c97974b79e36a946b5dcd6c7e407 (diff)
downloadmocca-2390462418facd6c323143c06cc30c1ba6051c97.tar.gz
mocca-2390462418facd6c323143c06cc30c1ba6051c97.tar.bz2
mocca-2390462418facd6c323143c06cc30c1ba6051c97.zip
Honor EXIF orientation metadata for JPEG logos
Diffstat (limited to 'pdf-over-signator')
-rw-r--r--pdf-over-signator/pom.xml4
-rw-r--r--pdf-over-signator/src/main/java/at/asit/pdfover/signator/CachedFileNameEmblem.java189
2 files changed, 150 insertions, 43 deletions
diff --git a/pdf-over-signator/pom.xml b/pdf-over-signator/pom.xml
index f66f9aad..bd829225 100644
--- a/pdf-over-signator/pom.xml
+++ b/pdf-over-signator/pom.xml
@@ -20,5 +20,9 @@
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.drewnoakes</groupId>
+ <artifactId>metadata-extractor</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/pdf-over-signator/src/main/java/at/asit/pdfover/signator/CachedFileNameEmblem.java b/pdf-over-signator/src/main/java/at/asit/pdfover/signator/CachedFileNameEmblem.java
index fe08abb6..73f25837 100644
--- a/pdf-over-signator/src/main/java/at/asit/pdfover/signator/CachedFileNameEmblem.java
+++ b/pdf-over-signator/src/main/java/at/asit/pdfover/signator/CachedFileNameEmblem.java
@@ -26,14 +26,24 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.Iterator;
import java.util.Properties;
import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.imaging.ImageProcessingException;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.MetadataException;
+import com.drew.metadata.exif.ExifDirectoryBase;
+import com.drew.metadata.exif.ExifIFD0Directory;
+
/**
*
*/
@@ -44,6 +54,16 @@ public class CachedFileNameEmblem implements Emblem {
private static final Logger log = LoggerFactory
.getLogger(CachedFileNameEmblem.class);
+ private final String fileDir = System.getProperty("user.home") + File.separator + ".pdf-over"; //$NON-NLS-1$ //$NON-NLS-2$
+ private final String imgFileName = ".emblem"; //$NON-NLS-1$
+ private final String imgFileExt = "png"; //$NON-NLS-1$
+ private final String propFileName = ".emblem.properties"; //$NON-NLS-1$
+
+ private final String imgProp = "IMG"; //$NON-NLS-1$
+ private final String hshProp = "HSH"; //$NON-NLS-1$
+ private final int maxWidth = 480;
+ private final int maxHeight = 600;
+
private String fileName = null;
/**
@@ -59,24 +79,126 @@ public class CachedFileNameEmblem implements Emblem {
return DigestUtils.md5Hex(is);
}
+ /**
+ * Correctly rotate JPEG image by EXIF header
+ * @param img the image
+ * @param imgFile the image file
+ * @return the fixed image
+ */
+ public static BufferedImage fixImage(BufferedImage img, File imgFile) {
+ int oheight = img.getHeight();
+ int owidth = img.getWidth();
+
+ // Read EXIF metadata for jpeg
+ ImageInputStream iis = null;
+ try {
+ iis = ImageIO.createImageInputStream(imgFile);
+ Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis);
+
+ while (imageReaders.hasNext()) {
+ ImageReader reader = imageReaders.next();
+ log.debug(reader.getFormatName());
+ if (reader.getFormatName().equals("JPEG")) {
+ try {
+ Metadata metadata = ImageMetadataReader.readMetadata(imgFile);
+ int orientation = metadata.getFirstDirectoryOfType(
+ ExifIFD0Directory.class).getInt(
+ ExifDirectoryBase.TAG_ORIENTATION);
+ if (orientation > 2) {
+ // rotate
+ double rotation = 0;
+ int height = owidth;
+ int width = oheight;
+ switch ((orientation + 1) / 2) {
+ case 2:
+ rotation = Math.PI;
+ height = oheight;
+ width = owidth;
+ break;
+ case 3:
+ rotation = Math.PI/2;
+ break;
+ case 4:
+ rotation = 3*Math.PI/2;
+ break;
+ }
+ log.debug("EXIF orientation " + orientation + ", rotating " + rotation + "rad");
+ BufferedImage result = new BufferedImage(width, height, img.getType());
+ Graphics2D g = result.createGraphics();
+ g.translate((width - owidth) / 2, (height - oheight) / 2);
+ g.rotate(rotation, owidth / 2, oheight / 2);
+ g.drawRenderedImage(img, null);
+ g.dispose();
+ img = result;
+ owidth = width;
+ oheight = height;
+ }
+ if (((orientation < 5) && (orientation % 2 == 0)) ||
+ (orientation > 5) && (orientation % 2 == 1)) {
+ // flip
+ log.debug("flipping image");
+ BufferedImage result = new BufferedImage(owidth, oheight, img.getType());
+ Graphics2D g = result.createGraphics();
+ g.drawImage(img, owidth, 0, -owidth, oheight, null);
+ g.dispose();
+ img = result;
+ }
+ } catch (ImageProcessingException e) {
+ log.error("Error reading emblem metadata", e);
+ } catch (MetadataException e) {
+ log.error("Error reading emblem metadata", e);
+ }
+ }
+ }
+ } catch (IOException e) {
+ log.error("Error reading image" , e);
+ } finally {
+ try {
+ if (iis != null)
+ iis.close();
+ } catch (IOException e) {
+ log.debug("Error closing stream", e);
+ }
+ }
+ return img;
+ }
+
+ private static BufferedImage scaleImage(BufferedImage img, int maxWidth, int maxHeight) {
+ int oheight = img.getHeight();
+ int owidth = img.getWidth();
+
+ double ratio = (double)owidth/(double)oheight;
+
+ int height = oheight;
+ int width = owidth;
+ if (height > maxHeight) {
+ height = maxHeight;
+ width = (int) (maxHeight * ratio);
+ }
+ if (width > maxWidth) {
+ width = maxWidth;
+ height = (int) (maxWidth / ratio);
+ }
+ BufferedImage result = img;
+ if (width != owidth || height == oheight) {
+ //scale image
+ log.debug("Scaling emblem: " + owidth + "x" + oheight + " to " + width + "x" + height); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ result = new BufferedImage(width, height, img.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : img.getType());
+ Graphics2D g = result.createGraphics();
+ g.drawImage(img, 0, 0, width, height, null);
+ g.dispose();
+ }
+ return result;
+ }
+
/* (non-Javadoc)
* @see at.asit.pdfover.signator.Emblem#getFileName()
*/
@Override
public String getFileName() {
- final String fileDir = System.getProperty("user.home") + File.separator + ".pdf-over"; //$NON-NLS-1$ //$NON-NLS-2$
- final String imgFileName = ".emblem"; //$NON-NLS-1$
- final String imgFileExt = "png"; //$NON-NLS-1$
- final String propFileName = ".emblem.properties"; //$NON-NLS-1$
-
- final String imgProp = "IMG"; //$NON-NLS-1$
- final String hshProp = "HSH"; //$NON-NLS-1$
- final int maxWidth = 480;
- final int maxHeight = 600;
-
String emblemImg = this.fileName;
String emblemHsh = null;
- String cachedEmblemFileName = fileDir + File.separator + imgFileName + "." + imgFileExt; //$NON-NLS-1$
+ String cachedEmblemFileName = this.fileDir + File.separator + this.imgFileName + "." + this.imgFileExt; //$NON-NLS-1$
if (emblemImg == null || !(new File(emblemImg).exists()))
return null;
@@ -84,11 +206,11 @@ public class CachedFileNameEmblem implements Emblem {
Properties emblemProps = new Properties();
// compare cache, try to load if match
try {
- InputStream in = new FileInputStream(new File(fileDir, propFileName));
+ InputStream in = new FileInputStream(new File(this.fileDir, this.propFileName));
emblemProps.load(in);
- if (emblemImg.equals(emblemProps.getProperty(imgProp))) {
+ if (emblemImg.equals(emblemProps.getProperty(this.imgProp))) {
emblemHsh = getFileHash(emblemImg);
- if (emblemHsh.equals(emblemProps.getProperty(hshProp))) {
+ if (emblemHsh.equals(emblemProps.getProperty(this.hshProp))) {
log.debug("Emblem cache hit: " + cachedEmblemFileName); //$NON-NLS-1$
return cachedEmblemFileName; //$NON-NLS-1$
}
@@ -102,36 +224,17 @@ public class CachedFileNameEmblem implements Emblem {
// create new cache
if (emblemHsh == null)
emblemHsh = getFileHash(emblemImg);
- emblemProps.setProperty(imgProp, emblemImg);
- emblemProps.setProperty(hshProp, emblemHsh);
- BufferedImage img = ImageIO.read(new File(emblemImg));
- int oheight = img.getHeight();
- int owidth = img.getWidth();
- double ratio = (double)owidth/(double)oheight;
-
- int height = oheight;
- int width = owidth;
- if (height > maxHeight) {
- height = maxHeight;
- width = (int) (maxHeight * ratio);
- }
- if (width > maxWidth) {
- width = maxWidth;
- height = (int) (maxWidth / ratio);
- }
- BufferedImage cacheImg = img;
- if (width != owidth || height == oheight) {
- //scale image
- log.debug("Scaling emblem: " + owidth + "x" + oheight + " to " + width + "x" + height); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
- cacheImg = new BufferedImage(width, height, img.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : img.getType());
- Graphics2D g = cacheImg.createGraphics();
- g.drawImage(img, 0, 0, width, height, null);
- g.dispose();
- }
+ emblemProps.setProperty(this.imgProp, emblemImg);
+ emblemProps.setProperty(this.hshProp, emblemHsh);
+ File imgFile = new File(emblemImg);
+
+ BufferedImage img = ImageIO.read(imgFile);
+ img = fixImage(img, imgFile);
+ img = scaleImage(img, this.maxWidth, this.maxHeight);
- File file = new File(fileDir, imgFileName + "." + imgFileExt); //$NON-NLS-1$
- ImageIO.write(cacheImg, imgFileExt, file); // ignore returned boolean
- OutputStream out = new FileOutputStream(new File(fileDir, propFileName));
+ File file = new File(this.fileDir, this.imgFileName + "." + this.imgFileExt); //$NON-NLS-1$
+ ImageIO.write(img, this.imgFileExt, file); // ignore returned boolean
+ OutputStream out = new FileOutputStream(new File(this.fileDir, this.propFileName));
emblemProps.store(out, null);
} catch (IOException e) {
log.error("Can't save emblem cache", e); //$NON-NLS-1$