在 XERP 的定制商品图稿场景里,一张订单照片可能被多个图片位置使用。矩形、长条或轮廓区域取相同素材,却不能直接共用裁切参数。这篇文章只讨论一个可复现的小问题:同图源、不同矩形区域,如何分别计算居中的 cover 布局?
我是 XERP 项目方。下面是独立演示算法和几何示意图,不是生产代码摘录,不涉及实际买家照片,也不声称这段示例涵盖设计器的全部能力。

contain 希望完整显示图片,允许区域留白;cover 希望区域被填满,允许裁掉部分图片。它们不能静默互换。
设原图宽高为 sw, sh,目标区域为 tw, th。居中、无旋转、矩形区域的 cover 缩放比例为:
s = max(tw / sw, th / sh)取最大比值后,缩放图片的宽和高都不会小于区域。剩余部分在左右或上下裁掉。这里不做主体识别,选择居中只是一个确定的几何约定。

把目标区域反算回原图坐标,得到源裁切宽高:
cropW = tw / s
cropH = th / s
sx = (sw - cropW) / 2
sy = (sh - cropH) / 2原图是 1600 × 900,位置 A 是 400 × 400:
4/9;900 × 900;sx = 350, sy = 0,左右各裁掉 350 个源图像素。
位置 B 是 600 × 300,同样的原图:
3/8;1600 × 800;sx = 0, sy = 50,上下各裁掉 50 个源图像素。这两份参数显然不同。共用的是图像内容,不是位置 A 的缩放或裁切值。

只使用标准库。返回值同时包含源裁切区与目标坐标偏移,调用端按自己的渲染 API 选用。
from math import isfinite
def cover_rect(sw, sh, tw, th):
values = (sw, sh, tw, th)
if any(isinstance(x, bool) or not isinstance(x, (int, float))
or not isfinite(x) or x <= 0 for x in values):
raise ValueError('dimensions must be finite positive numbers')
scale = max(tw / sw, th / sh)
cw, ch = tw / scale, th / scale
sx, sy = (sw - cw) / 2, (sh - ch) / 2
return dict(scale=scale, dx=-sx * scale, dy=-sy * scale,
sx=sx, sy=sy, sw=cw, sh=ch)
for target in [(400, 400), (600, 300)]:
print(target, cover_rect(1600, 900, *target))dx/dy 是把缩放后的图片放到目标区域时的偏移。另一种画法是使用源裁切四元组 sx, sy, sw, sh,将该源区域绘制到目标矩形。两种表达来自同一几何关系,不要在不同坐标系间重复乘缩放比例。
例如 Canvas 2D 可以用它的九参数 drawImage 形式绘制源裁切区,再由目标路径约束可见区域。若使用旋转、非矩形路径或编辑器中间变换,需要另行处理坐标与裁切关系,不能把本示例直接当完整设计器实现。
可以让两个位置引用一个素材标识,并分别保留目标区域。换图后用新图尺寸重新计算各位置,不把某个位置的 scale/crop 写回共享素材。
如果裁切结果被缓存,源图变化、源图尺寸变化、目标区域尺寸变化,都要让对应布局重新计算。这里没有建议额外建任务状态机,只是明确结果依赖哪些输入。

我实际运行了独立示例的六组几何检查:横图进方形、横图进长条、竖图进方形、方形进长条、相同比例以及等比放大。还检查了五类非法输入:零、负数、NaN、Infinity 和布尔值。
检查的性质包括:
r = cover_rect(sw, sh, tw, th)
assert r['sx'] >= -1e-9 and r['sy'] >= -1e-9
assert r['sx'] + r['sw'] <= sw + 1e-9
assert r['sy'] + r['sh'] <= sh + 1e-9
assert abs(r['sw'] * r['scale'] - tw) < 1e-8
assert abs(r['sh'] * r['scale'] - th) < 1e-8执行结果为 PASS: 6 geometry cases; 5 invalid-input cases。这证明上述演示通过了列出的检查,不是 XERP 全产品回归,也不是业务成功率。

cover 不知道照片中哪个人物重要。示意图里用几何形状代替人像,也能看到左右裁切会丢掉边缘内容。所以公式通过测试后,仍要检查主体位置;多人合照、人物贴边、不同轮廓区域,需要业务侧提供明确规则或人工调整。
这也是订单图稿场景仍需要审图的原因:导出文件成功回答“有没有结果”,不回答“当前结果是否符合这一单的制作要求”。共享图源、独立布局、结果核对,是三个不同的问题。
本文的边界是有限正尺寸、居中、无旋转矩形 cover。没有实现人脸识别、自动取景、文字排版或生产交接,讨论这些能力时需要另外的证据与验证。欢迎交流你在编辑器或报表排版中遇到的坐标系问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。