PW系列 | Topsy−Turvy (SetDIBitsToDevice)

版权

本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/128082389.

内容

《Programming Windows》(Charles Petzold, 第五版) 第15章的SetDIBitsToDevice 函数:

SetDIBitsToDevice (
    hdc, 
    xDst,     // xDst
    yDst,     // yDst
    cxSrc,    // cxSrc
    cySrc,    // cySrc
    xSrc,     // xSrc
    ySrc,     // ySrc
    yScan,    // first scan line
    cyScans,  // number of scan lines
    pBits,
    pInfo,
    fClrUse );

Src 是图像数据里的坐标: Bottom-up 的坐标原点在左上角(数据首行); Top-down 的原点在左下角(数据末行).

Bottom-up

一般是Bottom-up 的. Bottom-up 数据(即存储) 与展示的方向相反:

(0,0)  -------- 首行数据(显示为图片末行)
       --------
       .
       .
       .
       -------- 末行数据(显示为图片首行)

原点在左上角, 即(xSrc, ySrc) 是从存储开始往下ySrc 行再往右xSrc 列.

Top-down

Top-down 数据与展示的方向一致:

       -------- 首行数据(显示为图片首行)
       --------
       .
       .
       .
(0,0)  --------  末行数据(显示为图片末行)     

原点在左下角, 即(xSrc, ySrc) 是存储末尾往上ySrc 行再往左"行宽-xSrc" 列.

yScan

逐行展示见"Sequential Display" 小节的SEQDISP.C:

			for (y = 0; y < cyDib; y++) {
				......
				SetDIBitsToDevice(hdc,
								  0,      // xDst
								  0,      // yDst
								  cxDib,  // cxSrc
								  cyDib,  // cySrc
								  0,      // xSrc
								  0,      // ySrc
								          // first scan line
								  bTopDown ? cyDib - y - 1 : y,
								  1,      // number of scan lines
								  pBits + y * iRowLength,
								  pbmi,
								  DIB_RGB_COLORS );
				Sleep(10); // (Sleep - 本文增加的)
			}

Bottom-up (即 !bTopDown) 时yScan 从0 递增: 读首行数据->展示到屏幕末行->读第二行数据->展示到屏幕次末行->… .
Top-down 时yScan 初值=cyDib-1, 因为数据原点在左下角, 所以读取的是存储开始位置的首行.
由此推测, 不论Bottom-up 或Top-down, 为了实现的效率数据总是从头开始往后顺序读取.
增加Sleep 后实测可看到: Bottom-up 图是从下往上显示的, Top-down 图是从上往下.

总结

只需记住: Bottom-up 数据原点在左上角, Top-down 数据原点在左下角, 所有Src 参数都是相对于此原点.

分析

Bottom-up 时(xSrc,ySrc) 数据区域实际是颠倒后再显示到(xDst,yDst) 屏幕区域(因为反向). 这就是"The Topsy−Turvy World of DIBs" 小节里的:
Source => Destination
(xSrc,ySrc) => (xDst,yDst+cySrc-1)
(xSrc,ySrc+cySrc-1) => (xDst,yDst)
即Src 矩形上下翻转后的左上角 对应Dst 矩形的左上角(xDst,yDst).
这个反向就是造成chaos 的主因.

Top-down 时顺序一致: Src 矩形的左上角 对应Dst 矩形的左上角(xDst,yDst). 但参数需指定Src 矩形的左下而非左上角. 原作者认为将Src 原点定在最末行首(存储的既非开始也非结束位置) 也不常见.

SetDIBitsToDevice 好处是参数不受数据方向的影响: “you can select the same part of the image to display using identical arguments”.

在该小节末尾原作者推荐统一将数据原点对应到显示区域的左上角.

附录

如何生成Top-down DIB

将原来的Bottom-up 文件在小画家里上下颠倒后另存; 将另存文件的biHeight 改为负值即可.

例如高度240 在原文件里4字节Hex 依次是: F0 0 0 0.
-240 的Hex 是FFFFFF10, 4字节依次替换为Hex: 10 FF FF FF.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值