Adding a new ImageMagickImageProcessor class to replace
authorgrok <grok>
Wed, 27 Jul 2005 11:46:14 +0000 (11:46 +0000)
committergrok <grok>
Wed, 27 Jul 2005 11:46:14 +0000 (11:46 +0000)
the old JAIImageProcessor class. Removing the non-free JAI,
will bring us closer to making mir free. The new class uses
ImageMagick commandline programs who's path may be specified
in the config.properties configuration file.
I did a few other minor changes, like adding a ChangeLog file
and adding a few comments.

12 files changed:
ChangeLog [new file with mode: 0755]
doc/installation/installation.xml
etc/config.properties-dist
source/OpenMir.java
source/mir/media/image/ImageMagickImageProcessor.java [new file with mode: 0755]
source/mir/media/image/ImageProcessor.java
source/mir/media/image/JAIImageProcessor.java
source/mir/servlet/ServletModuleDispatch.java
source/mir/util/ExecFunctions.java [new file with mode: 0755]
source/mir/util/FileFunctions.java
source/mircoders/entity/EntityImages.java
source/mircoders/media/MediaHandlerImagesExtern.java

diff --git a/ChangeLog b/ChangeLog
new file mode 100755 (executable)
index 0000000..0fb0ece
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,8 @@
+2005-07-26  Grok  <grok@no-log.org>
+
+       * source/mir/media/image/ImageMagickImageProcessor.java:
+       Adding a new ImageMagickImageProcessor class to replace 
+       the old JAIImageProcessor class. Removing the non-free JAI,
+       will bring us closer to making mir free. The new class uses
+       ImageMagick commandline programs who's path may be specified
+       in the config.properties configuration file.
index 45802ea..58b0413 100755 (executable)
@@ -555,7 +555,7 @@ host         all         127.0.0.1     255.0.0.0           password
         
         For this, first a proper password needs to be selected for the postgres
 
-        super user:
+        super user. As root, do:
            <informalexample>
              <programlisting><literal>su postgres</literal>
 <literal>psql template1</literal>
@@ -571,7 +571,8 @@ local        all                                           password
           </programlisting>
       </para>
       <para>
-        
+        Don't forget to restart the database so that these changes will be taken
+into acount (/etc/init.d/postgresql restart).
       </para>
     </section>
     <section>
index a3a1970..ea638ab 100755 (executable)
@@ -275,6 +275,12 @@ ServletModule.OpenIndy.MaxMediaUploadItems=20
 #
 ServletModule.OpenIndy.DefaultMediaUploadItems=1
 
+# path to ImageMagick executables. Default is "" (nothing), which 
+# means executables will be searched using the default system PATH
+# example:Producer.Image.ImageMagickPath=/usr/local/ImageMagick/bin
+#
+Producer.Image.ImageMagickPath=
+
 
 ######################
 # PDF configurations #
index 7a06b08..928449e 100755 (executable)
@@ -46,7 +46,7 @@ import mircoders.servlet.ServletModuleOpenIndy;
  *  OpenMir.java - main servlet for open posting and comment feature to articles
  *
  *  @author RK 1999-2001, the mir-coders group
- *  @version $Id: OpenMir.java,v 1.35.2.4 2005/01/22 23:27:36 zapata Exp $
+ *  @version $Id: OpenMir.java,v 1.35.2.5 2005/07/27 11:46:14 grok Exp $
  *
  */
 
