Hdib.cpp
上传用户:cjd055
上传日期:2013-04-01
资源大小:608k
文件大小:13k
源码类别:

交通/航空行业

开发平台:

Visual C++

  1. // HDib.cpp: implementation of the CDib class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "HDib.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #endif
  10. //////////////////////////////////////////////////////////////////////
  11. // Construction/Destruction
  12. //////////////////////////////////////////////////////////////////////
  13. CDib::CDib()
  14. {
  15. m_BmpLoaded=FALSE;
  16. m_Buffer=0;
  17. m_Buffer1=0;
  18. m_BmpInfo=0;
  19. m_Quad=0;
  20. m_hPal=0;
  21. BmpMarker=('M'<<8)|'B';
  22. Width=0;
  23. Height=0;
  24. }
  25. CDib::~CDib()
  26. {
  27. Free();
  28. }
  29. //释放所有动态分配的内存:
  30. void CDib::Free()
  31. {
  32. if(m_Buffer)
  33. {
  34. delete [] m_Buffer;
  35. m_Buffer=0;
  36. }
  37. if(m_Buffer1)
  38. {
  39. delete [] m_Buffer1;
  40. m_Buffer1=0;
  41. }
  42. if(m_BmpInfo)
  43. {
  44. delete [] m_BmpInfo;
  45. m_BmpInfo=0;
  46. }
  47. if(m_Quad)
  48. {
  49. delete [] m_Quad;
  50. m_Quad=0;
  51. }
  52. }
  53. void CDib::Resize(int sz)
  54. {
  55. if(m_Buffer)
  56. {
  57. delete [] m_Buffer;
  58. m_Buffer=0;
  59. }
  60. if(m_Buffer1)
  61. {
  62. delete [] m_Buffer1;
  63. m_Buffer1=0;
  64. }
  65. m_Buffer=new BYTE[sz];
  66. m_Buffer1=new BYTE[sz];
  67. //位图每一行占据的字节数:
  68. Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧
  69. //位图数据区尺寸(字节):
  70. BufferSize=Bpl*Height;
  71. }
  72. //从文件中读取位图:
  73. BOOL CDib::LoadBmp(LPCTSTR fn)
  74. {
  75. int j;
  76. if(fn=="")
  77. {
  78. return FALSE;
  79. }
  80. Free();
  81.     arcFileName=fn;
  82. //打开bmp文件:
  83. ifstream files(fn,ios::binary|ios::nocreate);
  84. if(!files.is_open())
  85. {
  86. return FALSE;
  87. }
  88. //读入BITMAPFILEHEADER:
  89. files.read((LPSTR)&m_BmpFH, sizeof(BITMAPFILEHEADER));
  90. //判断是否是bmp文件:
  91. if (m_BmpFH.bfType != BmpMarker)
  92. {
  93. return FALSE;
  94. }
  95. //读入BITMAPINFO:
  96. DWORD bmpinfosz;
  97. bmpinfosz=m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER) 
  98.       +256*sizeof(RGBQUAD);  //40+256*4
  99. m_BmpInfo=(LPBITMAPINFO) new BYTE[bmpinfosz];
  100. files.read((char *)m_BmpInfo,m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)); //m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)=40
  101. //计算位图的相关数据信息:
  102. CalBmpData();
  103. //只支持8位以上的位图:
  104. if(BPP>32)
  105. {
  106. Free();
  107. return FALSE;
  108. }
  109. //读入位图数据:
  110. m_Buffer=new BYTE[BufferSize];
  111. m_Buffer1=new BYTE[BufferSize];
  112. files.read((char *)m_Buffer,BufferSize);
  113. if(m_BmpInfo->bmiHeader.biCompression!=BI_RGB)
  114. {
  115. Free();
  116. return FALSE;
  117. }
  118. if(!CreatePalette())
  119. {
  120. Free();
  121. return FALSE;
  122. }
  123.     for ( j=0;j<(int)BufferSize;j++)
  124. {
  125.     *(m_Buffer1+j)=*(m_Buffer+j);
  126. }
  127. m_BmpLoaded=TRUE;
  128. return TRUE;
  129. }
  130. //将内存中的位图存入文件:
  131. BOOL CDib::SaveBmp(LPCTSTR fn)
  132. {
  133. if(fn=="")
  134. {
  135. return FALSE;
  136. }
  137. if(!m_BmpLoaded)
  138. {
  139. return FALSE;
  140. }
  141. if(m_BmpInfo==0||m_Buffer==0)
  142. {
  143. return FALSE;
  144. }
  145. //1. 更改m_BmpInfo->bmiHeader.biSizeImage:
  146. //1. biSizeImage=位图数据的大小:
  147. m_BmpInfo->bmiHeader.biSizeImage=BufferSize;
  148. //2. 填充bmpfh结构;
  149. BITMAPFILEHEADER bmpfh;
  150. memset(&bmpfh,0,sizeof(BITMAPFILEHEADER));
  151. bmpfh.bfType=BmpMarker;
  152. //bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize:
  153. bmpfh.bfSize=sizeof(BITMAPFILEHEADER)+
  154.        sizeof(BITMAPINFO)+
  155.            (NumberOfColors-1)*sizeof(RGBQUAD)+
  156.    BufferSize;
  157. bmpfh.bfReserved1=0;
  158. bmpfh.bfReserved2=0;
  159. bmpfh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+
  160.               m_BmpInfo->bmiHeader.biSize+
  161.   PaletteSize();
  162. //3. 写文件:
  163. FILE * fp;
  164. size_t sz;
  165. if((fp=fopen(fn,"wb"))==NULL)
  166. {
  167. return FALSE;
  168. }
  169. //1). 写入BITMAPFILEHEADER:
  170. sz=fwrite((void *)&bmpfh,sizeof(BITMAPFILEHEADER),1,fp);
  171. if(sz!=1)
  172. {
  173. fclose(fp);
  174. return FALSE;
  175. }
  176. //2). 写入BITMAPINFO:
  177. sz=fwrite((void *)m_BmpInfo,sizeof(BITMAPINFO)+(NumberOfColors-1)*sizeof(RGBQUAD),1,fp);
  178. if(sz!=1)
  179. {
  180. fclose(fp);
  181. return FALSE;
  182. }
  183. //3). 写入位图数据:
  184. sz=fwrite(m_Buffer,1,BufferSize,fp);
  185. if(sz!=BufferSize)
  186. {
  187. fclose(fp);
  188. return FALSE;
  189. }
  190. fclose(fp);
  191. return TRUE;
  192. }
  193. //获取位图内存地址:
  194. BYTE * CDib::GetBuffer()
  195. {
  196. return m_Buffer;
  197. }
  198. //根据像素在位图中的位置求像素在内存中的地址:
  199. BYTE * CDib::FindPos(DWORD x, DWORD y)
  200. {
  201. BYTE * pos;
  202. if(!m_BmpLoaded)
  203. {
  204. return 0;
  205. }
  206. pos=m_Buffer+Bpl*(Height-1-y)+x*BPP/8;
  207. return pos;
  208. }
  209. //将位图的子画面存入文件:
  210. BOOL CDib::PickBitmapToFile(LPCTSTR fn, DWORD xt, DWORD yt, 
  211. DWORD xb, DWORD yb)
  212. {
  213. BYTE * buf;
  214. DWORD w,h,bpl,bufsize,n0;
  215. if(!m_BmpLoaded)
  216. {
  217. return FALSE;
  218. }
  219. if(m_BmpInfo==0||m_Buffer==0)
  220. {
  221. return FALSE;
  222. }
  223. if(fn=="")
  224. {
  225. return FALSE;
  226. }
  227. //1. 计算基本参数:
  228. Sort(xt,xb);
  229. Sort(yt,yb);
  230. if(xt>Width)
  231. {
  232. return FALSE;
  233. }
  234. if(yt>Width)
  235. {
  236. return FALSE;
  237. }
  238. if(xb>Width)
  239. {
  240. xb=Width;
  241. }
  242. if(yb>Height)
  243. {
  244. yb=Height;
  245. }
  246. w=xb-xt;//子画面宽度;
  247. h=yb-yt;//子画面高度;
  248. bpl=(w*(BPP/8)+3)&~3;//每一行大小;
  249. n0=bpl-w*BPP/8;//需要在每一行末尾添加的0的数目;
  250. bufsize=bpl*h;//位图数据区大小;
  251. //2. 填写位图区:
  252. BYTE * pos,* bufpos;
  253. pos=FindPos(xt,yt);//找到(xt,yt)像素在内存中的位置;
  254. buf=new BYTE[bufsize];
  255. memset((void *)buf,0,bufsize);
  256. UINT i;
  257. bufpos=buf+bpl*(h-1);
  258. for(i=0;i<h;i++)
  259. {
  260. memcpy(bufpos,pos,w*BPP/8);
  261. bufpos-=bpl;
  262. pos-=Bpl;
  263. }
  264. //3. 填写位图结构:
  265. BITMAPFILEHEADER fh;
  266. BITMAPINFO       info;
  267. memset(&fh  ,0,sizeof(BITMAPFILEHEADER));
  268. memset(&info,0,sizeof(BITMAPINFO));
  269. //1. 填充BITMAPINFO结构:
  270. info.bmiHeader.biBitCount=(WORD)BPP;
  271. info.bmiHeader.biClrImportant=m_BmpInfo->bmiHeader.biClrImportant;
  272. info.bmiHeader.biClrUsed=m_BmpInfo->bmiHeader.biClrUsed;
  273. info.bmiHeader.biCompression=BI_RGB;
  274. info.bmiHeader.biHeight=h;
  275. info.bmiHeader.biPlanes=m_BmpInfo->bmiHeader.biPlanes;
  276. info.bmiHeader.biSize=m_BmpInfo->bmiHeader.biSize;
  277. info.bmiHeader.biSizeImage=bufsize;
  278. info.bmiHeader.biWidth=w;
  279. info.bmiHeader.biXPelsPerMeter=m_BmpInfo->bmiHeader.biXPelsPerMeter;
  280. info.bmiHeader.biYPelsPerMeter=m_BmpInfo->bmiHeader.biYPelsPerMeter;
  281. info.bmiColors[0]=m_BmpInfo->bmiColors[0];
  282. //2. 填充bmpfh结构;
  283. fh.bfType=BmpMarker;
  284. //bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize:
  285. fh.bfSize=sizeof(BITMAPFILEHEADER)+
  286.        sizeof(BITMAPINFO)+
  287.            (NumberOfColors-1)*sizeof(RGBQUAD)+
  288.    bufsize;
  289. fh.bfReserved1=0;
  290. fh.bfReserved2=0;
  291. fh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+
  292.               m_BmpInfo->bmiHeader.biSize+
  293.   PaletteSize();
  294. //4. 写文件:
  295. FILE * fp;
  296. if((fp=fopen(fn,"wb"))==NULL)
  297. {
  298. return FALSE;
  299. }
  300. //1). 写入BITMAPFILEHEADER:
  301. fwrite((char *)&fh,sizeof(BITMAPFILEHEADER),1,fp);
  302. //2). 写入BITMAPINFOHEADER部分:
  303. fwrite((char *)&info.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
  304. //3). //写入彩色表部分:
  305. if(BPP<16)
  306. {
  307. fwrite((char *)&m_Quad[0],NumberOfColors*sizeof(RGBQUAD),1,fp);
  308. }
  309. //4). 写入位图数据:
  310. fwrite((char *)buf,bufsize,1,fp);
  311. delete buf;
  312. fclose(fp);
  313. return TRUE;
  314. }
  315. void CDib::CalBmpData()
  316. {
  317. if(m_BmpInfo==0)
  318. {
  319. return;
  320. }
  321. //1. 位图宽度(像素):
  322. Width=m_BmpInfo->bmiHeader.biWidth;
  323. //位图高度(像素):
  324. Height=m_BmpInfo->bmiHeader.biHeight;
  325. //位图色彩深度:
  326. BPP=m_BmpInfo->bmiHeader.biBitCount; //取值可为1,4,8,16,24,32,如取值16,24,32,则彩色表不是必须的
  327. //位图每一行占据的字节数:
  328. Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧
  329. //位图数据区尺寸(字节):
  330. BufferSize=Bpl*Height;
  331. //为m_Quad分配内存:
  332. //如果色彩数目大于8 则返回:
  333. if(m_BmpInfo->bmiHeader.biBitCount>=16)
  334. {
  335. NumberOfColors=0;
  336. return;
  337. }
  338. if(m_BmpInfo->bmiHeader.biClrUsed!=0)
  339. {
  340. NumberOfColors=m_BmpInfo->bmiHeader.biClrUsed;
  341. }
  342. else
  343. {
  344. switch(BPP){
  345. case 1:
  346. NumberOfColors=2;
  347. break;
  348. case 4:
  349. NumberOfColors=16;
  350. break;
  351. case 8:
  352. NumberOfColors=256;
  353. break;
  354. default:
  355. return;
  356. }
  357. }
  358. //读取 logical palette
  359. m_Quad=new RGBQUAD[NumberOfColors];
  360. for(DWORD i=0;i<NumberOfColors;i++)
  361. {
  362. m_Quad[i]=m_BmpInfo->bmiColors[i];
  363. }
  364. }
  365. void CDib::SetBmpMarker(DWORD b, DWORD m)
  366. {
  367. BmpMarker=(WORD)((m<<8)|b); //'m'左移8位 and 'b' 再强制类型转换
  368. }
  369. DWORD CDib::PaletteSize()
  370. {
  371. if (m_BmpInfo==0)
  372. {
  373. return 0;
  374. }
  375. return (DWORD)NumberOfColors*sizeof(RGBQUAD);//256*4
  376. }
  377. //using bmp file's QUAD to change phisical palette
  378. BOOL CDib::CreatePalette()
  379. {
  380. if (m_BmpInfo==0)
  381. {
  382. return FALSE;
  383. }
  384. //16位以下的位图均需要 logical palette
  385. if(BPP>=16)
  386. {
  387. return TRUE;
  388. }
  389. DWORD i;
  390. // allocate memory block for 逻辑彩色区logical palette
  391. LPLOGPALETTE lpPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*NumberOfColors]; //sizeof(PALETTEENTRY)*NumberOfColors=4*256 bytes
  392. // if not enough memory, clean up and return NULL
  393. if (lpPal == 0)
  394. {
  395. return FALSE;
  396. }
  397. // set version and number of palette entries
  398. lpPal->palVersion = PALVERSION;
  399. lpPal->palNumEntries = (WORD)NumberOfColors;
  400. for (i=0;i<NumberOfColors;i++)
  401. {
  402. lpPal->palPalEntry[i].peRed   = m_Quad[i].rgbRed;
  403. lpPal->palPalEntry[i].peGreen = m_Quad[i].rgbGreen;
  404. lpPal->palPalEntry[i].peBlue  = m_Quad[i].rgbBlue;
  405. lpPal->palPalEntry[i].peFlags = 0;
  406. }
  407. /* according to bmp file palette table,create the palette and 
  408. get handle to it */
  409. if (m_hPal)
  410. {
  411. ::DeleteObject((HGDIOBJ)m_hPal); //删除老的逻辑调色对象
  412. }
  413. m_hPal=::CreatePalette(lpPal); //创建新的逻辑调色对象
  414. if(!m_hPal)
  415. {
  416. return FALSE;
  417. }
  418. delete [] lpPal; //作用完即destroy logical Palette
  419. return TRUE;
  420. }
  421. BOOL CDib::Draw(HDC hDC, LPRECT rcDest, LPRECT rcSrc)
  422. {
  423. if (!m_BmpLoaded)
  424. {
  425. return FALSE;
  426. }
  427. HPALETTE hOldPal = 0;        // Previous palette
  428. // Get the DIB's palette, then select it into DC
  429. if (m_hPal!=0)
  430. {
  431. // Select as background since we have
  432. // already realized in forground if needed
  433. hOldPal = ::SelectPalette(hDC,m_hPal,TRUE); //selects the specified logical palette into a device context
  434. }
  435. /* Make sure to use the stretching mode best for color pictures */
  436. ::SetStretchBltMode(hDC, COLORONCOLOR);
  437. /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  438. BOOL Ok;
  439. if ((RECTWIDTH(rcDest)  == RECTWIDTH(rcSrc)) &&
  440.     (RECTHEIGHT(rcDest) == RECTHEIGHT(rcSrc)))
  441. {
  442. Ok = ::SetDIBitsToDevice(hDC,                                 // hDC
  443.  rcDest->left,                        // DestX
  444.  rcDest->top,                         // DestY
  445.  RECTWIDTH(rcDest),                   // nDestWidth
  446.  RECTHEIGHT(rcDest),                  // nDestHeight
  447.  rcSrc->left,                         // SrcX
  448.  Height-rcSrc->top -RECTHEIGHT(rcSrc),// SrcY
  449.  0,                                   // nStartScan
  450.  (WORD)Height,                        // nNumScans
  451.  m_Buffer,                            // lpBits
  452.  m_BmpInfo,                           // lpBitsInfo
  453.  DIB_RGB_COLORS);                     // wUsage
  454. }
  455.    else
  456.    {
  457.   Ok = ::StretchDIBits(hDC,                            // hDC
  458.    rcDest->left,               // DestX
  459.    rcDest->top,                // DestY
  460.    RECTWIDTH(rcDest),          // nDestWidth
  461.    RECTHEIGHT(rcDest),         // nDestHeight
  462.    rcSrc->left,                // SrcX
  463.    rcSrc->top,                 // SrcY
  464.    RECTWIDTH(rcSrc),           // wSrcWidth
  465.    RECTHEIGHT(rcSrc),          // wSrcHeight
  466.    m_Buffer,                   // lpBits
  467.    m_BmpInfo,                   // lpBitsInfo
  468.    DIB_RGB_COLORS,             // wUsage
  469.    SRCCOPY);                   // dwROP
  470.    }
  471. /* Reselect old palette */
  472. if (hOldPal != 0)
  473. {
  474. ::SelectPalette(hDC, hOldPal, TRUE); //恢复老的调色板
  475. }
  476.    return Ok;
  477. }
  478. void CDib::Sort(DWORD &x0, DWORD &x1)
  479. {
  480. DWORD t;
  481. if(x0>x1)
  482. {
  483. t=x1;
  484. x1=x0;
  485. x0=t;
  486. }
  487. }
  488. BITMAPINFOHEADER CDib::GetImageInfo(LPCTSTR fn, DWORD &w, DWORD &h)
  489. {
  490. BITMAPFILEHEADER bmpfilehdr;
  491. BITMAPINFOHEADER bmpinfohdr;
  492. w=0;
  493. h=0;
  494. memset(&bmpfilehdr,0,sizeof(BITMAPFILEHEADER)); //初始化内存并得到内存指针;
  495. memset(&bmpinfohdr,0,sizeof(BITMAPINFOHEADER));
  496. ifstream file( fn, ios::binary | ios::nocreate ); //打开已存在的且二进制的文件;
  497. if (!file.is_open())
  498. {
  499. return bmpinfohdr;
  500. }
  501. file.read( (char*)&bmpfilehdr, sizeof(bmpfilehdr) );
  502. if (bmpfilehdr.bfType!=(WORD)BmpMarker)
  503. {
  504. return bmpinfohdr;
  505. }
  506. file.read( (char*)&bmpinfohdr, sizeof(bmpinfohdr) );
  507. w=bmpinfohdr.biWidth;
  508. h=bmpinfohdr.biHeight;
  509. return bmpinfohdr;
  510. }
  511. void CDib::restoreimage()
  512. {
  513. int j;
  514.     for ( j=0;j<(int)BufferSize;j++)
  515. {
  516.     *(m_Buffer+j)=*(m_Buffer1+j);
  517. }
  518. }
  519. BOOL CDib::GetBlueImg()
  520. {
  521.     if (BPP<=8)
  522.    return FALSE;
  523. int i,j;
  524. for(i=0;i<(int)Height;i++)
  525. {
  526. for ( j=0;j<(int)Bpl-2;j=j+3)
  527. {
  528.     *(m_Buffer+i*Bpl+j+1)=0;
  529. *(m_Buffer+i*Bpl+j+2)=0;
  530. }
  531. }
  532.     return TRUE;
  533. }
  534. BOOL CDib::GetGreenImg()
  535. {
  536.     if (BPP<=8)
  537.    return FALSE;
  538. int i,j;
  539. for(i=0;i<(int)Height;i++)
  540. {
  541. for ( j=0;j<(int)Bpl-2;j=j+3)
  542. {
  543.     *(m_Buffer+i*Bpl+j)=0;
  544. *(m_Buffer+i*Bpl+j+2)=0;
  545. }
  546. }
  547.     return TRUE;
  548. }
  549. BOOL CDib::GetRedImg()
  550. {
  551.     if (BPP<=8)
  552.    return FALSE;
  553. int i,j;
  554. for(i=0;i<(int)Height;i++)
  555. {
  556. for ( j=0;j<(int)Bpl-2;j=j+3)
  557. {
  558.     *(m_Buffer+i*Bpl+j)=0;
  559. *(m_Buffer+i*Bpl+j+1)=0;
  560. }
  561. }
  562.     return TRUE;
  563. }