DIBPrcs.cpp
上传用户:aqingfeng
上传日期:2014-03-25
资源大小:1839k
文件大小:13k
源码类别:

波变换

开发平台:

Visual C++

  1. /*************************************************************************
  2.  * 文件DIBPrcs.cpp用来存放有关DIB的操作函数
  3.  * 文件头存放在GlobalApi.h中
  4.  *************************************************************************
  5.  */
  6. #include "GlobalApi.h"
  7. #include "stdafx.h"
  8. #include "dib.h"
  9. /*************************************************************************
  10.  *
  11.  * 函数名称:
  12.  *   GetSystemPalette()
  13.  *
  14.  * 输入参数:
  15.  *   无
  16.  *
  17.  * 返回值:
  18.  *   HPALETTE - 系统调色板句柄
  19.  *
  20.  * 说明:
  21.  *   该函数获得当前正在使用的系统调色板的句柄
  22.  *
  23.  *************************************************************************
  24.  */
  25. HPALETTE GetSystemPalette() 
  26. // 设备上下文
  27. HDC hDC;                
  28. // 声明调色板句柄、指针等临时变量
  29. static HPALETTE hPal = NULL;   
  30. HANDLE hLogPal;         
  31. LPLOGPALETTE lpLogPal;  
  32. // 当前系统调色板的颜色数
  33. int nColors;            
  34.  
  35.      // 获得当前系统设备上下文
  36. hDC = GetDC(NULL); 
  37. if (!hDC) 
  38. return NULL; 
  39.  
  40. // 获得当前系统调色板的颜色数目
  41. nColors = ( 1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
  42.     
  43. // 给调色板分配内存
  44. hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors * 
  45. sizeof(PALETTEENTRY)); 
  46. if (!hLogPal) 
  47. return NULL; 
  48.  
  49. // 得到调色板内存指针
  50. lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
  51.  
  52. // 设置调色板信息
  53. lpLogPal->palVersion = 0x300; 
  54. lpLogPal->palNumEntries = nColors; 
  55.  
  56. // 将系统的调色板拷贝到当前的逻辑调色板中
  57. GetSystemPaletteEntries(hDC, 0, nColors, 
  58.             (LPPALETTEENTRY)(lpLogPal->palPalEntry)); 
  59.  
  60. // 创建Windows调色板
  61. hPal = CreatePalette(lpLogPal); 
  62.  
  63. // 释放已分配内存并删除临时对象
  64. GlobalUnlock(hLogPal); 
  65. GlobalFree(hLogPal); 
  66. ReleaseDC(NULL, hDC); 
  67.  
  68. // 返回
  69. return hPal; 
  70.  
  71. /*************************************************************************
  72.  *
  73.  * 函数名称:
  74.  *   CopyPalette
  75.  *
  76.  * 输入参数:
  77.  *   HPALETTE hPalSrc - 需要拷贝的源调色板句柄
  78.  *
  79.  * 返回值:
  80.  *   HPALETTE - 如果操作成功,则返回拷贝的调色板句柄
  81.  *
  82.  * 说明:
  83.  *   该函数将创建一个新的调色板,并从指定的调色板拷贝调色板内容
  84.  *
  85.  *************************************************************************
  86.  */
  87. HPALETTE CopyPalette(HPALETTE hPalSrc)
  88. {
  89. // 调色板指针,临时变量
  90. PLOGPALETTE     plogPal;
  91. // 声明一个调色板句柄和一个临时句柄
  92. HPALETTE        hPalette;
  93. HANDLE hTemp;
  94. // 调色板表项数
  95. int             iNumEntries=0;
  96.     
  97. // 获取调色板中的表项数
  98. iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL);
  99. if (iNumEntries == 0) 
  100. return (HPALETTE) NULL;
  101. // 分配调色板内存,得到句柄
  102. hTemp = GlobalAlloc(GHND, sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries);
  103. if (! hTemp)
  104. return (HPALETTE) NULL;
  105. // 得到调色板的指针
  106. plogPal = (PLOGPALETTE)GlobalLock(hTemp);
  107. if (! plogPal) 
  108. return (HPALETTE) NULL;
  109. // 设置调色板的信息
  110. plogPal->palVersion = 0x300;
  111. plogPal->palNumEntries = (WORD) iNumEntries;
  112.     
  113. // 获取逻辑调色板中指定范围的调色板表项
  114. GetPaletteEntries(hPalSrc, 0, iNumEntries, plogPal->palPalEntry);
  115. // 创建一个Windows调色板
  116. hPalette = CreatePalette(plogPal);
  117. // 释放以分配的内存
  118. GlobalUnlock( hTemp );
  119. GlobalFree  ( hTemp );
  120. return hPalette;
  121. }
  122.  
  123. /*************************************************************************
  124.  *
  125.  * 函数名称:
  126.  *   ReadDIB
  127.  *
  128.  * 输入参数:
  129.  *   CFile* pFile - 需要打开的DIB文件
  130.  *   LPBITMAPINFOHEADER* pLpBMIH - DIB信息头指针的指针
  131.  *   LPBYTE* pLpImage - DIB位图数据块指针的指针
  132.  *
  133.  * 返回值:
  134.  *   BOOL - 如果操作成功,则返回TRUE
  135.  *
  136.  * 说明:
  137.  *   该函数将指定文件中的DIB文件载入,其中信息头和调色板放在*pLpBMIH中
  138.  *   图象数据存放到*pLpImage中。
  139.  *
  140.  *************************************************************************
  141.  */
  142.  BOOL ReadDIB(CFile* pFile, LPBITMAPINFOHEADER* pLpBMIH, LPBYTE* pLpImage)
  143.  {
  144.  // 临时存放信息的变量
  145.   int nCount, nSize;
  146. BITMAPFILEHEADER bmfh;
  147. // 信息头指针
  148. //LPBITMAPINFOHEADER lpBMIH;
  149. // DIB图象数据指针
  150. //LPBYTE lpImage;
  151. // 进行读操作
  152. try 
  153. {
  154. // 读取文件头
  155. nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
  156. if(nCount != sizeof(BITMAPFILEHEADER)) {
  157. throw new CException;
  158. }
  159. // 如果文件类型部位"BM",则返回并进行相应错误处理
  160. if(bmfh.bfType != 0x4d42) {
  161. throw new CException;
  162. }
  163. // 计算信息头加上调色板的大小,并分配相应的内存
  164. nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
  165. *pLpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
  166. // 读取信息头和调色板
  167. nCount = pFile->Read(*pLpBMIH, nSize); 
  168. // 计算图象数据大小并设置调色板指针
  169. if((*pLpBMIH)->biSize != sizeof(BITMAPINFOHEADER)) {
  170. TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmapn");
  171. throw new CException;
  172. }
  173. // 如果图象数据内存大小为0,则重新计算
  174. if((*pLpBMIH)->biSizeImage == 0) {
  175. DWORD dwBytes = ((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) / 32;
  176. if(((DWORD) (*pLpBMIH)->biWidth * (*pLpBMIH)->biBitCount) % 32) {
  177. dwBytes++;
  178. }
  179. dwBytes *= 4;
  180. (*pLpBMIH)->biSizeImage = dwBytes * (*pLpBMIH)->biHeight;
  181. }
  182. // 分配图象数据内存,并从文件中读取图象数据
  183. *pLpImage = (LPBYTE) new char[(*pLpBMIH)->biSizeImage];
  184. nCount = pFile->Read((*pLpImage), (*pLpBMIH)->biSizeImage); 
  185. }
  186. // 错误处理
  187. catch(CException* pe) 
  188. {
  189. AfxMessageBox("Read error");
  190. pe->Delete();
  191. return FALSE;
  192. }
  193. // 将指针赋值
  194. // 返回
  195. return TRUE;
  196.  }
  197.  /*************************************************************************
  198.  *
  199.  * 函数名称:
  200.  *   MakeDIBPalette()
  201.  *
  202.  * 输入参数:
  203.  *   LPVOID lpvColorTable - 颜色表指针
  204.  *   LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
  205.  *
  206.  * 返回值:
  207.  *   HPALETTE - 如果成功,则调色板句柄
  208.  *
  209.  * 说明:
  210.  *   该函数将读取颜色表,并创建一个Windows调色板,并返回此调色板的句柄
  211.  *
  212.  ************************************************************************
  213.  */
  214. HPALETTE MakeDIBPalette(LPVOID lpvColorTable,  LPBITMAPINFOHEADER lpBMIH)
  215. {
  216. // 调色板句柄
  217. HPALETTE hPalette = NULL;
  218. // 颜色表颜色数
  219. int nColorTableEntries;
  220. // 设置DIB中的调色板指针
  221. // lpvColorTable = (LPBYTE) lpBMIH + sizeof(BITMAPINFOHEADER);
  222. // 计算调色板的表项数
  223. if(lpBMIH->biClrUsed == 0) {
  224. switch(lpBMIH->biBitCount) {
  225. case 1:
  226. nColorTableEntries = 2;
  227. break;
  228. case 4:
  229. nColorTableEntries = 16;
  230. break;
  231. case 8:
  232. nColorTableEntries = 256;
  233. break;
  234. case 16:
  235. case 24:
  236. case 32:
  237. nColorTableEntries = 0;
  238. break;
  239. default:
  240. break;
  241. }
  242. }
  243. // 否则调色板的表项数就是用到的颜色数目
  244. else {
  245. nColorTableEntries = lpBMIH->biClrUsed;
  246. }
  247. ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256)); 
  248. // 如果不存在调色板,则返回FALSE
  249. if(nColorTableEntries == 0) return FALSE;
  250. // 给逻辑调色板分配内存
  251. LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
  252. nColorTableEntries * sizeof(PALETTEENTRY)];
  253. // 设置逻辑调色板的信息
  254. pLogPal->palVersion = 0x300;
  255. pLogPal->palNumEntries = nColorTableEntries;
  256. // 拷贝DIB中的颜色表到逻辑调色板
  257. LPRGBQUAD pDibQuad = (LPRGBQUAD) lpvColorTable;
  258. for(int i = 0; i < nColorTableEntries; i++) {
  259. pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
  260. pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
  261. pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
  262. pLogPal->palPalEntry[i].peFlags = 0;
  263. pDibQuad++;
  264. }
  265. // 创建逻辑调色板
  266. hPalette = ::CreatePalette(pLogPal);
  267. // 删除临时变量
  268. delete pLogPal;
  269. // 返回调色板句柄
  270. return hPalette;
  271. }
  272.  /*************************************************************************
  273.  *
  274.  * 函数名称:
  275.  *   PaintDIB()
  276.  *
  277.  * 输入参数:
  278.  *   CDC* pDC - 指向将要接收DIB图象的设备上下文指针 
  279.  *   LPBITMAPINFOHEADER lpBMIH - DIB信息头指针
  280.  *   LPBYTE lpImage; - DIB位图数据块地址 
  281.  *   CPoint origin - 显示DIB的逻辑坐标
  282.  *   CSize size - 显示矩形的宽度和高度
  283.  *   HPALETTE hPalette - 指向DIB的调色板句柄
  284.  *
  285.  * 返回值:
  286.  *   BOOL - 如果成功,则返回TRUE
  287.  *
  288.  * 说明:
  289.  *   该函数将DIB图象进行显示
  290.  *
  291.  ************************************************************************
  292.  */
  293. BOOL PaintDIB(CDC* pDC, LPBITMAPINFOHEADER lpBMIH, LPBYTE lpImage, CPoint origin, CSize size, HPALETTE hPalette)
  294. {
  295. if(lpBMIH == NULL) return FALSE;
  296. // 如果调色板不为空,则将调色板选入设备上下文
  297. if(hPalette != NULL) {
  298. ::SelectPalette(pDC->GetSafeHdc(), hPalette, TRUE);
  299. }
  300. // 设置显示模式
  301. pDC->SetStretchBltMode(COLORONCOLOR);
  302. // 在设备的origin位置上画出大小为size的图象
  303. ::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y,size.cx,size.cy,
  304. 0, 0, lpBMIH->biWidth, lpBMIH->biHeight,
  305. lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS, SRCCOPY);
  306. // 返回
  307. return TRUE;
  308. }
  309. /*************************************************************************
  310.  *
  311.  * 函数名称:
  312.  *   CopyDIB()
  313.  *
  314.  * 输入参数:
  315.  *   CDib* pDibSrc - 指向源数据的CDib对象指针
  316.  *   CDib* pDibDst - 指向拷贝目标的CDib对象指针
  317.  *
  318.  * 返回值:
  319.  *   BOOL - 如果操作成功,则返回TRUE
  320.  *
  321.  * 说明:
  322.  *   该函数将源CDib类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
  323.  *
  324.  *************************************************************************
  325.  */
  326. BOOL CopyDIB(CDib* pDibSrc, CDib* pDibDst)
  327. {
  328. // 将目的CDib对象清空
  329. pDibDst->Empty();
  330. // 计算信息头加上调色板的大小,并分配相应的内存
  331. int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pDibSrc->m_nColorTableEntries;
  332. pDibDst->m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSizeHdr];
  333. pDibDst->m_nBmihAlloc = pDibDst->m_nImageAlloc = pDibDst->crtAlloc;
  334. try{
  335. // 拷贝信息头和调色板
  336. memcpy(pDibDst->m_lpBMIH,pDibSrc->m_lpBMIH,nSizeHdr);
  337. // 如果结构的长度不对,则进行错误处理
  338. if(pDibDst->m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {
  339. TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmapn");
  340. throw new CException;
  341. }
  342. // 保存图象数据内存大小到CDib对象的数据成员中
  343. pDibDst->m_dwSizeImage = pDibDst->m_lpBMIH->biSizeImage;
  344. // 如果图象数据内存大小为0,则重新计算
  345. if(pDibDst->m_dwSizeImage == 0) {
  346. DWORD dwBytes = ((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) / 32;
  347. if(((DWORD) pDibDst->m_lpBMIH->biWidth * pDibDst->m_lpBMIH->biBitCount) % 32) {
  348. dwBytes++;
  349. }
  350. dwBytes *= 4;
  351. pDibDst->m_dwSizeImage = dwBytes * pDibDst->m_lpBMIH->biHeight; 
  352. }
  353. // 设置DIB中的调色板指针
  354. pDibDst->m_lpvColorTable = (LPBYTE) pDibDst->m_lpBMIH + sizeof(BITMAPINFOHEADER);
  355. // 计算调色板的表项数
  356. pDibDst->ComputePaletteSize(pDibDst->m_lpBMIH->biBitCount);
  357. // 如果DIB中存在调色板,则创建一个Windows调色板
  358. pDibDst->MakePalette();
  359. // 分配图象数据内存,并拷贝图象数据
  360. pDibDst->m_lpImage = (LPBYTE) new char[pDibDst->m_dwSizeImage];
  361. memcpy(pDibDst->m_lpImage, pDibSrc->m_lpImage,pDibDst->m_dwSizeImage);
  362. }
  363. catch(CException* pe) 
  364. {
  365. AfxMessageBox("Copy DIB error");
  366. pDibDst->Empty();
  367. pe->Delete();
  368. return FALSE;
  369. }
  370. return TRUE;
  371. }
  372. /*************************************************************************
  373.  *
  374.  * 函数名称:
  375.  *   CopyScreenToDIB
  376.  *
  377.  * 输入参数:
  378.  *   LPRECT lpRect - 需要拷贝的屏幕区域
  379.  *   CDib* pDibDest - 指向目标CDib对象的指针
  380.  *
  381.  * 返回值:
  382.  *   BOOL - 如果操作成功,则返回TRUE
  383.  *
  384.  * 说明:
  385.  *   该函数将指定矩形位置内的屏幕内容拷贝到DIB中源CDib类pDibSrc中的数据拷贝到pDibDst中
  386.  *
  387.  *************************************************************************
  388.  */
  389. BOOL CopyScreenToDIB(LPRECT lpRect, CDib* pDibDest)
  390. {
  391. // 屏幕设备上下文和内存设备上下文句柄
  392. HDC         hScrDC, hMemDC;         
  393. // 声明BITMAP临时句柄和以前的BITMAP句柄
  394. HBITMAP     hBitmap, hOldBitmap;    
  395. // 调色板句柄
  396. HPALETTE    hPalette;       
  397.     
  398. // 获取矩形区域的坐标
  399. int         nX, nY, nX2, nY2;
  400. // DIB图象的高度和宽度
  401. int         nWidth, nHeight; 
  402. // 屏幕分辨率
  403. int         xScrn, yScrn;    
  404.  
  405.         // 如果给定的矩形区域为空,则不进行进一步的处理
  406. if (IsRectEmpty(lpRect)) 
  407. return FALSE; 
  408.  
  409.      // 得到一个屏幕设备上下文
  410. hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); 
  411. // 创建与屏幕设备兼容的内存设备上下文
  412. hMemDC = CreateCompatibleDC(hScrDC); 
  413.  
  414. // 得到矩形的区域坐标
  415. nX = lpRect->left; 
  416. nY = lpRect->top; 
  417. nX2 = lpRect->right; 
  418. nY2 = lpRect->bottom; 
  419.  
  420. // 得到屏幕的分辨率,以便后面的判断处理
  421. xScrn = GetDeviceCaps(hScrDC, HORZRES); 
  422. yScrn = GetDeviceCaps(hScrDC, VERTRES); 
  423.  
  424. // 判断矩形区域是否超出屏幕
  425.  
  426. if (nX < 0) 
  427. nX = 0; 
  428. if (nY < 0) 
  429.         nY = 0; 
  430. if (nX2 > xScrn) 
  431.         nX2 = xScrn; 
  432. if (nY2 > yScrn) 
  433.         nY2 = yScrn; 
  434.  
  435. // 计算DIB图象的高度和宽度
  436. nWidth = nX2 - nX; 
  437. nHeight = nY2 - nY; 
  438.  
  439. // 创建一个与屏幕设备上下文兼容的DDB位图
  440. hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); 
  441.  
  442. // 将DDB位图选入内存设备上下文
  443. hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); 
  444.  
  445. // 将屏幕中指定区域的图象传输到内存设备上下文中
  446. BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); 
  447.  
  448. // 然后将以前的图象选入,并得到屏幕区域的DDB图象句柄
  449. hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); 
  450.  
  451. // 将临时的设备上下文删除
  452. DeleteDC(hScrDC); 
  453. DeleteDC(hMemDC); 
  454.  
  455. // 得到当前系统调色板
  456. hPalette = GetSystemPalette(); 
  457.  
  458. // 将DDB图象转换为DIB图象
  459. pDibDest->ConvertFromDDB(hBitmap,hPalette);
  460. // 删除临时对象
  461. DeleteObject(hPalette); 
  462. DeleteObject(hBitmap); 
  463. return TRUE;
  464. }