Linux平台下对JMagick的一个简单封装


最近需要给图片加上社区的水印,也需要对用户上传的图片进行压缩和裁剪。Google之,最后选中ImageMagick开源库。ImageMagick提供一个通过JNI调用的Java接口JMagick。虽然不能提供所有ImageMagick的接口,但已经很不错了。

JMagick在Windows下配置很简单,在Linux上配置有一些复杂,主要是依赖库的安装配置。感兴趣的可以查阅相关的资料。注意安装时ImageMagick和JMagick的版本要匹配。

封装的代码如下,基于网络上的代码改动而成,测试通过。

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;

import magick.CompositeOperator;
import magick.CompressionType;
import magick.DrawInfo;
import magick.ImageInfo;
import magick.MagickException;
import magick.MagickImage;
import magick.PixelPacket;
import magick.PreviewType;

public class JMagicjWrapper {

 private static final String[] Type = {
  ".JPG",
  ".JPEG",
  ".BMP",
  ".GIF",
  ".PNG"
 };
 
 public static boolean checkType(String path){
  for (int i = 0; i < Type.length; i++) {
   if (path.toUpperCase().endsWith(Type[i])) {
    return true;
   }else {
    continue;
   }
  }
  return false;
 }
 
 /**改变图片大小
  * @param filePath 原图片位置
  *    toPath  新图片位置
  *    width  新图片的宽度
  *    height  新图片的高度
  * @return
  * @throw
  * @author sulliy@sina.com 2010-8-11
  */
 public static void imageResize(String filePath, String toPath, int width, int height)
   throws MagickException {
  ImageInfo info = null;
  MagickImage image = null;
  Dimension imageDim = null;
  MagickImage scaled = null;
  
  if (!checkType(filePath) || !checkType(toPath)) {
   return;
  }
  
  try {
   info = new ImageInfo(filePath);
   image = new MagickImage(info);
   imageDim = image.getDimension();
   if (width <= 0 || height <= 0) {
    height = 120;
    width = 120;
   }
   scaled = image.scaleImage(width, height);
   scaled.setFileName(toPath);
   scaled.writeImage(info);
  } finally {
   if (scaled != null) {
    scaled.destroyImages();
   }
  }
 }

 /**创建图片水印
  * @param  filePath 源文件路径
  *     toImg  生成文件位置
  *     logoPath logo路径
  *     pos   logo在源图片中的相对位置,以像素点为单位
  * @return
  * @throw MagickException
  * @author sulliy@sina.com 2010-8-11
  */
 public static void createWaterPrintByImg(String filePath, String toImg,
   String logoPath, Point pos) throws MagickException {
  if (!checkType(filePath) || !checkType(toImg) || !checkType(logoPath)) {
   return;
  }
  
  ImageInfo info = new ImageInfo();
  MagickImage fImage = null;
  MagickImage sImage = null;
  MagickImage fLogo = null;
  MagickImage sLogo = null;
  Dimension imageDim = null;
  Dimension logoDim = null;
  try {
   fImage = new MagickImage(new ImageInfo(filePath));
   imageDim = fImage.getDimension();
   int width = imageDim.width;
   int height = imageDim.height;
   sImage = fImage.scaleImage(width, height);
   
   fLogo = new MagickImage(new ImageInfo(logoPath));
   //fLogo.transparentImage(PixelPacket.queryColorDatabase("white"), 65535); //设置背景色
   logoDim = fLogo.getDimension();
   int lw = logoDim.width;
   int lh = logoDim.height;
   
   //默认或者参数出错时,LOGO放在右下角
   if (width <= (int)pos.getX() || height <= (int)pos.getY()) {
    pos.setLocation(width - lw, height - lh);
   }
   
   sLogo = fLogo.scaleImage(lw, lh);
   sImage.compositeImage(CompositeOperator.AtopCompositeOp, sLogo,
     (int)pos.getX(), (int)pos.getY());
   sImage.setFileName(toImg);
   sImage.writeImage(info);
  } finally {
   if (sImage != null) {
    sImage.destroyImages();
   }
  }
 }

 /**创建文字水印
  * @param  filePath 源文件路径
  *     toImg  生成文件位置
  *     text  水印文本
  *     pos   logo在源图片中的相对位置,以像素点为单位
  *     pointSize 用于设置点阵大小
  * @return
  * @throw MagickException
  * @author sulliy@sina.com 2010-8-11
  */
 public static void createWaterPrintByText(String filePath, String toImg, String text
   , Point pos, int pointSize)
   throws MagickException {
  if (!checkType(filePath) || !checkType(toImg)) {
   return;
  }
  
  if (null == text || "".equals(text)) {
   text = "sulliy@sina.com";
  }
  
  ImageInfo info = new ImageInfo(filePath);
  if (filePath.toUpperCase().endsWith("JPG")
    || filePath.toUpperCase().endsWith("JPEG")) {
   info.setCompression(CompressionType.JPEGCompression); // 压缩类别为JPEG格式
   info.setPreviewType(PreviewType.JPEGPreview); // 预览格式为JPEG格式
   info.setQuality(95);
  }
  MagickImage aImage = new MagickImage(info);
  Dimension imageDim = aImage.getDimension();
  int width = imageDim.width;
  int height = imageDim.height;
  
  if (width <= (int)pos.getX() || height <= (int)pos.getY()) {
   pos.setLocation(0, 0);
  }
  
  int a = 0;
  int b = 0;
  String[] as = text.split("");
  for (String string : as) {
   if (string.matches("[\u4E00-\u9FA5]")) {
    a++;
   }
   if (string.matches("[a-zA-Z0-9]")) {
    b++;
   }
  }
  int tl = a * 12 + b * 6 ;//字符长度
  MagickImage scaled = aImage.scaleImage(width, height);
  if (width > tl && height > 5) {
   DrawInfo aInfo = new DrawInfo(info);
   aInfo.setFill(PixelPacket.queryColorDatabase("white"));
   aInfo.setUnderColor(new PixelPacket(65535, 65535, 65535, 65535));//设置为透明颜色
   aInfo.setPointsize(pointSize);
   // 解决中文乱码问题,自己可以去随意定义个自己喜欢字体,我在这用的微软雅黑
   String fontPath = "C:/WINDOWS/Fonts/MSIMHEI.TTF";
   // String fontPath = "/usr/maindata/MSYH.TTF";
   aInfo.setFont(fontPath);
   aInfo.setTextAntialias(true);
   aInfo.setOpacity(0);//透明度
   aInfo.setText(text);
   aInfo.setGeometry("+" + ((int)pos.getX() + "+" + (int)pos.getY()));
   scaled.annotateImage(aInfo);
  }
  scaled.setFileName(toImg);
  scaled.writeImage(info);
  scaled.destroyImages();
 }

 /**切取图片
  * @param  imgPath  原图路径
  *     toPath  生成文件位置
  *     w   左上位置横坐标
  *     h   左上位置竖坐标
  *     x   右下位置横坐标
  *     y   右下位置竖坐标
  * @return
  * @throw MagickException
  * @author sulliy@sina.com 2010-8-11
  */
 public static void cutImg(String imgPath, String toPath, int w, int h,
   int x, int y) throws MagickException {
  ImageInfo infoS = null;
  MagickImage image = null;
  MagickImage cropped = null;
  Rectangle rect = null;
  try {
   infoS = new ImageInfo(imgPath);
   image = new MagickImage(infoS);
   rect = new Rectangle(x, y, w, h);
   cropped = image.cropImage(rect);
   cropped.setFileName(toPath);
   cropped.writeImage(infoS);

  } finally {
   if (cropped != null) {
    cropped.destroyImages();
   }
  }
 }
 
 /**删除图片文件
  * @param src  图片位置
  * @return
  * @throw
  * @author sulliy@sina.com 2010-8-11
  */
 public static boolean removeFile(String src) throws SecurityException{
  try {
   if (!checkType(src)) {
    return false;
   }
   
   File file = new File(src);
   return file.delete();  
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }
}

可以写个简单的测试

import java.awt.Point;

import magick.MagickException;


public class JMagicjWrapperTest {
 public static void main(String[] args) throws MagickException{
  
  //test for function imageResize
  
  JMagicjWrapper.imageResize("pics.jpg", "reSize20x30.png", 20, 30);
  JMagicjWrapper.imageResize("pics.jpg", "reSize250x200.jpeg", 250, 200);
  JMagicjWrapper.imageResize("pics.jpg", "reSize50x50.jpg", 50, 50);
  JMagicjWrapper.imageResize("pics.jpg", "reSize120x120.bmp", 120, 120);
  JMagicjWrapper.imageResize("pics.jpg", "reSize.tif", 20, 30);//not create file
  
  
  //test for function createWaterPrintByImg
  JMagicjWrapper.createWaterPrintByImg("pics.jpg", "wpl.gif", "logo.jpg", new Point(100,100));
  JMagicjWrapper.imageResize("wpl.gif", "logo250x200.gif", 250, 200);
  //Because file "wpl.gif" may not be release, the later function cause a error, can not open file handle.
  //JMagicjWrapper.createWaterPrintByImg("pics.jpg", "wpl.gif", "logoFull.jpg", new Point(1680,1050));//not create file
  //JMagicjWrapper.createWaterPrintByImg("pics.jpg", "wpl.gif", "logoExt.jpg", new Point(2000,1000));//not create file
  
  //test for function createWaterPrintByText
  //This function can not handle Chinese Character, I'll continue to takle the issue
  JMagicjWrapper.createWaterPrintByText("pics1.jpg", "wpt.gif", "For Test", new Point(300,300), 100);
 }
}

运行可能会报无法获得文件句柄的错误,请仔细检查图片的路径。

 

相关内容