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();
        } 
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM