JAVA通過BufferedImage進行圖片的繪製,縮放,裁剪,水印等操作

最近開發當中,通過JAVA對圖片進行了很多的操作,之前很少接觸這方面的知識,特此記錄下來

讀取圖片

//讀取圖片  通過JAVA自帶的ImageIO裏面的read方法
BufferedImage bufImage = ImageIO.read(File input);
BufferedImage bufImage = ImageIO.read(URL input);
BufferedImage bufImage = ImageIO.read(InputStream input);
BufferedImage bufImage = ImageIO.read(ImageInputStream input)

保存圖片

/**
 *  image:RenderedImage 接口的實現類, BufferedImage 實現了 RenderedImage 接口
 *  formatName: 保存的圖片格式的名稱
 *  output: 結果輸出位置
 */
ImageIO.write(RenderedImage image, String formatName, File output);
ImageIO.write(RenderedImage image, String formatName, OutputStream output);

繪製圖片

/**
 * 創建一個指定寬高的圖片內存對象
 * width : 寬度
 * height : 高度
 * imageType : 圖片類型   參數爲BufferedImage 自身定義的常量   
 *	TYPE_3BYTE_BGR :代表8位RGB分量圖像
        TYPE_INT_ARGB :代表8位RGBA顏色組件包裝成整數像素的圖像
	......
 */
BufferedImage image = new BufferedImage(width, height, imageType);
//獲取圖片的畫布
Graphics2D graphics = image.createGraphics();

//然後使用 Graphics 類在圖片上繪製線段、矩形、圖片、文本,設置背景顏色等等操作

// 設置畫布顏色
void setColor(Color c)
// 設置字體顏色
void setFont(Font font)
// 設置線的寬度
setStroke(Stroke s)
// 設置背景顏色
void setBackground(Color c)
// 擦除某一區域(擦除後顯示背景色)
void clearRect(int x, int y, int width, int height)
// 回收 Graphics 釋放資源   操作完畢後一定要釋放資源
void dispose()

// 繪製一條線段(如果兩點爲同一點,則繪製點)  
void  drawLine(int x1,  int y1,  int x2,  int y2)
// 繪製一個矩形(空心)  
void  drawRect(int x,  int y,  int width,  int height) 
// 繪製一個橢圓(空心) 
void  drawOval(int x,  int y,  int width,  int height)
// 繪製一個圓弧(弧線) 
void  drawArc(int x,  int y,  int width,  int height,  int startAngle,  int arcAngle)
// 繪製一張圖片 ImageObserver:接收有關 Image 信息通知的異步更新接口,沒用到直接傳空
boolean  drawImage(Image image,  int x,  int y, ImageObserver observer)
// 繪製一段文本
void  drawString(String str,  int x,  int y)
...........................

縮放圖片

/**
 *@param   width: 縮放後的寬度
 *@param   height: 縮放後的高度
 *@param   hints:  圖像重採樣算法的類型
 *
 *  hints 參數取值爲以下之一(Image 類中的常量):
 *     SCALE_AREA_AVERAGING: 使用 Area Averaging 圖像縮放算法;
 *     SCALE_DEFAULT: 使用默認的圖像縮放算法;
 *     SCALE_SMOOTH: 選擇圖像平滑度比縮放速度具有更高優先級的圖像縮放算法。
 *     ......
 */
Image getScaledInstance(int width, int height, int hints);

