zoukankan      html  css  js  c++  java
  • JMagic 操作 ImageMagick 处理图片

    项目描述

    imagemagick是功能强大的图片处理库,以稳定及高效率著称,众多语言对该库进行封装处理。比如php、java。由于我们是java项目,直接使用java通过JNI技术调用ImageMagick是不行的。因为ImageMagick开发时没有使用java JNI生成的头文件。可以使用JMagick解决,JMagick是由c语言开发的,开发时使用了java JNI生成的头文件,所以java可以通过JNI技术调用JMagick。JMagick再调用ImageMagick。这里我们处理图片使用的是JMagick暴露的java接口。

    下载和安装

    Windows安装使用Jmagick及imagemagick步骤如下:

    1、访问jmagick网站下载: http://downloads.jmagick.org

    2、目前JMagick只有32位的,所以只能选择32位的ImageMagick,并且版本支持很低,目前只到ImageMagick-6.3.9-0,只能使用32位的JDK,64位进程不能够调用32位的dll,想在64位的系统上用jmagick不仅要将jdk换成32位,而且jmagick.dll也得放到SysWOW64下面,不能放到System32中。

    3、下载两个文件:红框的两个或者绿框的两个。

    关于Q8,Q16,Q32的说明:(建议使用8,现在数码相机照的相片,每一种颜色就是8位深,3种颜色就是24位,所以选8) 
    支持的参数有3种,分别是 8,16,32。默认值是16。 
    Q8表示: 8-bits per pixel quantum 
    Q16表示:16-bits per pixel quantum 
    Q32表示:32-bits per pixel quantum 

    使用16-bit per pixel quantums在处理图片时比8-bit慢15%至50%,并须要更多的内存。 
    处理一张1024x768像素的图片8-bit要使用3.6M内存,16-bit要使用7.2M内存。计算方法是: (5 * Quantum Depth * Rows * Columns) / 8 

    大多数电脑显示使用8-bit per pixel quantums。使用16-bit per pixel quantums在处理图片时比8-bit慢15%至50%,并须要更多的内存。比如处理一张1024x768像素的图片8-bit要使用3M内存,16-bit要使用8M内存。8-bit可表示0-255种值,16-bit可表示0-65535种值。默认值是8-bit。
    另外Windows下有动态版(dll),有静态版(static),这里使用了动态版。

    4、下载时注意版本问题。不要到imagemagick官方网站下载imagemagick,这样会导致下载的imagemagick版本和jmagick版本不对应,导致调用出现异常。比如出现memor allocate not enough 的异常。

    这是我下载出来的文件(我公司电脑系统是WIN7-32位,安装的也是32位的JDK):

    5、双击下载的ImageMagick-6.3.9-0-Q8-windows-dll.exe文件安装即可,一直点击下一步就可以。这里如果勾选了红框标注的选项,环境变量会自动配好的。

    在命令行使用

    到这里就可以在DOS命令窗口中使用了,具体使用命令可以参考这篇博客:http://www.charry.org/docs/linux/ImageMagick/ImageMagick.html,下面截图演示对桌面图片的处理:

    在Java中使用

    1、将ImageMagick安装目录下的所有的.dll文件复制到  C:/ windows/System32的目录下(这一步有可能省略,等待验证)

    2、解压jmagick-win-6.3.9-Q8.zip , 将jmagick.dll放到 C:/windows/System32 目录下。这里是为了能在Java中使用jmagick的类进行操作ImageMagick,如果不复制的话,会报UnsatisfiedLinkError: no JMagick in java.library.path.异常。

    3、将jmagick.jar加入到eclipse下相关项目的build path中的libraries  中即完成了相应的安装。接下来就可以在java项目中使用了。

    4、Java中通过jmagick操作ImageMagick,示例代码:

      1 package com.demo.test;   
      2  
      3 import java.awt.Dimension;
      4 import java.awt.Rectangle;
      5 import java.text.SimpleDateFormat;
      6 import java.util.Date;   
      7  
      8 
      9 import magick.CompositeOperator;
     10 import magick.CompressionType;
     11 import magick.DrawInfo;
     12 import magick.ImageInfo;
     13 import magick.MagickException;
     14 import magick.MagickImage;
     15 import magick.PixelPacket;
     16 import magick.PreviewType;   
     17  
     18 public class ImageTools {   
     19  
     20     static{
     21         //不能漏掉这个,不然jmagick.jar的路径找不到
     22         //System.setProperty("jmagick.systemclassloader","no");
     23     }   
     24  
     25     /**
     26      * 压缩图片
     27      * @param filePath 源文件路径
     28      * @param toPath   缩略图路径
     29      */
     30     public static void createThumbnail(String filePath, String toPath) throws MagickException{
     31         ImageInfo info = null;
     32         MagickImage image = null;
     33         Dimension imageDim = null;
     34         MagickImage scaled = null;
     35         try{
     36             info = new ImageInfo(filePath);
     37             image = new MagickImage(info);
     38             imageDim = image.getDimension();
     39             int wideth = imageDim.width;
     40             int height = imageDim.height;
     41             if (wideth > height) {
     42                 height = 660 * height / wideth;
     43                 wideth = 660;
     44             }
     45             scaled = image.scaleImage(wideth, height);//小图片文件的大小.
     46             scaled.setFileName(toPath);
     47             scaled.writeImage(info);
     48         }finally{
     49             if(scaled != null){
     50                 scaled.destroyImages();
     51             }
     52         }
     53     }   
     54  
     55     /**
     56      * 水印(图片logo)
     57      * @param filePath  源文件路径
     58      * @param toImg     修改图路径
     59      * @param logoPath  logo图路径
     60      * @throws MagickException
     61      */
     62     public static void initLogoImg(String filePath, String toImg, String logoPath) throws MagickException {
     63         ImageInfo info = new ImageInfo();
     64         MagickImage fImage = null;
     65         MagickImage sImage = null;
     66         MagickImage fLogo = null;
     67         MagickImage sLogo = null;
     68         Dimension imageDim = null;
     69         Dimension logoDim = null;
     70         try {
     71             fImage = new MagickImage(new ImageInfo(filePath));
     72             imageDim = fImage.getDimension();
     73             int width = imageDim.width;
     74             int height = imageDim.height;
     75             if (width > 660) {
     76                 height = 660 * height / width;
     77                 width = 660;
     78             }
     79             sImage = fImage.scaleImage(width, height);   
     80  
     81             fLogo = new MagickImage(new ImageInfo(logoPath));
     82             logoDim = fLogo.getDimension();
     83             int lw = width / 8;
     84             int lh = logoDim.height * lw / logoDim.width;
     85             sLogo = fLogo.scaleImage(lw, lh);   
     86  
     87             sImage.compositeImage(CompositeOperator.AtopCompositeOp, sLogo,  width-(lw + lh/10), height-(lh + lh/10));
     88             sImage.setFileName(toImg);
     89             sImage.writeImage(info);
     90         } finally {
     91             if(sImage != null){
     92                 sImage.destroyImages();
     93             }
     94         }
     95     }   
     96  
     97     /**
     98      * 水印(文字)
     99      * @param filePath 源文件路径
    100      * @param toImg    修改图路径
    101      * @param text     名字(文字内容自己随意)
    102      * @throws MagickException
    103      */
    104     public static void initTextToImg(String filePath, String toImg,  String text) throws MagickException{
    105             ImageInfo info = new ImageInfo(filePath);
    106             if (filePath.toUpperCase().endsWith("JPG") || filePath.toUpperCase().endsWith("JPEG")) {
    107                 info.setCompression(CompressionType.JPEGCompression); //压缩类别为JPEG格式
    108                 info.setPreviewType(PreviewType.JPEGPreview); //预览格式为JPEG格式
    109                 info.setQuality(95);
    110             }
    111             MagickImage aImage = new MagickImage(info);
    112             Dimension imageDim = aImage.getDimension();
    113             int wideth = imageDim.width;
    114             int height = imageDim.height;
    115             if (wideth > 660) {
    116                 height = 660 * height / wideth;
    117                 wideth = 660;
    118             }
    119             int a = 0;
    120             int b = 0;
    121             String[] as = text.split("");
    122             for (String string : as) {
    123                 if(string.matches("[u4E00-u9FA5]")){
    124                     a++;
    125                 }
    126                 if(string.matches("[a-zA-Z0-9]")){
    127                     b++;
    128                 }
    129             }
    130             int tl = a*12 + b*6 + 300;
    131             MagickImage scaled = aImage.scaleImage(wideth, height);
    132             if(wideth > tl && height > 5){
    133                 DrawInfo aInfo = new DrawInfo(info);
    134                 aInfo.setFill(PixelPacket.queryColorDatabase("white"));
    135                 aInfo.setUnderColor(new PixelPacket(0,0,0,100));
    136                 aInfo.setPointsize(12);
    137                 //解决中文乱码问题,自己可以去随意定义个自己喜欢字体,我在这用的微软雅黑
    138                 String fontPath = "C:/WINDOWS/Fonts/MSYH.TTF";
    139                 //String fontPath = "/usr/maindata/MSYH.TTF";
    140                 aInfo.setFont(fontPath);
    141                 aInfo.setTextAntialias(true);
    142                 aInfo.setOpacity(0);
    143                 aInfo.setText(" " + text + "于 " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " 上传于我的相册网,版权归作者所有!");
    144                 aInfo.setGeometry("+" + (wideth-tl) + "+" + (height-5));
    145                 scaled.annotateImage(aInfo);
    146             }
    147             scaled.setFileName(toImg);
    148             scaled.writeImage(info);
    149             scaled.destroyImages();
    150     }   
    151  
    152     /**
    153      * 切图
    154      * @param imgPath 源图路径
    155      * @param toPath  修改图路径
    156      * @param w
    157      * @param h
    158      * @param x
    159      * @param y
    160      * @throws MagickException
    161      */
    162     public static void cutImg(String imgPath, String toPath, int w, int h, int x, int y) throws MagickException {
    163         ImageInfo infoS = null;
    164         MagickImage image = null;
    165         MagickImage cropped = null;
    166         Rectangle rect = null;
    167         try {
    168             infoS = new ImageInfo(imgPath);
    169             image = new MagickImage(infoS);
    170             rect = new Rectangle(x, y, w, h);
    171             cropped = image.cropImage(rect);
    172             cropped.setFileName(toPath);
    173             cropped.writeImage(infoS);   
    174  
    175         } finally {
    176             if (cropped != null) {
    177                 cropped.destroyImages();
    178             }
    179         }
    180     }
    181     
    182     /**
    183      * 测试
    184      * @param args
    185      */
    186     public static void main(String[] args) {
    187         try {
    188              cutImg("C:\Users\Administrator\Desktop\test\new3.jpg", "C:\Users\Administrator\Desktop\test\new5.jpg", 100, 100, 300, 150);
    189         } catch (MagickException e) {
    190             e.printStackTrace();
    191         }
    192     }
    193 }
  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/wbxk/p/7111531.html
Copyright © 2011-2022 走看看