photos
相册选择、拍照、保存和资源查询。
访问系统照片库:选图、拍照、保存图片/视频、读取资源与相册,以及图片 Base64 转换。
边界:走系统照片/相机界面,用户可随时取消(返回None或False)。visionOCR 要 bytes,vision_helper检测要 Base64;大文件不要塞进storage。
#模块概览
| 项 | 说明 |
|---|---|
| 导入 | import photos |
| 适合做什么 | 选图上传、拍照存档、相册浏览、视觉识别前置 |
| 调用时机 | pick_image / capture_image 放在按钮回调;不要写在 body() 中 |
| 推荐顺序 | 用户点击 → pick_image / capture_image → 判空 → 处理或 save_image |
| 取消处理 | 用户取消返回 None;保存失败返回 False |
#双入口:脚本与 AppUI
| 入口 | 第一行 | 适合场景 |
|---|---|---|
| Python 模块 | import photos | pick_image()、capture_image() 等函数式调用 |
| AppUI 组件 | import appui + PhotoPicker | 表单内嵌选图、on_picked 回调绑定 |
两种入口共享相册权限与取消语义;相机场景见 camera-module,任意文件见 file-picker-module。
#快速开始
下面脚本从相册选一张图,打印尺寸;用户取消时友好退出:
import photos
image = photos.pick_image()
if image is None:
print("用户取消选图")
else:
width, height = photos.get_image_size(image)
print(f"已选择 {width}×{height}")
saved = photos.save_image(image, format="JPEG", quality=0.85)
print("保存到相册:", "成功" if saved else "失败")
没有 Pillow 时,用 pick_image(raw_data=True) 获取 bytes。
#AppUI 示例 {#appui-photo-picker}
选图和拍照都在按钮回调里执行;取消时保持页面可操作。表单内嵌选图也可用 appui.PhotoPicker(见 AppUI 媒体参考)。
import appui
import photos
state = appui.State(
status="等待操作",
size="—",
saved="—",
message="点击按钮开始",
)
def pick_photo():
image = photos.pick_image()
if image is None:
state.batch_update(
status="已取消",
size="—",
saved="—",
message="用户取消选图",
)
return
width, height = photos.get_image_size(image)
state.batch_update(
status="已选图",
size=f"{width}×{height}",
saved="—",
message="选图成功,可继续处理或保存",
)
def capture_and_save():
image = photos.capture_image()
if image is None:
state.batch_update(
status="已取消",
size="—",
saved="—",
message="用户取消拍照",
)
return
width, height = photos.get_image_size(image)
ok = photos.save_image(image, format="JPEG", quality=0.85)
state.batch_update(
status="已拍照",
size=f"{width}×{height}",
saved="已保存到相册" if ok else "保存失败",
message="拍照流程完成",
)
def body():
return appui.NavigationStack(
appui.Form([
appui.Section("操作", [
appui.Button("从相册选图", action=pick_photo)
.button_style("bordered_prominent"),
appui.Button("拍照并保存", action=capture_and_save),
]),
appui.Section("结果", [
appui.LabeledContent("状态", value=state.status),
appui.LabeledContent("尺寸", value=state.size),
appui.LabeledContent("保存", value=state.saved),
appui.Text(state.message).foreground_color("secondaryLabel"),
]),
]).navigation_title("照片")
)
appui.run(body, state=state)
#API 参考
#速查
| API | 作用 |
|---|---|
pick_image(...) | 系统选图 → PIL.Image / bytes / None |
capture_image(...) | 系统拍照 → PIL.Image / None |
save_image(image, ...) | 保存图片到相册 → bool |
save_video(path) | 保存本地视频文件到相册 → bool |
get_assets(...) | 列举照片资源 → list[Asset] |
pick_asset(...) | 选择单个 Asset |
pick_image_base64(...) | 选图并返回 Base64 字符串 |
get_image_size(image) | 图片尺寸 → (width, height) |
#选图与拍照
pick_image(raw_data=False) — 打开系统照片选择器。
image = photos.pick_image()
if image is None:
print("用户取消")
raw = photos.pick_image(raw_data=True) # 无 Pillow 时用 bytes
默认返回 PIL.Image;raw_data=True 返回 bytes。show_albums、multi 等兼容参数会被接受但当前由系统界面决定行为。
capture_image() — 打开系统相机拍照,取消返回 None。camera、flash 等参数为兼容入口,实际由系统拍照界面控制。
image = photos.capture_image()
if image:
photos.save_image(image)
pick_asset() — 选择照片库中的 Asset 对象,便于读取元数据:
asset = photos.pick_asset()
if asset:
print(asset.pixel_width, asset.pixel_height)
data = asset.get_image(original=True, raw_data=True)
#保存
save_image(image, format="JPEG", quality=0.85) — 保存 PIL.Image 或 bytes 到照片库。
ok = photos.save_image(image, format="JPEG", quality=0.85)
save_video(path) — 把本地视频文件路径写入相册(不读入内存):
import network
import photos
path = "demo.mp4"
if network.download("https://example.com/demo.mp4", path):
ok = photos.save_video(path)
album_name 等参数会被接受但当前忽略,文件保存到系统默认位置。
#读取资源
get_assets(media_type="photo", limit=20) — 列举资源,务必设置合理 limit。
assets = photos.get_assets(media_type="photo", limit=20)
for asset in assets[:3]:
print(asset.local_identifier, asset.pixel_width, asset.pixel_height)
media_type 支持 photo、video、all。limit=0 表示不限制,列表页不建议使用。
Asset 常用属性:local_identifier、media_type、pixel_width、pixel_height、creation_date、duration、is_favorite。
asset = photos.pick_asset()
if asset:
image = asset.get_image(original=True)
raw = asset.get_image(original=True, raw_data=True)
其他读取 API:get_recent_images(count=10)、get_favorites()、get_count(media_type="photo")。
#相册
| API | 说明 |
|---|---|
get_albums() | 用户相册 |
get_smart_albums() | 系统智能相册 |
get_moments() | 时刻分组 |
create_album(title) | 创建相册 |
get_screenshots_album() | 截图相册 |
get_recently_added_album() | 最近添加 |
get_selfies_album() | 自拍相册 |
#Base64
给 vision_helper 等需要 Base64 的流程使用:
import photos
import vision_helper
payload = photos.pick_image_base64(format="JPEG", quality=0.85)
if payload:
result = vision_helper.detect_barcodes(payload)
print(result)
| API | 说明 |
|---|---|
pick_image_base64(...) | 选图 → Base64 |
capture_image_base64(...) | 拍照 → Base64 |
image_to_base64(image, ...) | 已有图片 → Base64 |
base64_to_image(b64_string) | Base64 → PIL.Image |
注意:vision OCR 接收 bytes;vision_helper 检测接收 Base64 字符串。
#常见错误
| 错误写法 | 后果 | 修正 |
|---|---|---|
不判断 pick_image() 返回值 | 用户取消后崩溃 | 先 if image is None: return |
get_assets(limit=0) 拉全库 | 内存和耗时暴涨 | 设置合理 limit |
把 Base64 存进 storage | 体积大、读写慢 | 存文件路径或按需重选 |
把文件路径传给 vision_helper | 类型错误 | 用 pick_image_base64 或 image_to_base64 |
在 body() 里打开选图器 | 刷新时反复弹窗 | 放进按钮回调 |
#相关文档
| 文档 | 用途 |
|---|---|
| vision | 图片 bytes OCR |
| vision_helper | Base64 人脸/条码/分类检测 |
| permission | 照片权限状态查询 |
| 原生能力入口 | MiniApp 场景配方 |
#预期效果
运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。