GraphicsMagick+im4java图片处理

一、windows上安装ImageMagick(参考:https://my.oschina.net/roaminlove/blog/96279)
地址:http://ftp.icm.edu.pl/pub/unix/graphics/GraphicsMagick/windows/
关于Q8,Q16(默认),Q32的说明:
  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,现在数码相机照的相片,每一种颜色就是8位深,3种颜色就是24位。注意事项:windows下运行,需要配置ImageMagick的安装路径,可用配置文件方式,也可配环境变量“PATH:D:\Program Files\GraphicsMagick-1.3.18-Q8”。

 

二. Linux下的安装与配置ImageMagick(Centos64、Redhat下测试成功)(参考:http://blog.csdn.net/blackonline/article/details/61195842)

1、查看所需依赖是否安装
      yum install -y gcc libpng libjpeg libpng-devel libjpeg-devel ghostscript libtiff libtiff-devel freetype freetype-devel

或:rpm -q libjpeg libjpeg-devel libpng libpng-devel freetype freetype- devel libtiff

2.下载GraphicsMagick

    wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.25.tar.gz

3、新建文件夹graphicsMagick,在文件夹内解压GraphicsMagick-1.3.25.tar.gz

     tar -zxvf GraphicsMagick-1.3.25.tar.gz

4、编译

      ./configure --with-quantum-depth=8 --enable-shared

5、安装

      make

      make install

6、验证

      gm -version

7、测试,新建测试文件夹test,在测试文件夹储存一张测试图片testin.jpg,运行如下命名,查看是否成功

      gm convert -scale 100x100 testin.jpg testout.jpg

8、常用命令介绍 

      http://blog.csdn.net/cbbbc/article/details/52175559   

      http://blog.csdn.net/haima1998/article/details/73951312

 

三、下载 im4java(参考:http://blog.csdn.net/tangpengtao/article/details/9208047)

地址:http://sourceforge.net/projects/im4java/?source=directory

im4java的思路是通过线程或者进程执行graphicsmagick的命令,它的api只是为了能生成命令,而不是调用graphicsmagick的库。IM4JAVA是同时支持ImageMagick和GraphicsMagick的,这里是bool值,如果为true则使用GM,如果为false支持IM。

 

四、常用工具类

1.工具类

package img.GraphicsMagick;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.ResourceBundle;
import org.apache.commons.lang.SystemUtils;
import org.im4java.core.ConvertCmd;
import org.im4java.core.IM4JavaException;
import org.im4java.core.IMOperation;
import org.im4java.core.IdentifyCmd;
import org.im4java.process.ArrayListOutputConsumer;

public class Test1 {
    
    public static String imageMagickPath = null;  
    
    private static boolean is_windows = false;
    
    /**获取ImageMagick的路径,获取操作系统是否为WINDOWS*/  
    static{
        // 通过ResourceBundle.getBundle()静态方法来获取,这种方式来获取properties属性文件不需要加.properties后缀名,只需要文件名即可。
        ResourceBundle resource = ResourceBundle.getBundle("config"); //src文件夹下的配置文件直接写文件名
        imageMagickPath = resource.getString("imageMagickPath");  
        is_windows = SystemUtils.IS_OS_WINDOWS;
    }  

    public static int getSize(String imagePath) {
        int size = 0;
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(imagePath);
            size = inputStream.available();
            inputStream.close();
            inputStream = null;
        } catch (FileNotFoundException e) {
            size = 0;
            System.out.println("文件未找到!");
        } catch (IOException e) {
            size = 0;
            System.out.println("读取文件大小错误!");
        } finally {
            // 可能异常为关闭输入流,所以需要关闭输入流
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    System.out.println("关闭文件读入流异常");
                }
                inputStream = null;
            }
        }
        return size;
    }

    public static int getWidth(String imagePath) {
        int line = 0;
        try {
            IMOperation op = new IMOperation();
            op.format("%w"); // 设置获取宽度参数
            op.addImage(1);
            
            IdentifyCmd identifyCmd = new IdentifyCmd(true);
            ArrayListOutputConsumer output = new ArrayListOutputConsumer();
            identifyCmd.setOutputConsumer(output);
            if (is_windows) {
                identifyCmd.setSearchPath(imageMagickPath);
            }
            identifyCmd.run(op, imagePath);
            ArrayList<String> cmdOutput = output.getOutput();
            assert cmdOutput.size() == 1;
            line = Integer.parseInt(cmdOutput.get(0));
        } catch (Exception e) {
            line = 0;
            System.out.println("运行指令出错!"+e.toString());
        }
        return line;
    }
    
    public static int getHeight(String imagePath) {
        int line = 0;
        try {
            IMOperation op = new IMOperation();

            op.format("%h"); // 设置获取高度参数
            op.addImage(1);
            IdentifyCmd identifyCmd = new IdentifyCmd(true);
            ArrayListOutputConsumer output = new ArrayListOutputConsumer();
            identifyCmd.setOutputConsumer(output);
            if (is_windows) {
                identifyCmd.setSearchPath(imageMagickPath);
            }
            identifyCmd.run(op, imagePath);
            ArrayList<String> cmdOutput = output.getOutput();
            assert cmdOutput.size() == 1;
            line = Integer.parseInt(cmdOutput.get(0));
        } catch (Exception e) {
            line = 0;
            System.out.println("运行指令出错!"+e.toString());
        }
        return line;
    }
    
    public static String getImageInfo(String imagePath) {
        String line = null;
        try {
            IMOperation op = new IMOperation();
            op.format("width:%w,height:%h,path:%d%f,size:%b%[EXIF:DateTimeOriginal]");
            op.addImage(1);
            IdentifyCmd identifyCmd = new IdentifyCmd(true);
            ArrayListOutputConsumer output = new ArrayListOutputConsumer();
            identifyCmd.setOutputConsumer(output);
            if (is_windows) {
                identifyCmd.setSearchPath(imageMagickPath);
            }
            identifyCmd.run(op, imagePath);
            ArrayList<String> cmdOutput = output.getOutput();
            assert cmdOutput.size() == 1;
            line = cmdOutput.get(0);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return line;
    }
    
    /**
     * 根据坐标裁剪图片
     * @param imagePath  源图片路径
     * @param newPath    处理后图片路径
     * @param x          起始X坐标
     * @param y          起始Y坐标
     * @param width      裁剪宽度
     * @param height     裁剪高度
     * @return           返回true说明裁剪成功,否则失败
     */
    public static boolean cutImage1(String imagePath, String newPath, int x, int y, int width, int height) {
        boolean flag = false;
        try {
            IMOperation op = new IMOperation();
            op.addImage(imagePath);
            op.crop(width, height, x, y);/** width:裁剪的宽度 * height:裁剪的高度 * x:开始裁剪的横坐标 * y:开始裁剪纵坐标 */
            op.addImage(newPath);
            ConvertCmd convert = new ConvertCmd(true);
            if (is_windows) {
                convert.setSearchPath(imageMagickPath);
            }
            convert.run(op);
            flag = true;
        } catch (IOException e) {
            System.out.println("文件读取错误!");
            flag = false;
        } catch (InterruptedException e) {
            flag = false;
        } catch (IM4JavaException e) {
            flag = false;
        }
        return flag;
    }
    
    /**
     * 根据坐标裁剪图片
     * @param srcPath   要裁剪图片的路径
     * @param newPath   裁剪图片后的路径
     * @param x         起始横坐标
     * @param y         起始挫坐标
     * @param x1                    结束横坐标
     * @param y1                    结束挫坐标
     */
    public static void cutImage2(String srcPath, String newPath, int x, int y, int x1, int y1) {
        try {
            IMOperation op = new IMOperation();
            int width = x1 - x; // 裁剪的宽度
            int height = y1 - y;//裁剪的高度 
            op.addImage(srcPath);
            op.crop(width, height, x, y);
            op.addImage(newPath);
            ConvertCmd convert = new ConvertCmd(true);
            if (is_windows) {
                convert.setSearchPath(imageMagickPath);
            }
            convert.run(op);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IM4JavaException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 根据尺寸等比例缩放图片       大边达到指定尺寸
     * [参数height为null,按宽度缩放比例缩放;参数width为null,按高度缩放比例缩放]
     * @param imagePath   源图片路径
     * @param newPath     处理后图片路径
     * @param width       缩放后的图片宽度
     * @param height      缩放后的图片高度
     * @return            返回true说明缩放成功,否则失败
     */
    public static boolean zoomImage1(String imagePath, String newPath, Integer width, Integer height) {
        boolean flag = false;
        try {
            IMOperation op = new IMOperation();
            op.addImage(imagePath);
            if (width == null) {// 根据高度缩放图片
                op.resize(null, height);
            } else if (height == null) {// 根据宽度缩放图片
                op.resize(width);
            } else {
                op.resize(width, height);
            }
            op.addImage(newPath);
            // IM4JAVA是同时支持GraphicsMagick和ImageMagick的,如果为true则使用GM,如果为false支持IM。  
            ConvertCmd convert = new ConvertCmd(true);
            // 判断系统
            String osName = System.getProperty("os.name").toLowerCase();  
            if(osName.indexOf("win") >= 0) { 
                convert.setSearchPath(imageMagickPath);   
            } 
            convert.run(op);
            flag = true;
        } catch (IOException e) {
            System.out.println("文件读取错误!");
            flag = false;
        } catch (InterruptedException e) {
            flag = false;
        } catch (IM4JavaException e) {
            System.out.println(e.toString());
            flag = false;
        } 
        return flag;
    }
    
    /**
     * 根据像素缩放图片
     * @param width   缩放后的图片宽度
     * @param height  缩放后的图片高度
     * @param srcPath 源图片路径
     * @param newPath 缩放后图片的路径
     * @param type    1大小       2比例
     */
    public static String zoomImage2(int width, int height, String srcPath, String newPath, int type, String quality) throws Exception {
        IMOperation op = new IMOperation();
        op.addImage();
        String raw = "";
        if (type == 1) {  // 按像素大小
            raw = width + "x" + height + "^";
        } else {          // 按像素百分比
            raw = width + "%x" + height + "%";
        }
        ConvertCmd cmd = new ConvertCmd(true);
        op.addRawArgs("-sample", raw);
        if ((quality != null && !quality.equals(""))) {
            op.addRawArgs("-quality", quality);
        }
        op.addImage();

        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.indexOf("win") != -1) {
            cmd.setSearchPath(imageMagickPath);
        }
        try {
            cmd.run(op, srcPath, newPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newPath;
    }
    
    /**
     * 图片旋转
     * @param imagePath   源图片路径
     * @param newPath     处理后图片路径
     * @param degree      旋转角度
     */
    public static boolean rotate(String imagePath, String newPath, double degree) {
        boolean flag = false;
        try {
            // 1.将角度转换到0-360度之间
            degree = degree % 360;
            if (degree <= 0) {
                degree = 360 + degree;
            }
            IMOperation op = new IMOperation();
            op.addImage(imagePath);
            op.rotate(degree);
            op.addImage(newPath);
            ConvertCmd cmd = new ConvertCmd(true);
            if (is_windows) {
                cmd.setSearchPath(imageMagickPath);
            }
            cmd.run(op);
            flag = true;
        } catch (Exception e) {
            flag = false;
            System.out.println("图片旋转失败!");
        }
        return flag;
    }

    /**
     * 给图片加水印
     * @param srcPath  源图片路径
     * @param destPath 目标图片路径
     */
    public static void addImgText(String srcPath, String destPath) throws Exception {
        try {
            IMOperation op = new IMOperation();
            op.font("Arial").gravity("southeast").pointsize(150).fill("#BCBFC8").draw("text 100,100 co188.com");
            op.quality(85d);  //压缩质量
            op.addImage(srcPath);
            op.addImage(destPath);
            ConvertCmd cmd = new ConvertCmd(true);
            if (is_windows) {
                cmd.setSearchPath(imageMagickPath);
            }
            cmd.run(op);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /** 
     * 先等比例缩放,后居中切割图片 
     * @param srcPath 源图路径 
     * @param desPath 目标图保存路径 
     * @param rectw 待切割在宽度 
     * @param recth 待切割在高度 
     */  
    public static void cropImageCenter(String srcPath, String desPath, int width, int height) {  
        try {
            IMOperation op = new IMOperation();  
            op.addImage();  
            op.resize(width, height, '^').gravity("center").extent(width, height);  
            //op.resize(width, height).background("gray").gravity("center").extent(width, height);
            op.addImage();  
            ConvertCmd convert = new ConvertCmd(true);
            if (is_windows) {
                convert.setSearchPath(imageMagickPath);
            }
            convert.run(op, srcPath, desPath);
        } catch (IOException | InterruptedException | IM4JavaException e) {
            e.printStackTrace();
        }  
    } 
    
    public static void main(String[] args) throws Exception {
        Long start = System.currentTimeMillis();
        // System.out.println("原图片宽度:" + getWidth("D:\\test\\map.jpg"));
        // System.out.println("原图片高度:" + getHeight("D://test//map.jpg"));
        // System.out.println("原图片信息:" + getImageInfo("D://test//map.jpg"));
        // cutImage2("D://test//map.jpg", "D://test//m.jpg", 10, 10, 200, 200);
        // rotate("D://test//map.jpg", "D://test//m.jpg", 10);
        // drawImg("D://test//map.jpg", "D://test//ma.jpg", 1500, 1500);
        // zoomImage1( "D://test//map.jpg", "D://test//mapppp.jpg",280, 200);
        // zoomImage2(280, 200 ,"D://test//map.jpg", "D://test//mapppppppappp.jpg",1,null);
        // addImgText("D://test//map1.jpg", "D://test//map111.jpg");
        cropImageCenter("D://test//haidilao.jpg", "D://test//haidilao1112.jpg", 400, 400);
        
        Long end = System.currentTimeMillis();
        System.out.println("time:" + (end - start));
    }
    
}

2.配置文件:   /Test/src/config.properties

imageMagickPath=D:\\Program Files\\GraphicsMagick-1.3.28-Q16

 

五、返回输入输出流

package img.GraphicsMagick;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.lang.SystemUtils;
import org.im4java.core.ConvertCmd;
import org.im4java.core.IM4JavaException;
import org.im4java.core.IMOperation;
import org.im4java.process.Pipe;

/**
 * 将图片装换压缩成固定的大小格式的图片
 * im4java + GraphicsMagick-1.3.24-Q16
 */
public class GraphicsMagicUtilOfIM4Java {
     
    private static final String GRAPHICS_MAGICK_PATH = "D:\\Program Files\\GraphicsMagick-1.3.28-Q16";
    private static final boolean IS_WINDOWS = SystemUtils.IS_OS_WINDOWS;
    
    // 压缩图片,返回输出流
    public static OutputStream zoomPic(OutputStream os, InputStream is, String contentType, Integer width, Integer height)
            throws IOException, InterruptedException, IM4JavaException {
        IMOperation op = buildIMOperation(contentType, width, height);
 
        Pipe pipeIn = new Pipe(is, null);
        Pipe pipeOut = new Pipe(null, os);
 
        ConvertCmd cmd = new ConvertCmd(true);
        if (IS_WINDOWS) { // linux下不要设置此值,不然会报错
            cmd.setSearchPath(GRAPHICS_MAGICK_PATH);
        }
        cmd.setInputProvider(pipeIn);
        cmd.setOutputConsumer(pipeOut);
        cmd.run(op);
        return os;
    }
    
    // 压缩图片,返回输入流
    public static InputStream convertThumbnailImage(InputStream is, String contentType, double width, double height) {
        try {
            IMOperation op = buildIMOperation(contentType, width, height);
 
            Pipe pipeIn = new Pipe(is, null);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Pipe pipeOut = new Pipe(null, os);
 
            ConvertCmd cmd = new ConvertCmd(true);
            if (IS_WINDOWS) {
                cmd.setSearchPath(GRAPHICS_MAGICK_PATH);
            }
            cmd.setInputProvider(pipeIn);
            cmd.setOutputConsumer(pipeOut);
            cmd.run(op);
            return new ByteArrayInputStream(os.toByteArray());
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }
    
    // 构建IMOperation
    private static IMOperation buildIMOperation(String contentType, Number width, Number height) {
        IMOperation op = new IMOperation();
 
        String widHeight = width + "x" + height;
        op.addImage("-");                                  // 命令:从输入流中读取图片
        op.addRawArgs("-scale", widHeight);                // 按照给定比例缩放图片
        op.addRawArgs("-gravity", "center");                 // 缩放参考位置 对图像进行定位
        op.addRawArgs("-extent", widHeight);               // 限制JPEG文件的最大尺寸
        op.addRawArgs("+profile", "*");                    // 去除Exif信息
        // 设置图片压缩格式
        op.addImage(contentType.substring(contentType.indexOf("/") + 1) + ":-");
        return op;
    }
 
    /**
     * 先等比例缩放,后居中切割图片 
     * @param os
     * @param is
     * @param width
     * @param height
     */
    public static void zoomPic(InputStream is, OutputStream os, Integer width, Integer height) {
        try {
            IMOperation op = new IMOperation();
            op.addImage("-");                                  // 命令:从输入流中读取图片
            op.resize(width, height, '^').gravity("center").extent(width, height); 
            op.addRawArgs("+profile", "*");                    // 去除Exif信息       
            op.addImage("jpg" + ":-");                         // 设置图片压缩格式
            Pipe pipeIn = new Pipe(is, null);
            is.close();
            Pipe pipeOut = new Pipe(null, os);
            os.close();
            ConvertCmd cmd = new ConvertCmd(true);
            if (IS_WINDOWS) { // Linux下不要设置此值,不然会报错
                cmd.setSearchPath(GRAPHICS_MAGICK_PATH);
            }
            cmd.setInputProvider(pipeIn);
            cmd.setOutputConsumer(pipeOut);
            cmd.run(op);
        } catch (IOException | InterruptedException | IM4JavaException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 图片旋转
     * @param is
     * @param os
     * @param degree
     */
    public static byte[] rotate(InputStream is, double degree) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            // 将角度转换到0-360度之间
            degree = degree % 360;
            if (degree <= 0) {
                degree = 360 + degree;
            }
            IMOperation op = new IMOperation();
            op.addImage("-");
            op.rotate(degree);
            op.addImage("jpg" + ":-");
            Pipe pipeIn = new Pipe(is, null);
            is.close();
            Pipe pipeOut = new Pipe(null, os);
            os.close();
            ConvertCmd cmd = new ConvertCmd(true);
            if (IS_WINDOWS) {
                cmd.setSearchPath(GRAPHICS_MAGICK_PATH);
            }
            cmd.setInputProvider(pipeIn);
            cmd.setOutputConsumer(pipeOut);
            cmd.run(op);
        } catch (IOException | InterruptedException | IM4JavaException e) {
            e.printStackTrace();
            return null;
        }
        return os.toByteArray();
    }
    
    public static void main(String[] args) throws Exception {
        // 输入输出文件路径/文件
        File srcFile = new File("D:\\test\\wKgB-1pycFOAAGicAAUp98UmwuU169.jpg");
        File destFile = new File("D:\\test\\www1211211.jpg");
        
        byte[] bytes = getByte(srcFile);
        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        
        byte[] rotate = rotate(is, 300);
        
        FileOutputStream fis = new FileOutputStream(destFile);
        fis.write(rotate);
     }
    
    /**
     * 将file文件转为字节数组
     */
    public static byte[] getByte(File file){
        byte[] bytes = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            bytes = new byte[fis.available()];
            fis.read(bytes);
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        } 
        return bytes;
    }
    
    /**
     * 将字节流写到指定文件
     */
    public static void writeFile(ByteArrayOutputStream os, File file){
        try {
            if (file.exists()) {
                file.delete();
            }
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(os.toByteArray());
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

 

posted on 2018-02-10 15:34 xieegai 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/xieegai/p/8438918.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GraphicsMagick号称图像处理领域的瑞士军刀。 短小精悍的代码却提供了一个鲁棒、高效的工具和库集合,来处理图像的读取、写入和操作,支持超过88种图像格式,包括重要的DPX、GIF、JPEG、JPEG-2000、PNG、PDF、PNM和TIFF。 通过使用OpenMP可是利用多线程进行图片处理,增强了通过扩展CPU提高处理能力。 GraphicsMagick可以在绝大多数的平台上使用,Linux、Mac、Windows都没有问题。 GraphicsMagick 支持大图片处理,并且已经做过GB级别的图像处理实验。GraphicsMagick能够动态的生成图片,特别适用于互联网的应用。可以用来处理调整尺寸、旋转、加亮、颜色调整、增加特效等方面。GaphicsMagick不仅支持命令行的模式,同时也支持C、C++、Perl、PHP、Tcl、 Ruby等的调用。事实上,GraphicsMagick是从 ImageMagick 5.5.2 分支出来的,但是现在他变得更稳定和优秀,下面就是两个之间的一些比较。 GM更有效率(测评),能更快的完成处理工作 GM更小更容易安装 GM已经被Flickr和Etsy使用,每天处理百万计的图片 GM与已经安装的软件不会发生冲突 GM几乎没有安全问题 GM的手册非常丰富 im4javaImageMagick的一个Java开源接口,使用起来非常方便。 很多网站都会用到对图片的一些处理,包括图片的裁剪、给图片加水印、按比例缩放图片等操作,用ImageMagick实现这些功能,性能非常好,图片还不会失真. 本文档详细的介绍了 GraphicsMagick+im4java的搭建过程,对一些搭建过程中出现的问题进行了详细的解答,避免采坑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值