一、理论
stride 中文叫步长 / 行跨度。
在图像内存布局里:一行图像数据在内存中占用的字节数。
很多时候 stride 会大于图像宽度对应的字节数:stride >= width * bytes_per_pixel
多出的这部分叫padding(填充/补边)。
为什么要有padding?
硬件ISP、内存控制器喜欢按固定字节对齐(常见 128/64/32字节对齐)。
GPU/ISP访问内存,对齐地址读取效率更高;硬件不支持非对齐访问,会报错。
所以每行末尾填充一段无效字节,凑成对齐。
width:图像有效像素宽度
stride:内存中一行总字节长度(有效像素 + padding)
height:图像有效高度
图像总内存大小 ≈ stride * height
重点坑:不能用 width 去遍历内存,必须用 stride!
二、代码示例
// 示例:RGBA8888,每个像素4字节,图像有效宽度 100像素
int width = 100;
int bytes_per_pixel = 4;
int line_bytes = width * bytes_per_pixel; // 100*4 = 400字节
// 硬件要求128字节对齐,向上对齐
int align = 128;
int stride = ((line_bytes + align -1)/align) * align;
// 400向上对齐到128的倍数:400 → 512
// stride = 512字节,每行末尾有 112字节padding,无效数据
// 访问第y行像素起始地址
unsigned char* get_line_ptr(unsigned char* buf, int y, int stride)
{
return buf + y * stride;
}
如果错误用 width 去计算行地址,读到padding填充垃圾数据,画面花屏、色偏。
三、手机影像算法集成实际工作场景
你做Camera HAL、算法集成,stride是每天都会碰到的概念:
Android Camera HAL、ISP、YUV(NV21/NV12/YUV420)全部带stride。
RAW图、YUV图,buffer的stride由底层硬件/框架分配,不是你按width算出来的。
拿到buffer之后,一定要读平台给出的stride信息,不能自己根据图像width计算。
NV12/NV21 还要区分 Y平面 stride 和 UV平面 stride
Y平面有y_stride;UV平面有uv_stride,二者可以不一样。
很多新人踩坑:直接用width遍历YUV,读到padding,出现画面右侧竖条花屏。
算法集成场景
算法库输入buffer,需要传入stride参数。
第三方降噪、HDR算法,如果传入错误stride,处理出来的图像花屏、噪点异常,而且bug很难复现,只在特定分辨率/对齐模式下出现。
内存拷贝场景
做图像crop、图像拷贝时:每行只拷贝width*bpp有效像素,跳过padding。
面试高频一句话坑:
stride是一行内存总字节数,不等于width乘以像素字节,因为硬件对齐引入padding。
✅ 精简版
stride是图像一行在内存占用的总字节数。为满足ISP内存对齐要求,stride通常大于有效像素宽度占用字节,多出部分是padding填充。
影像开发中,不能直接用图像width计算内存地址,必须使用buffer自带的stride。YUV图像Y平面和UV平面stride可以不同。如果误用width代替stride,会读到padding垃圾数据,造成图像花屏。