zoukankan      html  css  js  c++  java
  • 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/.

     

     
     


  • 相关阅读:
    SpringCloud学习(三)服务消费者(Feign)(Finchley版本)
    go爬虫系列
    SpringCloud学习(二)服务消费者(rest+ribbon)(Finchley版本)
    SpringCloud学习(一)服务的注册与发现Eureka(Finchley版本)
    JDK源码分析(11) ConcurrentLinkedQueue
    ServiceFabric极简文档-4.1 学习路线图
    ServiceFabric极简文档-4.0 开发环境搭建
    ServiceFabric极简文档-3. 发布脚本
    ServiceFabric极简文档-2 部署环境搭建-配置文件
    ServiceFabric极简文档-1.3删除群集
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/5395332.html
Copyright © 2011-2022 走看看