DirectX Toolkit WICTextureLoader.cpp纹理内存分配逻辑疑问
WICTextureLoader 行字节计算逻辑解析
你看到的(总bit数 + 7u) / 8u计算式,是内存计算领域针对非负整数向上取整到字节边界的经典写法,核心作用是避免非整数字节的位数据被截断,保证内存分配的大小能完整覆盖单行图像的所有像素数据。
先把对应的计算逻辑列出来:
// Allocate temporary memory for image uint64_t rowBytes = (uint64_t(twidth) * uint64_t(bpp) + 7u) / 8u; uint64_t numBytes = rowBytes * uint64_t(theight);
计算规则的数学本质
我们平时用整数除法做bit转字节计算的时候,默认是向下取整的。比如6个bit直接除以8,结果是0,完全存不下这6个bit的信息。而(x + n -1)/n是通用的非负整数向上取整公式,这里n取8(因为1字节=8bit),就简化为(x +7)/8:
- 当总bit数刚好能被8整除时,加7之后再除以8,结果和直接整除完全一致,不会多占不必要的内存
- 当总bit数不能被8整除时,加7的操作会让整数除法的结果向上抬升1,把不足1字节的剩余位补齐为完整字节,不会漏算数据
举几个实际计算例子就很清楚:
- 3像素宽的1bit/像素单色图,单行总bit数为3:代入公式得
(3+7)/8 =1,刚好分配1字节空间覆盖全部像素,剩余5bit作为对齐空位 - 8像素宽的1bit/像素单色图,单行总bit数为8:代入公式得
(8+7)/8=1,和直接整除结果一致,没有多余开销 - 10像素宽的4bit/像素索引图,单行总bit数为40:刚好被8整除,公式计算结果和直接除以8完全相同
纹理加载场景的特殊必要性
平时我们接触的16bit、32bit每像素的纹理,单行总bit数天生就是8的整数倍,这段计算和直接整除没有区别。但WIC需要支持全格式的图像解码,包括1bit单色位图、2bit/4bit低色深索引图、12bit每像素的高色深格式,这类格式下的单行总bit数经常无法被8整除。
如果去掉加7的步骤,直接用向下取整的除法算行字节,会导致临时内存缓冲区的大小不足,没法存下整行的最后几个像素位,后续把缓冲区数据拷贝到Direct3D纹理资源时,就会出现图像边缘截断、像素错位、花屏的问题。
内容的提问来源于stack exchange,提问作者cecil
相关产品推荐
相关产品推荐

