发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
/////////////////////////////////////////////////////////////////////// // DibImage.cpp: implementation of the CDibImage class. // DIB(Independent Bitmap) 函数: // // PaintDIB() - 绘制DIB对象 // CreateDIBPalette() - 创建DIB对象调色板 // FindDIBBits() - 返回DIB图像象素起始位置 // DIBWidth() - 返回DIB宽度 // DIBHeight() - 返回DIB高度 // PaletteSize() - 返回DIB调色板大小 // DIBNumColors() - 计算DIB调色板颜色数目 // CopyHandle() - 拷贝内存块 // // SaveDIB() - 将DIB保存到指定文件中 // ReadDIBFile() - 重指定文件中读取DIB对象 ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DIBDisplay.h" #include "DibImage.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CDibImage::CDibImage() { } CDibImage::~CDibImage() { } ////////////////////////////////////////////////////////////////////// // function ////////////////////////////////////////////////////////////////////// /************************************************************************* * 函数名称: * PaintDIB() * 参数: * HDC hDC - 输出设备DC * LPRECT lpDCRect - 绘制矩形区域 * HDIB hDIB - 指向DIB对象的指针 * LPRECT lpDIBRect - 要输出的DIB区域 * CPalette* pPal - 指向DIB对象调色板的指针 * 返回值: * BOOL - 绘制成功返回TRUE,否则返回FALSE。 * 说明: * 该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者 * SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指 * 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数 * lpDIBRect指定。 ************************************************************************/ BOOL CDibImage::PaintDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, CPalette* pPal) { LPSTR lpDIBHdr; // BITMAPINFOHEADER指针 LPSTR lpDIBBits; // DIB象素指针 BOOL bSuccess=FALSE; // 成功标志 HPALETTE hPal=NULL; // DIB调色板 HPALETTE hOldPal=NULL; // 以前的调色板 if (hDIB == NULL) { return FALSE; } lpDIBHdr = (LPSTR)::GlobalLock((HGLOBAL) hDIB);// 锁定DIB lpDIBBits = FindDIBBits(lpDIBHdr); // 找到DIB图像象素起始位置 if (pPal != NULL) // 获取DIB调色板,并选中它 { hPal = (HPALETTE) pPal->m_hObject; hOldPal = ::SelectPalette(hDC, hPal, TRUE); // 选中调色板 } ::SetStretchBltMode(hDC, COLORONCOLOR); // 设置显示模式 // 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象 if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) { // 原始大小,不用拉伸。 bSuccess = ::SetDIBitsToDevice(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), // SrcY 0, // nStartScan (WORD)DIBHeight(lpDIBHdr), // nNumScans lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS); // wUsage } else { // 非原始大小,拉伸。 bSuccess = ::StretchDIBits(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX lpDIBRect->top, // SrcY RECTWIDTH(lpDIBRect), // wSrcWidth RECTHEIGHT(lpDIBRect), // wSrcHeight lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS, // wUsage SRCCOPY); // dwROP } ::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定 if (hOldPal != NULL) { ::SelectPalette(hDC, hOldPal, TRUE); // 恢复以前的调色板 } return bSuccess; } /************************************************************************* * 函数名称: * CreateDIBPalette() * 参数: * HDIB hDIB - 指向DIB对象的指针 * CPalette* pPal - 指向DIB对象调色板的指针 * 返回值: * BOOL - 创建成功返回TRUE,否则返回FALSE。 * 说明: * 该函数按照DIB创建一个逻辑调色板,从DIB中读取颜色表并存到调色板中, * 最后按照该逻辑调色板创建一个新的调色板,并返回该调色板的句柄。这样 * 可以用最好的颜色来显示DIB图像。 ************************************************************************/ BOOL CDibImage::CreateDIBPalette(HDIB hDIB, CPalette* pPal) { LPLOGPALETTE lpPal; // 指向逻辑调色板的指针 HANDLE hLogPal; // 逻辑调色板的句柄 HPALETTE hPal = NULL; // 调色板的句柄 int i; // 循环变量 WORD wNumColors; // 颜色表中的颜色数目 LPSTR lpbi; // 指向DIB的指针 LPBITMAPINFO lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO结构的指针 BOOL bWinStyleDIB; // 表明是否是Win3.0 DIB的标记 BOOL bResult = FALSE; // 创建结果 if (hDIB == NULL) { return FALSE; } lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 锁定DIB lpbmi = (LPBITMAPINFO)lpbi; // 获取指向BITMAPINFO结构的指针(Win3.0) lpbmc = (LPBITMAPCOREINFO)lpbi; // 获取指向BITMAPCOREINFO结构的指针 wNumColors = DIBNumColors(lpbi);// 获取DIB中颜色表中的颜色数目 if (wNumColors != 0) { // 分配为逻辑调色板内存 hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); // 如果内存不足,退出 if (hLogPal == 0) { ::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定 return FALSE; } lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); lpPal->palVersion = PALVERSION; // 设置版本号 lpPal->palNumEntries = (WORD)wNumColors;// 设置颜色数目 bWinStyleDIB = IS_WIN30_DIB(lpbi); // 判断是否是WIN3.0的DIB // 读取调色板 for (i = 0; i < (int)wNumColors; i++) { if (bWinStyleDIB) { // 读取红色绿色蓝色分量 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } else { // 读取红色绿色蓝色分量 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } } bResult = pPal->CreatePalette(lpPal);// 按照逻辑调色板创建调色板,并返回指针 ::GlobalUnlock((HGLOBAL) hLogPal); // 解除锁定 ::GlobalFree((HGLOBAL) hLogPal); // 释放逻辑调色板 } ::GlobalUnlock((HGLOBAL) hDIB); // 解除锁定 return bResult; } /************************************************************************* * 函数名称: * FindDIBBits() * 参数: * LPSTR lpbi - 指向DIB对象的指针 * 返回值: * LPSTR - 指向DIB图像象素起始位置 * 说明: * 该函数计算DIB中图像象素的起始位置,并返回指向它的指针。 ************************************************************************/ LPSTR CDibImage::FindDIBBits(LPSTR lpbi) { return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi)); } /************************************************************************* * 函数名称: * DIBWidth() * 参数: * LPSTR lpbi - 指向DIB对象的指针 * 返回值: * DWORD - DIB中图像的宽度 * 说明: * 该函数返回DIB中图像的宽度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER * 中的biWidth值;对于其它返回BITMAPCOREHEADER中的bcWidth值。 ************************************************************************/ DWORD CDibImage::DIBWidth(LPSTR lpDIB) { LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中图像的宽度 if (IS_WIN30_DIB(lpDIB)) { return lpbmi->biWidth; // 对于Windows 3.0 DIB,返回lpbmi->biWidth } else { return (DWORD)lpbmc->bcWidth; // 对于其它格式的DIB,返回lpbmc->bcWidth } } /************************************************************************* * 函数名称: * DIBHeight() * 参数: * LPSTR lpDIB - 指向DIB对象的指针 * 返回值: * DWORD - DIB中图像的高度 * 说明: * 该函数返回DIB中图像的高度。对于Windows 3.0 DIB,返回BITMAPINFOHEADER * 中的biHeight值;对于其它返回BITMAPCOREHEADER中的bcHeight值。 ************************************************************************/ DWORD CDibImage::DIBHeight(LPSTR lpDIB) { LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO结构的指针 lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中图像的宽度 if (IS_WIN30_DIB(lpDIB)) { return lpbmi->biHeight; // 对于Windows 3.0 DIB,返回lpbmi->biHeight } else { return (DWORD)lpbmc->bcHeight; // 对于其它格式的DIB,返回lpbmc->bcHeight } } /************************************************************************* * 函数名称: * PaletteSize() * 参数: * LPSTR lpbi - 指向DIB对象的指针 * 返回值: * WORD - DIB中调色板的大小 * 说明: * 该函数返回DIB中调色板的大小。对于Windows 3.0 DIB,返回颜色数目× * RGBQUAD的大小;对于其它返回颜色数目×RGBTRIPLE的大小。 ************************************************************************/ WORD CDibImage::PaletteSize(LPSTR lpbi) { // 计算DIB中调色板的大小 if (IS_WIN30_DIB (lpbi)) { //返回颜色数目×RGBQUAD的大小 return (WORD)(DIBNumColors(lpbi) * sizeof(RGBQUAD)); } else { //返回颜色数目×RGBTRIPLE的大小 return (WORD)(DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); } } /************************************************************************* * 函数名称: * DIBNumColors() * 参数: * LPSTR lpbi - 指向DIB对象的指针 * 返回值: * WORD - 返回调色板中颜色的种数 * 说明: * 该函数返回DIB中调色板的颜色的种数。对于单色位图,返回2, * 对于16色位图,返回16,对于256色位图,返回256;对于真彩色 * 位图(24位),没有调色板,返回0。 ************************************************************************/ WORD CDibImage::DIBNumColors(LPSTR lpbi) { WORD wBitCount; // 对于Windows的DIB, 实际颜色的数目可以比象素的位数要少。 // 对于这种情况,则返回一个近似的数值。 // 判断是否是WIN3.0 DIB if (IS_WIN30_DIB(lpbi)) { DWORD dwClrUsed; dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; // 读取dwClrUsed值 if (dwClrUsed != 0) { // 如果dwClrUsed(实际用到的颜色数)不为0,直接返回该值 return (WORD)dwClrUsed; } } // 读取象素的位数 if (IS_WIN30_DIB(lpbi)) { wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; // 读取biBitCount值 } else { wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; // 读取biBitCount值 } // 按照象素的位数计算颜色数目 switch (wBitCount) { case 1: return 2; break; case 4: return 16; break; case 8: return 256; break; default: return 0; break; } } /************************************************************************* * 函数名称: * CopyHandle() * 参数: * HGLOBAL h - 要复制的内存区域 * 返回值: * HGLOBAL - 复制后的新内存区域 * 说明: * 该函数复制指定的内存区域。返回复制后的新内存区域,出错时返回0。 ************************************************************************/ HGLOBAL CDibImage::CopyHandle (HGLOBAL h) { if (h == NULL) { return NULL; } DWORD dwLen = ::GlobalSize((HGLOBAL) h); // 获取指定内存区域大小 HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 分配新内存空间 if (hCopy != NULL) // 判断分配是否成功 { void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); void* lp = ::GlobalLock((HGLOBAL) h); memcpy(lpCopy, lp, dwLen); ::GlobalUnlock(hCopy); ::GlobalUnlock(h); } return hCopy; } /************************************************************************* * 函数名称: * SaveDIB() * 参数: * HDIB hDib - 要保存的DIB * CFile& file - 保存文件CFile * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE或者CFileException * 说明: * 该函数将指定的DIB对象保存到指定的CFile中。该CFile由调用程序打开和关闭。 *************************************************************************/ BOOL CDibImage::SaveDIB(HDIB hDib, CFile& file) { BITMAPFILEHEADER bmfHdr; // Bitmap文件头 LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指针 DWORD dwDIBSize; // DIB大小 if (hDib == NULL) { return FALSE; } // 读取BITMAPINFO结构,并锁定 lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) { return FALSE; } // 判断是否是WIN3.0 DIB if (!IS_WIN30_DIB(lpBI)) { // 不支持其它类型的DIB保存 ::GlobalUnlock((HGLOBAL) hDib); return FALSE; } //////////////////////////////////////////////////////////////////////// // 填充文件头/////////////////////////////////////////////////////////// bmfHdr.bfType = DIB_HEADER_MARKER; // 文件类型"BM" // 计算DIB大小时,最简单的方法是调用GlobalSize()函数。但是全局内存大小并 // 不是DIB真正的大小,它总是多几个字节。这样就需要计算一下DIB的真实大小。 // 文件头大小+颜色表大小 // (BITMAPINFOHEADER和BITMAPCOREHEADER结构的第一个DWORD都是该结构的大小) dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); // 计算图像大小 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // 对于RLE位图,没法计算大小,只能信任biSizeImage内的值 dwDIBSize += lpBI->biSizeImage; } else { DWORD dwBmBitsSize; // 象素的大小 dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; // 大小为Width * Height dwDIBSize += dwBmBitsSize; // 计算出DIB真正的大小 // 更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的) lpBI->biSizeImage = dwBmBitsSize; } // 计算文件大小:DIB大小+BITMAPFILEHEADER结构大小 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); // 两个保留字 bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; // 计算偏移量bfOffBits,它的大小为Bitmap文件头大小+DIB头大小+颜色表大小 bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); ///////////////////////////////////////////////////////////////////////// // 尝试写文件//////////////////////////////////////////////////////////// TRY { file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 写文件头 file.WriteHuge(lpBI, dwDIBSize); // 写DIB头和象素 } CATCH (CFileException, e) { ::GlobalUnlock((HGLOBAL) hDib); THROW_LAST(); } END_CATCH ::GlobalUnlock((HGLOBAL) hDib); return TRUE; } /************************************************************************* * 函数名称: * ReadDIBFile() * 参数: * CFile& file - 要读取得文件文件CFile * 返回值: * HDIB - 成功返回DIB的句柄,否则返回NULL。 * 说明: * 该函数将指定的文件中的DIB对象读到指定的内存区域中。除BITMAPFILEHEADER * 外的内容都将被读入内存。 *************************************************************************/ HDIB CDibImage::ReadDIBFile(CFile& file) { BITMAPFILEHEADER bmfHeader; HDIB hDIB; LPSTR pDIB; DWORD dwBitsSize; dwBitsSize = file.GetLength(); // 获取DIB(文件)长度(字节) // 尝试读取DIB文件头 if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) { return NULL; } // 判断是否是DIB对象,检查头两个字节是否是"BM" if (bmfHeader.bfType != DIB_HEADER_MARKER) { return NULL; } // 为DIB分配内存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { return NULL; } pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 读象素 { ::GlobalUnlock((HGLOBAL) hDIB); ::GlobalFree((HGLOBAL) hDIB); return NULL; } ::GlobalUnlock((HGLOBAL) hDIB); return hDIB; }
来自: 学海无涯GL > 《图像》
0条评论
发表
请遵守用户 评论公约
3
// PaintDIB() - 绘制DIB对象// CreateDIBPalette() - 创建DIB对象调色板// FindDIBBits() - 返回DIB图像象素起始位置// DIBWidth() - 返回DIB宽度// DIBHeight() ...
数字图像处理领域的二十四个典型算法及vc实现、第二章
// 指向DIB的指针 LPSTR lpDIB;// 源图像的宽度和高度 LONG lWidth; LONG lHeight; // 旋转后图像的宽度和高度 LONG lNewWidth; LONG l...
| 天极Yesky - 全球中文IT第一门户 - 软件 - VC数字图像处理编程讲座之三
这样作的目的是为了在程序文件对话框中可以选择BMP或DIB格式的位图文件。// 位图所有像素所占的总字节数//以下五句为文件头结构填充值bmfHdr.bfType =0x4d42; // 文件为"BMP"类型bmfHdr.bfSi...
DrawDib函数组的使用
DrawDib函数组的使用 Microsoft的针对与设备无关位图(DIB位图),在其WIN32 SDK的Multimedia中提供了一组绘制DIB位图的高性能函数组──DrawDib函数组。总的来说,DrawDib函数组类似于StretchDIBits函...
vc 保存Bitmap到文件
//设置位图信息头结构 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = Bitmap.bmWidth; bi.biHeight = Bitmap.bmHeight; bi.biPlanes ...
VC++图像处理编程 - LiteQ的日志 - 网易博客
7. 图像的基本处理:图像的二值化、图像的亮度和对比度的调整、图像的边缘增强、如何得到图像的直方图、图像直方图的修正、图像的平滑、图像的锐化等、图像的伪彩色、彩色图像转换为黑白图像、物体边...
实现图片的黑白二值化
//lps指向数据区 lpS = lpS + sizeof(BITMAPINFOHEADER); //扫描整个图片,实现二值化 for(int i = 0;i <height;i++) for(int j = 0 ;j <width;j++) { //得到象素数据在数据区...
对比度拉伸
// 每列 for(j = 0; j <cxDIB; j++) { // 指向DIB第i行,第j个象素的指针 lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (cyDIB - 1 - i) + j; // 计算新的灰度值 if(*lpSrc<r1) ...
数字图像处理---构造DIB类(一)
CDib::CDib(){// 设置信息头中的信息m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);m_lpBMIH->biWidth = size.cx;m_lpBMIH->biHeight = size.cy;m_lpBMIH->biPlanes = 1;m_lpBMIH->biBi...
微信扫码,在手机上查看选中内容