CBitmapEx.cpp
上传用户:zhaobiao
上传日期:2013-10-27
资源大小:92k
文件大小:12k
源码类别:

OpenCV

开发平台:

Visual C++

  1. // CBITMAPEX.CPP
  2. // CBitmap extention
  3. //
  4. // (c) Vadim Gorbatenko, 1997-99 
  5. // gvv@mail.tomsknet.ru
  6. // All rights reserved
  7. //
  8. //___________________________________________________________________________________________
  9. #include "stdafx.h"
  10. #include "CBitmapEx.h"
  11. #define WIDTHBYTES(bits)        (((bits) + 31) / 32 * 4)
  12. #define PALETTESIZE(lpbi) (_DIBNumColors((LPBITMAPINFOHEADER) lpbi)* sizeof (RGBQUAD))
  13. #define DIBCOLORS(lpbi)         ((LPRGBQUAD)((LPBYTE)(lpbi) + (int)(lpbi)->biSize))
  14. #define DIBPTR(lpbi)            (LPBYTE)(DIBCOLORS((LPBITMAPINFOHEADER)lpbi) + (UINT)((LPBITMAPINFOHEADER)lpbi)->biClrUsed)
  15. HANDLE _dibFromBitmap(HBITMAP hBitmap);
  16. BOOL _writeDib(HANDLE hdib, LPCSTR filename);
  17. INT _DIBNumColors (LPBITMAPINFOHEADER  lpbi);
  18. CBitmapEx::CBitmapEx():CBitmap()
  19. {
  20. _modBMP= NULL;
  21. }
  22. CBitmapEx::~CBitmapEx()
  23. {
  24. EndModify();//just in case:)
  25. }
  26. HANDLE CBitmapEx::DibFromBitmap()
  27. {return _dibFromBitmap((HBITMAP)GetSafeHandle());}
  28. HANDLE CBitmapEx::DibFromBitmap(HBITMAP hb)
  29. {return _dibFromBitmap(hb);}
  30. BOOL CBitmapEx::CreateFromDib(LPBITMAPINFO lpBi)
  31. {
  32. if(!lpBi || _modBMP) return FALSE;
  33. if(((LPBITMAPINFOHEADER)lpBi)->biCompression != BI_RGB)
  34. return FALSE;
  35. if(GetSafeHandle( ))
  36. {
  37. //check existing size
  38. BITMAP bmp;
  39. GetObject(sizeof BITMAP, &bmp);
  40. CSize sz = GetSize();
  41. if(bmp.bmWidth == ((LPBITMAPINFOHEADER)lpBi)->biWidth &&
  42. bmp.bmHeight == ((LPBITMAPINFOHEADER)lpBi)->biHeight)
  43. {
  44. // special case: we don't  need to destroy existing
  45. // DDB, just rewrite bits.
  46. // Note: we must be sure, the color resolution is
  47. // not changed, so, let's test it:
  48. HDC    hdc = ::GetDC(NULL);
  49. int    hdc_bits = GetDeviceCaps(hdc,BITSPIXEL);
  50. if(hdc_bits == bmp.bmBitsPixel)
  51. {
  52. //ok to set new bits
  53. BOOL ret = ::SetDIBits(
  54. hdc,     // handle to device context
  55. (HBITMAP)GetSafeHandle( ), // handle to bitmap
  56. 0,    // starting scan line
  57. bmp.bmHeight,    // number of scan lines
  58.     DIBPTR(lpBi),   // array of bitmap bits
  59. lpBi, // address of structure with bitmap data
  60. DIB_RGB_COLORS // type of color indexes to use
  61. ) == bmp.bmHeight;
  62.  
  63. ::ReleaseDC(NULL,hdc);
  64. return ret;
  65. }
  66. else
  67. ::ReleaseDC(NULL,hdc);
  68. }
  69. //delete existing bitmap:(
  70. DeleteObject();
  71. }
  72. //create a new DDB
  73.     HDC         hdc;
  74.     HBITMAP     hbm;
  75. //Create DDB
  76.     hdc = ::GetDC(NULL);
  77.     hbm = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpBi,(LONG)CBM_INIT,
  78.                  DIBPTR(lpBi), lpBi, DIB_RGB_COLORS );
  79.     ::ReleaseDC(NULL,hdc);
  80. if(!hbm) return FALSE;
  81. DeleteObject();//delete attached bitmap
  82. if(!Attach( (HGDIOBJ) hbm ))
  83. {::DeleteObject((HGDIOBJ)hbm); return FALSE;}
  84. return TRUE;
  85. }
  86. #define sfiltr "Image files (*.BMP)|*.BMP||"
  87. #define sext "BMP"
  88. #define smask NULL
  89. BOOL CBitmapEx::Open(LPCSTR filename, LPCSTR DialogTitle)
  90. {
  91. if(GetSafeHandle( ))
  92. return FALSE;
  93. CString Path;
  94. if(!filename)
  95. {
  96. CFileDialog openAs( TRUE,sext,
  97. smask,  OFN_NOCHANGEDIR|OFN_FILEMUSTEXIST|
  98. OFN_PATHMUSTEXIST,
  99. sfiltr); 
  100. //substitude dialog title
  101. if(DialogTitle)
  102. openAs.m_ofn.lpstrTitle=DialogTitle;
  103. if(openAs.DoModal()==IDOK)
  104.   
  105.  Path=openAs.GetPathName( );
  106.   
  107. else return FALSE;
  108. }
  109. else Path= filename;
  110. CFile file;
  111.      
  112. if(!file.Open(Path,CFile::modeRead|CFile::typeBinary))
  113. return FALSE;
  114.    BITMAPFILEHEADER   bmfHeader;
  115.    LPBITMAPINFOHEADER lpbi;
  116.    DWORD              dwBitsSize;
  117.    HANDLE             hDIB;
  118.    // get length of DIB in bytes for use when reading
  119. dwBitsSize = file.GetLength();
  120. BOOL ret=TRUE;
  121. TRY
  122. {
  123.   if( file.Read(&bmfHeader, sizeof (BITMAPFILEHEADER))!=
  124.    sizeof (BITMAPFILEHEADER)||
  125.    bmfHeader.bfType!=((WORD) ('M' << 8) | 'B')) ret=FALSE;
  126. }
  127. CATCH (CFileException, e)
  128. {
  129. ret=FALSE;
  130. }
  131. END_CATCH
  132. if(!ret) return FALSE;
  133.    // Allocate memory for DIB
  134. dwBitsSize -= sizeof(BITMAPFILEHEADER);
  135.    
  136.     hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  137. if(!hDIB) return FALSE;
  138. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  139. TRY
  140. {
  141. if(file.ReadHuge((LPVOID)lpbi, dwBitsSize)!=dwBitsSize)
  142. ret=FALSE;
  143. }
  144. CATCH (CFileException, e)
  145. {
  146. ret=FALSE;
  147. }
  148. END_CATCH
  149.       file.Close();
  150.       
  151. if(!ret)
  152. {GlobalUnlock (hDIB); GlobalFree (hDIB); return FALSE;}
  153.     
  154.     HDC         hdc;
  155.     HBITMAP     hbm;
  156. //Create DDB
  157.     hdc = ::GetDC(NULL);
  158.     hbm = CreateDIBitmap(hdc,(LPBITMAPINFOHEADER)lpbi,(LONG)CBM_INIT,
  159.                  DIBPTR(lpbi),(LPBITMAPINFO)lpbi,DIB_RGB_COLORS );
  160.     ::ReleaseDC(NULL,hdc);
  161. GlobalUnlock (hDIB);
  162. GlobalFree (hDIB); 
  163. if(!hbm)
  164.        {return FALSE;}
  165. if(GetSafeHandle( ))
  166. DeleteObject();
  167. if(!Attach( (HGDIOBJ) hbm ))
  168. {::DeleteObject((HGDIOBJ)hbm); return FALSE;}
  169. return ret;
  170. }
  171. BOOL CBitmapEx::Save(LPCSTR filename, LPCSTR DialogTitle)
  172. {
  173. if(!GetSafeHandle( ))
  174. return FALSE;
  175. CString Path;
  176. if(!filename)
  177. {
  178. CFileDialog saveAs( FALSE,sext,
  179. smask, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
  180. sfiltr); 
  181. if(DialogTitle)
  182. saveAs.m_ofn.lpstrTitle=DialogTitle;
  183. if(saveAs.DoModal()==IDOK)
  184. Path=saveAs.GetPathName( );
  185.   
  186. else return FALSE;
  187. }
  188. else Path=filename;
  189. CFile file;
  190.     
  191. if(!file.Open((LPCSTR)Path,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary))
  192. return FALSE;
  193. HANDLE hdib=_dibFromBitmap((HBITMAP)GetSafeHandle( ));
  194. if(!hdib) return FALSE;
  195.     BITMAPFILEHEADER hdr;
  196.     LPBITMAPINFOHEADER  lpbi;
  197.     lpbi = (LPBITMAPINFOHEADER)GlobalLock (hdib);
  198.     // Fill in the fields of the file header 
  199.     hdr.bfType = ((WORD) ('M' << 8) | 'B');  // "BM"
  200.     hdr.bfSize = GlobalSize (hdib) + sizeof (BITMAPFILEHEADER);
  201.     hdr.bfReserved1     = 0;
  202.     hdr.bfReserved2     = 0;
  203.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  204.                           PALETTESIZE((LPSTR)lpbi);
  205. BOOL ret=TRUE;
  206. TRY
  207. {   
  208. file.Write((LPSTR)&hdr, sizeof (BITMAPFILEHEADER));
  209. file.WriteHuge((LPSTR)lpbi, GlobalSize (hdib));
  210. }
  211. CATCH (CFileException, e)
  212. {
  213. ret=FALSE;
  214. }
  215. END_CATCH
  216.    
  217.    file.Close();
  218.     GlobalUnlock (hdib);
  219.      GlobalFree (hdib);
  220.    
  221.  return ret;
  222. }
  223. // Get DC for "in-memory" drawing
  224. CDC *CBitmapEx::BegingModify()
  225. {
  226. CWnd* dtw= CWnd::GetDesktopWindow( );
  227. CDC *dc=dtw->GetDC();
  228. if(_modDC.m_hDC)
  229. _modDC.DeleteDC( );
  230. _modDC.CreateCompatibleDC(dc);
  231. _modBMP = _modDC.SelectObject(this);
  232. dtw->ReleaseDC(dc);
  233. return &_modDC;
  234. }
  235. // Create color bitmap
  236. BOOL  CBitmapEx::CreateColor(int dx, int dy)
  237. {
  238. if(GetSafeHandle()) return FALSE;
  239. HDC hScrDC = ::GetDC(NULL);
  240. HDC hMemDC = ::CreateCompatibleDC(hScrDC);
  241. BOOL r = CreateCompatibleBitmap(CDC::FromHandle(hScrDC), dx, dy);
  242.   
  243. ::DeleteDC(hMemDC);
  244. ::ReleaseDC(NULL,hScrDC);
  245. return r;
  246. }
  247. // Create monocolor bitmap
  248. BOOL  CBitmapEx::CreateMono(int dx, int dy)
  249. {
  250. if(GetSafeHandle()) return FALSE;
  251. CDC mDC;
  252. mDC.CreateCompatibleDC(NULL); //for mono!
  253. BOOL r = CreateCompatibleBitmap( &mDC, dx, dy );
  254. mDC.DeleteDC( );
  255. return r;
  256. }
  257. // This was the first extention i've done! :)))
  258. CSize CBitmapEx::GetSize()
  259. {
  260. BITMAP bmp;
  261. if(!GetSafeHandle()) return CSize(0,0);
  262. GetObject(sizeof BITMAP, &bmp);
  263. return CSize(bmp.bmWidth,bmp.bmHeight);
  264. }
  265. void  CBitmapEx::BitBlt(CDC *dc_to, POINT at, DWORD rop)
  266. {
  267. CSize sz=GetSize();
  268. dc_to->BitBlt(at.x,at.y, sz.cx, sz.cy, 
  269. BegingModify(),//source context
  270. 0,0,  rop);
  271. EndModify();
  272. }
  273. void  CBitmapEx::StretchBlt(CDC *dc_to, CRect to, DWORD rop)
  274. {
  275. CSize sz=GetSize();
  276. dc_to->StretchBlt(to.left, to.top, 
  277. to.Width(), to.Height(),
  278. BegingModify(),//source context
  279. 0,0,
  280. sz.cx, sz.cy,  
  281. rop);
  282. EndModify();
  283. }
  284. void CBitmapEx::EndModify()
  285. {
  286.     if(_modDC.m_hDC && _modBMP)
  287. _modDC.SelectObject(_modBMP);
  288. if(_modDC.m_hDC)
  289. _modDC.DeleteDC( );
  290. _modBMP = NULL;
  291. }
  292. //Copy the other bitmap to this 
  293. BOOL CBitmapEx::CopyRect(CBitmap& bmp, CRect& rc)
  294. {
  295. CWnd* dtw= CWnd::GetDesktopWindow( );
  296. CDC *dc=dtw->GetDC();
  297. CDC cdc;
  298. CDC cdc2;
  299. cdc2.CreateCompatibleDC(dc);
  300. cdc.CreateCompatibleDC(dc);
  301. bmp.CreateCompatibleBitmap( dc, rc.Width(), rc.Height());
  302. CBitmap *ob2=cdc2.SelectObject(&bmp);
  303. CBitmap *ob=cdc.SelectObject(this);
  304. cdc2.BitBlt( 0, 0, rc.Width(), rc.Height(), 
  305. &cdc, rc.left, rc.top, SRCCOPY );
  306. cdc2.SelectObject(ob2);
  307. cdc.SelectObject(ob);
  308. dtw->ReleaseDC(dc);
  309. return TRUE;
  310. }
  311. DWORD CBitmapEx::DibImageSize(HANDLE hDIB)
  312. {
  313. if(!hDIB) return 0;
  314. LPBITMAPINFOHEADER lpbmInfoHdr=(LPBITMAPINFOHEADER) GlobalLock (hDIB);
  315. DWORD sz=sizeof (BITMAPINFOHEADER)+PALETTESIZE ((LPSTR) lpbmInfoHdr) + lpbmInfoHdr->biSizeImage;
  316. GlobalUnlock(hDIB);
  317. return sz;
  318. }
  319. /////////////////////////////////////////////////
  320. // DDB->DIB
  321. HANDLE _dibFromBitmap(HBITMAP hBitmap)
  322. {
  323.    HDC                  hDC;
  324.    WORD wBits;
  325.    HPALETTE  hPal=NULL;
  326.    BITMAP               bm;
  327.    BITMAPINFOHEADER     bi;
  328.    BITMAPINFOHEADER     *lpbi;
  329.    DWORD                dwLen;
  330.    HANDLE               hDIB;
  331.    if (!hBitmap)
  332.       return NULL;
  333.    ::GetObject (hBitmap, sizeof (bm), (LPSTR)&bm);
  334.     wBits =  bm.bmBitsPixel;
  335.    bi.biSize               = sizeof (BITMAPINFOHEADER);
  336.    bi.biWidth              = bm.bmWidth;
  337.    bi.biHeight             = bm.bmHeight;
  338.    bi.biPlanes             = 1;
  339.    bi.biBitCount           = wBits;
  340.    bi.biCompression        = BI_RGB;
  341.    bi.biSizeImage          = 0;
  342.    bi.biXPelsPerMeter      = 0;
  343.    bi.biYPelsPerMeter      = 0;
  344.    bi.biClrUsed            = 0;
  345.    bi.biClrImportant       = 0;
  346.    dwLen  = bi.biSize + PALETTESIZE ((LPSTR) &bi);
  347.    hDIB   = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,dwLen);
  348.    if (!hDIB)
  349.       return NULL;
  350.    lpbi   = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  351.    *lpbi  = bi;
  352.    
  353.    HWND hWnd= GetFocus();
  354.    
  355.    if(!hWnd)
  356.    {//load default system palette
  357.     hPal   = (HPALETTE)GetStockObject (DEFAULT_PALETTE);
  358.     hDC    = GetDC (NULL);
  359.     hPal   = SelectPalette (hDC, hPal, FALSE);
  360.     RealizePalette(hDC);
  361. }
  362.    else
  363.     {
  364. //or get palette from focused window
  365. HDC hDCw    = GetDC (hWnd);
  366. hPal   = SelectPalette (hDCw, (HPALETTE)GetStockObject (DEFAULT_PALETTE), FALSE);
  367.     hDC    = GetDC (NULL);
  368.     hPal   = SelectPalette (hDC, hPal, FALSE);
  369. RealizePalette(hDC);
  370. SelectPalette (hDCw, hPal, FALSE);
  371. ReleaseDC(hWnd,hDCw);
  372. }
  373.    // calculate the biSizeImage
  374.    GetDIBits (hDC,
  375.               hBitmap,
  376.               0,
  377.               (WORD) bi.biHeight,
  378.               NULL,
  379.               (LPBITMAPINFO) lpbi,
  380.               DIB_RGB_COLORS);
  381.    bi = *lpbi;
  382.    GlobalUnlock(hDIB);
  383.    // If the driver did not fill in the biSizeImage field, 
  384.    // make one up
  385.    if (bi.biSizeImage == 0)
  386.       {
  387.       bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * wBits) * bm.bmHeight;
  388.       if (bi.biCompression != BI_RGB)
  389.          bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  390.       }
  391.    DWORD sl =dwLen;
  392.    HGLOBAL hPtr =hDIB;
  393.    dwLen = bi.biSize + PALETTESIZE((LPSTR)&bi) + bi.biSizeImage;
  394. // if you have plans to use DDE or clipboard, you have
  395.     // to allocate memory with GMEM_DDESHARE flag
  396.    if(!(hDIB = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,dwLen))) 
  397.    {
  398.       SelectPalette(hDC,hPal,FALSE);
  399.       ReleaseDC(NULL,hDC);
  400.   GlobalFree(hPtr);
  401.   return NULL;}
  402.    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  403. LPBITMAPINFOHEADER lpS=(LPBITMAPINFOHEADER)GlobalLock(hPtr);
  404. CopyMemory(lpbi,lpS,sl);
  405. GlobalUnlock(hPtr);
  406. GlobalFree(hPtr);
  407.     // actually fill lpBits
  408.    if (GetDIBits( hDC,
  409.          hBitmap,
  410.          0,
  411.          (WORD) bi.biHeight,
  412.          (LPSTR) lpbi + (WORD) lpbi->biSize + PALETTESIZE((LPSTR) lpbi),
  413.          (LPBITMAPINFO) lpbi, DIB_RGB_COLORS) == 0)
  414.       {
  415.       GlobalUnlock (hDIB);
  416.       hDIB = NULL;
  417.       SelectPalette (hDC, hPal, FALSE);
  418.       ReleaseDC (NULL, hDC);
  419.       return NULL;
  420.       }
  421.    bi = *lpbi;
  422.    GlobalUnlock (hDIB);
  423.    SelectPalette (hDC, hPal, FALSE);
  424.    ReleaseDC (NULL, hDC);
  425.    //OK
  426.    return hDIB;
  427. }
  428. int _DIBNumColors (LPBITMAPINFOHEADER lpbi)
  429. {
  430.       if (lpbi->biClrUsed)
  431.          return (int)lpbi->biClrUsed;
  432.    switch (lpbi->biBitCount)
  433.       {
  434.       case 1:
  435.          return 2;
  436.       case 4:
  437.          return 16;
  438.       case 8:
  439.          return 256;
  440.       default:
  441.          return 0; //16,24,32 bits bitmap has no color table
  442.       }
  443. }