zoukankan      html  css  js  c++  java
  • 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 FilesGraphicsMagick-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("%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();
            } 
        }
    }
  • 相关阅读:
    弹性盒模型:flex多行多列两端对齐,列不满左对齐
    小程序之程序构造器App()
    微信小程序之执行环境
    微信小程序之 ECMAScript
    小程序~WeUI下载使用
    补充拓展:CSS权重值叠加
    微信小程序~模板template引用
    小程序~列表渲染~key
    一个完整URL的组成
    CSS的BEM规范学习
  • 原文地址:https://www.cnblogs.com/xieegai/p/8438918.html
Copyright © 2011-2022 走看看