易码技术论坛

 找回密码
 加入易码
搜索
查看: 553247|回复: 8

[教程] [抛砖]关于DDB和DIB图像绘制……

[复制链接]
发表于 2006-10-6 17:32:19 | 显示全部楼层
那DDB的结构是怎么样的呢,这么说读入的图像数据就是设备相关了。
但是应用起来感觉DDB这一层是透明的,OS的API接管了所有相关操作。
不过这样对于图像数据的操作感觉很不方便。
比如我有由一个调色板和一个图像矩阵构成的图像数据文件,要怎么才能将正确其显示呢?
发表于 2006-10-6 19:41:47 | 显示全部楼层
引用第1楼yzk03702006-10-06 17:32发表的“”:
比如我有由一个调色板和一个图像矩阵构成的图像数据文件,要怎么才能将正确其显示呢?

这个属于DIB和DDB之间的操作问题了,不过,WinGDI里面恰好提供了这个功能。
  1. int SetDIBits(
  2.   HDC hdc,            // handle to DC
  3.   HBITMAP hbmp,         // handle to bitmap
  4.   UINT uStartScan,       // starting scan line
  5.   UINT cScanLines,       // number of scan lines
  6.   CONST VOID *lpvBits,    // array of bitmap bits
  7.   CONST BITMAPINFO *lpbmi,  // bitmap data
  8.   UINT fuColorUse        // type of color indexes to use
  9. );
复制代码