@@ -72,6 +72,9 @@ public class OpenMir extends AbstractServlet {
     aResponse.setContentType("text/html; charset="+configuration.getString("Mir.DefaultHTMLCharset"));
 
     try {
+      // call appropriate ServletModuleOpenIndy method 
+      // as specified in http request 
+      // example: OpenMir?do=opensession calls the opensession method
       ServletModuleDispatch.dispatch(ServletModuleOpenIndy.getInstance(), aRequest, aResponse);
     }
     catch (Throwable e) {
diff --git a/source/mir/media/image/ImageMagickImageProcessor.java b/source/mir/media/image/ImageMagickImageProcessor.java
new file mode 100755 (executable)
index 0000000..3838634
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2001, 2002 The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir 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 Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your version.
+ */
+
+package mir.media.image;
+
+import mir.log.LoggerWrapper;
+import mir.media.MediaExc;
+import mir.media.MediaFailure;
+import mir.util.StreamCopier;
+import mir.util.ExecFunctions;
+import mir.config.MirPropertiesConfiguration;
+
+import java.io.*;
+import java.util.StringTokenizer;
+
+
+
+/**
+ * Image processing by calling the ImageMagick command line progrmas
+ * "convert" and "identify". The main task of this class is to scale
+ * images. The path to ImageMagick commandline programs can be
+ * specified in the coonfiguration file.
+ * @author <grok@no-log.org>, the Mir-coders group
+ */
+public class ImageMagickImageProcessor implements ImageProcessor 
+{
+  protected static MirPropertiesConfiguration configuration = 
+    MirPropertiesConfiguration.instance();
+  static final LoggerWrapper logger = 
+    new LoggerWrapper("media.image.imagemagick");
+
+  private ImageFile sourceImage;
+  private ImageFile scaledImage;
+
+  /**
+   * ImageFile  is a  thin  wrapper  around a  file  that contains  an
+   * image.  It uses  ImageMagick  to retreive  information about  the
+   * image. It  can also scale images using  ImageMagick. Intended for
+   * use in the ImageMagickImageProcessor class.
+   */
+  static class ImageFile
+  {
+    /** path to the file represented by this class */
+    File file;
+    /** whether the file must be deleted on cleanup */
+    boolean fileIsTemp=false;
+    /** image information is stored here to avoid multiple costly calls to 
+     *  "identify" */
+    int width;
+    int height;
+    /** Image type as returned by identify %m : "PNG", "GIF", ...  */
+    String type;
+    /** number of scenes in image >1 (typically animated gif) */
+    boolean isAnimation;
+
+    /** Empty constructor automatically creates a temporary file 
+     * that will later hold an image */
+    ImageFile() throws IOException
+    {
+      file=File.createTempFile("mirimage","");
+      fileIsTemp=true;
+    }
+    /** if the file doesn't already have an image in it 
+     * we don't want to read its information */
+    ImageFile(File file,boolean doReadInfo) throws IOException
+    {
+      this.file=file;
+      if(doReadInfo){readInfo();}
+    }
+    ImageFile(File file) throws IOException
+    {
+      this(file,true);
+    }
+    /** delete temporary files  */
+    public void cleanup()
+    {
+      logger.debug("ImageFile.cleanup()");
+      if(fileIsTemp)
+      { 
+        logger.debug("deleting:"+file);
+        file.delete();
+        file=null;
+        fileIsTemp=false;
+      }
+    }
+    void debugOutput()
+    {
+      logger.debug(" filename:"+file+
+                   " Info:"+
+                   " width:"+width+
+                   " height:"+height+
+                   " type:"+type+
+                   " isAnimation:"+isAnimation);
+    }
+    private void checkFile() throws IOException
+    {
+      if(file==null || !file.exists())
+      {
+        String message="ImageFile.checkFile file \""+file+
+          "\" does not exist";
+        logger.error(message);
+        throw new IOException(message);
+      }
+    }
+
+    /** Uses the imagemagick "identify" command to retreive image information */
+    public void readInfo() throws IOException
+    {
+      checkFile();
+      String infoString=ExecFunctions.execIntoString
+        (getImageMagickPath()+
+         "identify "+
+         file.getAbsolutePath()+" "+
+         "-format \"%w %h %m %n \"");// extra space, for multiframe (animations)
+      StringTokenizer st = new StringTokenizer(infoString);
+      width      =Integer.parseInt(st.nextToken());
+      height     =Integer.parseInt(st.nextToken());
+      type       =                 st.nextToken() ;
+      isAnimation=Integer.parseInt(st.nextToken())>1;
+    } 
+
+    public ImageFile scale(float aScalingFactor) throws IOException
+    {
+      logger.debug("ImageFile.scale");
+      checkFile();
+      ImageFile result=new ImageFile();
+      String command=getImageMagickPath()+"convert "+
+        file.getAbsolutePath()+" "+
+        "-scale "+
+        new Float(aScalingFactor*100).toString()+"% "+
+        result.file.getAbsolutePath();
+      logger.debug("ImageFile.scale:command:"+command);
+      ExecFunctions.simpleExec(command);
+      result.readInfo();
+      return result;
+    }
+  }
+
+  public ImageMagickImageProcessor(InputStream inputImageStream)
+    throws IOException
+  {
+    logger.debug("ImageMagickImageProcessor(stream)");
+    sourceImage=new ImageFile();
+    // copy stream into temporary file 
+    StreamCopier.copy(inputImageStream,new FileOutputStream(sourceImage.file));
+    sourceImage.readInfo();
+    sourceImage.debugOutput();
+  }
+
+
+  public ImageMagickImageProcessor(File aFile) throws IOException 
+  {
+    logger.debug("ImageMagickImageProcessor(file)");
+    sourceImage=new ImageFile(aFile);
+    sourceImage.debugOutput();
+  }
+
+  /**
+   * Deletes temporary files 
+   */
+  public void cleanup()
+  {
+    logger.debug("ImageMagickImageProcessor.cleanup()");
+    sourceImage.cleanup();
+    scaledImage.cleanup();
+  }
+
+  /**
+   * Path to ImageMagick commandline programs
+   */
+  private static String getImageMagickPath()
+  {
+    String result=configuration.getString("Producer.Image.ImageMagickPath");
+    // we want the path to finish by "/", so add it if it's missing
+    if(result.length()!=0 && !result.endsWith("/"))
+    {
+      result=result.concat("/");
+    }
+    logger.debug("getImageMagickPath:"+result);
+    return result;
+  }
+
+  public void descaleImage(int aMaxSize) throws MediaExc {
+    descaleImage(aMaxSize, 0);
+  }
+
+  public void descaleImage(int aMaxSize, float aMinDescale) throws MediaExc {
+    descaleImage(aMaxSize, aMaxSize, aMinDescale, 0);
+  }
+
+  public void descaleImage(int aMaxSize, int aMinResize) throws MediaExc 
+  {
+    descaleImage(aMaxSize, aMaxSize, 0, aMinResize);
+  }
+
+  public void descaleImage(int aMaxSize, float aMinDescale, int aMinResize) 
+    throws MediaExc 
+  {
+    descaleImage(aMaxSize, aMaxSize, aMinDescale, aMinResize);
+  }
+
+  /** {@inheritDoc} */
+  public void descaleImage(int   aMaxWidth, int aMaxHeight, 
+                           float aMinDescale, int aMinResize) throws MediaExc 
+  {
+    float scale;
+    logger.debug("descaleImage:"+
+                 "  aMaxWidth:"+aMaxWidth+
+                 ", aMaxHeight:"+aMaxHeight+
+                 ", aMinDescale:"+aMinDescale+
+                 ", aMinResize:"+aMinResize);
+    if ((aMaxWidth >0 && getWidth ()>aMaxWidth +aMinResize-1) || 
+        (aMaxHeight>0 && getHeight()>aMaxHeight+aMinResize-1))
+    {
+      logger.debug("descaleImage: image needs scaling");
+
+      scale=1;
+
+      if (aMaxWidth>0 && getWidth()>aMaxWidth) 
+      {
+        scale = Math.min(scale, (float) aMaxWidth / (float) getWidth());
+      }
+      if (aMaxHeight>0 && getHeight()>aMaxHeight) 
+      {
+        scale = Math.min(scale, (float) aMaxHeight / (float) getHeight());
+      }
+
+      if (1-scale>aMinDescale) 
+      {
+        scaleImage(scale);
+      }
+    }
+    else
+    {
+      logger.debug("descaleImage: image size is ok, not scaling image");
+      try{scaledImage=new ImageFile(sourceImage.file);}
+      catch(IOException e){throw new MediaExc(e.toString());}
+    }
+  }
+
+
+  /**
+   * Scales image by a factor using the convert ImageMagick command
+   */
+  public void scaleImage(float aScalingFactor) 
+    throws MediaExc 
+  {
+    logger.debug("scaleImage:"+aScalingFactor);
+    try
+    {
+      // first cleanup previous temp scaledimage file if necesary
+      if(scaledImage!=null){scaledImage.cleanup();}
+      // now create temp file and execute convert
+      scaledImage=sourceImage.scale(aScalingFactor);
+    }
+    catch(Exception e){throw new MediaExc(e.toString());}
+    logger.debug(" scaledImage:");
+    scaledImage.debugOutput();
+  }
+
+  public int getWidth() {
+    return sourceImage.width;
+  }
+
+  public int getHeight() {
+    return sourceImage.height;
+  }
+
+  public int getScaledWidth() {
+    return scaledImage.width;
+  }
+
+  public int getScaledHeight() {
+    return scaledImage.height;
+  }
+
+  public void writeScaledData(OutputStream aStream, String anImageType) 
+    throws MediaExc
+  {
+    // we can't asume that requested "anImageType" is the same as the
+    // scaled image type, so we have to convert 
+    try
+    {
+      // if image is an animation and target type doesn't support
+      // animations, then just use first frame
+      String frame="";
+      scaledImage.debugOutput();
+      if(scaledImage.isAnimation && !anImageType.equals("GIF"))
+      {
+        frame="[0]";
+      }
+      // ImageMagick "convert" into temp file
+      File temp=File.createTempFile("mirimage","");
+      String command=getImageMagickPath()+"convert "+
+        scaledImage.file.getAbsolutePath()+frame+" "+
+        anImageType+":"+temp.getAbsolutePath();
+      logger.debug("writeScaledData command:"+command);
+      ExecFunctions.simpleExec(command);
+      // copy temp file into stream
+      StreamCopier.copy(new FileInputStream(temp),aStream);
+      temp.delete();
+    }
+    catch(Exception e){throw new MediaExc(e.toString());}
+  }
+
+  public byte[] getScaledData(String anImageType) throws MediaExc 
+  {
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    writeScaledData(outputStream, anImageType);
+    return outputStream.toByteArray();
+  }
+
+  public void writeScaledData(File aFile, String anImageType) throws MediaExc {
+    try {
+      writeScaledData(new BufferedOutputStream
+                      (new FileOutputStream(aFile),8192), anImageType);
+    }
+    catch (FileNotFoundException f) {
+      throw new MediaFailure(f);
+    }
+  }
+}
index 89c7243..8ddc3f3 100755 (executable)
@@ -33,7 +33,6 @@ package mir.media.image;
 import mir.media.MediaExc;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.OutputStream;
 
 public interface ImageProcessor {
@@ -58,9 +57,15 @@ public interface ImageProcessor {
   public int getHeight();
   public int getScaledWidth();
   public int getScaledHeight();
-  public void writeScaledData(OutputStream aStream, String anImageType);
-  public byte[] getScaledData(String anImageType);
+  public void writeScaledData(OutputStream aStream, String anImageType) 
+    throws MediaExc;
+  public byte[] getScaledData(String anImageType) throws MediaExc;
   public void writeScaledData(File aFile, String anImageType) throws MediaExc;
+
+  /**
+   * call this when you're over using this object (removes temp files)
+   */
+  public void cleanup();
 }
 
 
index 986a3f3..17ae00d 100755 (executable)
@@ -100,6 +100,8 @@ public class JAIImageProcessor implements ImageProcessor {
     this(new ByteArraySeekableStream(anImageData));\r
   }\r
 \r
+  public void cleanup(){}\r
+  \r
   public void descaleImage(int aMaxSize) throws MediaExc {\r
     descaleImage(aMaxSize, 0);\r
   }\r
index 5661acf..5fd290e 100755 (executable)
@@ -42,7 +42,7 @@ import mir.log.LoggerWrapper;
  * Dispatcher, calls the method passed to ServletModule Class, through the "do"
  * Parameter (via POST or GET)
  *
- * @version $Id: ServletModuleDispatch.java,v 1.15.2.2 2005/03/26 11:26:25 zapata Exp $
+ * @version $Id: ServletModuleDispatch.java,v 1.15.2.3 2005/07/27 11:46:14 grok Exp $
  *
  * @author rk
  */
@@ -70,6 +70,8 @@ public final class ServletModuleDispatch {
 
   public static void dispatch(ServletModule aServletModule, HttpServletRequest aRequest,
        HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleFailure {
+    // look for requested method's name in the "do" http request param, 
+    // if not present, use default action 
     String doParam = aRequest.getParameter("do");
     logger.debug("ServletModuleDispatch: " + aServletModule.toString() + " with method " + doParam);
 
@@ -80,6 +82,7 @@ public final class ServletModuleDispatch {
         throw new ServletModuleExc("no parameter do supplied!");
     }
 
+    // ok, we have the method's name, now call it
     try {
       Method method = aServletModule.getClass().getMethod(doParam,SIGNATURE);
       if (method != null) {
diff --git a/source/mir/util/ExecFunctions.java b/source/mir/util/ExecFunctions.java
new file mode 100755 (executable)
index 0000000..9192207
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2001, 2002 The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir 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 Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with  any library licensed under the Apache Software License,
+ * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
+ * (or with modified versions of the above that use the same license as the above),
+ * and distribute linked combinations including the two.  You must obey the
+ * GNU General Public License in all respects for all of the code used other than
+ * the above mentioned libraries.  If you modify this file, you may extend this
+ * exception to your version of the file, but you are not obligated to do so.
+ * If you do not wish to do so, delete this exception statement from your version.
+ */
+package mir.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Execute system commands. Warning: the current implementation is
+ * unix specific. 
+ */
+public class ExecFunctions
+{
+  /**
+   * Executes a full command (including arguments) in a subshell
+   * and returns the output of the command in a string. Output is
+   * redirected into a temporary fil which is then read into the string
+   */
+  public static String execIntoString(String command)
+    throws IOException
+  {
+    return new String(execIntoByteArray(command));
+  }
+
+  /**
+   * Executes a full command (including arguments) in a subshell
+   * and returns the output of the command in an array of
+   * bytes. Output is redirected into a temporary fil which is then
+   * read into the string
+   */
+  public static byte[] execIntoByteArray(String command)
+    throws IOException
+  {
+    File commandOutput=File.createTempFile("mircmd","");
+    int exitStatus;
+    try
+    {
+      // WARNING: unix specific
+      exitStatus=Runtime.getRuntime().exec(new String[]{
+        "/bin/sh","-c",
+        command+" "+
+        ">"+commandOutput.getAbsolutePath()
+      }).waitFor();
+    }
+    catch(InterruptedException e){ throw new IOException(e.toString());}
+    if(exitStatus!=0)
+    {
+        throw new IOException("command exit satus:"+exitStatus);
+    }
+    byte [] result=FileFunctions.readFileIntoByteArray
+      (commandOutput.getAbsolutePath());
+    commandOutput.delete();
+    return result;
+  }
+
+  /**
+   * Executes a full command (including arguments) in a subshell.
+   * Standard input and output go to /dev/null
+   */
+  public static void simpleExec(String command)
+    throws IOException
+  {
+    int exitStatus;
+    try
+    {
+      // WARNING: unix specific
+      exitStatus=Runtime.getRuntime().exec(new String[]{
+        "/bin/sh","-c",
+        command+" "+">/dev/null 2>/dev/null"
+      }).waitFor();
+    }
+    catch(InterruptedException e){ throw new IOException(e.toString());}
+    if(exitStatus!=0)
+    {
+        throw new IOException("command exit satus:"+exitStatus);
+    }
+  }
+  
+}
index 08fd66b..a49c149 100755 (executable)
@@ -158,6 +158,27 @@ public class FileFunctions {
     }
   }
 
+  /**
+   * Reads the content of a file into a string
+   */
+  public static String readFileIntoString(String fileName) 
+   throws IOException
+  {
+    return new String(readFileIntoByteArray(fileName));
+  }
+  /**
+   * Reads the content of a file into an array of bytes
+   */
+  public static byte[] readFileIntoByteArray(String fileName) 
+    throws IOException
+  {
+    FileInputStream input = new FileInputStream(fileName);
+    int size= input.available();
+    byte result[]= new byte[size];
+    input.read(result);
+    return result;
+  }
+
   public static class RegExpFileFilter implements FilenameFilter {
     private RE expression;
 
@@ -209,4 +230,4 @@ public class FileFunctions {
     }
                return new File(aParentIfRelative, aPath);
   }
-}
\ No newline at end of file
+}
index 360394c..eb6392a 100755 (executable)
@@ -38,7 +38,9 @@ import mir.log.LoggerWrapper;
 import mir.storage.DatabaseFailure;
 import mir.util.StreamCopier;
 import mir.media.image.ImageProcessor;
-import mir.media.image.JAIImageProcessor;
+// FIXME: delete this when finished testing ImageMagickImageProcessor
+//import mir.media.image.JAIImageProcessor;
+import mir.media.image.ImageMagickImageProcessor;
 
 public class EntityImages extends EntityUploadedMedia
 {
@@ -73,10 +75,13 @@ public class EntityImages extends EntityUploadedMedia
   public void setImage(InputStream anInputStream, String type) throws DatabaseFailure {
     if (anInputStream != null) {
       try {
-        ByteArrayOutputStream inputData = new ByteArrayOutputStream();
-        StreamCopier.copy(anInputStream, inputData);
+        // FIXME: delete this when finished testing ImageMagickImageProcessor
+        //ByteArrayOutputStream inputData = new ByteArrayOutputStream();
+        //StreamCopier.copy(anInputStream, inputData);
 
-        ImageProcessor processor = new JAIImageProcessor(inputData.toByteArray());
+        ImageProcessor processor = new ImageMagickImageProcessor(anInputStream);
+        // FIXME: delete this when finished testing ImageMagickImageProcessor
+        //ImageProcessor processor = new JAIImageProcessor(inputData.toByteArray());
         processor.descaleImage(maxImageSize, minDescaleRatio, minDescaleReduction);
 
         ByteArrayOutputStream imageData = new ByteArrayOutputStream();
@@ -93,7 +98,7 @@ public class EntityImages extends EntityUploadedMedia
 
         setFieldValue("icon_height", new Integer(processor.getScaledHeight()).toString());
         setFieldValue("icon_width", new Integer(processor.getScaledWidth()).toString());
-
+        processor.cleanup();
         update();
       }
       catch (Exception e) {
index 2e001c7..d12f111 100755 (executable)
@@ -40,7 +40,9 @@ import mir.log.LoggerWrapper;
 import mir.media.MediaExc;
 import mir.media.MediaFailure;
 import mir.media.image.ImageProcessor;
-import mir.media.image.JAIImageProcessor;
+// FIXME: delete this when finished testing ImageMagickImageProcessor
+//import mir.media.image.JAIImageProcessor;
+import mir.media.image.ImageMagickImageProcessor;
 import mir.misc.StringUtil;
 
 
@@ -84,7 +86,9 @@ public class MediaHandlerImagesExtern extends MediaHandlerGeneric
         throw new MediaExc("error in MediaHandlerImagesExtern.produce(): " + filePath + " does not exist!");
       }
       else {
-        ImageProcessor processor = new JAIImageProcessor(imageFile);
+        // FIXME: delete this when finished testing ImageMagickImageProcessor
+        //        ImageProcessor processor = new JAIImageProcessor(imageFile);
+        ImageProcessor processor = new ImageMagickImageProcessor(imageFile);
 
         processor.descaleImage(maxIconSize, minDescaleRatio, minDescaleReduction);
         File dir = new File(iconFile.getParent());
@@ -99,6 +103,7 @@ public class MediaHandlerImagesExtern extends MediaHandlerGeneric
         anImageEntity.setFieldValue("icon_height", new Integer(processor.getScaledHeight()).toString());
         anImageEntity.setFieldValue("icon_width", new Integer(processor.getScaledWidth()).toString());
 
+        processor.cleanup();
         anImageEntity.setFieldValue("icon_path", iconPath);
         anImageEntity.setFieldValue("publish_path", filePath);