App Inventor 2 图片处理教程 - 缩放、裁剪、存储与转换

« 返回首页

概述

本文介绍App Inventor 2中常见的图片处理需求:

  • 图片缩放(等比/固定尺寸)
  • 图片存储到本地/相册
  • 图片格式转换
  • Canvas绘制图片
  • 图片选择和裁剪

图片选择

使用ImagePicker

ImagePicker让用户从手机相册选择图片:

when Button1.Click() {
  ImagePicker1.Open()
}
when ImagePicker1.AfterPicking(path) {
  if path != "" {
    Image1.Picture = path
    Label1.Text = join("图片路径:", path)
  }
}

使用FilePicker(选择任意文件)

when Button2.Click() {
  FilePicker1.Open()
}

when FilePicker1.AfterPicking(path) {
  if endsWith(path, ".jpg") || endsWith(path, ".png") {
    Image1.Picture = path
  }
}

使用Camera拍照

when Button3.Click() {
  Camera1.TakePicture()
}
when Camera1.AfterPicture(image) {
  Image1.Picture = image
}

图片缩放

方案一:Canvas缩放(推荐)

通过Canvas将图片绘制到指定尺寸:

global sourcePath = ""
global targetWidth = 200
global targetHeight = 200

when Button4.Click() {
  Canvas1.Width = global_targetWidth
  Canvas1.Height = global_targetHeight
  Canvas1.Clear()
  Canvas1.DrawImage(global_sourcePath, 0, 0, global_targetWidth, global_targetHeight)
}

when Button5.Click() {
  global scaledImage = Canvas1.Save()
  Label1.Text = join("已保存:", global_scaledImage)
}

方案二:等比缩放

保持宽高比的缩放:

function scaleSize(origW, origH, maxSide) {
  var scaleRatio = 0
  var newW = 0
  var newH = 0
  if origW >= origH {
    scaleRatio = maxSide / origW
    newW = maxSide
    newH = floor(origH * scaleRatio)
  } else {
    scaleRatio = maxSide / origH
    newH = maxSide
    newW = floor(origW * scaleRatio)
  }
  return createDictionary(createPair("width", newW), createPair("height", newH))
}

方案三:WebView + Canvas缩放(精确控制)

使用HTML5 Canvas进行高质量缩放:

<!-- resize.html -->
<canvas id="canvas"></canvas>
<script>
function resizeImage(dataUrl, maxW, maxH) {
  var img = new Image();
  img.onload = function() {
    var ratio = Math.min(maxW / img.width, maxH / img.height);
    var w = Math.floor(img.width * ratio);
    var h = Math.floor(img.height * ratio);
    var canvas = document.getElementById('canvas');
    canvas.width = w;
    canvas.height = h;
    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, w, h);
    window.AppInventor.setWebViewString(canvas.toDataURL('image/jpeg', 0.8));
  };
  img.src = dataUrl;
}
</script>

图片存储

保存到应用私有目录

when Button6.Click() {
  // Canvas保存到应用目录
  var savePath = "/sdcard/AppInventor/Assets/my_image.png"
  Canvas1.Save()
  Label1.Text = join("已保存到:", savePath)
}

保存到相册

使用FileTools扩展或File组件:

// 方案1:使用File组件复制到相册目录
when Button7.Click() {
  var srcPath = Canvas1.Save()
  var destPath = join("/sdcard/DCIM/Camera/my_photo_", Clock1.FormatDateTime(Clock1.Now(), "yyyyMMdd_HHmmss"), ".png")
  File1.SaveFile(File1.ReadFrom(srcPath), destPath)
}
when File1.AfterFileSaved(fileName) {
  Label1.Text = join("✅ 已保存到相册:", fileName)
}

注意:Android 10+的分区存储限制,直接写入DCIM目录可能需要特殊权限。推荐使用FileTools扩展的 SaveFileToGallery 方法。

使用FileTools扩展

FileTools扩展 提供了直接保存图片到相册的方法:

when Button8.Click() {
  FileTools1.SaveFile(global_imagePath, "MyAppPhotos")
}

图片裁剪

Canvas裁剪

global cropX = 50
global cropY = 50
global cropW = 200
global cropH = 200

when Button9.Click() {
  // 在Canvas上绘制裁剪区域
  Canvas2.Width = global_cropW
  Canvas2.Height = global_cropH
  Canvas2.Clear()
  // drawImage的源区域参数
  Canvas2.DrawImage(Image1.Picture, global_cropX, global_cropY, global_cropW, global_cropH, 0, 0, global_cropW, global_cropH)
}

WebView裁剪(支持手势框选)

更灵活的方式是在WebView中用JavaScript实现图片裁剪,支持拖拽选择区域。

图片格式转换

Canvas转Base64

when Button10.Click() {
  var base64Data = Canvas1.Save()
  Label1.Text = base64Data
}

Base64转图片

when Button11.Click() {
  Image1.Picture = join("data:image/png;base64,", TextBox1.Text)
}

实战案例:头像上传

功能需求

  • 从相册选择或拍照获取头像
  • 等比缩放到200x200
  • 圆形裁剪
  • 上传到服务器

积木块代码

global avatarPath = ""

when Button12.Click() {
  ImagePicker2.Open()
}

when ImagePicker2.AfterPicking(path) {
  if path != "" {
    global_avatarPath = path
    // 缩放到200x200
    Canvas1.Width = 200
    Canvas1.Height = 200
    Canvas1.Clear()
    Canvas1.DrawImage(path, 0, 0, 200, 200)
    Image1.Picture = Canvas1.Save()
  }
}

when Button13.Click() {
  var base64 = Canvas1.Save()
  Web1.Url = "https://api.example.com/upload/avatar"
  Web1.PostText(join("image=", base64))
}

when Web1.GotText(url, responseCode, responseType, responseContent) {
  if responseContent == "success" {
    Label1.Text = "✅ 头像上传成功"
  } else {
    Label1.Text = "❌ 上传失败"
  }
}

常见问题

Q1: 图片显示变形怎么办?

使用等比缩放,不要强制拉伸。Image组件设置 ScalePictureToFit = true 可以自动等比缩放。

Q2: 大图片导致OOM(内存溢出)?

App Inventor处理大图片(>5MB)容易崩溃。解决方案:

  • 先用Canvas缩小到合理尺寸(如1024x1024)
  • 使用WebView方案处理大图
  • 避免同时加载多张大图

Q3: 图片保存到相册后手机相册看不到?

需要通知系统扫描新文件。使用FileTools扩展的 scanFile 方法:

FileTools1.ScanFile(global_savePath)

或者重启手机后才会出现。

Q4: 如何获取图片的宽高?

App Inventor内置组件不直接提供图片尺寸信息。可以用WebView获取:

var img = new Image();
img.onload = function() {
  window.AppInventor.setWebViewString(img.width + "," + img.height);
};
img.src = imagePath;

总结

需求 推荐方案
选择图片 ImagePicker / Camera
缩放图片 Canvas绘制
存储到相册 FileTools扩展
裁剪图片 Canvas / WebView
格式转换 Canvas + Base64
上传图片 Web组件 + Base64
文档反馈