图片工具箱:获取图片大小、裁剪、压缩、旋转、加水印(附 .aia 源码)

图片工具箱:选一张照片,看它多大、多少像素,然后裁剪、旋转、压缩、加水印,每一步都能撤销,满意了直接分享或保存。

下载 ImageToolbox.aia 返回搜索需求专题

这一篇回答的搜索:inventor 获取图片大小、appinventor 图片裁剪、裁剪图片、复制图片、上传图片预览时很清楚到手机上就不清楚了、照相机拍摄完成后设置图像、做相册、TaifunImage / ImageProcessor / ImageUtilities / ImageCompressor 拓展怎么用。

界面

图片工具箱界面布局预览

图为由最终 .aia 生成的布局预览,不是真机截图。

能做什么

分组 操作 说明
取图 从相册选图、拍一张 图像选择器 / 照相机,拿到图片路径
信息 宽 × 高、文件大小 宽高按照片实际显示方向;处理几步后对比原图大小
裁剪 正方形、圆形头像、按比例裁 按比例:左/上/宽/高都填百分比,不同分辨率的照片用同一组数字
调整 顺时针 90°、左右镜像、转黑白、按宽度缩放 缩放时高度按比例自动算
压缩 最长边 + 质量 上传前用:最长边 1280、质量 80 通常能把几 MB 的照片压到几百 KB
水印 文字 + 位置 字号按图片宽度自动,带阴影,深浅背景都看得清
撤销 / 分享 每一步都记下来 退回上一步;分享面板里可以「保存到相册」或发给好友

关掉 App 再打开,会接着上次处理到的那一步。

核心代码

图片处理组件的每个方法都返回一张新图片的路径,原图不会被改动。所以只要把每一步的路径记在列表里,撤销就是删掉最后一项。

取图与显示大小

global 历史 = []

when 图像选择器_相册.AfterPicking() {
  历史 = [图像选择器_相册.Selection]
  显示()
}

when 照相机1.AfterPicture(image) {
  历史 = [image]
  显示()
}

procedure 显示() {
  var 图 = 历史[length(历史)]
  图像_预览.Picture = 图
  标签_信息.Text = join(图片处理1.ImageWidth(图), " × ", 图片处理1.ImageHeight(图), " 像素 · ", decimals(图片处理1.FileSize(图) / 1024, 1), " KB")
}

拍照完成后直接把 image 交给图像组件的 Picture 就能显示,这就是「照相机拍摄完成时设置图像为图像路径」的写法。

处理一步、撤销一步

global 历史 = []

procedure 应用(新路径) {
  if isEmpty(新路径) {
    底部提示条1.Show("处理失败,换一张图试试")
  } else {
    listadd(历史, 新路径)
    图像_预览.Picture = 新路径
  }
}

when 按钮_正方形.Click() {
  应用(图片处理1.CropSquare(历史[length(历史)]))
}

when 按钮_旋转.Click() {
  应用(图片处理1.Rotate(历史[length(历史)], 90))
}

when 按钮_撤销.Click() {
  if length(历史) > 1 {
    listremove(历史, length(历史))
    图像_预览.Picture = 历史[length(历史)]
  }
}

处理失败时组件返回空文本(同时触发图片处理组件自己的「处理失败时」事件,不弹系统错误框),所以先判断再记步骤。

按比例裁剪

Crop 的参数是像素。用户想的是「去掉四周一圈」,所以界面上填百分比,按当前图片宽高换算:

when 按钮_自定义.Click() {
  var 图 = 图像_预览.Picture
  var 宽 = 图片处理1.ImageWidth(图)
  var 高 = 图片处理1.ImageHeight(图)
  图像_预览.Picture = 图片处理1.Crop(图, round(宽 * 文本输入框_左.Text / 100), round(高 * 文本输入框_上.Text / 100), round(宽 * 文本输入框_宽.Text / 100), round(高 * 文本输入框_高.Text / 100))
}

上传前压缩

when 按钮_压缩.Click() {
  var 压缩后 = 图片处理1.Compress(图像_预览.Picture, 1280, round(滑动条_质量.ThumbPosition))
  标签_信息.Text = join("压缩后 ", decimals(图片处理1.FileSize(压缩后) / 1024, 1), " KB")
  图像_预览.Picture = 压缩后
}

常见问题

现象 原因与处理
上传前预览很清楚,到手机上就不清楚 两种情况:① 图片被压得太狠——质量低于 60、最长边小于 800 时细节会糊,换成质量 80、最长边 1280;② 素材图本身像素太小,被图像组件拉伸到全屏宽。素材按显示尺寸的 2~3 倍准备。
读出来的宽高和看到的反了 手机照片常带「旋转方向」标记,图片处理组件按实际显示方向返回宽高;其它方式读的是原始方向,竖拍照片宽高会对调。
获取图片大小返回 0 路径读不到:被系统清理了,或是没有读取权限的共享目录。图像选择器选出的路径可以直接用。
圆形头像四周是黑的 圆形裁剪总是保存成 PNG(圆外透明);如果之后又做了压缩,压缩输出是 JPEG,透明会变成黑/白。圆形放在最后一步。
怎么保存到相册 / 复制图片 结果在 App 专属目录。点「分享」,在分享面板里选「保存到相册」或文件管理器;需要直接复制文件可以用文件增强组件的 CopyFile。
调整照片透明度、抠掉白色背景 内置组件没有透明度调节。抠白底这类逐像素处理可以参考 灰度图找深色像素 的画布取色思路,或使用 TaifunImage 拓展。

用到的组件

相关教程:图片处理教程 · 图片上传到服务器 · 图像矫正

验证范围

最终 .aia 已通过:正式编辑器载入与保存重开 0 错误、后台导入、Android APK 编译,并用真实图片文件(Pillow 执行同样的裁剪/旋转/缩放/压缩)执行了积木的 22 项业务检查(无图提示、宽高与大小、正方形与撤销、按比例裁剪与越界、旋转、缩放、压缩参数与效果、保持原尺寸、水印位置、圆形 PNG、处理失败不记步、分享、重启续接、结果被清理时重置、拍照重新开始)。手机相册与相机的授权流程以实测为准。详见验证记录。

文档反馈