縮放的使用實例代碼:

  /**
     * JAVA 圖像等比縮放
     * @param srcImageFile  縮放的圖片
     * @param destImageFile  縮放後的圖片
     * @param scale  縮放比例
     * @return
     */
    public static boolean scale(File srcImageFile, File destImageFile,float scale){
        try {
            //使用ImageIO的read方法讀取圖片
            BufferedImage read = ImageIO.read(srcImageFile);
            //獲取縮放後的寬高
            int width = (int) (read.getWidth()*scale);
            int height = (int) (read.getHeight()*scale);
            //調用縮放方法獲取縮放後的圖片
            Image img = read.getScaledInstance(width , height, Image.SCALE_DEFAULT);
            //創建一個新的緩存圖片
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            //獲取畫筆
            Graphics2D graphics = image.createGraphics();
            //將Image對象畫在畫布上,最後一個參數,ImageObserver:接收有關 Image 信息通知的異步更新接口,沒用到直接傳空
            graphics.drawImage(img, 0, 0,null);
            //一定要釋放資源
            graphics.dispose();
            //獲取到文件的後綴名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法進行輸出
            ImageIO.write(image,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

裁剪圖片

/**
* 
* @param x     裁剪時x的座標(左上角)
* @param y     裁剪時y的座標(左上角)
* @param width  裁剪後的圖片寬度
* @param height 裁剪後的圖片高度
* 
* 裁剪後返回的是一個新的圖片緩存對象
*/
 BufferedImage  getSubimage(int x,int y, int width  ,int height )

裁剪圖片實例代碼:

    /**
     * JAVA裁剪圖片
     * @param srcImageFile  需要裁剪的圖片
     * @param x     裁剪時x的座標(左上角)
     * @param y     裁剪時y的座標(左上角)
     * @param width  裁剪後的圖片寬度
     * @param height 裁剪後的圖片高度
     * @param destImageFile  裁剪後的圖片
     * @return
     */
    public static boolean cut(File srcImageFile, int x,int y,int width,int height,File destImageFile){
        try {
            //使用ImageIO的read方法讀取圖片
            BufferedImage read = ImageIO.read(srcImageFile);
            //調用裁剪方法
            BufferedImage image = read.getSubimage(x, y, width, height);
            //獲取到文件的後綴名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法進行輸出
            ImageIO.write(image,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
            return  false;
        }
        return true;
    }

添加水印

水印的添加主要是通過下面的方法進行的添加。
// 繪製一張圖片 ImageObserver:接收有關 Image 信息通知的異步更新接口,沒用到直接傳空
boolean  drawImage(Image image,  int x,  int y, ImageObserver observer)
//設置水印透明度
void setComposite(Composite comp)
// 繪製一段文本
void  drawString(String str,  int x,  int y)

文本水印

    /**
     *  JAVA添加文字水印
     * @param srcImageFile  目標圖片
     * @param destImageFile 結果圖片
     * @param text         文字內容
     * @param x            水印x座標
     * @param y            水印y座標
     * @return
     */
    public static boolean watermarkText(File srcImageFile, File destImageFile, String text,int x,int y) {
        try {
            //使用ImageIO的read方法讀取圖片
            BufferedImage read = ImageIO.read(srcImageFile);
            Graphics2D graphics = read.createGraphics();
	    // 設置“抗鋸齒”的屬性
	    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 設置字體類型和大小
            graphics.setFont(new Font("微軟雅黑", Font.PLAIN, 20));
            // 設置顏色
            graphics.setColor(new Color(255,255,255));
            // 添加文字
            graphics.drawString(text,x,y);
            graphics.dispose();
            //獲取到文件的後綴名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法進行輸出
            ImageIO.write(read,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

圖片水印

    /**
     *  JAVA添加文字水印
     * @param srcImageFile  目標圖片
     * @param destImageFile 結果圖片
     * @param waterImage    水印圖片
     * @param x            水印x座標
     * @param y            水印y座標
     * @return
     */
    public static boolean watermarkImage(File srcImageFile,File destImageFile, File waterImage,int x,int y) {
        try {
            //使用ImageIO的read方法讀取圖片
            BufferedImage read = ImageIO.read(srcImageFile);
            BufferedImage image = ImageIO.read(waterImage);
            //獲取畫布
            Graphics2D graphics = read.createGraphics();
            //設置透明度爲0.5
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,0.5f));
            //添加水印
            graphics.drawImage(image,x,y,null);
            //關閉透明度
            //graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            graphics.dispose();
            //獲取到文件的後綴名
            String fileName = srcImageFile.getName();
            String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);
            //使用ImageIO的write方法進行輸出
            ImageIO.write(read,formatName,destImageFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

如何擦除水印?
第一種方法 :
// 擦除某一區域(擦除後顯示背景色)
void clearRect(int x, int y, int width, int height)

第二種方法:色素替代法
找到水印的顏色編碼,然後用背景色顏色編碼替代。
代碼實現:略 (這種清除水印的需求還是交給PS這種專業軟件去做吧)

貝塞爾曲線

通常繪製線段直接使用一下的方法就可以了drawLine方法就可以了。但是在實現曲線的時候就很難看,所以需要用到貝塞爾曲線。
可以通過Path類來實現貝塞爾曲線的效果

BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
// 設置“抗鋸齒”的屬性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//獲取路徑操作
Path2D path = new GeneralPath();
//通過移動到指定的浮點精度指定的指定的座標,向路徑添加一個點。
path.moveTo(192, 18);
//添加一個彎曲段,由兩個新定義的點,通過繪製一條二次曲線相交的當前座標和指定的座標 (x2,y2)的路徑,使用指定的點 (x1,y1)作爲二次參考
path.quadTo(120, 12, 253, 67);
graphics.draw(path);
graphics.dispose();

總結

JAVA操作圖片的話算是一個非常冷門的功能了,最多就是圖片的縮放,裁剪,水印這三種情況。如果需要進行一些額外的操作的話,就非常需要認真的查閱下JDK的API,並且JAVA操作圖片調試起來也非常的不方便。總的來說就是複雜的圖片操作需求還是交給更專業的軟件(PS)來進行操作吧!!!
JDK1.8在線API

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章