手工创建的8位DDB的显示?

yfwill 2004-12-30 05:58:49
程序需要处理很多大图像,在每个大图像上寻找目标,然后标记出区域,这部分是别人做的,而且是在DLL中。我的任务是把小图像从大图像上取出来,显示到窗体上。
我开始的做法是:建立一个CompatibleDC(CreateCompatibleDC(NULL))将大图像hBitmap选入,在创建一个CompatibleDC(CreateCompatibleDC(NULL))和一个CBitmap (小图象)将CBitmap选入,然后通过BitBlt拷贝。这样生成了一个和原图像一样的32位小图象。但是在系统显示属性不是真彩色的情况下,图像就不能显示。
原图像是32位的,因为小图像需要显示成灰度图还要存储到数据库里,出于空间的考虑,我打算使用8位的灰度图。我使用了CBitmap对象。但是无论如何也显示不出来。肯定是DDB与调色板的问题,该怎么解决?
谢谢!

...全文
93 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
老夏Max 2004-12-31
  • 打赏
  • 举报
回复
把DDB转换成DIB
设备相关位图(DDB)显示方式是尽可能与显示设备驱动程序相匹配,这样,DDB不可能与其他显示设备兼容;而设备无关位图(DIB)能与所有显示设备兼容,但是,其缺点在于显示速度比较慢。

我们需要把DDB转换为DIB的一种情况是,需要将位图保存到一个文件中。下面是其实现的代码。

// DDBToDIB - Creates a DIB from a DDB
// bitmap - Device dependent bitmap
// dwCompression - Type of compression - see BITMAPINFOHEADER
// pPal - Logical palette
HANDLE DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal )
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;


ASSERT( bitmap.GetSafeHandle() );

// The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;

// If a palette has not been supplied use defaul palette
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

// Get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

// Initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

// Compute the size of the infoheader and the color table
int nColors = (1 << bi.biBitCount); if( nColors> 256 )
nColors = 0;
dwLen = bi.biSize + nColors * sizeof(RGBQUAD);

// We need a device context to get the DIB from
hDC = GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);

// Allocate enough memory to hold bitmapinfoheader and color table
hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

if (!hDIB){
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

lpbi = (LPBITMAPINFOHEADER)hDIB;

*lpbi = bi;

// Call GetDIBits with a NULL lpBits param, so the device driver
// will calculate the biSizeImage field
GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

bi = *lpbi;

// If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;

// If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}

// Realloc the buffer so that it can hold all the bits
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB);

// Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

// Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB;

// FINALLY get the DIB
BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi // address for bitmap bits
+ (bi.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table

if( !bGotBits )
{
GlobalFree(hDIB);

SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}

SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return hDIB;
}

hhoking 2004-12-31
  • 打赏
  • 举报
回复
DDB是没办法帮你做灰度处理的。

首先确认,别人给你的大图像是DDB的?(也就是一个HBITMAP句柄?)
如果是DDB,那么源图就无所谓位深了,它的位深就是系统显示位深。
那么,你用BitBlt拷贝是没问题的,得到的图也是DDB。不过注意创建兼容DC,参考DC值不要传NULL,
CreateCompatibleDC(hdc);

关键在于你需要将DDB的图转成DIB的图来做灰度处理。可以统一转为24位或32位DIB图,调用API:
GetDIBits()

然后再转为8位灰度,需要自己写函数转,公式:
Grey = 0.299 * R + 0.587 * G + 0.114 * B
I_Love_CPP 2004-12-30
  • 打赏
  • 举报
回复
参考:

Device-Dependent Bitmaps
Device-dependent bitmaps (DDBs) are described by using a single structure, the BITMAP structure. The members of this structure specify the width and height of a rectangular region, in pixels; the width of the array that maps entries from the device palette to pixels; and the device's color format, in terms of color planes and bits per pixel.
(注意这儿:--->)
An application can retrieve the color format of a device by calling the GetDeviceCaps function and specifying the appropriate constants. Note that a DDB does not contain color values; instead, the colors are in a device-dependent format. For more information, see Color in Bitmaps. Because each device can have its own set of colors, a DDB created for one device may not display well on a different device.

To use a DDB in a device context, it must have the color organization of that device context. Thus, a DDB is often called a compatible bitmap and it usually has better GDI performance than a DIB. For example, to create a bitmap for video memory, it is best to use a compatible bitmap with the same color format as the primary display. Once in video memory, rendering to the bitmap and displaying it to the screen are significantly faster than from a system memory surface or directly from a DIB.
(解决方法:--->)
To transfer a bitmap between devices with different color organization, use GetDIBits to convert the compatible bitmap to a DIB and call SetDIBits or StretchDIBits to display the DIB to the second device.

:)

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