图像模块
脚本入口: eve.Image()
解码图片文件 / 创建像素缓冲,并操作原始像素数据。
基本用法
ImageData 是 Image / Font / Model3D 共用的脚本类:FontData.newGlyphImageData(...) 和 ModelData.getEmbeddedTextureImageData(...) 返回的对象可以直接调用下面的像素与旋转接口。
对象关系与调用时机
eve.Image() 负责创建和解码 ImageData:
newImageData(data):解码fs.read()/fs.newFileData()得到的编码数据,返回新建的ImageData(脚本持有)。newImageDataFromFile(path):从 VFS 路径经**统一资源缓存**解码——同一路径重复加载共享一份ImageData, 文件变化时原地刷新(见docs/dev/superpowers/specs/2026-08-20-unified-resource-cache.md)。 该实例由缓存持有,脚本不要自行释放;需要独立副本时用clone()。newEmptyImageData(w, h, format):创建全透明/黑色画布,配合setPixel/getPixelR/G/B/A做 CPU 像素编辑, 再用gfx.newTexture(imageData)上传为纹理。
ImageData::rotate(radians, filter, expand) 按**逆映射**旋转像素:遍历目标图每个像素,用逆旋转矩阵回算源坐标, 再按 filter 采样。
| 参数 | 含义 |
|---|---|
radians | 弧度;与 Math.rotate2* 同号(Y 向下时视觉为顺时针,同 LÖVE) |
filter | "nearest" / "linear" / "rotsprite"(Xenowhirl:Scale2x×3 → 偏移搜索 → 最近邻缩回) |
expand | true 时画布扩到容纳整图 AABB;false 保持原尺寸(可能裁切) |
返回同格式的新 ImageData(调用方拥有);源范围外采样为透明黑。rotsprite 只挑选已有调色板颜色,不引入插值新色。
ImageData.scalePcg(width, height, filter) 原地执行 Pcg ScaleTexture 的精确取样规则, filter 为 "point" 或 "bilinear"。Point 使用 floor(sourceSize / destinationSize * coordinate);Bilinear 使用 (sourceSize - 1) / destinationSize,忠实保留其不会采到最后一行/列端点的行为。 它返回结构化 Result,成功值为写入像素数;非法尺寸、滤镜或不足 2x2 的 Bilinear 源图 不会改变原图。调用会替换当前 ImageData 的像素和尺寸;共享缓存图片应先 clone()。
目标导向指南
加载并上传一张 PNG 为纹理
同一路径重复调用只解码一次;文件修改后由热重载在原地刷新。
CPU 生成 / 修改像素
用 newEmptyImageData(w, h, "RGBA8") 建画布,setPixel(x, y, r, g, b, a) 写入,getPixelR/G/B/A 读回; clone() 深拷贝,paste(src, dx, dy, sx, sy, sw, sh) 拷贝子区域,rotate(...) 旋转。注意像素坐标越界会抛异常。
模型表面绘制可用 paintCircleUv(u, v, radiusPixels, r, g, b, a, wrapU, wrapV): UV 原点按模型约定位于左下,函数会自动反转 V 到图像左上像素原点。radiusPixels 以像素为单位,wrapU / wrapV 适用于需要穿过 UV 缝的画笔。返回实际改变的像素数。
需要编辑器事务或运行时撤销时,使用 newUvPaintSession()。initialize(image) 会复制输入, paintCircle(...) 在候选副本上完成整笔绘制后原子提交,undo()、restore()、bake() 分别 撤销一笔、恢复基线和固化新基线;currentImageResult() 返回独立 owning 快照, copyCurrentTo(image) 则把当前结果复制到已有 ImageData,便于保持脚本变量的静态类型并上传;可传给 Graphics.updateTextureFromImageData() 原位刷新 GPU 纹理。Session 最多保存 32 笔历史,且不持有 模型、射线命中、Physics World 或 GPU Texture;鼠标、触摸、VR 和编辑器适配器统一负责把表面命中 经 ModelData.mapSurfacePointToUv() 转成 UV。
CPU 编辑器与 GPU Canvas 喷涂共享 newUvPaintRegion() 创建的可复用 scratch。其 prepare(width, height, u, v, radiusU, radiusV, r, g, b, a, flipV) 返回结构化 Result,提供统一验证、原子替换及裁剪后的 getX/Y/Width/Height、中心和颜色。CPU 路径由 UvPaintSession 执行并保留撤销,GPU 路径 直接用该矩形提交 shader;像素状态仍分别由会话或 Canvas 唯一拥有,不建立双份同步状态。
常见问题
- 把
newImageData(data)与newEmptyImageData(w, h, format)混淆:前者解码编码数据,后者创建空白画布。 - 传给
newImageData的不是fs.read()返回的数据对象:会得到类型转换错误。 - 修改
newImageDataFromFile返回的像素:它由缓存共享,修改会影响同路径后续引用;需要独立副本先clone()。 - 每帧把字形重新转纹理:应缓存 ImageData/Texture。
API 快查
Image:getName()、newImageData(data)、newImageDataFromFile(path)、newEmptyImageData(width, height, format)、newUvPaintRegion()、isCompressed(data)ImageData:getWidth()、getHeight()、getFormat()、getSize()、getPixelSize()、isSRGB()、inside(x, y)、clone()、paste(src, dx, dy, sx, sy, sw, sh)、rotate(radians, filter, expand)、scalePcg(width, height, filter)、getPixelR(x, y)、getPixelG(x, y)、getPixelB(x, y)、getPixelA(x, y)、setPixel(x, y, r, g, b, a)、paintCircleUv(u, v, radiusPixels, r, g, b, a, wrapU, wrapV)UvPaintSession:initialize(image)、paintCircle(...)、undo()、restore()、bake()、currentImageResult()、copyCurrentTo(image)、getRevision()、getUndoCount()、isInitialized()UvPaintRegion:getCenterX()、getCenterY()、getX()、getY()、getWidth()、getHeight()、getR()、getG()、getB()、getA()、prepare(...)
使用要点
- 模块对象和它创建的资源对象应保存在全局或实体状态中,不要在每帧重复创建。
- 带
update(dt)的系统应在eve_update调用;绘制方法应在eve_render调用。 - 参数约束、默认值和返回类型以对应模块头文件及
addFunc绑定为准;本文 API 快查与当前源码同步生成。
源码: src/modules/image/ 相关测试: 在 test/ 中搜索 image。