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).
1
2
3
------WebKitFormBoundaryAuaPsyCAjglAoLNd
Content-Disposition: form-data; name="avatar_data"
{"x":19.999999999999996,"y":-9.969788519637461,"height":160,"width":160,"rotate":0}
    当然还存在完整的图片数据, 为avatar_file字段.
1
2
3
------WebKitFormBoundaryAuaPsyCAjglAoLNd
Content-Disposition: form-data; name="avatar_file"; filename="tu17250_14.jpg"
Content-Type: image/jpeg
    由此可见, 图片的裁剪工作是由服务器端完成的, 客户端只是设定了裁剪信息.

图片处理:
这边也罗列一下图片处理的java代码片段吧.
主要包括裁剪, 缩放等操作.
裁剪操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 *
 * @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;
 
}
缩放操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 *
 * @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   mumuxinfei  阅读(3253)  评论(1编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示