/******************************************************************************* * Australian National University Data Commons * Copyright (C) 2013 The Australian National University * * This file is part of Australian National University Data Commons. * * Australian National University Data Commons is free software: you * can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package au.edu.anu.datacommons.image.magick; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import au.edu.anu.datacommons.image.filter.ImageAndDistFileFilter; import au.edu.anu.datacommons.image.main.DefaultProperties; /** * ConvertImage * * Australian National University Data Commons * * Convert Image functions * * JUnit Coverage: * None * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner (GT) Initial * </pre> * */ public class ConvertImage { /** * Constructor * * Constructor for the ConvertImage * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * */ public ConvertImage() { } /** * addTextToImage * * Add a strapline of text to the bottom of an image * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param filename A file or directory to retrieve the image for * @param leftText The text to place on the left of the * @param rightText * @throws IOException */ public void addTextToImage(String filename, String leftText, String rightText) throws IOException { File file = new File(filename); if (file.isFile()) { addTextToImage(file, leftText, rightText); } // Will need to change this if we want to recursively move through directories else if (file.isDirectory()) { System.out.println("Processing Images for Directory: " + file.getAbsolutePath()); File[] files = file.listFiles(new ImageAndDistFileFilter()); for (File filteredFile : files) { if (filteredFile.isFile()) { addTextToImage(filteredFile, leftText, rightText); } } } System.out.println("Adding Captions Complete"); } /** * addTextToImage * * Add the strapline text to an image for the given file * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param file * @param leftText * @param rightText * @throws IOException */ public void addTextToImage(File file, String leftText, String rightText) throws IOException { System.out.println("Adding Caption To: " + file.getAbsolutePath()); boolean performJavaText = true; try { addTextToImageMagick(file, leftText, rightText); performJavaText = false; } catch (IOException e) { System.out.println("Cannot convert image with Image Magick"); } if (performJavaText) { System.out.println("Adding caption via Java Images"); addTextToImageJava(file, leftText, rightText); } } /** * addTextToImageJava * * Add text to the image via the java graphics2d class * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param file The file to add text to * @param leftText The left caption to add * @param rightText The right caption to add * @throws IOException */ private void addTextToImageJava(File file, String leftText, String rightText) throws IOException { BufferedImage image = ImageIO.read(file); String name = file.getName(); String filename = name.substring(0, name.lastIndexOf(".")); String suffix = name.substring(name.lastIndexOf(".") + 1); int space = getStrapHeight(image.getHeight()); BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight() + space, BufferedImage.TYPE_INT_BGR); Graphics2D g2d = (Graphics2D) newImage.createGraphics(); g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)); g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)); g2d.drawImage(image, 0, 0, null); g2d.setColor(Color.BLACK); g2d.drawRect(0, image.getHeight(), image.getWidth(), space); g2d.setColor(Color.WHITE); g2d.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, space - 4)); FontMetrics fm = g2d.getFontMetrics(); g2d.drawString(leftText, 2, newImage.getHeight() - 2); int rightTextWidth = fm.stringWidth(rightText); g2d.drawString(rightText, newImage.getWidth() - rightTextWidth - 2, newImage.getHeight() - 2); g2d.dispose(); File outputFile = new File(file.getParent() + File.separator + filename + "-dist." + suffix); ImageIO.write(newImage, suffix, outputFile); } /** * addTextToImageMagick * * Add text to the image via image magick * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param file The file to add text to * @param leftText The left caption to add * @param rightText The right caption to add * @throws IOException */ private void addTextToImageMagick(File file, String leftText, String rightText) throws IOException { String name = file.getName(); String filename = name.substring(0, name.lastIndexOf(".")); String suffix = name.substring(name.lastIndexOf(".") + 1); String newFilename = file.getParent() + File.separator + filename + "-dist." + suffix; Dimension imageSize = getImageSize(file); //int space = 14; int space = getStrapHeight(imageSize.getHeight()); int pointsize = space - 4; String imageMagickLocation = DefaultProperties.getProperty("imagemagick.location"); StringBuilder sb = new StringBuilder(); sb.append("\""); sb.append(imageMagickLocation); sb.append("\" \"(\" "); sb.append(file.getAbsolutePath()); sb.append(" -gravity south -background black -splice 0x"); sb.append(space); sb.append(" \")\" -fill white -font Arial -pointsize "); sb.append(pointsize); sb.append(" -gravity southwest -annotate 0 \""); sb.append(leftText); sb.append("\" -gravity southeast -annotate 0 \""); sb.append(rightText); sb.append("\" "); sb.append(newFilename); Process process = Runtime.getRuntime().exec(sb.toString()); try { process.waitFor(); } catch (InterruptedException e) { System.out.println("Image Magick Process Interrupted"); } } /** * getStrapHeight * * Get the height for the black strapline * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param height * @return */ private int getStrapHeight(int height) { return getStrapHeight(new Double(height)); } /** * getStrapHeight * * Get the height for the black strapline * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param height * @return */ private int getStrapHeight(double height) { return Math.max(new Double(height * 0.02).intValue(), 14); } /** * getImageSize * * Retrieve the dimensions of the image * * <pre> * Version Date Developer Description * 0.1 12/04/2013 Genevieve Turner(GT) Initial * </pre> * * @param file * @return * @throws IOException */ private Dimension getImageSize(File file) throws IOException { ImageInputStream in = ImageIO.createImageInputStream(file); try { final Iterator readers = ImageIO.getImageReaders(in); if (readers.hasNext()) { ImageReader reader = (ImageReader) readers.next(); try { reader.setInput(in); return new Dimension(reader.getWidth(0), reader.getHeight(0)); } finally { reader.dispose(); } } } finally { if (in != null) { in.close(); } } return null; } }