DibObject.cpp
上传用户:xayxjz
上传日期:2022-08-07
资源大小:2188k
文件大小:50k
源码类别:

图形图象

开发平台:

Visual C++

  1. //DibObject.cpp
  2. #include "stdafx.h"
  3. #include "DibObject.h"
  4. IMPLEMENT_DYNCREATE(CDibObject, CObject)
  5. char *CDibObject::szExtensions[] = { ".BMP", ".GIF", ".PCX", ".TGA", ".JPG", ".TIF", "" };
  6.         
  7. //Diagnostics and dump member functions, overridden
  8. #ifdef _DEBUG
  9. void CDibObject::Dump(CDumpContext &dc) const
  10. {
  11. //call base class function first
  12. CObject::Dump(dc);
  13. //now do the stuff for our specific class
  14. dc<<"File Name:"<<m_pszFilename<<"n";
  15. }
  16. #endif
  17. #ifdef _DEBUG
  18. void CDibObject::AssertValid() const
  19. {
  20. //call inherited AssertValid first
  21. CObject::AssertValid();
  22. //check CDibObject members...
  23. ASSERT(m_pszFilename != NULL); //must exist
  24. ASSERT(m_hDib != NULL); //must exist
  25. }
  26. #endif
  27. ////////////////////////////////////////////////////////////////////////
  28. //CDibObject类的构造函数     
  29. //----------------------------------------------------------------------
  30. //基本功能:这是一个无参数的构造函数。它简单地创建一个CDibObject对象并
  31. // 初始化其内部变量。
  32. //----------------------------------------------------------------------
  33. //参数说明:无
  34. //----------------------------------------------------------------------
  35. //返 回 值:无
  36. ////////////////////////////////////////////////////////////////////////
  37. CDibObject::CDibObject()
  38. {
  39. //调用辅助函数初始化其内部变量。
  40. InitVars();
  41. }
  42. ////////////////////////////////////////////////////////////////////////
  43. //CDibObject类的构造函数     
  44. //----------------------------------------------------------------------
  45. //基本功能:用一个CDibObject对象通过复制操作来创建一个CDibObject对象。
  46. //----------------------------------------------------------------------
  47. //参数说明:CDibObject *pDibObject
  48. //----------------------------------------------------------------------
  49. //返 回 值:无
  50. ////////////////////////////////////////////////////////////////////////
  51. CDibObject::CDibObject(CDibObject *pDibObject)
  52. {
  53. InitVars();
  54. KillImage();
  55. m_nWidth = pDibObject->m_nWidth;
  56. m_nHeight = pDibObject->m_nHeight;
  57. m_nPlanes = pDibObject->m_nPlanes;
  58. m_nBits = pDibObject->m_nBits;
  59. m_nColors = pDibObject->m_nColors;
  60. m_nImageType = pDibObject->m_nImageType;
  61. m_nX = pDibObject->m_nX;
  62. m_nY = pDibObject->m_nY;
  63. m_nLastError = pDibObject->m_nLastError;
  64. m_nScreenPlanes = pDibObject->m_nScreenPlanes;
  65. m_nScreenBits = pDibObject->m_nScreenBits;
  66. m_nPaletteBytes = pDibObject->m_nPaletteBytes;
  67. m_nQuality = pDibObject->m_nQuality;
  68. m_nPaletteCreationType = pDibObject->m_nPaletteCreationType;
  69. int nNumColors = m_nColors;
  70. int nWidthBytes = WidthBytes( m_nBits, m_nWidth );
  71. if( pDibObject->m_hDib != NULL )
  72. {
  73. DWORD dwSize = ::GlobalSize( pDibObject->m_hDib );
  74. char *pData = (char *) ::GlobalLock( pDibObject->m_hDib );
  75. if( pData != NULL )
  76. {
  77. HGLOBAL hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
  78. if( hGlobal != NULL ){
  79. char *pDestData = (char *) ::GlobalLock( hGlobal );
  80. if( pDestData != NULL )
  81. {
  82. memcpy( pDestData, pData, dwSize );
  83. ::GlobalUnlock( hGlobal );
  84. m_hDib = hGlobal;
  85. }
  86. else ::GlobalFree( hGlobal );
  87. }
  88. ::GlobalUnlock( pDibObject->m_hDib );
  89. }
  90. }
  91. }
  92. ////////////////////////////////////////////////////////////////////////
  93. //CDibObject类的构造函数     
  94. //----------------------------------------------------------------------
  95. //基本功能:构造一个CDibObject对象。唯一的要求的一个参数是文件名。如果
  96. // 给出了CDC设备上下文参数,图像加载后会立即在该设备上下文中显示
  97. // 出来。如果给出了nX或nY参数,图像会显示在该坐标指定的位置,否
  98. // 则,图像总是显示在坐标为(0, 0)的位置。
  99. //----------------------------------------------------------------------
  100. //参数说明:const char *pszFilename
  101. // CDC *pDC,默认为NULL
  102. // int nX,默认为-1
  103. // int nY,默认为-1
  104. //----------------------------------------------------------------------
  105. ////////////////////////////////////////////////////////////////////////
  106. CDibObject::CDibObject( const char *pszFilename,
  107.    CDC *pDC, int nX, int nY )
  108. {
  109. InitVars();
  110. Load( pszFilename, pDC, nX, nY );
  111. }
  112. ////////////////////////////////////////////////////////////////////////
  113. //CDibObject类的析构函数     
  114. //----------------------------------------------------------------------
  115. //基本功能:析构CDibObject对象,删除该对象中的图像及相应的变量
  116. //----------------------------------------------------------------------
  117. //参数说明:无
  118. ////////////////////////////////////////////////////////////////////////
  119. CDibObject::~CDibObject()
  120. {
  121. if( m_hDib ) ::GlobalFree( m_hDib );
  122. if( m_pszFilename != NULL ) delete [] m_pszFilename;
  123. if( m_pLogPal != NULL ) delete [] m_pLogPal;
  124. }
  125. ////////////////////////////////////////////////////////////////////////
  126. //InitVars()函数     
  127. //----------------------------------------------------------------------
  128. //基本功能:初始化CDibObject类内部变量
  129. //----------------------------------------------------------------------
  130. //参数说明:BOOL bFlag 标记类中是否有图像打开,默认值为FALSE
  131. ////////////////////////////////////////////////////////////////////////
  132. void CDibObject::InitVars( BOOL bFlag )
  133. {
  134. m_nWidth = m_nHeight = m_nBits = m_nColors = m_nImageType = 0;
  135. m_nX = m_nY = 0;
  136. m_nLastError = 0;
  137. m_hDib = NULL;
  138. m_nPaletteCreationType = FIXED_PALETTE;
  139. if( !bFlag )
  140. {
  141. m_pszFilename = NULL;
  142. m_pLogPal = NULL;
  143. }
  144. m_nQuality = 50;
  145. }
  146. ////////////////////////////////////////////////////////////////////////
  147. //BOOL Load()     
  148. //----------------------------------------------------------------------
  149. //基本功能:本函数把一个图像文件载入CDibObject类。必需的一个参数是文件
  150. // 名。如果给出了CDC设备上下文参数,图像一加载就被绘制。如果给
  151. // 出了nX或nY参数,图像将显示在该坐标指定的位置。否则,图像总是
  152. // 显示在坐标为(0,0)的位置。
  153. //----------------------------------------------------------------------
  154. //参数说明:const char *pszFilename
  155. // CDC *pDC,默认为NULL
  156. // int nX,默认为-1
  157. // int nY,默认为-1
  158. //----------------------------------------------------------------------
  159. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  160. ////////////////////////////////////////////////////////////////////////
  161. BOOL CDibObject::Load( const char *pszFilename, 
  162. CDC *pDC, int nX, int nY )
  163. {
  164. //获取图像文件类型
  165. m_nImageType = FileType( pszFilename );
  166. if( m_nImageType == 0 )
  167. {
  168. m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
  169. return( FALSE );
  170. }
  171. //删除已存在的图像
  172. KillImage();
  173. m_pszFilename = new char [strlen(pszFilename)+1];
  174. if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
  175. //根据文件类型调用ImageLoad.dll动态链接库中的相应函数打开图像文件
  176. switch( m_nImageType )
  177. {
  178. case IMAGETYPE_BMP:
  179. m_hDib = ::LoadBMP( pszFilename );
  180. if( m_hDib == NULL ){
  181. m_nLastError = ::GetLastPicLibError();
  182. return( FALSE );
  183. }
  184. break;
  185. case IMAGETYPE_GIF:
  186. m_hDib = ::LoadGIF( pszFilename );
  187. if( m_hDib == NULL ){
  188. m_nLastError = ::GetLastPicLibError();
  189. return( FALSE );
  190. }
  191. break;
  192. case IMAGETYPE_JPG:
  193. m_hDib = ::LoadJPG( pszFilename );
  194. if( m_hDib == NULL ){
  195. m_nLastError = ::GetLastPicLibError();
  196. return( FALSE );
  197. }
  198. break;
  199. case IMAGETYPE_PCX:
  200. m_hDib = ::LoadPCX( pszFilename );
  201. if( m_hDib == NULL ){
  202. m_nLastError = ::GetLastPicLibError();
  203. return( FALSE );
  204. }
  205. break;
  206. case IMAGETYPE_TGA:
  207. m_hDib = ::LoadTGA( pszFilename );
  208. if( m_hDib == NULL ){
  209. m_nLastError = ::GetLastPicLibError();
  210. return( FALSE );
  211. }
  212. break;
  213. case IMAGETYPE_TIF:
  214. m_hDib = ::LoadTIF( pszFilename );
  215. if( m_hDib == NULL ){
  216. m_nLastError = ::GetLastPicLibError();
  217. return( FALSE );
  218. }
  219. break;
  220. }
  221. //处理图像信息头
  222. ProcessImageHeader();
  223. //处理调色板
  224. ProcessPalette();
  225. //若传入了设备上下文指针,就在指定的设备上下文中绘制图像
  226. if( pDC != NULL ) Draw( pDC, nX, nY );
  227. return( TRUE );
  228. }
  229. ////////////////////////////////////////////////////////////////////////
  230. //BOOL GetImageInfo()     
  231. //----------------------------------------------------------------------
  232. //基本功能:本函数获取图像宽度、高度、位平面数、每个像素点的位数、以及颜
  233. // 色数的信息。值为NULL的参数将不被传入。
  234. //----------------------------------------------------------------------
  235. //参数说明:const char *pszFilename
  236. // int *pnWidth, 默认为NULL
  237. // int *pnHeight, 默认为NULL
  238. // int *pnPlanes, 默认为NULL
  239. // int *pnBitsPerPixel, 默认为NULL
  240. // int *pnNumColors, 默认为NULL
  241. //----------------------------------------------------------------------
  242. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  243. //----------------------------------------------------------------------
  244. ////////////////////////////////////////////////////////////////////////
  245. BOOL CDibObject::GetImageInfo( const char *pszFilename, int *pnWidth,
  246. int *pnHeight, int *pnPlanes, int *pnBitsPerPixel, int *pnNumColors )
  247. {
  248. int nImageType;
  249. //获取图像文件类型
  250. nImageType = FileType( pszFilename );
  251. if( nImageType == 0 )
  252. {
  253. m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
  254. return( FALSE );
  255. }
  256. //根据文件类型调用ImageLoad.dll动态链接库中的相应函数获取图像信息
  257. switch( nImageType )
  258. {
  259. case IMAGETYPE_BMP:
  260. return( ::GetBMPInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  261. case IMAGETYPE_GIF:
  262. return( ::GetGIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  263. case IMAGETYPE_JPG:
  264. return( ::GetJPGInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  265. case IMAGETYPE_PCX:
  266. return( ::GetPCXInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  267. case IMAGETYPE_TGA:
  268. return( ::GetTGAInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  269. case IMAGETYPE_TIF:
  270. return( ::GetTIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  271. }
  272. return( FALSE );
  273. }
  274. ////////////////////////////////////////////////////////////////////////
  275. //int GetLastError()     
  276. //----------------------------------------------------------------------
  277. //基本功能:本函数返回所发生的最后一次CDibObject类错误。详细错误信息见
  278. // "ImageErrors.h"头文件。
  279. //----------------------------------------------------------------------
  280. //参数说明:无
  281. //----------------------------------------------------------------------
  282. //返 回 值:int nErrorNumber
  283. //----------------------------------------------------------------------
  284. ////////////////////////////////////////////////////////////////////////
  285. int CDibObject::GetLastError( void )
  286. {
  287. return( m_nLastError );
  288. }
  289. ////////////////////////////////////////////////////////////////////////
  290. //BOOL Save()     
  291. //----------------------------------------------------------------------
  292. //基本功能:本函数保存驻留于CDibObject对象中的当前图像(图像类型定义见
  293. // GetImageType()函数。
  294. //----------------------------------------------------------------------
  295. //参数说明:const char *pszFilename
  296. // int nType,默认为-1
  297. //----------------------------------------------------------------------
  298. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  299. //----------------------------------------------------------------------
  300. ////////////////////////////////////////////////////////////////////////
  301. BOOL CDibObject::Save( const char *pszFilename, int nType )
  302. {
  303. //若没有指定文件类型,则根据文件名判断其文件类型
  304. if( nType == -1 ) nType = ExtensionIndex( pszFilename );
  305. if( nType < IMAGETYPE_FIRSTTYPE || nType > IMAGETYPE_LASTTYPE ) return( FALSE );
  306. m_nImageType = nType;
  307. delete [] m_pszFilename;
  308. m_pszFilename = new char [strlen(pszFilename)+1];
  309. if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
  310. //根据文件类型调用ImageLoad.dll动态链接库中的相应函数保存图像
  311. switch( m_nImageType )
  312. {
  313. case IMAGETYPE_BMP:
  314. return( ::SaveBMP( pszFilename, m_hDib ) );
  315. break;
  316. case IMAGETYPE_GIF:
  317. return( ::SaveGIF( pszFilename, m_hDib ) );
  318. break;
  319. case IMAGETYPE_JPG:
  320. return( ::SaveJPG( pszFilename, m_hDib, m_nQuality ) );
  321. break;
  322. case IMAGETYPE_PCX:
  323. return( ::SavePCX( pszFilename, m_hDib ) );
  324. break;
  325. case IMAGETYPE_TGA:
  326. return( ::SaveTGA( pszFilename, m_hDib ) );
  327. break;
  328. case IMAGETYPE_TIF:
  329. return( ::SaveTIF( pszFilename, m_hDib ) );
  330. break;
  331. }
  332. return( TRUE );
  333. }
  334. ////////////////////////////////////////////////////////////////////////
  335. //int ExtensionIndex()
  336. //----------------------------------------------------------------------
  337. //基本功能:本函数返回文件名指定的图像类型。
  338. //----------------------------------------------------------------------
  339. //参数说明:无
  340. //----------------------------------------------------------------------
  341. //返 回 值:int nWidth
  342. //----------------------------------------------------------------------
  343. ////////////////////////////////////////////////////////////////////////
  344. int CDibObject::ExtensionIndex( const char *pszFilename )
  345. {
  346. int Index = 0;
  347. char *pszExtension;
  348. pszExtension = (char *) &pszFilename[strlen(pszFilename)-4];
  349. while( szExtensions[Index][0] )
  350. {
  351. if( !stricmp( pszExtension, szExtensions[Index] ) ) return( Index + 1 );
  352. Index++;
  353. }
  354. return( -1 );
  355. }
  356. ////////////////////////////////////////////////////////////////////////
  357. //int GetWidth()
  358. //----------------------------------------------------------------------
  359. //基本功能:本函数返回图像的像素宽度数。
  360. //----------------------------------------------------------------------
  361. //参数说明:无
  362. //----------------------------------------------------------------------
  363. //返 回 值:int nWidth
  364. //----------------------------------------------------------------------
  365. ////////////////////////////////////////////////////////////////////////
  366. int CDibObject::GetWidth( void )
  367. {
  368. return( m_nWidth );
  369. }
  370. ////////////////////////////////////////////////////////////////////////
  371. //int GetHeight( void )
  372. //----------------------------------------------------------------------
  373. //基本功能:本函数返回图像的像素高度数。
  374. //----------------------------------------------------------------------
  375. //参数说明:无
  376. //----------------------------------------------------------------------
  377. //返 回 值:int nHeight
  378. //----------------------------------------------------------------------
  379. ////////////////////////////////////////////////////////////////////////
  380. int CDibObject::GetHeight( void )
  381. {
  382. return( m_nHeight );
  383. }
  384. ////////////////////////////////////////////////////////////////////////
  385. //int GetNumBits( void )
  386. //----------------------------------------------------------------------
  387. //基本功能:本函数返回图像的像素数:1、4、8、16、24、32。
  388. //----------------------------------------------------------------------
  389. //参数说明:无
  390. //----------------------------------------------------------------------
  391. //返 回 值:int nBits
  392. ////////////////////////////////////////////////////////////////////////
  393. int CDibObject::GetNumBits( void )
  394. {
  395. return( m_nBits );
  396. }
  397. ////////////////////////////////////////////////////////////////////////
  398. //int GetNumColors( void )
  399. //----------------------------------------------------------------------
  400. //基本功能:本函数返回图像调色板中的颜色。图像为16位色或更高时返回值为0。
  401. //----------------------------------------------------------------------
  402. //参数说明:无
  403. //----------------------------------------------------------------------
  404. //返 回 值:int nColors
  405. ////////////////////////////////////////////////////////////////////////
  406. int CDibObject::GetNumColors( void )
  407. {
  408. return( m_nColors );
  409. }
  410. ////////////////////////////////////////////////////////////////////////
  411. //BOOL GetPaletteData()     
  412. //----------------------------------------------------------------------
  413. //基本功能:本函数将当前RGB调色板数据填入到所传入的指针中。如果图像是16
  414. // 位色或更高时则不进行任何操作。
  415. //----------------------------------------------------------------------
  416. //参数说明:RGBQUAD *pRGBPalette
  417. //----------------------------------------------------------------------
  418. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  419. ////////////////////////////////////////////////////////////////////////
  420. BOOL CDibObject::GetPaletteData( RGBQUAD *pRGBPalette )
  421. {
  422. m_nLastError = IMAGELIB_HDIB_NULL;
  423. if( m_hDib == NULL ) return( FALSE );
  424. char *pTemp;
  425. pTemp = (char *) ::GlobalLock( m_hDib );
  426. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  427. if( pTemp == NULL ) return( FALSE );
  428. memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)],
  429. m_nPaletteBytes );
  430. m_nLastError = IMAGELIB_SUCCESS;
  431. ::GlobalUnlock( m_hDib );
  432. return( TRUE );
  433. }
  434. ////////////////////////////////////////////////////////////////////////
  435. //RGBQUAD GetPaletteData()     
  436. //----------------------------------------------------------------------
  437. //基本功能:本函数返回一个指向CDibObject调色板数据序列的指针。如果图像
  438. // 是16位色或更高时则返回NULL。
  439. //----------------------------------------------------------------------
  440. //参数说明:无
  441. //----------------------------------------------------------------------
  442. //返 回 值:返回一个指向CDibObject调色板数据序列的指针
  443. ////////////////////////////////////////////////////////////////////////
  444. RGBQUAD *CDibObject::GetPaletteData( void )
  445. {
  446. m_nLastError = IMAGELIB_HDIB_NULL;
  447. if( m_hDib == NULL ) return( NULL );
  448. m_nLastError = IMAGELIB_NO_PALETTE_FOR_HIGH_COLOR;
  449. if( m_nColors <= 0 || m_nColors > 256 ) return( NULL );
  450. RGBQUAD *pRGBPalette;
  451. pRGBPalette = new RGBQUAD [m_nColors];
  452. if( pRGBPalette == NULL )
  453. {
  454. m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
  455. return( NULL );
  456. }
  457. char *pTemp;
  458. pTemp = (char *) ::GlobalLock( m_hDib );
  459. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  460. if( pTemp == NULL )
  461. {
  462. delete [] pRGBPalette;
  463. return( NULL );
  464. }
  465. memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], 
  466. m_nColors * sizeof( RGBQUAD ) );
  467. m_nLastError = IMAGELIB_SUCCESS;
  468. ::GlobalUnlock( m_hDib );
  469. return( pRGBPalette );
  470. }
  471. ////////////////////////////////////////////////////////////////////////
  472. //int GetImageType()     
  473. //----------------------------------------------------------------------
  474. //基本功能:本函数返回图像的类型。图像类型定义如下:
  475. // #define IMAGETYPE_NONE 0
  476. // #define IMAGETYPE_BMP 1
  477. // #define IMAGETYPE_GIF 2
  478. // #define IMAGETYPE_PCX 3
  479. // #define IMAGETYPE_TGA 4
  480. // #define IMAGETYPE_JPG 5
  481. // #define IMAGETYPE_TIF 6
  482. //----------------------------------------------------------------------
  483. //参数说明:const char *pFilename
  484. //----------------------------------------------------------------------
  485. //返 回 值:int nImageType
  486. ////////////////////////////////////////////////////////////////////////
  487. int CDibObject::GetImageType( const char *pFilename )
  488. {
  489. return( ::FileType( pFilename ) );
  490. }
  491. ////////////////////////////////////////////////////////////////////////
  492. //int GetImageType()     
  493. //----------------------------------------------------------------------
  494. //基本功能:本函数返回图像的类型。图像类型定义如下:
  495. // #define IMAGETYPE_NONE 0
  496. // #define IMAGETYPE_BMP 1
  497. // #define IMAGETYPE_GIF 2
  498. // #define IMAGETYPE_PCX 3
  499. // #define IMAGETYPE_TGA 4
  500. // #define IMAGETYPE_JPG 5
  501. // #define IMAGETYPE_TIF 6
  502. //----------------------------------------------------------------------
  503. //参数说明:无
  504. //----------------------------------------------------------------------
  505. //返 回 值:int nImageType
  506. ////////////////////////////////////////////////////////////////////////
  507. int CDibObject::GetImageType( void )
  508. {
  509. return( m_nImageType );
  510. }
  511. ////////////////////////////////////////////////////////////////////////
  512. //BOOL Draw( CDC *pDC, int nX, int nY )     
  513. //----------------------------------------------------------------------
  514. //基本功能:本函数是在设备描述表上绘制图像。如果X和Y坐标没有给出,图像会
  515. // 被画在(0,0)坐标或上次传入的有效坐标处。
  516. //----------------------------------------------------------------------
  517. //参数说明:CDC *pDC
  518. // int nX,默认为-1
  519. // int nY,默认为-1
  520. //----------------------------------------------------------------------
  521. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  522. ////////////////////////////////////////////////////////////////////////
  523. BOOL CDibObject::Draw( CDC *pDC, int nX, int nY )
  524. {
  525. if( nX != -1 ) m_nX = nX;
  526. if( nY != -1 ) m_nY = nY;
  527. m_nLastError = IMAGELIB_HDIB_NULL;
  528. //没有打开图像
  529. if( m_hDib == NULL ) return( FALSE );
  530. char *pTemp;
  531. //锁定图像对象句柄
  532. pTemp = (char *) ::GlobalLock( m_hDib );
  533. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  534. if( pTemp == NULL ) return( NULL );
  535. //图像信息头
  536. BITMAPINFOHEADER *pBIH;
  537. pBIH = (BITMAPINFOHEADER *) &pTemp[sizeof(BITMAPFILEHEADER)];
  538. int nRet = ::StretchDIBits( pDC->m_hDC, m_nX, m_nY, m_nWidth, m_nHeight, 0, 0, 
  539. m_nWidth, m_nHeight, 
  540. (const void FAR *) &pTemp[sizeof(BITMAPFILEHEADER)+
  541.   sizeof(BITMAPINFOHEADER)+
  542.   m_nPaletteBytes], 
  543. (BITMAPINFO *) pBIH, DIB_RGB_COLORS, SRCCOPY );
  544. ::GlobalUnlock( m_hDib );
  545. m_nLastError = IMAGELIB_STRETCHDIBITS_ERROR;
  546. if( nRet != m_nHeight ) return( FALSE );
  547. m_nLastError = IMAGELIB_SUCCESS;
  548. return( TRUE );
  549. }
  550. ////////////////////////////////////////////////////////////////////////
  551. //BOOL CreateLogPalette()     
  552. //----------------------------------------------------------------------
  553. //基本功能:本函数根据指定的调色板指针及颜色数创建一个逻辑调色板。
  554. //----------------------------------------------------------------------
  555. //参数说明:CDC *pDC
  556. // int nX,默认为-1
  557. // int nY,默认为-1
  558. //----------------------------------------------------------------------
  559. //返 回 值:创建的逻辑调色板指针
  560. ////////////////////////////////////////////////////////////////////////
  561. LOGPALETTE *CDibObject::CreateLogPalette( RGBQUAD *pPalette, 
  562.    int nNumColors )
  563. {
  564. LOGPALETTE *pLogPal;
  565. int i;
  566. if( pPalette == NULL ) return( NULL );
  567. pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)];
  568. if( pLogPal == NULL ) return( NULL );
  569. //指定调色板版本号
  570. pLogPal->palVersion = 0x300;
  571. //指定调色板颜色数
  572. pLogPal->palNumEntries = (unsigned short) nNumColors;
  573. //复制调色板各颜色项
  574. for( i=0; i<nNumColors; i++ )
  575. {
  576. pLogPal->palPalEntry[i].peRed = pPalette[i].rgbRed;
  577. pLogPal->palPalEntry[i].peGreen = pPalette[i].rgbGreen;
  578. pLogPal->palPalEntry[i].peBlue = pPalette[i].rgbBlue;
  579. pLogPal->palPalEntry[i].peFlags = 0;
  580. }
  581. return( pLogPal );
  582. }
  583. ////////////////////////////////////////////////////////////////////////
  584. //void ProcessImageHeader()     
  585. //----------------------------------------------------------------------
  586. //基本功能:本函数处理图像信息头各项内容。
  587. //----------------------------------------------------------------------
  588. //参数说明:无
  589. //----------------------------------------------------------------------
  590. //返 回 值:无
  591. ////////////////////////////////////////////////////////////////////////
  592. void CDibObject::ProcessImageHeader( void )
  593. {
  594. m_nLastError = IMAGELIB_HDIB_NULL;
  595. if( m_hDib == NULL ) return;
  596. char *pTemp;
  597. BITMAPINFOHEADER *pBIH;
  598. pTemp = (char *) ::GlobalLock( m_hDib );
  599. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  600. if( pTemp == NULL ) return;
  601. //得到图像信息头指针
  602. pBIH = (BITMAPINFOHEADER *) &pTemp[sizeof(BITMAPFILEHEADER)];
  603. m_nWidth = pBIH->biWidth;
  604. m_nHeight = pBIH->biHeight;
  605. m_nPlanes = pBIH->biPlanes;
  606. m_nBits = pBIH->biBitCount;
  607. m_nColors = 1 << m_nBits;
  608. if( m_nPlanes > 1 ) m_nColors <<= ( m_nPlanes - 1 );
  609. if( m_nBits >= 16 ) m_nColors = 0;
  610. int nWidthBytes = WidthBytes(m_nBits, m_nWidth);
  611. pBIH->biSizeImage = nWidthBytes * m_nHeight;
  612. ::GlobalUnlock( m_hDib );
  613. m_nLastError = IMAGELIB_SUCCESS;
  614. }
  615. ////////////////////////////////////////////////////////////////////////
  616. //void ProcessPalette()     
  617. //----------------------------------------------------------------------
  618. //基本功能:处理体调色板。
  619. //----------------------------------------------------------------------
  620. //参数说明:无
  621. //----------------------------------------------------------------------
  622. //返 回 值:无
  623. ////////////////////////////////////////////////////////////////////////
  624. void CDibObject::ProcessPalette( void )
  625. {
  626. m_nLastError = IMAGELIB_HDIB_NULL;
  627. if( m_hDib == NULL ) return;
  628. CWindowDC WindowDC( NULL );
  629. m_nScreenPlanes = WindowDC.GetDeviceCaps( PLANES );
  630. m_nScreenBits = WindowDC.GetDeviceCaps( BITSPIXEL );
  631. m_nPaletteBytes = 0;
  632. m_Palette.DeleteObject();
  633. if( m_nBits <= 8 ) m_nPaletteBytes = m_nColors * sizeof( RGBQUAD );
  634. if( m_nScreenBits >= 16 ) return;
  635. char *pTemp;
  636. pTemp = (char *) ::GlobalLock( m_hDib );
  637. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  638. if( pTemp == NULL ) return;
  639. if( m_nBits <= 8 ){
  640. RGBQUAD *pRGBPalette;
  641. pRGBPalette = (RGBQUAD *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  642. LOGPALETTE *pPalette;
  643. pPalette = CreateLogPalette( pRGBPalette, m_nColors );
  644. if( pPalette == NULL ){
  645. m_nLastError = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
  646. goto ProcessPaletteExit;
  647. }
  648. m_Palette.CreatePalette( pPalette );
  649. delete [] pPalette;
  650. }
  651. m_nLastError = IMAGELIB_SUCCESS;
  652. ProcessPaletteExit:
  653. ::GlobalUnlock( m_hDib );
  654. }
  655. ////////////////////////////////////////////////////////////////////////
  656. //void KillImage()     
  657. //----------------------------------------------------------------------
  658. //基本功能:清除当前CDibObject类中的图像对象。
  659. //----------------------------------------------------------------------
  660. //参数说明:无
  661. //----------------------------------------------------------------------
  662. //返 回 值:无
  663. ////////////////////////////////////////////////////////////////////////
  664. void CDibObject::KillImage( void )
  665. {
  666. if( m_hDib ) ::GlobalFree( m_hDib );
  667. m_hDib = NULL;
  668. if( m_pLogPal != NULL ) delete [] m_pLogPal;
  669. m_pLogPal = NULL;
  670. if( m_pszFilename != NULL ) delete [] m_pszFilename;
  671. m_pszFilename = NULL;
  672. m_Palette.DeleteObject();
  673. }
  674. ////////////////////////////////////////////////////////////////////////
  675. //BOOL SetPalette( CDC *pDC )     
  676. //----------------------------------------------------------------------
  677. //基本功能:本函数将该设备描述表的调色板分配给相应的图像。当一个图像被载
  678. // 入时,它的调色板信息便被存入CDibObject对象中。
  679. //----------------------------------------------------------------------
  680. //参数说明:CDC *pDC
  681. //----------------------------------------------------------------------
  682. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  683. //----------------------------------------------------------------------
  684. ////////////////////////////////////////////////////////////////////////
  685. BOOL CDibObject::SetPalette( CDC *pDC )
  686. {
  687. m_nLastError = IMAGELIB_HDIB_NULL;
  688. if( m_hDib == NULL ) return( FALSE );
  689. pDC->SelectPalette( &m_Palette, FALSE );
  690. pDC->RealizePalette();
  691. m_nLastError = IMAGELIB_SUCCESS;
  692. return( TRUE );
  693. }
  694. ////////////////////////////////////////////////////////////////////////
  695. //BOOL IsLoaded( void )     
  696. //----------------------------------------------------------------------
  697. //基本功能:本函数判断是否已经载入了一幅图像
  698. //----------------------------------------------------------------------
  699. //参数说明:无
  700. //----------------------------------------------------------------------
  701. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  702. //----------------------------------------------------------------------
  703. ////////////////////////////////////////////////////////////////////////
  704. BOOL CDibObject::IsLoaded( void )
  705. {
  706. return( m_hDib != NULL );
  707. }
  708. ////////////////////////////////////////////////////////////////////////
  709. //void GetDIBPointer()     
  710. //----------------------------------------------------------------------
  711. //基本功能:得到图像DIB数据指针。
  712. //----------------------------------------------------------------------
  713. //参数说明:int *nWidthBytes 图像的字节宽度
  714. // int nNewBits 新设置的图像颜色位数
  715. // int *nNewWidthBytes 图像颜色位数改变后的字节宽度
  716. // int nNewWidth 新设置的图像宽度(像素)
  717. //----------------------------------------------------------------------
  718. //返 回 值:无
  719. ////////////////////////////////////////////////////////////////////////
  720. void *CDibObject::GetDIBPointer( int *nWidthBytes,
  721.  int nNewBits, 
  722.  int *nNewWidthBytes,
  723.  int nNewWidth )
  724. {
  725. m_nLastError = IMAGELIB_HDIB_NULL;
  726. if( m_hDib == NULL ) return( NULL );
  727. void *pTemp;
  728. pTemp = ::GlobalLock( m_hDib );
  729. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  730. if( pTemp == NULL ) return( NULL );
  731. if( nWidthBytes != NULL ) *nWidthBytes = WidthBytes( m_nBits, m_nWidth );
  732. if( nNewWidthBytes != NULL )
  733. {
  734. if( nNewWidth == -1 ) nNewWidth = m_nWidth;
  735. *nNewWidthBytes = WidthBytes( nNewBits, nNewWidth );
  736. }
  737. return( pTemp );
  738. }
  739. ////////////////////////////////////////////////////////////////////////
  740. //int WidthBytes()     
  741. //----------------------------------------------------------------------
  742. //基本功能:本函数根据传入的像素位数及图像宽度(像素)计算其字节宽度。
  743. //----------------------------------------------------------------------
  744. //参数说明:int nBits 每像素位数
  745. // int nWidth 图像的宽度
  746. //----------------------------------------------------------------------
  747. //返 回 值:int 图像的字节宽度
  748. //----------------------------------------------------------------------
  749. ////////////////////////////////////////////////////////////////////////
  750. int CDibObject::WidthBytes( int nBits, int nWidth )
  751. {
  752. int nWidthBytes;
  753. nWidthBytes = nWidth;
  754. if( nBits == 1 ) nWidthBytes = ( nWidth + 7 ) / 8;
  755. else if( nBits == 4 ) nWidthBytes = ( nWidth + 1 ) / 2;
  756. else if( nBits == 16 ) nWidthBytes = nWidth * 2;
  757. else if( nBits == 24 ) nWidthBytes = nWidth * 3;
  758. else if( nBits == 32 ) nWidthBytes = nWidth * 4;
  759. //一个数的后两位为零,则该数为4的整数倍
  760. while( ( nWidthBytes & 3 ) != 0 ) nWidthBytes++;
  761. return( nWidthBytes );
  762. }
  763. ////////////////////////////////////////////////////////////////////////
  764. //void NormalizeCoordinates()     
  765. //----------------------------------------------------------------------
  766. //基本功能:规格化处理的图像区域。
  767. //----------------------------------------------------------------------
  768. //参数说明:int *nX1 处理区域左上角X坐标
  769. // int *nY1 处理区域左上角Y坐标
  770. // int *nX2 处理区域右下角X坐标
  771. // int *nY2 处理区域右下角Y坐标
  772. // BOOL *bCompleteImage 处理区域是否为全部区域
  773. // BOOL *bLessThanHalf 处理区域是否为一半区域
  774. //----------------------------------------------------------------------
  775. //返 回 值:无
  776. ////////////////////////////////////////////////////////////////////////
  777. void CDibObject::NormalizeCoordinates( int *nX1, int *nY1, int *nX2, int *nY2, 
  778.   BOOL *bCompleteImage, BOOL *bLessThanHalf )
  779. {
  780. if( *nX1 == -1 ) *nX1 = 0;
  781. if( *nY1 == -1 ) *nY1 = 0;
  782. if( *nX2 == -1 ) *nX2 = m_nWidth - 1;
  783. if( *nY2 == -1 ) *nY2 = m_nHeight - 1;
  784. if( *nX1 > *nX2 ){
  785. int nTemp;
  786. nTemp = *nX1;
  787. *nX1 = *nX2;
  788. *nX2 = nTemp;
  789. }
  790. if( *nY1 > *nY2 ){
  791. int nTemp;
  792. nTemp = *nY1;
  793. *nY1 = *nY2;
  794. *nY2 = nTemp;
  795. }
  796. if( *nX1 < 0 ) *nX1 = 0;
  797. if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
  798. if( *nX2 < 0 ) *nX2 = 0;
  799. if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
  800. if( *nY1 < 0 ) *nY1 = 0;
  801. if( *nY1 > m_nHeight - 1 ) *nY1 = m_nHeight - 1;
  802. if( *nY2 < 0 ) *nY2 = 0;
  803. if( *nY2 > m_nHeight - 1 ) *nY2 = m_nHeight - 1;
  804. if( bCompleteImage != NULL ) *bCompleteImage = TRUE;
  805. if( bLessThanHalf != NULL ) *bLessThanHalf = FALSE;
  806. if( *nX1 > 0 || *nY1 > 0 || *nX2 < m_nWidth - 1 || *nY2 < m_nHeight - 1 ){
  807. if( bCompleteImage != NULL ) *bCompleteImage = FALSE;
  808. DWORD dwTotalPixels, dwThesePixels;
  809. dwTotalPixels = (DWORD) m_nWidth * m_nHeight;
  810. dwThesePixels = (DWORD) ( (*nX2) - (*nX1) + 1 ) * (DWORD) ( (*nY2) - (*nY1) + 1 );
  811. if( bLessThanHalf != NULL && dwThesePixels <= dwTotalPixels / 2 ) *bLessThanHalf = TRUE;
  812. }
  813. }
  814. ////////////////////////////////////////////////////////////////////////
  815. //void operator=()     
  816. //----------------------------------------------------------------------
  817. //基本功能:“=”操作符重载。
  818. //----------------------------------------------------------------------
  819. //参数说明:CDibObject &DibObject 另一个CDibObject图像对象。
  820. //----------------------------------------------------------------------
  821. //返 回 值:无
  822. ////////////////////////////////////////////////////////////////////////
  823. void CDibObject::operator= (const CDibObject &DibObject)
  824. {
  825. KillImage();
  826. m_nWidth = DibObject.m_nWidth;
  827. m_nHeight = DibObject.m_nHeight;
  828. m_nPlanes = DibObject.m_nPlanes;
  829. m_nBits = DibObject.m_nBits;
  830. m_nColors = DibObject.m_nColors;
  831. m_nImageType = DibObject.m_nImageType;
  832. m_nX = DibObject.m_nX;
  833. m_nY = DibObject.m_nY;
  834. m_nLastError = DibObject.m_nLastError;
  835. m_nScreenPlanes = DibObject.m_nScreenPlanes;
  836. m_nScreenBits = DibObject.m_nScreenBits;
  837. m_nPaletteBytes = DibObject.m_nPaletteBytes;
  838. m_nQuality = DibObject.m_nQuality;
  839. m_nPaletteCreationType = DibObject.m_nPaletteCreationType;
  840. int nNumColors = m_nColors;
  841. int nWidthBytes = WidthBytes( m_nBits, m_nWidth );
  842. if( DibObject.m_hDib != NULL ){
  843. DWORD dwSize = ::GlobalSize( DibObject.m_hDib );
  844. char *pData = (char *) ::GlobalLock( DibObject.m_hDib );
  845. if( pData != NULL ){
  846. HGLOBAL hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
  847. if( hGlobal != NULL ){
  848. char *pDestData = (char *) ::GlobalLock( hGlobal );
  849. if( pDestData != NULL ){
  850. memcpy( pDestData, pData, dwSize );
  851. if( nNumColors != 0 ) CreatePaletteFromDIB( (RGBQUAD *) &pData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], nNumColors );
  852. else if( DibObject.m_pLogPal != NULL ){
  853. m_pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+DibObject.m_pLogPal->palNumEntries*sizeof(PALETTEENTRY)];
  854. if( m_pLogPal != NULL ){
  855. for( int i=0; i<DibObject.m_pLogPal->palNumEntries; i++ ) m_pLogPal[i] = DibObject.m_pLogPal[i];
  856. m_Palette.CreatePalette( m_pLogPal );
  857. }
  858. }
  859. ::GlobalUnlock( hGlobal );
  860. m_hDib = hGlobal;
  861. }
  862. else ::GlobalFree( hGlobal );
  863. }
  864. ::GlobalUnlock( DibObject.m_hDib );
  865. }
  866. }
  867. if( DibObject.m_pszFilename != NULL ){
  868. m_pszFilename = new char [strlen(DibObject.m_pszFilename)+1];
  869. strcpy( m_pszFilename, DibObject.m_pszFilename );
  870. }
  871. }
  872. ////////////////////////////////////////////////////////////////////////
  873. //void CreatePaletteFromDIB()     
  874. //----------------------------------------------------------------------
  875. //基本功能:从当前CDibObject位图对象中创建调色板。
  876. //----------------------------------------------------------------------
  877. //参数说明:RGBQUAD *pRGBPalette 调色板指针
  878. // int nNumColors 图像颜色数
  879. //----------------------------------------------------------------------
  880. //返 回 值:无
  881. ////////////////////////////////////////////////////////////////////////
  882. void CDibObject::CreatePaletteFromDIB( RGBQUAD *pRGBPalette, int nNumColors )
  883. {
  884. if( pRGBPalette != NULL ){
  885. LOGPALETTE *pPalette;
  886. pPalette = CreateLogPalette( pRGBPalette, nNumColors );
  887. if( pPalette != NULL ){
  888. m_Palette.CreatePalette( pPalette );
  889. delete [] pPalette;
  890. }
  891. else m_nLastError = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
  892. }
  893. }
  894. ////////////////////////////////////////////////////////////////////////
  895. //int GetNearestIndex()     
  896. //----------------------------------------------------------------------
  897. //基本功能:获取相近颜色索引值。
  898. //----------------------------------------------------------------------
  899. //参数说明:unsigned char ucRed 红色分量
  900. // unsigned char ucGreen 绿色分量
  901. // unsigned char ucBlue 蓝色分量
  902. // RGBQUAD *pRGBPalette 调色板指针
  903. // int nNumColors 颜色数
  904. //----------------------------------------------------------------------
  905. //返 回 值:int 相近颜色索引值
  906. //----------------------------------------------------------------------
  907. ////////////////////////////////////////////////////////////////////////
  908. int CDibObject::GetNearestIndex( unsigned char ucRed,
  909.  unsigned char ucGreen, 
  910.  unsigned char ucBlue, 
  911.  RGBQUAD *pRGBPalette, 
  912.  int nNumColors )
  913. {
  914. int i, Index = 0;
  915. DWORD NewDiff, Diff = 100000L;
  916. DWORD Red, Green, Blue;
  917. for( i=0; i<nNumColors; i++ )
  918. {
  919. if( ucRed > pRGBPalette[i].rgbRed ) Red = (DWORD) ( pRGBPalette[i].rgbRed - ucRed );
  920. else Red = (DWORD) ( ucRed - pRGBPalette[i].rgbRed );
  921. if( ucGreen > pRGBPalette[i].rgbGreen ) Green = (DWORD) ( pRGBPalette[i].rgbGreen - ucGreen );
  922. else Green = (DWORD) ( ucGreen - pRGBPalette[i].rgbGreen );
  923. if( ucBlue > pRGBPalette[i].rgbBlue ) Blue = (DWORD) ( pRGBPalette[i].rgbBlue - ucBlue );
  924. else Blue = (DWORD) ( ucBlue - pRGBPalette[i].rgbBlue );
  925. NewDiff = ( Red * Red ) + ( Green * Green ) + ( Blue * Blue );
  926. if( NewDiff < Diff )
  927. {
  928. if( NewDiff <= 1 ) return( i );
  929. Diff = NewDiff;
  930. Index = i;
  931. }
  932. }
  933. return( Index );
  934. }
  935. ////////////////////////////////////////////////////////////////////////
  936. //BOOL ChangeFormat( int nNewBitsPerPixel )     
  937. //----------------------------------------------------------------------
  938. //基本功能:本函数将图像从当前分辨率转化为指定分辨率。
  939. //----------------------------------------------------------------------
  940. //参数说明:int nNewBitsPerPixel
  941. //----------------------------------------------------------------------
  942. //返 回 值:BOOL:成功返回TRUE,失败返回FALSE
  943. ////////////////////////////////////////////////////////////////////////
  944. BOOL CDibObject::ChangeFormat( int nNewBitsPerPixel )
  945. {
  946. m_nLastError = IMAGELIB_SUCCESS;
  947. if( nNewBitsPerPixel == m_nBits ) return( TRUE );
  948. int nOldWidthBytes, nNewWidthBytes;
  949. char *pBuffer = (char *) GetDIBPointer( &nOldWidthBytes, nNewBitsPerPixel, &nNewWidthBytes );
  950. if( pBuffer == NULL ) return( FALSE );
  951. BITMAPINFOHEADER *pOldBIH, *pNewBIH;
  952. BITMAPFILEHEADER *pOldBFH, *pNewBFH;
  953. RGBQUAD *pOldRGBPalette, *pNewRGBPalette;
  954. unsigned char *pOldBits, *pNewBits;
  955. int nNumColors, nNumNewColors;
  956. pOldBFH = (BITMAPFILEHEADER *) pBuffer;
  957. pOldBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  958. pOldRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  959. nNumColors = m_nColors;
  960. nNumNewColors = 1 << nNewBitsPerPixel;
  961. if( nNewBitsPerPixel > 8 ) nNumNewColors = 0;
  962. pOldBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  963. if( m_nBits >= 16 && nNewBitsPerPixel < 16 ){
  964. if( m_pLogPal != NULL ) delete [] m_pLogPal;
  965. m_pLogPal = CreatePaletteFromBitmap( nNumNewColors, pOldBits, m_nBits, m_nWidth, m_nHeight );
  966. }
  967. HGLOBAL hGlobal;
  968. DWORD dwSize;
  969. dwSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + m_nHeight * nNewWidthBytes;
  970. hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
  971. if( hGlobal == NULL ){
  972. ::GlobalUnlock( m_hDib );
  973. return( FALSE );
  974. }
  975. pBuffer = (char *) ::GlobalLock( hGlobal );
  976. if( pBuffer == NULL ){
  977. ::GlobalFree( hGlobal );
  978. ::GlobalUnlock( m_hDib );
  979. return( FALSE );
  980. }
  981. pNewBFH = (BITMAPFILEHEADER *) pBuffer;
  982. pNewBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  983. pNewRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  984. *pNewBFH = *pOldBFH;
  985. *pNewBIH = *pOldBIH;
  986. int i, j = nNumNewColors;
  987. if( m_nBits < 16 && nNewBitsPerPixel < 16 ){
  988. for( i=0; i<j; i++ ) pNewRGBPalette[i] = pOldRGBPalette[i];
  989. }
  990. else if( m_nBits >= 16 ){
  991.   for( i=0; i<j; i++ ){
  992. pNewRGBPalette[i].rgbRed = m_pLogPal->palPalEntry[i].peRed;
  993. pNewRGBPalette[i].rgbGreen = m_pLogPal->palPalEntry[i].peGreen;
  994. pNewRGBPalette[i].rgbBlue = m_pLogPal->palPalEntry[i].peBlue;
  995. }
  996. }
  997. pNewBIH->biBitCount = nNewBitsPerPixel;
  998. pNewBIH->biSizeImage = nNewWidthBytes * m_nHeight;
  999. pNewBIH->biClrUsed = nNumNewColors;
  1000. pNewBFH->bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + pNewBIH->biSizeImage;
  1001. pNewBFH->bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD );
  1002. pNewBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumNewColors*sizeof(RGBQUAD)];
  1003. m_nPaletteBytes = nNumNewColors * sizeof( RGBQUAD );
  1004. for( int y=0; y<m_nHeight; y++ ){
  1005. unsigned char ucRed, ucGreen, ucBlue;
  1006. unsigned char *pSrc, *pDest;
  1007. pSrc = pOldBits;
  1008. pSrc += ( nOldWidthBytes * y );
  1009. pDest = pNewBits;
  1010. pDest += ( nNewWidthBytes * y );
  1011. for( int x=0; x<m_nWidth; x++ ){
  1012. switch( m_nBits ){
  1013. case 1:
  1014. if( pSrc[x/8] & ( 0x80 >> ( x & 7 ) ) )
  1015. ucRed = ucGreen = ucBlue = 0xff;
  1016. else
  1017. ucRed = ucGreen = ucBlue = 0x00;
  1018. break;
  1019. case 4:
  1020. if( !( x & 1 ) ){
  1021. ucRed = pOldRGBPalette[pSrc[x/2]>>4].rgbRed;
  1022. ucGreen = pOldRGBPalette[pSrc[x/2]>>4].rgbGreen;
  1023. ucBlue = pOldRGBPalette[pSrc[x/2]>>4].rgbBlue;
  1024. }
  1025. else{
  1026. ucRed = pOldRGBPalette[pSrc[x/2]&15].rgbRed;
  1027. ucGreen = pOldRGBPalette[pSrc[x/2]&15].rgbGreen;
  1028. ucBlue = pOldRGBPalette[pSrc[x/2]&15].rgbBlue;
  1029. }
  1030. break;
  1031. case 8:
  1032. ucRed = pOldRGBPalette[pSrc[x]].rgbRed;
  1033. ucGreen = pOldRGBPalette[pSrc[x]].rgbGreen;
  1034. ucBlue = pOldRGBPalette[pSrc[x]].rgbBlue;
  1035. break;
  1036. case 16:
  1037. GETRGB555( ucRed, ucGreen, ucBlue, &pSrc[x*2] );
  1038. break;
  1039. case 24:
  1040. ucRed = pSrc[x*3+2];
  1041. ucGreen = pSrc[x*3+1];
  1042. ucBlue = pSrc[x*3];
  1043. break;
  1044. case 32:
  1045. GETRGB888( ucRed, ucGreen, ucBlue, &pSrc[x*4] );
  1046. break;
  1047. }
  1048. switch( nNewBitsPerPixel ){
  1049. case 1:
  1050. if( !( x & 7 ) ) pDest[x/8] = 0;
  1051. pDest[x/8] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << ( x & 7 );
  1052. break;
  1053. case 4:
  1054. if( !( x & 1 ) )
  1055. pDest[x/2] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << 4;
  1056. else
  1057. pDest[x/2] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
  1058. break;
  1059. case 8:
  1060. pDest[x] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
  1061. break;
  1062. case 16:
  1063. PUTRGB555( ucRed, ucGreen, ucBlue, &pDest[x*2] );
  1064. break;
  1065. case 24:
  1066. pDest[x*3+2] = ucRed;
  1067. pDest[x*3+1] = ucGreen;
  1068. pDest[x*3] = ucBlue;
  1069. break;
  1070. case 32:
  1071. PUTRGB888( ucRed, ucGreen, ucBlue, &pDest[x*4] );
  1072. break;
  1073. }
  1074. }
  1075. }
  1076. ::GlobalUnlock( m_hDib );
  1077. ::GlobalFree( m_hDib );
  1078. ::GlobalUnlock( hGlobal );
  1079. m_hDib = hGlobal;
  1080. ProcessImageHeader();
  1081. return( TRUE );
  1082. }
  1083. ////////////////////////////////////////////////////////////////////////
  1084. //LOGPALETTE CreatePaletteFromBitmap()     
  1085. //----------------------------------------------------------------------
  1086. //基本功能:从当前CDibObject位图对象中创建逻辑调色板。
  1087. //----------------------------------------------------------------------
  1088. //参数说明:int nNumColors 颜色数
  1089. // unsigned char *pBits 位图数据指针
  1090. // int nBits 颜色位数
  1091. // int nWidth 图像宽度
  1092. // int nHeight 图像高度
  1093. //----------------------------------------------------------------------
  1094. //返 回 值:LOGPALETTE 逻辑调色板指针
  1095. ////////////////////////////////////////////////////////////////////////
  1096. LOGPALETTE *CDibObject::CreatePaletteFromBitmap(int nNumColors, 
  1097. unsigned char *pBits, int nBits, 
  1098. int nWidth, int nHeight )
  1099. {
  1100. RGBQUAD *pRGBPalette;
  1101. if( nBits != 8 && m_nPaletteCreationType == POPULARITY_PALETTE ) pRGBPalette = MakePopularityPalette( nNumColors, pBits, nBits, nWidth, nHeight );
  1102. else if( nBits != 8 && m_nPaletteCreationType == MEDIAN_CUT_PALETTE ) pRGBPalette = MakeMedianCutPalette( nNumColors, pBits, nBits, nWidth, nHeight );
  1103. else if( m_nPaletteCreationType == FIXED_PALETTE ) pRGBPalette = MakeFixedPalette( nNumColors );
  1104. if( pRGBPalette == NULL ) return( NULL );
  1105. LOGPALETTE *pLogPal = CreateLogPalette( pRGBPalette, nNumColors );
  1106. delete [] pRGBPalette;
  1107. return( pLogPal );
  1108. }
  1109. ////////////////////////////////////////////////////////////////////////
  1110. //void SetPaletteCreationType( int nType )     
  1111. //----------------------------------------------------------------------
  1112. //基本功能:当希望通过颜色还原得到一幅具有调色板的图像时,本函数负责设置
  1113. // 调色板的创建类型。可以设置如下:
  1114. // #define POPULARITY_PALETTE 0
  1115. // #define MEDIAN_CUT_PALETTE 1
  1116. // #define FIXED_PALETTE 2
  1117. //----------------------------------------------------------------------
  1118. //参数说明:int nType
  1119. //----------------------------------------------------------------------
  1120. //返 回 值:无
  1121. //----------------------------------------------------------------------
  1122. ////////////////////////////////////////////////////////////////////////
  1123. void CDibObject::SetPaletteCreationType( int nType )
  1124. {
  1125. m_nPaletteCreationType = nType;
  1126. }
  1127. ////////////////////////////////////////////////////////////////////////
  1128. //int GetPaletteCreationType( void )     
  1129. //----------------------------------------------------------------------
  1130. //基本功能:本函数返回用于下一次颜色还原操作的调色板类型。
  1131. //----------------------------------------------------------------------
  1132. //参数说明:无
  1133. //----------------------------------------------------------------------
  1134. //返 回 值:int nPaletteCreationType
  1135. //----------------------------------------------------------------------
  1136. ////////////////////////////////////////////////////////////////////////
  1137. int CDibObject::GetPaletteCreationType( void )
  1138. {
  1139. return( m_nPaletteCreationType );
  1140. }
  1141. RGBQUAD *CDibObject::MakePopularityPalette( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
  1142. {
  1143. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1144. if( pRGBQuad == NULL ) return( MakeFixedPalette( nNumColors ) );
  1145. memset( pRGBQuad, 0, nNumColors * sizeof( RGBQUAD ) );
  1146. BYTE ColMap[256][3];
  1147. if( !Popularity( pBits, nBits, nWidth, nHeight, ColMap ) ){
  1148. delete [] pRGBQuad;
  1149. return( MakeFixedPalette( nNumColors ) );
  1150. }
  1151. for( int i=0; i<nNumColors; i++ ){
  1152. pRGBQuad[i].rgbRed = ColMap[i][0];
  1153. pRGBQuad[i].rgbGreen = ColMap[i][1];
  1154. pRGBQuad[i].rgbBlue = ColMap[i][2];
  1155. }
  1156. return( pRGBQuad );
  1157. }
  1158. RGBQUAD *CDibObject::MakeMedianCutPalette( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
  1159. {
  1160. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1161. if( pRGBQuad == NULL ) return( MakeFixedPalette( nNumColors ) );
  1162. memset( pRGBQuad, 0, nNumColors * sizeof( RGBQUAD ) );
  1163. BYTE ColMap[256][3];
  1164. WORD *Hist = new WORD[32768];
  1165. if( Hist == NULL ){
  1166. delete [] pRGBQuad;
  1167. return( MakeFixedPalette( nNumColors ) );
  1168. }
  1169. memset( Hist, 0, 32768 * sizeof( WORD ) );
  1170. int nWidthBytes = WidthBytes( nBits, nWidth );
  1171. for( int y=0; y<nHeight; y++ ){
  1172. unsigned char *pData = pBits;
  1173. unsigned char ucRed, ucGreen, ucBlue;
  1174. WORD color;
  1175. pData += ( y * nWidthBytes );
  1176. for( int x=0; x<nWidth; x++ ){
  1177. switch( nBits ){
  1178. case 16:
  1179. GETRGB555( ucRed, ucGreen, ucBlue, &pData[x*2] );
  1180. break;
  1181. case 24:
  1182. ucRed = pData[x*3+2];
  1183. ucGreen = pData[x*3+1];
  1184. ucBlue = pData[x*3];
  1185. break;
  1186. case 32:
  1187. GETRGB888( ucRed, ucGreen, ucBlue, &pData[x*4] );
  1188. break;
  1189. }
  1190. color = _RGB( ucRed, ucGreen, ucBlue );
  1191. if( Hist[color] < 65535 ) Hist[color]++;
  1192. }
  1193. }
  1194. MedianCut( Hist, ColMap, (int) 256 );
  1195. for( int i=0; i<nNumColors; i++ ){
  1196. pRGBQuad[i].rgbRed = ColMap[i][0];
  1197. pRGBQuad[i].rgbGreen = ColMap[i][1];
  1198. pRGBQuad[i].rgbBlue = ColMap[i][2];
  1199. }
  1200. delete [] Hist;
  1201. return( pRGBQuad );
  1202. }
  1203. RGBQUAD *CDibObject::MakeFixedPalette( int nNumColors )
  1204. {
  1205. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1206. if( pRGBQuad == NULL ) return( NULL );
  1207. static int colors[] = {
  1208. 255, 255, 255,
  1209. 0, 0, 0,
  1210. 255, 0, 0,
  1211. 0, 0, 255,
  1212. 0, 255, 0,
  1213. 150, 150, 150,
  1214. 255, 255, 0,
  1215. 0, 150, 150,
  1216. 150, 0, 150,
  1217. 150, 150, 0,
  1218. 0, 255, 255,
  1219. 255, 0, 255,
  1220. 255, 120, 120,
  1221. 120, 255, 120,
  1222. 120, 120, 255,
  1223. 90, 90, 90 };
  1224. int nSteps = ( ( nNumColors + 15 ) / 16 );
  1225. for( int i=0; i<nSteps; i++ ){
  1226. for( int j=0; j<16; j++ ){
  1227. if( i * 16 + j < nNumColors ){
  1228. int r, g, b;
  1229. r = colors[j*3];
  1230. g = colors[j*3+1];
  1231. b = colors[j*3+2];
  1232. r = ( ( nSteps - i ) * r ) / nSteps;
  1233. g = ( ( nSteps - i ) * g ) / nSteps;
  1234. b = ( ( nSteps - i ) * b ) / nSteps;
  1235. pRGBQuad[i*16+j].rgbRed = (unsigned char) r;
  1236. pRGBQuad[i*16+j].rgbGreen = (unsigned char) g;
  1237. pRGBQuad[i*16+j].rgbBlue = (unsigned char) b;
  1238. }
  1239. }
  1240. }
  1241. return( pRGBQuad );
  1242. }
  1243. //得到调色板字节数
  1244. int CDibObject::GetPaletteBytes( void )
  1245. {
  1246. return( m_nPaletteBytes );
  1247. }
  1248. ////////////////////////////////////////////////////////////////////////
  1249. //HGLOBALBOOL GetDib( void )     
  1250. //----------------------------------------------------------------------
  1251. //基本功能:本函数返回当前载入的图像Dib句柄。
  1252. //----------------------------------------------------------------------
  1253. //参数说明:无
  1254. //----------------------------------------------------------------------
  1255. //返 回 值:HGLOBALBOOL hDib
  1256. //----------------------------------------------------------------------
  1257. ////////////////////////////////////////////////////////////////////////
  1258. HGLOBAL CDibObject::GetDib( void )
  1259. {
  1260. return( m_hDib );
  1261. }
  1262. ////////////////////////////////////////////////////////////////////////
  1263. //CPalette GetPalette( void )     
  1264. //----------------------------------------------------------------------
  1265. //基本功能:本函数返回一个指向CPalette对象的指针。
  1266. //----------------------------------------------------------------------
  1267. //参数说明:无
  1268. //----------------------------------------------------------------------
  1269. //返 回 值:CPalette *Palette
  1270. //----------------------------------------------------------------------
  1271. ////////////////////////////////////////////////////////////////////////
  1272. CPalette *CDibObject::GetPalette( void )
  1273. {
  1274. return( &m_Palette );
  1275. }
  1276. //得到逻辑调色板
  1277. LOGPALETTE *CDibObject::GetLogPal( void )
  1278. {
  1279. return( m_pLogPal );
  1280. }
  1281. void CDibObject::ProcImgHead()
  1282. {
  1283. ProcessImageHeader();
  1284. }
  1285. char * CDibObject::GetImageName()
  1286. {
  1287. return( m_pszFilename );
  1288. }