native_image
原生图片检查、缩放、裁剪、旋转、滤镜与格式转换。
用 iOS 原生 Core Image 与 ImageIO 检查、缩放、裁剪、旋转和处理图片。像素不会先复制到 Python,适合 MiniApp 中的大图、IPA 图标、缩略图和批量素材流水线。
边界:native_image只接受本地文件路径。声明式 MiniApp 需启用file_system;外部分享进来的LaunchItem.path是 host-issued 只读授权,可直接作为输入而不额外要求file_system,但输出仍必须写入 MiniApp 可写目录。处理会主动移除原图元数据,避免把 GPS/相机信息带进输出。
#模块概览
| 项 | 说明 |
|---|---|
| 导入 | import native_image |
| 输入 | 本地可读图片路径,支持多帧图片的 frame_index |
| 输出 | JPEG、PNG、HEIC/HEIF、TIFF;先写临时文件再原子替换目标 |
| 性能 | 原生解码、Lanczos 缩放、Core Image 滤镜,不把完整像素数组搬进 Python |
| 能力 | 普通文件路径需 file_system;host-issued 外部输入只读授权除外 |
#快速开始
已复制
import os
import native_image
source = os.path.join(os.getcwd(), "source.jpg")
output = os.path.join(os.getcwd(), "thumbnail.heic")
info = native_image.inspect(source)
print(info["width"], info["height"], info.get("frame_count"))
result = native_image.thumbnail(
source,
output,
512,
format="heic",
quality=0.86,
)
print("已保存:", result["path"])
#外部启动输入
从系统分享页启动 MiniApp 时,输入文件由宿主创建只读授权;不要自行读取宿主环境变量。
已复制
import os
import miniapp_runtime
import native_image
request = miniapp_runtime.launch_request(required=True)
source = request.first.path
output = os.path.join(os.getcwd(), "shared-thumbnail.png")
native_image.thumbnail(source, output, 512, format="png")
print(output)
#一次完成多步处理
process() 使用唯一的视觉坐标契约:先按 EXIF 方向归一化,再按 inspect() 返回的左上角坐标裁剪,之后依次缩放、旋转、水平/垂直翻转、执行最多 16 个滤镜,最后无元数据编码。只缩放且不会放大时可安全使用 ImageIO 预缩略;包含裁剪或 stretch 时不会预先丢弃源像素。
已复制
import native_image
native_image.process(
"input.jpg",
"output.jpg",
resize={"width": 1600, "height": 1200, "mode": "fill"},
crop={"x": 100, "y": 80, "width": 1200, "height": 900},
rotate_degrees=90,
filters=[
{"name": "exposure", "ev": 0.35},
{"name": "vibrance", "amount": 0.25},
{"name": "sharpen", "sharpness": 0.3},
],
format="jpeg",
quality=0.9,
)
支持的滤镜名为 gaussian_blur、monochrome、sepia、vibrance、exposure、sharpen。参数既可像示例一样直接放在滤镜字典中,也可放进 parameters={...};两种写法不能为同一参数重复赋值。范围分别为:radius 0–100、intensity 0–1、amount -1–1、ev -10–10、sharpness 0–2。
#API 参考
| API | 用途 |
|---|---|
inspect(source_path, *, frame_index=0) | 读取尺寸、方向、帧数、像素和格式信息,不生成输出。width/height 是 EXIF 归一化后的视觉尺寸,和 crop 坐标完全一致;source_width/source_height 保留文件原始像素轴。 |
process(source_path, destination_path, *, resize=None, crop=None, rotate_degrees=0, flip_horizontal=False, flip_vertical=False, filters=None, format=None, quality=0.92, frame_index=0) | 在一次原生事务中组合全部处理步骤。 |
resize(source_path, destination_path, width, height, *, mode="fit", format=None, quality=0.92, frame_index=0) | 用 fit、fill 或 stretch 缩放。 |
thumbnail(source_path, destination_path, max_size, *, format=None, quality=0.88, frame_index=0) | 创建保持比例且边长不超过 max_size 的缩略图。 |
crop(source_path, destination_path, x, y, width, height, *, format=None, quality=0.92, frame_index=0) | 按左上角像素坐标裁剪。 |
rotate(source_path, destination_path, degrees, *, format=None, quality=0.92, frame_index=0) | 绕中心旋转任意有限角度。 |
NativeImageError | 原生解码、处理或编码失败,code 提供稳定错误码。 |
#失败路径
| 情况 | 处理 |
|---|---|
| 输入超出授权目录 | 使用当前 MiniApp 工作区路径或 LaunchItem.path,不要拼接宿主私有路径。 |
| 输出不可写 | 写到 MiniApp 的 Documents/Workspace,再按需分享或导出。 |
| 图片/帧无法解码 | 捕获 NativeImageError,向用户显示 code,保留原文件。 |
裁剪区域越界(invalid_crop) | 先用 inspect() 的视觉 width/height 限制 x/y/width/height。 |
| 格式不支持 | 使用 jpeg、png、heic 或 tiff。 |
| 大图或滤镜过多 | 输入文件最大 256 MiB;像素预算会按设备内存计算且最高 40 MP;同一时刻只执行一个原生处理,单次最多 16 个滤镜。先创建缩略图,不在 AppUI body() 中处理。 |
稳定运行时错误码由公开的原生能力契约统一生成。常见分支包括 file_denied、invalid_crop、invalid_resize、invalid_dimensions、pixel_limit、input_too_large、invalid_filter、unsupported_format、busy、cancelled 与 session_expired;不要匹配本地化错误文字。
#AppUI 使用规则
- 文件选择、分享输入和处理动作放在按钮回调或
.task中,不要在body()构建期执行。 - 处理中把状态写回
State,完成后再更新图片路径。 - 对同一目标路径的并发写入由业务层串行化,避免后一次结果覆盖前一次。
#相关文档
#预期效果
处理成功后返回最终路径、尺寸、格式和文件大小;失败时原目标文件不会留下半写入内容。