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/.

 

 
 


posted on 2016-04-15 16:22  mumuxinfei  阅读(3245)  评论(1编辑  收藏  举报

导航