图片切九宫格的像素坐标计算逻辑
用宽高和索引确定九宫格边界
图片切九宫格的核心不是把宽高简单除以 3,而是为 3 列、3 行分别计算边界。只要边界采用整数坐标,并保证相邻区域首尾相接,就能让 9 个区域完整覆盖原图,每个像素只被裁剪一次。
设原图宽度为 W、高度为 H,坐标原点位于左上角,横坐标向右增加,纵坐标向下增加。九宫格固定为 3 列 × 3 行,共 9 个区域,行号 r 和列号 c 的取值都为 0、1、2。
r=0表示第一行,r=2表示第三行。c=0表示第一列,c=2表示第三列。- 裁剪框使用半开区间
[x1,x2) × [y1,y2),包含左、上边界,不包含右、下边界。
在这种坐标约定下,第 r 行、第 c 列区域的基础计算公式为:
x1=floor(cW/3)x2=floor((c+1)W/3)y1=floor(rH/3)y2=floor((r+1)H/3)
例如,第一行第二列对应 r=0、c=1,因此横向范围是 [floor(W/3), floor(2W/3)),纵向范围是 [0, floor(H/3))。
非整除宽高的余数分配与像素对齐
当 W 或 H 不能被 3 整除时,三等分结果不是整数。若直接使用浮点坐标,例如把边界写成 333.33,就会遇到半像素、重复取整或区域之间出现缝隙的问题。图像像素必须落在整数网格上,因此应先生成整数边界,再执行裁剪。
常见做法有两类:
- 累计取整:直接计算边界序列
floor(0W/3)、floor(1W/3)、floor(2W/3)、floor(3W/3)。高度方向使用同样规则。 - 商余数分配:先计算
W=3q+s,其中q是商、s是余数,再把余数分给前s列。高度方向同理。
两种方式在合理实现下都能得到整数区域。累计边界的优点是公式直接,并且天然保证相邻区域的前一个 x2 等于后一个 x1;三个区域的宽度相加必然等于 W,高度相加必然等于 H。
以宽度 W=1000 为例,横向边界为 0、333、666、1000,三列宽度分别是 333、333、334。最后一列多 1 个像素并不是错误,而是余数的分配结果。
完整尺寸为 1000×701 像素时,按累计取整计算,宽度边界仍为 0、333、666、1000,高度边界为 0、233、467、701。对应的行高是 233、234、234。因此,不能把“9 张图尺寸完全相同”作为正确性的必要条件;正确目标是覆盖完整且不重复。
裁剪接口中的坐标参数与边界检查
一个裁剪框通常包含四个坐标:左坐标 x1、上坐标 y1、右坐标 x2、下坐标 y2。在半开区间规则下,输出尺寸为 (x2-x1) × (y2-y1)。
每个区域执行裁剪前,应检查以下条件:
0≤x1<x2≤W0≤y1<y2≤H- 相邻列满足前一块的
x2等于后一块的x1。 - 相邻行满足上一块的
y2等于下一块的y1。
不同接口不一定使用右下坐标。有的 API 接收 x1,y1,x2,y2,有的接收左上坐标加宽高,例如 x,y,width,height。遇到后一种形式,应先换算为 x2=x+width、y2=y+height,再检查是否越界。
- Pillow:
Image.crop()常见用法是传入四元组框坐标,具体边界行为应以所用版本文档为准。 - OpenCV:数组切片通常写成
image[y1:y2, x1:x2],行坐标在前,列坐标在后,属于半开区间写法。 - Canvas API:
drawImage()可使用源图起点、源区域宽高等参数,右下边界需要由起点和宽高换算,实际采样还可能受到缩放和插值影响。
不要把这些接口的坐标规则当成统一标准。尤其是右边界、下边界是否包含,取决于具体 API;使用半开区间时,前一块的右边界正好是后一块的左边界,不会重复裁剪。
结合在线工具验证九宫格裁剪结果
使用“图片切九宫格”时,可以按下面的流程检查结果:
- 上传原图,记录图片的实际宽度
W和高度H。 - 选择 3×3 切分,确认预览中有 9 个输出区域。
- 下载结果,逐张记录文件尺寸,并将列宽、行高分别相加。
- 用带余数的尺寸测试,例如
1000×701,检查列宽是否为333、333、334,行高是否为233、234、234或其他同样满足总和的分配方式。 - 将 9 张图按原来的行列顺序拼接,确认恢复后的尺寸仍为
1000×701,并检查边界像素没有重复或缺失。
工具的具体余数分配方式、输出图片格式和压缩行为取决于实现,不能默认所有在线工具都采用“余数放到最后一列和最后一行”。例如,有些实现把余数分给前几列,有些实现通过累计边界让最后一个区域承担余数;只要覆盖完整且区域不重叠,结果都可以成立。
九宫格的边界归属问题可以用一句规则判断:半开区间下,像素坐标小于右边界、下边界才属于当前区域。若工具采用左上角加宽高参数,则先换算出右下坐标,再检查 9 个框是否满足范围约束;不要为了追求相同尺寸而强行裁掉余数像素。
亮度对比度调整中的线性变换与S曲线
亮度/对比度调整看似只是拖动滑块,实际是在重排像素值。线性变换均匀改变整个亮度范围,S 型曲线则把对比度集中到特定区域;两者对暗部、亮部细节的影响并不相同。 先用灰度映射看懂两种调法 可以把灰度调整理解为一张“输入—输出”对照表:输入像
图片模糊处理中均值与高斯核的视觉差异
先把比较条件锁死:9×9 核不等于同样强度 均值模糊和高斯模糊都能让图片变软,但它们在文字边缘、细线和高对比度轮廓上的表现不同。要看出差异,不能只比较缩略图,而要固定图像、核尺寸、边界处理和输出格式,再观察局部细节与实际耗时。 使用同一张
EXIF方向标签的八种取值与显示纠正
先区分方向标签与图像像素 EXIF Orientation 是 JPEG 中记录“应该怎样显示”的方向标签,不等于文件里的像素已经旋转。处理照片时,必须把文件内的像素坐标、查看器执行的显示变换,以及导出时是否重写像素分开判断。 EXIF
像素取反与补色运算的色彩差异
两种“补色”算法为何结果不同 “补色”在图像处理中可能指两套不同规则:一套是对 RGB 通道做数值反转,另一套是沿 HSL 色轮把色相移动 180°。它们对纯红等高饱和颜色可能得到相同或相近结果,但面对灰色、低饱和色和不同明度的颜色,视觉结
灰度转换后对比度损失的补偿方法
彩色图片转成灰度图后层次变弱,通常不是“变黑”,而是不同颜色被压缩到同一条亮度轴上。补偿的目标是重新分配已有灰度值:用伽马校正调整暗部和中间调,用直方图拉伸扩大有效亮度范围;它们不能恢复已经丢失的色相信息。 说明灰度转换为何会损失对比度