com.hfg.image.ImageMagick Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.image;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import com.hfg.util.Executor;
import com.hfg.util.io.StreamUtil;
//------------------------------------------------------------------------------
/**
* Wrapper for ImageMagick tools.
*
* @author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
public class ImageMagick
{
private int mJpgQuality = 100;
private static File sBinDir = new File("/opt/local/bin");
private static File sConvertExe;
private static File sIdentifyExe;
private static String CORNER_ADD = "corner_add.png";
private static String CORNER_SUB = "corner_sub.png";
//###########################################################################
// PUBLIC FUNCTIONS
//###########################################################################
//--------------------------------------------------------------------------
/**
Sets the location of the ImageMagick bin dir. Defaults to '/opt/local/bin'.
* @param inValue
*/
public static void setBinDir(File inValue)
{
sBinDir = inValue;
}
//--------------------------------------------------------------------------
public static File getBinDir()
{
return sBinDir;
}
//--------------------------------------------------------------------------
public ImageMagick setJpgQuality(int inValue)
{
mJpgQuality = inValue;
return this;
}
//--------------------------------------------------------------------------
public int getJpgQuality()
{
return mJpgQuality;
}
//--------------------------------------------------------------------------
public Dimension getImageDimensions(File inImageFile)
{
StringBuilder cmd = new StringBuilder();
cmd.append(getIdentifyExe());
cmd.append(" -format '%wx%h'");
cmd.append(" '" + inImageFile + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("Problem getting dimensions of '" + inImageFile + "':\n"
+ "COMMAND: '" + cmd.toString() + "'\n"
+ executor.getSTDERR());
}
String[] pieces = executor.getSTDOUT().trim().split("x", 2);
return new Dimension(Integer.parseInt(pieces[0]), Integer.parseInt(pieces[1]));
}
//--------------------------------------------------------------------------
public void scaleImage(File inOrigImg, int inMaxDimension, File inScaledImg)
{
StringBuilder cmd = new StringBuilder();
cmd.append(getConvertExe());
if (inMaxDimension > 0)
{
cmd.append(" -size '" + (inMaxDimension * 2) + "x" + (inMaxDimension * 2) + "'");
}
cmd.append(" '" + inOrigImg + "'");
if (ImageFormat.isJPEG(inScaledImg)) cmd.append(" -quality " + mJpgQuality);
if (inMaxDimension > 0)
{
cmd.append(" -thumbnail '" + inMaxDimension + "x" + inMaxDimension + ">'");
}
cmd.append(" '" + inScaledImg + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("Problem creating scaled image of '" + inOrigImg + "':\n"
+ "COMMAND: '" + cmd.toString() + "'\n"
+ executor.getSTDERR());
}
}
//--------------------------------------------------------------------------
public void convertImage(File inOrigImg, File inDestImg)
{
StringBuilder cmd = new StringBuilder();
cmd.append(getConvertExe());
cmd.append(" '" + inOrigImg + "'");
if (ImageFormat.isJPEG(inDestImg)) cmd.append(" -quality " + mJpgQuality);
cmd.append(" '" + inDestImg + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("ImageMagick problem w/ command: '" + cmd.toString() + "'\n"
+ executor.getSTDERR());
}
}
//--------------------------------------------------------------------------
/**
Addes a white matte and a 1-pixel border.
*/
public void addMatte(File inImageFile, int inMatteWidth)
{
StringBuilder cmd = new StringBuilder();
cmd.append(getConvertExe());
cmd.append(" '" + inImageFile + "'");
cmd.append(" -bordercolor white -border " + (inMatteWidth - 1));
cmd.append(" -bordercolor grey -border 1");
cmd.append(" '" + inImageFile + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("Problem adding matte to image '" + inImageFile + ":\n"
+ executor.getSTDERR());
}
}
//--------------------------------------------------------------------------
public void addImageShadow(File inImageFile)
{
addImageShadow(inImageFile, inImageFile);
}
//--------------------------------------------------------------------------
public void addImageShadow(File inImageFile, File inOutputImageFile)
{
StringBuilder cmd = new StringBuilder();
cmd.append(getConvertExe());
cmd.append(" -page +2+2");
cmd.append(" '" + inImageFile + "'");
cmd.append(" \\( +clone -background black -shadow 60x4+4+4 \\)");
// cmd.append(" +swap -background none -mosaic -depth 8 -colors 256 -quality 95");
cmd.append(" +swap -background none -mosaic -quality 95");
cmd.append(" '" + inOutputImageFile + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("Problem adding shadow to image '" + inImageFile + ":\n"
+ executor.getSTDERR());
}
}
//--------------------------------------------------------------------------
public void roundImageCorners(File inImageFile)
{
roundImageCorners(inImageFile, inImageFile);
}
//--------------------------------------------------------------------------
public void roundImageCorners(File inImageFile, File inOutputImageFile)
{
File cornerAddFile = stageCornerResourceImage(CORNER_ADD, inOutputImageFile.getParentFile());
File cornerSubFile = stageCornerResourceImage(CORNER_SUB, inOutputImageFile.getParentFile());
StringBuilder cmd = new StringBuilder();
cmd.append(getConvertExe());
cmd.append(" '" + inImageFile + "'");
cmd.append(" -bordercolor black -border 1");
cmd.append(" -matte \\( '" + cornerAddFile.getPath() + "' -flip -flop \\)");
cmd.append(" -gravity NorthWest");
cmd.append(" -composite \\( '" + cornerAddFile.getPath() + "' -flop \\)");
cmd.append(" -gravity SouthWest");
cmd.append(" -composite \\( '" + cornerAddFile.getPath() + "' -flip \\)");
cmd.append(" -gravity NorthEast");
cmd.append(" -composite \\( '" + cornerAddFile.getPath() + "' \\)");
cmd.append(" -gravity SouthEast");
cmd.append(" -composite");
cmd.append(" -compose DstOut \\( '" + cornerSubFile.getPath() + "' -flip -flop \\)");
cmd.append(" -gravity NorthWest");
cmd.append(" -composite \\( '" + cornerSubFile.getPath() + "' -flop \\)");
cmd.append(" -gravity SouthWest");
cmd.append(" -composite \\( '" + cornerSubFile.getPath() + "' -flip \\)");
cmd.append(" -gravity NorthEast");
cmd.append(" -composite \\( '" + cornerSubFile.getPath() + "' \\)");
cmd.append(" -gravity SouthEast");
cmd.append(" -composite");
// cmd.append(" -depth 8 -colors 256 -quality 95");
cmd.append(" '" + inOutputImageFile + "'");
Executor executor = new Executor(cmd.toString());
int exitStatus = executor.exec();
if (exitStatus != 0)
{
throw new RuntimeException("Problem rounding corners of image '" + inImageFile + "':\n"
+ executor.getSTDERR());
}
}
//###########################################################################
// PRIVATE FUNCTIONS
//###########################################################################
//--------------------------------------------------------------------------
private static File getIdentifyExe()
{
if (null == sIdentifyExe)
{
sIdentifyExe = new File(sBinDir, "identify");
}
return sIdentifyExe;
}
//--------------------------------------------------------------------------
private static File getConvertExe()
{
if (null == sConvertExe)
{
sConvertExe = new File(sBinDir, "convert");
}
return sConvertExe;
}
//--------------------------------------------------------------------------
private static File stageCornerResourceImage(String inResource, File inTempDir)
{
File file;
try
{
InputStream stream = ImageMagick.class.getResourceAsStream("rsrc/" + inResource);
if (null == stream)
{
throw new RuntimeException("Resource '" + inResource + "' couldn't be found!");
}
file = new File(inTempDir, inResource);
file.deleteOnExit();
StreamUtil.writeToFile(stream, file);
}
catch (IOException e)
{
throw new RuntimeException("Problem staging corner image resource!", e);
}
return file;
}
}