web開發實戰--圖片裁剪和上傳


 

前言:
  最近的開發中, 有一個上傳頭像的任務. 由於頭像本身的特殊性, 其一般流程為選擇圖片, 編輯裁剪區域, 再繼而上傳圖片操作.
  看似簡單的東西, 實則是挺麻煩的一件事. 借助這次開發機會, 來具體談談圖片裁剪和文件異步上傳的基本原理.


技術點:
由於采用springmvc作為web的mvc框架, 因此文件上傳的基礎知識,可參考如下博文.
springmvc學習筆記--支持文件上傳和阿里雲OSS API簡介.

處理模式:
先來看看頭像編輯和上傳的一些案例吧.

  

    先上傳圖片, 然后選擇裁剪區域, 然后點擊完成. 此時圖片就會異步上傳, 並最終返回image url.
這邊涉及的問題包括如下:
1). 圖片文件的異步上傳如何實現?
2). 圖片的裁剪過程在哪里完成, 客戶端還是服務端?
帶着這些疑問, 我們來講述下后續的文章吧.

文件異步上傳原理:
眾所周知, 圖片是以multipart/form-data的表單模式進行上傳的. 這種模式是不支持異步刷新的, 或者確切地說不支持Ajax機制.
當然有需求, 就會有人前呼后繼去嘗試各種解決方案. 當前主流的思路是, 借助iframe來模擬實現無刷新的文件上傳.
動態生成一個臨時的iframe, 然后把需要post的目標轉移到該iframe. iframe請求結束后, 主頁面(父頁面)提取iframe的返回結果, 並進行相應的更新.
具體可以參考下博文: jquery插件--ajaxfileupload.js上傳文件原理分析.

頭像裁剪的原理:
回到之前的一個疑問: 圖片的裁剪是在客戶端完成, 還是在服務端完成呢?
我們借助一個cropper插件的一個實例demo, 用chrome控制台工具來檢測一下.
點擊一下, 可訪問cropper的插件站點.
可以發現其post表單中, 存在avatar_data字段, 其指定了裁剪范圍(x, y, width, height, rotate).
    ------WebKitFormBoundaryAuaPsyCAjglAoLNd
    Content-Disposition: form-data; name="avatar_data"
    {"x":19.999999999999996,"y":-9.969788519637461,"height":160,"width":160,"rotate":0}
    當然還存在完整的圖片數據, 為avatar_file字段.
    ------WebKitFormBoundaryAuaPsyCAjglAoLNd
    Content-Disposition: form-data; name="avatar_file"; filename="tu17250_14.jpg"
    Content-Type: image/jpeg
    由此可見, 圖片的裁剪工作是由服務器端完成的, 客戶端只是設定了裁剪信息.
 
        
圖片處理:
這邊也羅列一下圖片處理的java代碼片段吧.
主要包括裁剪, 縮放等操作.
裁剪操作:
    /**
     *
     * @param srcImage
     * @param x
     * @param y
     * @param dw
     * @param dh
     * @return
     */
    public static BufferedImage cutoffImage(
            BufferedImage srcImage, double x, double y, double dw, double dh) {

        int width = srcImage.getWidth();
        int height = srcImage.getHeight();

        double sx = Math.min(Math.max(0, x), width);
        double sy = Math.min(Math.max(0, y), height);

        double dx = Math.min(Math.max(0, x + dw), width);
        double dy = Math.min(Math.max(0, y + dh), height);

        BufferedImage subImage = srcImage.getSubimage(
                (int)sx, (int)sy, (int)(dx - sx), (int)(dy - sy)
        );

        return subImage;

    }
縮放操作:
    /**
     *
     * @param srcImage  源圖片
     * @param dstWidth  目標圖片的寬
     * @param dstHeight 目標圖片的高
     * @return
     */
    public static BufferedImage zoomImage(BufferedImage srcImage, int dstWidth, int dstHeight) {

        double wr = dstWidth * 1.0 / srcImage.getWidth();
        double hr = dstHeight * 1.0 / srcImage.getHeight();

        AffineTransformOp ato = new AffineTransformOp(
                AffineTransform.getScaleInstance(wr, hr), null
        );

        return ato.filter(srcImage, null);

    }
    對於java的圖片處理, 其實可挖掘的點很多, 這邊簡單寫寫.

總結:
很多人覺得, 插件集成很容易, 實則不是, 里面需要做很多工作, 對原理的了解和如何交互集成, 都需要費不少勁.
本文簡單講述了下圖片裁剪和上傳的基本原理, 相對還是比較水. 希望有一天, 能夠有機會對java的圖像處理, 做一個深入的理解, 包括性能和處理模式.
 
        
公眾號&游戲站點:
  個人微信公眾號: 木目的H5游戲世界

  

  個人游戲作品集站點(尚在建設中...): www.mmxfgame.com,  也可直接ip訪問http://120.26.221.54/.

 

 
 



免責聲明!

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



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