具体用法MSDN之即可。需要注意的是,fuColorUse要设置为DIB_PAL_COLOR,还有,调色板数据是放在lpbmi指向的BITMAPINFO structure里面。
发表于 2006-10-6 20:51:05 | 显示全部楼层
谢谢L,以前都一直没发现这个API,我去好好看看。
发表于 2006-10-6 21:58:59 | 显示全部楼层
再问问L,我想实现16灰的图像显示,用了以下代码,不过什么也看不到,而且要是把设置调色板的循环注释掉,会出现诡异的图像。
  1. static BITMAPINFO     bmpInfo;
  2. static BYTE data[0x2000];
  3. static HBITMAP bitmap;
  4. static HDC    hdcMem;
  5. switch (message)
  6. {
  7. case WM_CREATE:
  8.    hdc = GetDC(hWnd);
  9.    hdcMem = CreateCompatibleDC(hdc);
  10.    bitmap = CreateCompatibleBitmap(hdcMem, 128, 128);
  11.    SelectObject(hdcMem, bitmap);
  12.    // 初始化BITMAPINFO的BITMAPINFOHEADER部分
  13.    bmpInfo.bmiHeader.biSize      = sizeof(BITMAPINFOHEADER);
  14.    bmpInfo.bmiHeader.biWidth      = 128;
  15.    bmpInfo.bmiHeader.biHeight      = 128;
  16.    bmpInfo.bmiHeader.biPlanes      = 1;
  17.    bmpInfo.bmiHeader.biBitCount      = 4;
  18.    bmpInfo.bmiHeader.biCompression      = BI_RGB;
  19.    bmpInfo.bmiHeader.biSizeImage      = 0;
  20.    bmpInfo.bmiHeader.biXPelsPerMeter   = 96;
  21.    bmpInfo.bmiHeader.biYPelsPerMeter   = 96;
  22.    bmpInfo.bmiHeader.biClrUsed      = 16;
  23.    bmpInfo.bmiHeader.biClrImportant   = 16;
  24.    // 设置调色板
  25.    for(int i = 0; i < 16; i++)
  26.    {
  27.       bmpInfo.bmiColors[i].rgbBlue   = i * 0x11;
  28.       bmpInfo.bmiColors[i].rgbGreen   = i * 0x11;
  29.       bmpInfo.bmiColors[i].rgbRed   = i * 0x11;
  30.       bmpInfo.bmiColors[i].rgbReserved= 0;
  31.    }
  32.    // 产生一些图像数据
  33.    for(int i = 0; i < 0x2000; i++)
  34.    {
  35.       data[i] = i / 512;
  36.    }
  37.    // 转换
  38.    SetDIBits(hdcMem, bitmap, 0, 128, data, &bmpInfo, DIB_PAL_COLORS);
  39.    ReleaseDC(hWnd, hdc);
  40.    break;
  41. case WM_PAINT:
  42.    hdc = BeginPaint(hWnd, &ps);
  43.    // TODO: 在此添加任意绘图代码...
  44.    BitBlt(hdc, 10, 10, 128, 128, hdcMem, 0, 0, SRCCOPY);
  45.    EndPaint(hWnd, &ps);
  46.    break;
  47. ......
复制代码
发表于 2006-10-6 23:05:00 | 显示全部楼层
-----
发表于 2006-10-7 00:24:17 | 显示全部楼层
那个bmpInfo我改用BITMAPINFO *了,好为其分配空间,不过要是那个hBitmap不能绑的话,该怎么显示到窗体上呢?
发表于 2006-10-7 07:21:47 | 显示全部楼层
昨晚帖子没修改完整,本本不幸死机了…
已经补完,帖到你Q上。
不敢长时间开IE..开久了必死机……可见IE的CPU资源占用率…… =.=
发表于 2006-10-28 17:20:33 | 显示全部楼层
引用第3楼yzk03702006-10-06 20:51发表的“”:
谢谢L,以前都一直没发现这个API,我去好好看看。
YZK,你看书太粗心了吧,你以前传我的  WINDOWS 程序设计那本书里讲的很清楚,难道你木看?
 楼主| 发表于 2006-10-6 16:14:41 | 显示全部楼层 |阅读模式
  转自己Blog上面一篇旧文过来,抛砖引玉了。
最近的一点心得,写的很乱,而且不知道对不对。
但是至少我是这么理解的……

首先是感慨一下baidu和google的强大……
internet像一个无穷的宝藏,包罗万象。
我坚信目前我这种菜鸟水平的问题,应该都可以在搜索引擎上找到答案。
MSDN上的东西不够生动,而且有时候搜起来困难。
英文修养不够,老外的例子看得不够明白。

然后是关于DDB和DIB的。
网上随手都能搜索到很多DDB和DIB的解释,大部分一样。
前者设备相关,后者设备无关……这是字面意思,和没说一样。
这几天尝试理解了的具象了一点:

首先是DIB,DIB之所以设备无关,是因为他本身带有图像的描述信息。
比如储存的是多少bit色的图片,如果不是真彩则带有一个颜色表(调色板)。
这样程序在显示DIB的时候,可以根据这些信息把数据转换成符合当前显示模式的数据,再显示到屏幕上(传输到内存或者显存中)。
所以一个DIB图像在GDI中不能用一个简单的数组表示,需要有一个专门的结构来记录头部信息,以及颜色表。常见的Bmp图像就是在一个DIB图像的基础上,再加Bmp图像的文件头组成。
DIB的图像数据有点不方便地方在于,每行图像数据必须是DWORD的整数倍,也就是4字节的整数倍,不足补充0,而且是从下到上从左到右组成。

在MFC中,没有处理DIB的东西,我理解是指没有像CBitmap一样封装好的类。用于绘图的API还是有的,不过必须是包括DIB图像头部结构以及符合DIB的数据排布的图像数据,否则就不能显示。

DDB就是根据当前显示模式创建的图像,其实当我们把图像从BMP文件读入之后,系统内部储存的就是DDB了。比如CBitmap就是DDB,或者DDraw的surface所读入的数据也是DDB。
不同颜色格式的DDB是不能直接转换的……比如32bit的CBitmap就不能往24bit的CBitmap上面绘图,BitBlt方法会失败。
CBitmap调用CreateBitmap方法建立对象的话,必须指定合适的参数,如果和当前显示模式不同,就不能绘制在当前的屏幕上。所以一般不采用这种方式,调用CBitmap的另外一个Create方法建立兼容当前显示模式的CBitmap。

然后是关于DC的,也就是设备上下文。这个概念感觉很奇怪,虽然抽象出来一个DC有一定好处,但是具体用的时候会很麻烦,每次都要建立一个DC才能开始绘图或者写字等操作。这个DC是抽象于图像或者窗体之外的,所以感觉会很奇怪。本来是把图像绘制到窗体上,而他们之间也是可以绘制的,非要先建立两个关联到他们的DC,然后在DC之间操作-.-并且如果DC之间存在某种差异,就会操作失败。
您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-28 05:39 , Processed in 0.009409 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表