/*
*
* Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under
* one or more contributor license agreements (see COPYRIGHT for details).
* The CA licenses this file to you under the GNU Affero General Public
* License version 3, (the "License"); you may not use this file except in
* compliance with the License. This file is part of kune.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
\*/
package cc.kune.core.server.manager.file;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.io.File;
import java.io.FileNotFoundException;
import magick.ImageInfo;
import magick.MagickException;
import magick.MagickImage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import cc.kune.core.client.services.ImageSize;
// TODO: Auto-generated Javadoc
/**
* The Class ImageUtilsDefault.
*
* @author vjrj@ourproject.org (Vicente J. Ruiz Jurado)
*/
public class ImageUtilsDefault {
/** The Constant LOG. */
public static final Log LOG = LogFactory.getLog(ImageUtilsDefault.class);
/**
* Calculate centered coordinate.
*
* @param size
* the size
* @param crop
* the crop
* @return the int
*/
static int calculateCenteredCoordinate(final int size, final int crop) {
final int i = (size - crop) / 2;
return i < 0 ? 0 : i;
}
/**
* Calculate prop dim.
*
* @param origWidth
* the orig width
* @param origHeight
* the orig height
* @param maxSize
* the max size
* @return the dimension
*/
static Dimension calculatePropDim(final int origWidth, final int origHeight, final int maxSize) {
return calculatePropDim(origWidth, origHeight, maxSize, true);
}
/**
* Calculate prop dim.
*
* @param origWidth
* the orig width
* @param origHeight
* the orig height
* @param maxSize
* the max size
* @param toShortest
* the to shortest
* @return the dimension
*/
static Dimension calculatePropDim(final int origWidth, final int origHeight, final int maxSize,
final boolean toShortest) {
final boolean higher = origHeight > origWidth;
final int propHeight = origHeight * maxSize / origWidth;
final int propWidth = origWidth * maxSize / origHeight;
final double height = toShortest ? (higher ? propHeight : maxSize) : (higher ? maxSize : propHeight);
final double width = toShortest ? (!higher ? propWidth : maxSize) : (!higher ? maxSize : propWidth);
if ((higher && origHeight <= maxSize) || (!higher && origWidth <= maxSize)) {
return new Dimension(origWidth, origHeight);
}
return new Dimension((int) width, (int) height);
}
/**
* Check exist.
*
* @param fileOrig
* the file orig
* @throws FileNotFoundException
* the file not found exception
*/
private static void checkExist(final String fileOrig) throws FileNotFoundException {
final File file = new File(fileOrig);
if (!file.exists()) {
throw new FileNotFoundException();
}
}
/**
* Creates the empty image info.
*
* @return the image info
* @throws MagickException
* the magick exception
*/
private static ImageInfo createEmptyImageInfo() throws MagickException {
final ImageInfo imageInfo = new ImageInfo();
return imageInfo;
}
/**
* Creates the empty image info with no page.
*
* @return the image info
* @throws MagickException
* the magick exception
*/
private static ImageInfo createEmptyImageInfoWithNoPage() throws MagickException {
final ImageInfo imageInfo = createEmptyImageInfo();
imageInfo.setPage("0x0+0+0");
return imageInfo;
}
/**
* http://en.wikipedia.org/wiki/Thumbnail
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param cropDimension
* the crop dimension
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static void createThumb(final String fileOrig, final String fileDest, final int cropDimension)
throws MagickException, FileNotFoundException {
createThumb(fileOrig, fileDest, cropDimension, cropDimension);
}
/**
* Creates the thumb.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param thumbDimension
* the thumb dimension
* @param cropDimension
* the crop dimension
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static void createThumb(final String fileOrig, final String fileDest, final int thumbDimension,
final int cropDimension) throws MagickException, FileNotFoundException {
checkExist(fileOrig);
if (thumbDimension < cropDimension) {
throw new IndexOutOfBoundsException("Thumb dimension must be bigger than crop dimension");
}
final MagickImage imageOrig = readImage(fileOrig);
final Dimension origDimension = imageOrig.getDimension();
final int origHeight = origDimension.height;
final int origWidth = origDimension.width;
final Dimension proportionalDim = calculatePropDim(origWidth, origHeight, thumbDimension, true);
final MagickImage scaled = scaleImage(imageOrig, proportionalDim.width, proportionalDim.height);
final int x = calculateCenteredCoordinate(proportionalDim.width, cropDimension);
final int y = calculateCenteredCoordinate(proportionalDim.height, cropDimension);
cropImage(scaled, fileDest, x, y, cropDimension, cropDimension);
}
/**
* convert -density 300 -quality 100 -resize 720x file.pdf result.png
*
* @param pdfFile
* the pdf file
* @param newPngFile
* the new png file
* @return true, if successful
* @throws MagickException
* the magick exception
*/
static public boolean createThumbFromPdf(final String pdfFile, final String newPngFile)
throws MagickException {
final MagickImage pdf = readImage(pdfFile);
final MagickImage pdf1 = pdf.breakFrames()[0];
return writeImage(pdf1, newPngFile);
}
/**
* Crop image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param x
* the x
* @param y
* the y
* @param width
* the width
* @param height
* the height
* @return true, if successful
* @throws MagickException
* the magick exception
*/
private static boolean cropImage(final MagickImage fileOrig, final String fileDest, final int x,
final int y, final int width, final int height) throws MagickException {
final Rectangle rectangle = new Rectangle(x, y, width, height);
return cropImage(fileOrig, fileDest, rectangle);
}
/**
* Crop image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param rectangle
* the rectangle
* @return true, if successful
* @throws MagickException
* the magick exception
*/
private static boolean cropImage(final MagickImage fileOrig, final String fileDest,
final Rectangle rectangle) throws MagickException {
final MagickImage cropped = fileOrig.cropImage(rectangle);
cropped.setFileName(fileDest);
final ImageInfo imageInfo = createEmptyImageInfoWithNoPage();
return cropped.writeImage(imageInfo);
}
/**
* Crop image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param x
* the x
* @param y
* the y
* @param width
* the width
* @param height
* the height
* @return true, if successful
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static boolean cropImage(final String fileOrig, final String fileDest, final int x,
final int y, final int width, final int height) throws MagickException, FileNotFoundException {
final Rectangle rectangle = new Rectangle(x, y, width, height);
return cropImage(fileOrig, fileDest, rectangle);
}
/**
* Crop image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param rectangle
* the rectangle
* @return true, if successful
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static boolean cropImage(final String fileOrig, final String fileDest, final Rectangle rectangle)
throws MagickException, FileNotFoundException {
checkExist(fileOrig);
return cropImage(readImage(fileOrig), fileDest, rectangle);
}
/**
* Generate thumbs.
*
* @param absDir
* the abs dir
* @param filename
* the filename
* @param extension
* the extension
* @param isPdf
* the is pdf
* @param resizeWidth
* the resize width
* @param thumbSize
* the thumb size
* @param cropSize
* the crop size
* @param iconSize
* the icon size
*/
public static void generateThumbs(final String absDir, final String filename, final String extension,
final boolean isPdf, final int resizeWidth, final int thumbSize, final int cropSize,
final int iconSize) {
try {
final String fileOrig = absDir + filename;
final String withoutExtension = FileUtils.getFileNameWithoutExtension(filename, extension);
final String resizeName = absDir + withoutExtension + "." + ImageSize.sized + "." + extension;
final String thumbName = absDir + withoutExtension + "." + ImageSize.thumb + "." + extension;
final String iconName = absDir + withoutExtension + "." + ImageSize.ico + "." + extension;
final String previewName = absDir + withoutExtension + "." + extension;
scaleImageToMax(fileOrig, resizeName, resizeWidth);
createThumb(fileOrig, thumbName, thumbSize, cropSize);
createThumb(fileOrig, iconName, iconSize);
if (isPdf) {
createThumbFromPdf(fileOrig, previewName);
}
} catch (final NumberFormatException e) {
LOG.error("Image sizes in kune.properties are not integers", e);
} catch (final MagickException e) {
LOG.info("Problem generating image thumb for " + filename, e);
} catch (final FileNotFoundException e) {
LOG.info("Original image not found generating image thumb for " + filename, e);
}
}
/**
* Gets the dimension.
*
* @param file
* the file
* @return the dimension
* @throws MagickException
* the magick exception
*/
public static Dimension getDimension(final String file) throws MagickException {
final MagickImage imageOrig = readImage(file);
return imageOrig.getDimension();
}
/**
* FIXME: Not working, returns null always (bug).
*
* @param file
* the file
* @return the page
* @throws MagickException
* the magick exception
*/
public static String getPage(final String file) throws MagickException {
final ImageInfo imageInfo = new ImageInfo(file);
new MagickImage(imageInfo);
return imageInfo.getPage();
}
/**
* Read image.
*
* @param file
* the file
* @return the magick image
* @throws MagickException
* the magick exception
*/
private static MagickImage readImage(final String file) throws MagickException {
final ImageInfo imageInfo = new ImageInfo(file);
return new MagickImage(imageInfo);
}
/**
* Scale image.
*
* @param imageOrig
* the image orig
* @param width
* the width
* @param height
* the height
* @return the magick image
* @throws MagickException
* the magick exception
*/
private static MagickImage scaleImage(final MagickImage imageOrig, final int width, final int height)
throws MagickException {
return imageOrig.scaleImage(width, height);
}
/**
* Scale image.
*
* @param imageOrig
* the image orig
* @param fileDest
* the file dest
* @param width
* the width
* @param height
* the height
* @return true, if successful
* @throws MagickException
* the magick exception
*/
private static boolean scaleImage(final MagickImage imageOrig, final String fileDest, final int width,
final int height) throws MagickException {
final MagickImage imageDest = scaleImage(imageOrig, width, height);
return writeImage(imageDest, fileDest);
}
/**
* Scale image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param dimension
* the dimension
* @return true, if successful
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static boolean scaleImage(final String fileOrig, final String fileDest,
final Dimension dimension) throws MagickException, FileNotFoundException {
checkExist(fileOrig);
final MagickImage imageOrig = readImage(fileOrig);
return scaleImage(imageOrig, fileDest, (int) dimension.getWidth(), (int) dimension.getHeight());
}
/**
* Scale image.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param width
* the width
* @param height
* the height
* @return true, if successful
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static boolean scaleImage(final String fileOrig, final String fileDest, final int width,
final int height) throws MagickException, FileNotFoundException {
checkExist(fileOrig);
final MagickImage imageOrig = readImage(fileOrig);
return scaleImage(imageOrig, fileDest, width, height);
}
/**
* Scale image to max.
*
* @param fileOrig
* the file orig
* @param fileDest
* the file dest
* @param maxSize
* the max size
* @return true, if successful
* @throws MagickException
* the magick exception
* @throws FileNotFoundException
* the file not found exception
*/
public static boolean scaleImageToMax(final String fileOrig, final String fileDest, final int maxSize)
throws MagickException, FileNotFoundException {
checkExist(fileOrig);
final MagickImage imageOrig = readImage(fileOrig);
final Dimension origDimension = imageOrig.getDimension();
final int origHeight = origDimension.height;
final int origWidth = origDimension.width;
final Dimension proportionalDim = calculatePropDim(origWidth, origHeight, maxSize, false);
final MagickImage scaled = scaleImage(imageOrig, proportionalDim.width, proportionalDim.height);
return writeImage(scaled, fileDest);
}
/**
* Write image.
*
* @param imageDest
* the image dest
* @param fileDest
* the file dest
* @return true, if successful
* @throws MagickException
* the magick exception
*/
private static boolean writeImage(final MagickImage imageDest, final String fileDest)
throws MagickException {
imageDest.setFileName(fileDest);
return imageDest.writeImage(createEmptyImageInfo());
}
}