All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.image.ImageMagick Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
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;
   }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy