首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >同一张图片填充两个区域:cover 裁切计算与共享图源的边界

同一张图片填充两个区域:cover 裁切计算与共享图源的边界

原创
作者头像
UION
修改于 2026-10-08 22:37:45
修改于 2026-10-08 22:37:45
230
举报

在 XERP 的定制商品图稿场景里,一张订单照片可能被多个图片位置使用。矩形、长条或轮廓区域取相同素材,却不能直接共用裁切参数。这篇文章只讨论一个可复现的小问题:同图源、不同矩形区域,如何分别计算居中的 cover 布局?

我是 XERP 项目方。下面是独立演示算法和几何示意图,不是生产代码摘录,不涉及实际买家照片,也不声称这段示例涵盖设计器的全部能力。

技术示意1
技术示意1

1. 先区分完整展示与填满区域

contain 希望完整显示图片,允许区域留白;cover 希望区域被填满,允许裁掉部分图片。它们不能静默互换。

设原图宽高为 sw, sh,目标区域为 tw, th。居中、无旋转、矩形区域的 cover 缩放比例为:

代码语言:plaintext
复制
s = max(tw / sw, th / sh)

取最大比值后,缩放图片的宽和高都不会小于区域。剩余部分在左右或上下裁掉。这里不做主体识别,选择居中只是一个确定的几何约定。

技术示意2
技术示意2

2. 用原图坐标描述可见范围

把目标区域反算回原图坐标,得到源裁切宽高:

代码语言:plaintext
复制
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 个源图像素。
技术示意3
技术示意3

位置 B 是 600 × 300,同样的原图:

  • 缩放比例是 3/8;
  • 源裁切区域是 1600 × 800;
  • sx = 0, sy = 50,上下各裁掉 50 个源图像素。

这两份参数显然不同。共用的是图像内容,不是位置 A 的缩放或裁切值。

技术示意4
技术示意4

3. 一个可直接运行的 Python 示例

只使用标准库。返回值同时包含源裁切区与目标坐标偏移,调用端按自己的渲染 API 选用。

代码语言:python
复制
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 形式绘制源裁切区,再由目标路径约束可见区域。若使用旋转、非矩形路径或编辑器中间变换,需要另行处理坐标与裁切关系,不能把本示例直接当完整设计器实现。

4. 数据共享到哪里为止?

可以让两个位置引用一个素材标识,并分别保留目标区域。换图后用新图尺寸重新计算各位置,不把某个位置的 scale/crop 写回共享素材。

如果裁切结果被缓存,源图变化、源图尺寸变化、目标区域尺寸变化,都要让对应布局重新计算。这里没有建议额外建任务状态机,只是明确结果依赖哪些输入。

技术示意5
技术示意5

5. 如何验证,而不是只看一张演示图

我实际运行了独立示例的六组几何检查:横图进方形、横图进长条、竖图进方形、方形进长条、相同比例以及等比放大。还检查了五类非法输入:零、负数、NaN、Infinity 和布尔值。

检查的性质包括:

代码语言:python
复制
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 全产品回归,也不是业务成功率。

技术示意6
技术示意6

6. 几何正确,主体仍可能被裁掉

cover 不知道照片中哪个人物重要。示意图里用几何形状代替人像,也能看到左右裁切会丢掉边缘内容。所以公式通过测试后,仍要检查主体位置;多人合照、人物贴边、不同轮廓区域,需要业务侧提供明确规则或人工调整。

这也是订单图稿场景仍需要审图的原因:导出文件成功回答“有没有结果”,不回答“当前结果是否符合这一单的制作要求”。共享图源、独立布局、结果核对,是三个不同的问题。

本文的边界是有限正尺寸、居中、无旋转矩形 cover。没有实现人脸识别、自动取景、文字排版或生产交接,讨论这些能力时需要另外的证据与验证。欢迎交流你在编辑器或报表排版中遇到的坐标系问题。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 先区分完整展示与填满区域
  • 2. 用原图坐标描述可见范围
  • 3. 一个可直接运行的 Python 示例
  • 4. 数据共享到哪里为止?
  • 5. 如何验证,而不是只看一张演示图
  • 6. 几何正确,主体仍可能被裁掉
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档