IMAGEOBJECT.CPP
上传用户:alisonmail
上传日期:2013-02-28
资源大小:500k
文件大小:49k
源码类别:

图片显示

开发平台:

Visual C++

  1. // ImageObject.cpp
  2. #include "stdafx.h"
  3. #include "ImageObject.h"
  4. char *CImageObject::szExtensions[] = { ".BMP", ".GIF", ".PCX", ".TGA", ".JPG", ".TIF", "" };
  5. CImageObject::CImageObject()
  6. {
  7. InitVars();
  8. }
  9. CImageObject::CImageObject( const char *pszFilename, CDC *pDC, int nX, int nY )
  10. {
  11. InitVars();
  12. Load( pszFilename, pDC, nX, nY );
  13. }
  14. CImageObject::~CImageObject()
  15. {
  16. if( m_hDib ) ::GlobalFree( m_hDib );
  17. if( m_pszFilename != NULL ) delete [] m_pszFilename;
  18. }
  19. void CImageObject::InitVars( BOOL bFlag )
  20. {
  21. m_nWidth = m_nHeight = m_nBits = m_nColors = m_nImageType = 0;
  22. m_nX = m_nY = 0;
  23. m_nLastError = 0;
  24. m_hDib = NULL;
  25. m_nPaletteCreationType = FIXED_PALETTE;
  26. if( !bFlag ){
  27. m_pszFilename = NULL;
  28. m_pLogPal = NULL;
  29. }
  30. m_nQuality = 50;
  31. }
  32. BOOL CImageObject::Load( const char *pszFilename, CDC *pDC, int nX, int nY )
  33. {
  34. m_nImageType = FileType( pszFilename );
  35. if( m_nImageType == 0 ){
  36. m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
  37. return( FALSE );
  38. }
  39. KillImage();
  40. m_pszFilename = new char [strlen(pszFilename)+1];
  41. if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
  42. switch( m_nImageType ){
  43. case IMAGETYPE_BMP:
  44. m_hDib = ::LoadBMP( pszFilename );
  45. if( m_hDib == NULL ){
  46. m_nLastError = ::GetLastPicLibError();
  47. return( FALSE );
  48. }
  49. break;
  50. case IMAGETYPE_GIF:
  51. m_hDib = ::LoadGIF( pszFilename );
  52. if( m_hDib == NULL ){
  53. m_nLastError = ::GetLastPicLibError();
  54. return( FALSE );
  55. }
  56. break;
  57. case IMAGETYPE_JPG:
  58. m_hDib = ::LoadJPG( pszFilename );
  59. if( m_hDib == NULL ){
  60. m_nLastError = ::GetLastPicLibError();
  61. return( FALSE );
  62. }
  63. break;
  64. case IMAGETYPE_PCX:
  65. m_hDib = ::LoadPCX( pszFilename );
  66. if( m_hDib == NULL ){
  67. m_nLastError = ::GetLastPicLibError();
  68. return( FALSE );
  69. }
  70. break;
  71. case IMAGETYPE_TGA:
  72. m_hDib = ::LoadTGA( pszFilename );
  73. if( m_hDib == NULL ){
  74. m_nLastError = ::GetLastPicLibError();
  75. return( FALSE );
  76. }
  77. break;
  78. case IMAGETYPE_TIF:
  79. m_hDib = ::LoadTIF( pszFilename );
  80. if( m_hDib == NULL ){
  81. m_nLastError = ::GetLastPicLibError();
  82. return( FALSE );
  83. }
  84. break;
  85. }
  86. ProcessImageHeader();
  87. ProcessPalette();
  88. if( pDC != NULL ) Draw( pDC, nX, nY );
  89. return( TRUE );
  90. }
  91. BOOL CImageObject::GetImageInfo( const char *pszFilename, int *pnWidth,
  92. int *pnHeight, int *pnPlanes, int *pnBitsPerPixel, int *pnNumColors )
  93. {
  94. int nImageType;
  95. nImageType = FileType( pszFilename );
  96. if( nImageType == 0 ){
  97. m_nLastError = IMAGELIB_UNSUPPORTED_FILETYPE;
  98. return( FALSE );
  99. }
  100. switch( nImageType ){
  101. case IMAGETYPE_BMP:
  102. return( ::GetBMPInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  103. case IMAGETYPE_GIF:
  104. return( ::GetGIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  105. case IMAGETYPE_JPG:
  106. return( ::GetJPGInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  107. case IMAGETYPE_PCX:
  108. return( ::GetPCXInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  109. case IMAGETYPE_TGA:
  110. return( ::GetTGAInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  111. case IMAGETYPE_TIF:
  112. return( ::GetTIFInfo( pszFilename, pnWidth, pnHeight, pnPlanes, pnBitsPerPixel, pnNumColors ) );
  113. }
  114. return( FALSE );
  115. }
  116. int CImageObject::GetLastError( void )
  117. {
  118. return( m_nLastError );
  119. }
  120. BOOL CImageObject::Save( const char *pszFilename, int nType )
  121. {
  122. if( nType == -1 ) nType = ExtensionIndex( pszFilename );
  123. if( nType < IMAGETYPE_FIRSTTYPE || nType > IMAGETYPE_LASTTYPE ) return( FALSE );
  124. m_nImageType = nType;
  125. delete [] m_pszFilename;
  126. m_pszFilename = new char [strlen(pszFilename)+1];
  127. if( m_pszFilename != NULL ) strcpy( m_pszFilename, pszFilename );
  128. switch( m_nImageType ){
  129. case IMAGETYPE_BMP:
  130. return( ::SaveBMP( pszFilename, m_hDib ) );
  131. break;
  132. case IMAGETYPE_GIF:
  133. return( ::SaveGIF( pszFilename, m_hDib ) );
  134. break;
  135. case IMAGETYPE_JPG:
  136. return( ::SaveJPG( pszFilename, m_hDib, m_nQuality ) );
  137. break;
  138. case IMAGETYPE_PCX:
  139. return( ::SavePCX( pszFilename, m_hDib ) );
  140. break;
  141. case IMAGETYPE_TGA:
  142. return( ::SaveTGA( pszFilename, m_hDib ) );
  143. break;
  144. case IMAGETYPE_TIF:
  145. return( ::SaveTIF( pszFilename, m_hDib ) );
  146. break;
  147. }
  148. return( TRUE );
  149. }
  150. int CImageObject::ExtensionIndex( const char *pszFilename )
  151. {
  152. int Index = 0;
  153. char *pszExtension;
  154. pszExtension = (char *) &pszFilename[strlen(pszFilename)-4];
  155. while( szExtensions[Index][0] ){
  156. if( !stricmp( pszExtension, szExtensions[Index] ) ) return( Index + 1 );
  157. Index++;
  158. }
  159. return( -1 );
  160. }
  161. int CImageObject::GetWidth( void )
  162. {
  163. return( m_nWidth );
  164. }
  165. int CImageObject::GetHeight( void )
  166. {
  167. return( m_nHeight );
  168. }
  169. int CImageObject::GetNumBits( void )
  170. {
  171. return( m_nBits );
  172. }
  173. int CImageObject::GetNumColors( void )
  174. {
  175. return( m_nColors );
  176. }
  177. BOOL CImageObject::GetPaletteData( RGBQUAD *pRGBPalette )
  178. {
  179. m_nLastError = IMAGELIB_HDIB_NULL;
  180. if( m_hDib == NULL ) return( FALSE );
  181. char *pTemp;
  182. pTemp = (char *) ::GlobalLock( m_hDib );
  183. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  184. if( pTemp == NULL ) return( FALSE );
  185. memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], m_nPaletteBytes );
  186. m_nLastError = IMAGELIB_SUCCESS;
  187. ::GlobalUnlock( m_hDib );
  188. return( TRUE );
  189. }
  190. RGBQUAD *CImageObject::GetPaletteData( void )
  191. {
  192. m_nLastError = IMAGELIB_HDIB_NULL;
  193. if( m_hDib == NULL ) return( NULL );
  194. m_nLastError = IMAGELIB_NO_PALETTE_FOR_HIGH_COLOR;
  195. if( m_nColors <= 0 || m_nColors > 256 ) return( NULL );
  196. RGBQUAD *pRGBPalette;
  197. pRGBPalette = new RGBQUAD [m_nColors];
  198. if( pRGBPalette == NULL ){
  199. m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
  200. return( NULL );
  201. }
  202. char *pTemp;
  203. pTemp = (char *) ::GlobalLock( m_hDib );
  204. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  205. if( pTemp == NULL ){
  206. delete [] pRGBPalette;
  207. return( NULL );
  208. }
  209. memcpy( pRGBPalette, &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], m_nColors * sizeof( RGBQUAD ) );
  210. m_nLastError = IMAGELIB_SUCCESS;
  211. ::GlobalUnlock( m_hDib );
  212. return( pRGBPalette );
  213. }
  214. int CImageObject::GetImageType( const char *pFilename )
  215. {
  216. return( ::FileType( pFilename ) );
  217. }
  218. int CImageObject::GetImageType( void )
  219. {
  220. return( m_nImageType );
  221. }
  222. BOOL CImageObject::Draw( CDC *pDC, int nX, int nY )
  223. {
  224. if( nX != -1 ) m_nX = nX;
  225. if( nY != -1 ) m_nY = nY;
  226. m_nLastError = IMAGELIB_HDIB_NULL;
  227. if( m_hDib == NULL ) return( FALSE );
  228. char *pTemp;
  229. pTemp = (char *) ::GlobalLock( m_hDib );
  230. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  231. if( pTemp == NULL ) return( NULL );
  232. BITMAPINFOHEADER *pBIH;
  233. pBIH = (BITMAPINFOHEADER *) &pTemp[sizeof(BITMAPFILEHEADER)];
  234. int nRet = ::StretchDIBits( pDC->m_hDC, m_nX, m_nY, m_nWidth, m_nHeight, 0, 0, m_nWidth, m_nHeight, (const void FAR *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nPaletteBytes], (BITMAPINFO *) pBIH, DIB_RGB_COLORS, SRCCOPY );
  235. ::GlobalUnlock( m_hDib );
  236. m_nLastError = IMAGELIB_STRETCHDIBITS_ERROR;
  237. if( nRet != m_nHeight ) return( FALSE );
  238. m_nLastError = IMAGELIB_SUCCESS;
  239. return( TRUE );
  240. }
  241. LOGPALETTE *CImageObject::CreateLogPalette( RGBQUAD *pPalette, int nNumColors )
  242. {
  243. LOGPALETTE *pLogPal;
  244. int i;
  245. if( pPalette == NULL ) return( NULL );
  246. pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+nNumColors*sizeof(PALETTEENTRY)];
  247. if( pLogPal == NULL ) return( NULL );
  248. pLogPal->palVersion = 0x300;
  249. pLogPal->palNumEntries = (unsigned short) nNumColors;
  250. for( i=0; i<nNumColors; i++ ){
  251. pLogPal->palPalEntry[i].peRed = pPalette[i].rgbRed;
  252. pLogPal->palPalEntry[i].peGreen = pPalette[i].rgbGreen;
  253. pLogPal->palPalEntry[i].peBlue = pPalette[i].rgbBlue;
  254. pLogPal->palPalEntry[i].peFlags = 0;
  255. }
  256. return( pLogPal );
  257. }
  258. void CImageObject::ProcessImageHeader( void )
  259. {
  260. m_nLastError = IMAGELIB_HDIB_NULL;
  261. if( m_hDib == NULL ) return;
  262. char *pTemp;
  263. BITMAPINFOHEADER *pBIH;
  264. pTemp = (char *) ::GlobalLock( m_hDib );
  265. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  266. if( pTemp == NULL ) return;
  267. pBIH = (BITMAPINFOHEADER *) &pTemp[sizeof(BITMAPFILEHEADER)];
  268. m_nWidth = pBIH->biWidth;
  269. m_nHeight = pBIH->biHeight;
  270. m_nPlanes = pBIH->biPlanes;
  271. m_nBits = pBIH->biBitCount;
  272. m_nColors = 1 << m_nBits;
  273. if( m_nPlanes > 1 ) m_nColors <<= ( m_nPlanes - 1 );
  274. if( m_nBits >= 16 ) m_nColors = 0;
  275. ::GlobalUnlock( m_hDib );
  276. m_nLastError = IMAGELIB_SUCCESS;
  277. }
  278. void CImageObject::ProcessPalette( void )
  279. {
  280. m_nLastError = IMAGELIB_HDIB_NULL;
  281. if( m_hDib == NULL ) return;
  282. CWindowDC WindowDC( NULL );
  283. m_nScreenPlanes = WindowDC.GetDeviceCaps( PLANES );
  284. m_nScreenBits = WindowDC.GetDeviceCaps( BITSPIXEL );
  285. m_nPaletteBytes = 0;
  286. m_Palette.DeleteObject();
  287. if( m_nBits <= 8 ) m_nPaletteBytes = m_nColors * sizeof( RGBQUAD );
  288. if( m_nScreenBits >= 16 ) return;
  289. char *pTemp;
  290. pTemp = (char *) ::GlobalLock( m_hDib );
  291. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  292. if( pTemp == NULL ) return;
  293. if( m_nBits <= 8 ){
  294. RGBQUAD *pRGBPalette;
  295. pRGBPalette = (RGBQUAD *) &pTemp[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  296. LOGPALETTE *pPalette;
  297. pPalette = CreateLogPalette( pRGBPalette, m_nColors );
  298. if( pPalette == NULL ){
  299. m_nLastError = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
  300. goto ProcessPaletteExit;
  301. }
  302. m_Palette.CreatePalette( pPalette );
  303. delete [] pPalette;
  304. }
  305. m_nLastError = IMAGELIB_SUCCESS;
  306. ProcessPaletteExit:
  307. ::GlobalUnlock( m_hDib );
  308. }
  309. void CImageObject::KillImage( void )
  310. {
  311. if( m_hDib ) ::GlobalFree( m_hDib );
  312. m_hDib = NULL;
  313. if( m_pLogPal != NULL ) delete [] m_pLogPal;
  314. m_pLogPal = NULL;
  315. if( m_pszFilename != NULL ) delete [] m_pszFilename;
  316. m_pszFilename = NULL;
  317. m_Palette.DeleteObject();
  318. }
  319. BOOL CImageObject::SetPalette( CDC *pDC )
  320. {
  321. m_nLastError = IMAGELIB_HDIB_NULL;
  322. if( m_hDib == NULL ) return( FALSE );
  323. pDC->SelectPalette( &m_Palette, FALSE );
  324. pDC->RealizePalette();
  325. m_nLastError = IMAGELIB_SUCCESS;
  326. return( TRUE );
  327. }
  328. BOOL CImageObject::IsLoaded( void )
  329. {
  330. return( m_hDib != NULL );
  331. }
  332. void *CImageObject::GetDIBPointer( int *nWidthBytes, int nNewBits, int *nNewWidthBytes, int nNewWidth )
  333. {
  334. m_nLastError = IMAGELIB_HDIB_NULL;
  335. if( m_hDib == NULL ) return( NULL );
  336. void *pTemp;
  337. pTemp = ::GlobalLock( m_hDib );
  338. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  339. if( pTemp == NULL ) return( NULL );
  340. if( nWidthBytes != NULL ) *nWidthBytes = WidthBytes( m_nBits, m_nWidth );
  341. if( nNewWidthBytes != NULL ){
  342. if( nNewWidth == -1 ) nNewWidth = m_nWidth;
  343. *nNewWidthBytes = WidthBytes( nNewBits, nNewWidth );
  344. }
  345. return( pTemp );
  346. }
  347. int CImageObject::WidthBytes( int nBits, int nWidth )
  348. {
  349. int nWidthBytes;
  350. nWidthBytes = nWidth;
  351. if( nBits == 1 ) nWidthBytes = ( nWidth + 7 ) / 8;
  352. else if( nBits == 4 ) nWidthBytes = ( nWidth + 1 ) / 2;
  353. else if( nBits == 16 ) nWidthBytes = nWidth * 2;
  354. else if( nBits == 24 ) nWidthBytes = nWidth * 3;
  355. else if( nBits == 32 ) nWidthBytes = nWidth * 4;
  356. while( ( nWidthBytes & 3 ) != 0 ) nWidthBytes++;
  357. return( nWidthBytes );
  358. }
  359. BOOL CImageObject::Crop( int nX1, int nY1, int nX2, int nY2 )
  360. {
  361. NormalizeCoordinates( &nX1, &nY1, &nX2, &nY2 );
  362. if( nX2 - nX1 + 1 == m_nWidth && nY2 - nY1 + 1 == m_nHeight ) return( TRUE );
  363. unsigned char *pOldBuffer, *pNewBuffer;
  364. HGLOBAL hNewMemory;
  365. DWORD dwNewMemorySize;
  366. BITMAPFILEHEADER *pOldBFH, *pNewBFH;
  367. BITMAPINFOHEADER *pOldBIH, *pNewBIH;
  368. RGBQUAD *pOldPalette, *pNewPalette;
  369. unsigned char *pOldBits, *pNewBits, *pOldTemp, *pNewTemp;
  370. int nOldWidthBytes, nNewWidthBytes;
  371. int nNumColors, y, nPixelBytes;
  372. pOldBuffer = (unsigned char *) GetDIBPointer( &nOldWidthBytes, m_nBits, &nNewWidthBytes, nX2 - nX1 + 1 );
  373. if( pOldBuffer == NULL ) return( FALSE );
  374. pOldBFH = (BITMAPFILEHEADER *) pOldBuffer;
  375. pOldBIH = (BITMAPINFOHEADER *) &pOldBuffer[sizeof(BITMAPFILEHEADER)];
  376. nNumColors = m_nColors;
  377. pOldPalette = (RGBQUAD *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  378. pOldBits = (unsigned char *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  379. dwNewMemorySize = (DWORD) nNumColors * sizeof( RGBQUAD ) + sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewWidthBytes * ( nY2 - nY1 + 1 );
  380. m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
  381. hNewMemory = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwNewMemorySize );
  382. if( hNewMemory == NULL ){
  383. ::GlobalUnlock( m_hDib );
  384. return( FALSE );
  385. }
  386. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  387. pNewBuffer = (unsigned char *) ::GlobalLock( hNewMemory );
  388. if( pNewBuffer == NULL ){
  389. ::GlobalFree( hNewMemory );
  390. ::GlobalUnlock( m_hDib );
  391. return( FALSE );
  392. }
  393. pNewBFH = (BITMAPFILEHEADER *) pNewBuffer;
  394. pNewBIH = (BITMAPINFOHEADER *) &pNewBuffer[sizeof(BITMAPFILEHEADER)];
  395. pNewPalette = (RGBQUAD *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  396. pNewBits = (unsigned char *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  397. *pNewBFH = *pOldBFH;
  398. *pNewBIH = *pOldBIH;
  399. pNewBIH->biSizeImage = 0;
  400. pNewBIH->biWidth = nX2 - nX1 + 1;
  401. pNewBIH->biHeight = nY2 - nY1 + 1;
  402. if( nNumColors != 0 ) memcpy( pNewPalette, pOldPalette, nNumColors * sizeof( RGBQUAD ) );
  403. nPixelBytes = 1;
  404. if( pOldBIH->biBitCount == 16 ) nPixelBytes = 2;
  405. else if( pOldBIH->biBitCount == 24 ) nPixelBytes = 3;
  406. else if( pOldBIH->biBitCount == 32 ) nPixelBytes = 4;
  407. for( y=0; y<pNewBIH->biHeight; y++ ){
  408. pOldTemp = pOldBits;
  409. pOldTemp += ( ( pOldBIH->biHeight - 1 - ( y + nY1 ) ) * nOldWidthBytes );
  410. pOldTemp += ( nPixelBytes * nX1 );
  411. pNewTemp = pNewBits;
  412. pNewTemp += ( ( pNewBIH->biHeight - 1 - y ) * nNewWidthBytes );
  413. memcpy( pNewTemp, pOldTemp, nNewWidthBytes );
  414. pNewBIH->biSizeImage += nNewWidthBytes;
  415. }
  416. m_nWidth = pNewBIH->biWidth;
  417. m_nHeight = pNewBIH->biHeight;
  418. ::GlobalUnlock( m_hDib );
  419. ::GlobalUnlock( hNewMemory );
  420. ::GlobalFree( m_hDib );
  421. m_hDib = hNewMemory;
  422. m_nLastError = IMAGELIB_SUCCESS;
  423. return( TRUE );
  424. }
  425. void CImageObject::NormalizeCoordinates( int *nX1, int *nY1, int *nX2, int *nY2, BOOL *bCompleteImage, BOOL *bLessThanHalf )
  426. {
  427. if( *nX1 == -1 ) *nX1 = 0;
  428. if( *nY1 == -1 ) *nY1 = 0;
  429. if( *nX2 == -1 ) *nX2 = m_nWidth - 1;
  430. if( *nY2 == -1 ) *nY2 = m_nHeight - 1;
  431. if( *nX1 > *nX2 ){
  432. int nTemp;
  433. nTemp = *nX1;
  434. *nX1 = *nX2;
  435. *nX2 = nTemp;
  436. }
  437. if( *nY1 > *nY2 ){
  438. int nTemp;
  439. nTemp = *nY1;
  440. *nY1 = *nY2;
  441. *nY2 = nTemp;
  442. }
  443. if( *nX1 < 0 ) *nX1 = 0;
  444. if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
  445. if( *nX2 < 0 ) *nX2 = 0;
  446. if( *nX2 > m_nWidth - 1 ) *nX2 = m_nWidth - 1;
  447. if( *nY1 < 0 ) *nY1 = 0;
  448. if( *nY1 > m_nHeight - 1 ) *nY1 = m_nHeight - 1;
  449. if( *nY2 < 0 ) *nY2 = 0;
  450. if( *nY2 > m_nHeight - 1 ) *nY2 = m_nHeight - 1;
  451. if( bCompleteImage != NULL ) *bCompleteImage = TRUE;
  452. if( bLessThanHalf != NULL ) *bLessThanHalf = FALSE;
  453. if( *nX1 > 0 || *nY1 > 0 || *nX2 < m_nWidth - 1 || *nY2 < m_nHeight - 1 ){
  454. if( bCompleteImage != NULL ) *bCompleteImage = FALSE;
  455. DWORD dwTotalPixels, dwThesePixels;
  456. dwTotalPixels = (DWORD) m_nWidth * m_nHeight;
  457. dwThesePixels = (DWORD) ( (*nX2) - (*nX1) + 1 ) * (DWORD) ( (*nY2) - (*nY1) + 1 );
  458. if( bLessThanHalf != NULL && dwThesePixels <= dwTotalPixels / 2 ) *bLessThanHalf = TRUE;
  459. }
  460. }
  461. BOOL CImageObject::Stretch( int nNewWidth, int nNewHeight )
  462. {
  463. if( nNewWidth == m_nWidth && nNewHeight == m_nHeight ) return( TRUE );
  464. unsigned char *pOldBuffer, *pNewBuffer, *pOldTemp, *pNewTemp;
  465. HGLOBAL hNewMemory;
  466. DWORD dwNewMemorySize;
  467. BITMAPFILEHEADER *pOldBFH, *pNewBFH;
  468. BITMAPINFOHEADER *pOldBIH, *pNewBIH;
  469. RGBQUAD *pOldPalette, *pNewPalette;
  470. unsigned char *pOldBits, *pNewBits;
  471. int nOldWidthBytes, nNewWidthBytes;
  472. int nNumColors;
  473. int x, y, xx, yy;
  474. unsigned char Data;
  475. pOldBuffer = (unsigned char *) GetDIBPointer( &nOldWidthBytes, m_nBits, &nNewWidthBytes, nNewWidth );
  476. if( pOldBuffer == NULL ) return( FALSE );
  477. pOldBFH = (BITMAPFILEHEADER *) pOldBuffer;
  478. pOldBIH = (BITMAPINFOHEADER *) &pOldBuffer[sizeof(BITMAPFILEHEADER)];
  479. nNumColors = m_nColors;
  480. pOldPalette = (RGBQUAD *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  481. pOldBits = (unsigned char *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  482. dwNewMemorySize = (DWORD) nNumColors * sizeof( RGBQUAD ) + sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewWidthBytes * nNewHeight;
  483. m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
  484. hNewMemory = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwNewMemorySize );
  485. if( hNewMemory == NULL ){
  486. ::GlobalUnlock( m_hDib );
  487. return( FALSE );
  488. }
  489. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  490. pNewBuffer = (unsigned char *) ::GlobalLock( hNewMemory );
  491. if( pNewBuffer == NULL ){
  492. ::GlobalFree( hNewMemory );
  493. ::GlobalUnlock( m_hDib );
  494. return( FALSE );
  495. }
  496. pNewBFH = (BITMAPFILEHEADER *) pNewBuffer;
  497. pNewBIH = (BITMAPINFOHEADER *) &pNewBuffer[sizeof(BITMAPFILEHEADER)];
  498. pNewPalette = (RGBQUAD *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  499. pNewBits = (unsigned char *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  500. *pNewBFH = *pOldBFH;
  501. *pNewBIH = *pOldBIH;
  502. pNewBIH->biSizeImage = nNewWidthBytes * nNewHeight;
  503. pNewBIH->biWidth = nNewWidth;
  504. pNewBIH->biHeight = nNewHeight;
  505. if( nNumColors != 0 ) memcpy( pNewPalette, pOldPalette, nNumColors * sizeof( RGBQUAD ) );
  506. m_nWidth = nNewWidth;
  507. m_nHeight = nNewHeight;
  508. switch( m_nBits ){
  509. case 1:
  510. for( y=0; y<nNewHeight; y++ ){
  511. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  512. pOldTemp = pOldBits;
  513. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  514. pNewTemp = pNewBits;
  515. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  516. for( x=0; x<nNewWidth; x++ ){
  517. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  518. Data = pOldTemp[xx/8];
  519. Data >>= ( 7 - ( xx & 7 ) );
  520. Data &= 0x01;
  521. Data <<= ( 7 - ( x & 7 ) );
  522. pNewTemp[x/8] |= Data;
  523. }
  524. }
  525. break;
  526. case 4:
  527. for( y=0; y<nNewHeight; y++ ){
  528. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  529. pOldTemp = pOldBits;
  530. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  531. pNewTemp = pNewBits;
  532. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  533. for( x=0; x<nNewWidth; x++ ){
  534. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  535. Data = pOldTemp[xx/2];
  536. if( !( xx & 1 ) ) Data >>= 4;
  537. else Data &= 0x0f;
  538. if( !( x & 1 ) ) Data <<= 4;
  539. pNewTemp[x/2] |= Data;
  540. }
  541. }
  542. break;
  543. case 8:
  544. for( y=0; y<nNewHeight; y++ ){
  545. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  546. pOldTemp = pOldBits;
  547. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  548. pNewTemp = pNewBits;
  549. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  550. for( x=0; x<nNewWidth; x++ ){
  551. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  552. pNewTemp[x] = pOldTemp[xx];
  553. }
  554. }
  555. break;
  556. case 16:
  557. for( y=0; y<nNewHeight; y++ ){
  558. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  559. pOldTemp = pOldBits;
  560. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  561. pNewTemp = pNewBits;
  562. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  563. for( x=0; x<nNewWidth; x++ ){
  564. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  565. pNewTemp[x*2] = pOldTemp[xx*2];
  566. pNewTemp[x*2+1] = pOldTemp[xx*2+1];
  567. }
  568. }
  569. break;
  570. case 24:
  571. for( y=0; y<nNewHeight; y++ ){
  572. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  573. pOldTemp = pOldBits;
  574. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  575. pNewTemp = pNewBits;
  576. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  577. for( x=0; x<nNewWidth; x++ ){
  578. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  579. pNewTemp[x*3] = pOldTemp[xx*3];
  580. pNewTemp[x*3+1] = pOldTemp[xx*3+1];
  581. pNewTemp[x*3+2] = pOldTemp[xx*3+2];
  582. }
  583. }
  584. break;
  585. case 32:
  586. for( y=0; y<nNewHeight; y++ ){
  587. yy = ( pOldBIH->biHeight * y ) / nNewHeight;
  588. pOldTemp = pOldBits;
  589. pOldTemp += ( ( pOldBIH->biHeight - 1 - yy ) * nOldWidthBytes );
  590. pNewTemp = pNewBits;
  591. pNewTemp += ( ( nNewHeight - 1 - y ) * nNewWidthBytes );
  592. for( x=0; x<nNewWidth; x++ ){
  593. xx = ( pOldBIH->biWidth * x ) / nNewWidth;
  594. pNewTemp[x*4] = pOldTemp[xx*4];
  595. pNewTemp[x*4+1] = pOldTemp[xx*4+1];
  596. pNewTemp[x*4+2] = pOldTemp[xx*4+2];
  597. pNewTemp[x*4+3] = pOldTemp[xx*4+3];
  598. }
  599. }
  600. break;
  601. }
  602. ::GlobalUnlock( m_hDib );
  603. ::GlobalUnlock( hNewMemory );
  604. ::GlobalFree( m_hDib );
  605. m_hDib = hNewMemory;
  606. m_nLastError = IMAGELIB_SUCCESS;
  607. return( TRUE );
  608. }
  609. void CImageObject::operator= (const CImageObject &ImageObject)
  610. {
  611. KillImage();
  612. m_nWidth = ImageObject.m_nWidth;
  613. m_nHeight = ImageObject.m_nHeight;
  614. m_nPlanes = ImageObject.m_nPlanes;
  615. m_nBits = ImageObject.m_nBits;
  616. m_nColors = ImageObject.m_nColors;
  617. m_nImageType = ImageObject.m_nImageType;
  618. m_nX = ImageObject.m_nX;
  619. m_nY = ImageObject.m_nY;
  620. m_nLastError = ImageObject.m_nLastError;
  621. m_nScreenPlanes = ImageObject.m_nScreenPlanes;
  622. m_nScreenBits = ImageObject.m_nScreenBits;
  623. m_nPaletteBytes = ImageObject.m_nPaletteBytes;
  624. m_nQuality = ImageObject.m_nQuality;
  625. m_nPaletteCreationType = ImageObject.m_nPaletteCreationType;
  626. int nNumColors = m_nColors;
  627. int nWidthBytes = WidthBytes( m_nBits, m_nWidth );
  628. if( ImageObject.m_hDib != NULL ){
  629. DWORD dwSize = ::GlobalSize( ImageObject.m_hDib );
  630. char *pData = (char *) ::GlobalLock( ImageObject.m_hDib );
  631. if( pData != NULL ){
  632. HGLOBAL hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
  633. if( hGlobal != NULL ){
  634. char *pDestData = (char *) ::GlobalLock( hGlobal );
  635. if( pDestData != NULL ){
  636. memcpy( pDestData, pData, dwSize );
  637. if( nNumColors != 0 ) CreatePaletteFromDIB( (RGBQUAD *) &pData[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)], nNumColors );
  638. else if( ImageObject.m_pLogPal != NULL ){
  639. m_pLogPal = (LOGPALETTE *) new char [sizeof(LOGPALETTE)+ImageObject.m_pLogPal->palNumEntries*sizeof(PALETTEENTRY)];
  640. if( m_pLogPal != NULL ){
  641. for( int i=0; i<ImageObject.m_pLogPal->palNumEntries; i++ ) m_pLogPal[i] = ImageObject.m_pLogPal[i];
  642. m_Palette.CreatePalette( m_pLogPal );
  643. }
  644. }
  645. ::GlobalUnlock( hGlobal );
  646. m_hDib = hGlobal;
  647. }
  648. else ::GlobalFree( hGlobal );
  649. }
  650. ::GlobalUnlock( ImageObject.m_hDib );
  651. }
  652. }
  653. if( ImageObject.m_pszFilename != NULL ){
  654. m_pszFilename = new char [strlen(ImageObject.m_pszFilename)+1];
  655. strcpy( m_pszFilename, ImageObject.m_pszFilename );
  656. }
  657. }
  658. void CImageObject::CreatePaletteFromDIB( RGBQUAD *pRGBPalette, int nNumColors )
  659. {
  660. if( pRGBPalette != NULL ){
  661. LOGPALETTE *pPalette;
  662. pPalette = CreateLogPalette( pRGBPalette, nNumColors );
  663. if( pPalette != NULL ){
  664. m_Palette.CreatePalette( pPalette );
  665. delete [] pPalette;
  666. }
  667. else m_nLastError = IMAGELIB_LOGICAL_PALETTE_CREATION_ERROR;
  668. }
  669. }
  670. int CImageObject::GetNearestIndex( unsigned char ucRed, unsigned char ucGreen, unsigned char ucBlue, RGBQUAD *pRGBPalette, int nNumColors )
  671. {
  672. int i, Index = 0;
  673. DWORD NewDiff, Diff = 100000L;
  674. DWORD Red, Green, Blue;
  675. for( i=0; i<nNumColors; i++ ){
  676. if( ucRed > pRGBPalette[i].rgbRed ) Red = (DWORD) ( pRGBPalette[i].rgbRed - ucRed );
  677. else Red = (DWORD) ( ucRed - pRGBPalette[i].rgbRed );
  678. if( ucGreen > pRGBPalette[i].rgbGreen ) Green = (DWORD) ( pRGBPalette[i].rgbGreen - ucGreen );
  679. else Green = (DWORD) ( ucGreen - pRGBPalette[i].rgbGreen );
  680. if( ucBlue > pRGBPalette[i].rgbBlue ) Blue = (DWORD) ( pRGBPalette[i].rgbBlue - ucBlue );
  681. else Blue = (DWORD) ( ucBlue - pRGBPalette[i].rgbBlue );
  682. NewDiff = ( Red * Red ) + ( Green * Green ) + ( Blue * Blue );
  683. if( NewDiff < Diff ){
  684. if( NewDiff <= 1 ) return( i );
  685. Diff = NewDiff;
  686. Index = i;
  687. }
  688. }
  689. return( Index );
  690. }
  691. BOOL CImageObject::Rotate( int nDegrees )
  692. {
  693. m_nLastError = IMAGELIB_HDIB_NULL;
  694. if( m_hDib == NULL ) return( FALSE );
  695. m_nLastError = IMAGELIB_ROTATE_ERROR;
  696. switch( nDegrees ){
  697. case 90:
  698. if( !RotateIt( nDegrees ) ) return( FALSE );
  699. break;
  700. case 180:
  701. if( !Invert() ) return( FALSE );
  702. if( !Reverse() ) return( FALSE );
  703. break;
  704. case 270:
  705. if( !RotateIt( nDegrees ) ) return( FALSE );
  706. break;
  707. default:
  708. m_nLastError = IMAGELIB_ROTATION_VALUE_ERROR;
  709. return( FALSE );
  710. }
  711. m_nLastError = IMAGELIB_SUCCESS;
  712. return( TRUE );
  713. }
  714. BOOL CImageObject::RotateIt( int nDegrees )
  715. {
  716. int nNewWidth, nNewHeight;
  717. nNewWidth = m_nHeight;
  718. nNewHeight = m_nWidth;
  719. unsigned char *pOldBuffer, *pNewBuffer;
  720. HGLOBAL hNewMemory;
  721. DWORD dwNewMemorySize;
  722. BITMAPFILEHEADER *pOldBFH, *pNewBFH;
  723. BITMAPINFOHEADER *pOldBIH, *pNewBIH;
  724. RGBQUAD *pOldPalette, *pNewPalette;
  725. unsigned char *pOldBits, *pNewBits;
  726. int nOldWidthBytes, nNewWidthBytes;
  727. int nNumColors;
  728. pOldBuffer = (unsigned char *) GetDIBPointer( &nOldWidthBytes, m_nBits, &nNewWidthBytes, nNewWidth );
  729. if( pOldBuffer == NULL ) return( FALSE );
  730. pOldBFH = (BITMAPFILEHEADER *) pOldBuffer;
  731. pOldBIH = (BITMAPINFOHEADER *) &pOldBuffer[sizeof(BITMAPFILEHEADER)];
  732. nNumColors = m_nColors;
  733. pOldPalette = (RGBQUAD *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  734. pOldBits = (unsigned char *) &pOldBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  735. dwNewMemorySize = (DWORD) nNumColors * sizeof( RGBQUAD ) + sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNewWidthBytes * nNewHeight;
  736. m_nLastError = IMAGELIB_MEMORY_ALLOCATION_ERROR;
  737. hNewMemory = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwNewMemorySize );
  738. if( hNewMemory == NULL ){
  739. ::GlobalUnlock( m_hDib );
  740. return( FALSE );
  741. }
  742. m_nLastError = IMAGELIB_MEMORY_LOCK_ERROR;
  743. pNewBuffer = (unsigned char *) ::GlobalLock( hNewMemory );
  744. if( pNewBuffer == NULL ){
  745. ::GlobalFree( hNewMemory );
  746. ::GlobalUnlock( m_hDib );
  747. return( FALSE );
  748. }
  749. pNewBFH = (BITMAPFILEHEADER *) pNewBuffer;
  750. pNewBIH = (BITMAPINFOHEADER *) &pNewBuffer[sizeof(BITMAPFILEHEADER)];
  751. pNewPalette = (RGBQUAD *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  752. pNewBits = (unsigned char *) &pNewBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  753. *pNewBFH = *pOldBFH;
  754. *pNewBIH = *pOldBIH;
  755. pNewBIH->biSizeImage = nNewWidthBytes * nNewHeight;
  756. pNewBIH->biWidth = nNewWidth;
  757. pNewBIH->biHeight = nNewHeight;
  758. if( nNumColors != 0 ) memcpy( pNewPalette, pOldPalette, nNumColors * sizeof( RGBQUAD ) );
  759. m_nWidth = nNewWidth;
  760. m_nHeight = nNewHeight;
  761. if( nDegrees == 90 ) Rotate90( pNewBits, pOldBits );
  762. else Rotate270( pNewBits, pOldBits );
  763. ::GlobalUnlock( m_hDib );
  764. ::GlobalUnlock( hNewMemory );
  765. ::GlobalFree( m_hDib );
  766. m_hDib = hNewMemory;
  767. m_nLastError = IMAGELIB_SUCCESS;
  768. return( TRUE );
  769. }
  770. void CImageObject::Rotate90( unsigned char *pNewBits, unsigned char *pOldBits )
  771. {
  772. int nOldWidth, nOldHeight, nOldWidthBytes, nNewWidthBytes;
  773. nOldWidth = m_nHeight;
  774. nOldHeight = m_nWidth;
  775. unsigned char *pTemp;
  776. unsigned char Data, Data1, Data2, Data3, Data4, Mask, Shift;
  777. int x, y;
  778. switch( m_nBits ){
  779. case 1:
  780. nOldWidthBytes = ( nOldWidth + 7 ) / 8;
  781. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  782. nNewWidthBytes = ( m_nWidth + 7 ) / 8;
  783. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  784. for( y=0; y<m_nHeight; y++ ){
  785. pTemp = pNewBits;
  786. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  787. for( x=0; x<m_nWidth; x++ ){
  788. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+(y/8)];
  789. Data >>= ( 7 - ( y & 7 ) );
  790. Data &= 0x01;
  791. Shift = ( 7 - ( ( m_nWidth - 1 - x ) & 7 ) );
  792. Mask = 1 << Shift;
  793. Data <<= Shift;
  794. pTemp[(m_nWidth-1-x)/8] &= ( Mask ^ 0xff );
  795. pTemp[(m_nWidth-1-x)/8] |= Data;
  796. }
  797. }
  798. break;
  799. case 4:
  800. nOldWidthBytes = ( nOldWidth + 1 ) / 2;
  801. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  802. nNewWidthBytes = ( m_nWidth + 1 ) / 2;
  803. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  804. for( y=0; y<m_nHeight; y++ ){
  805. pTemp = pNewBits;
  806. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  807. for( x=0; x<m_nWidth; x++ ){
  808. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+(y/2)];
  809. if( !( y & 1 ) ) Data >>= 4;
  810. else Data &= 0x0f;
  811. if( ( x & 1 ) ){
  812. Data <<= 4;
  813. pTemp[(m_nWidth-1-x)/2] &= 0x0f;
  814. pTemp[(m_nWidth-1-x)/2] |= Data;
  815. }
  816. else{
  817. pTemp[(m_nWidth-1-x)/2] &= 0xf0;
  818. pTemp[(m_nWidth-1-x)/2] |= Data;
  819. }
  820. }
  821. }
  822. break;
  823. case 8:
  824. nOldWidthBytes = nOldWidth;
  825. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  826. nNewWidthBytes = m_nWidth;
  827. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  828. for( y=0; y<m_nHeight; y++ ){
  829. pTemp = pNewBits;
  830. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  831. for( x=0; x<m_nWidth; x++ ){
  832. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y];
  833. pTemp[m_nWidth-1-x] = Data;
  834. }
  835. }
  836. break;
  837. case 16:
  838. nOldWidthBytes = nOldWidth * 2;
  839. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  840. nNewWidthBytes = m_nWidth * 2;
  841. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  842. for( y=0; y<m_nHeight; y++ ){
  843. pTemp = pNewBits;
  844. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  845. for( x=0; x<m_nWidth; x++ ){
  846. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*2];
  847. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*2+1];
  848. pTemp[(m_nWidth-1-x)*2] = Data1;
  849. pTemp[(m_nWidth-1-x)*2+1] = Data2;
  850. }
  851. }
  852. break;
  853. case 24:
  854. nOldWidthBytes = nOldWidth * 3;
  855. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  856. nNewWidthBytes = m_nWidth * 3;
  857. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  858. for( y=0; y<m_nHeight; y++ ){
  859. pTemp = pNewBits;
  860. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  861. for( x=0; x<m_nWidth; x++ ){
  862. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*3];
  863. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*3+1];
  864. Data3 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*3+2];
  865. pTemp[(m_nWidth-1-x)*3] = Data1;
  866. pTemp[(m_nWidth-1-x)*3+1] = Data2;
  867. pTemp[(m_nWidth-1-x)*3+2] = Data3;
  868. }
  869. }
  870. break;
  871. case 32:
  872. nOldWidthBytes = nOldWidth * 4;
  873. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  874. nNewWidthBytes = m_nWidth * 4;
  875. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  876. for( y=0; y<m_nHeight; y++ ){
  877. pTemp = pNewBits;
  878. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  879. for( x=0; x<m_nWidth; x++ ){
  880. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*4];
  881. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*4+1];
  882. Data3 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*4+2];
  883. Data4 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+y*4+3];
  884. pTemp[(m_nWidth-1-x)*4] = Data1;
  885. pTemp[(m_nWidth-1-x)*4+1] = Data2;
  886. pTemp[(m_nWidth-1-x)*4+2] = Data3;
  887. pTemp[(m_nWidth-1-x)*4+3] = Data4;
  888. }
  889. }
  890. break;
  891. }
  892. }
  893. void CImageObject::Rotate270( unsigned char *pNewBits, unsigned char *pOldBits )
  894. {
  895. int nOldWidth, nOldHeight, nOldWidthBytes, nNewWidthBytes;
  896. nOldWidth = m_nHeight;
  897. nOldHeight = m_nWidth;
  898. unsigned char *pTemp;
  899. unsigned char Data, Data1, Data2, Data3, Data4, Mask, Shift;
  900. int x, y, yy;
  901. switch( m_nBits ){
  902. case 1:
  903. nOldWidthBytes = ( nOldWidth + 7 ) / 8;
  904. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  905. nNewWidthBytes = ( m_nWidth + 7 ) / 8;
  906. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  907. for( y=0; y<m_nHeight; y++ ){
  908. yy = m_nHeight - 1 - y;
  909. pTemp = pNewBits;
  910. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  911. for( x=0; x<m_nWidth; x++ ){
  912. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+(yy/8)];
  913. Data >>= ( 7 - ( yy & 7 ) );
  914. Data &= 0x01;
  915. Shift = ( 7 - ( x & 7 ) );
  916. Mask = 1 << Shift;
  917. Data <<= Shift;
  918. pTemp[x/8] &= ( Mask ^ 0xff );
  919. pTemp[x/8] |= Data;
  920. }
  921. }
  922. break;
  923. case 4:
  924. nOldWidthBytes = ( nOldWidth + 1 ) / 2;
  925. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  926. nNewWidthBytes = ( m_nWidth + 1 ) / 2;
  927. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  928. for( y=0; y<m_nHeight; y++ ){
  929. yy = m_nHeight - 1 - y;
  930. pTemp = pNewBits;
  931. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  932. for( x=0; x<m_nWidth; x++ ){
  933. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+(yy/2)];
  934. if( !( yy & 1 ) ) Data >>= 4;
  935. else Data &= 0x0f;
  936. if( !( x & 1 ) ){
  937. Data <<= 4;
  938. pTemp[x/2] &= 0x0f;
  939. pTemp[x/2] |= Data;
  940. }
  941. else{
  942. pTemp[x/2] &= 0xf0;
  943. pTemp[x/2] |= Data;
  944. }
  945. }
  946. }
  947. break;
  948. case 8:
  949. nOldWidthBytes = nOldWidth;
  950. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  951. nNewWidthBytes = m_nWidth;
  952. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  953. for( y=0; y<m_nHeight; y++ ){
  954. yy = m_nHeight - 1 - y;
  955. pTemp = pNewBits;
  956. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  957. for( x=0; x<m_nWidth; x++ ){
  958. Data = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy];
  959. pTemp[x] = Data;
  960. }
  961. }
  962. break;
  963. case 16:
  964. nOldWidthBytes = nOldWidth * 2;
  965. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  966. nNewWidthBytes = m_nWidth * 2;
  967. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  968. for( y=0; y<m_nHeight; y++ ){
  969. yy = m_nHeight - 1 - y;
  970. pTemp = pNewBits;
  971. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  972. for( x=0; x<m_nWidth; x++ ){
  973. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*2];
  974. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*2+1];
  975. pTemp[x*2] = Data1;
  976. pTemp[x*2+1] = Data2;
  977. }
  978. }
  979. break;
  980. case 24:
  981. nOldWidthBytes = nOldWidth * 3;
  982. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  983. nNewWidthBytes = m_nWidth * 3;
  984. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  985. for( y=0; y<m_nHeight; y++ ){
  986. yy = m_nHeight - 1 - y;
  987. pTemp = pNewBits;
  988. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  989. for( x=0; x<m_nWidth; x++ ){
  990. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*3];
  991. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*3+1];
  992. Data3 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*3+2];
  993. pTemp[x*3] = Data1;
  994. pTemp[x*3+1] = Data2;
  995. pTemp[x*3+2] = Data3;
  996. }
  997. }
  998. break;
  999. case 32:
  1000. nOldWidthBytes = nOldWidth * 4;
  1001. while( ( nOldWidthBytes & 3 ) != 0 ) nOldWidthBytes++;
  1002. nNewWidthBytes = m_nWidth * 4;
  1003. while( ( nNewWidthBytes & 3 ) != 0 ) nNewWidthBytes++;
  1004. for( y=0; y<m_nHeight; y++ ){
  1005. yy = m_nHeight - 1 - y;
  1006. pTemp = pNewBits;
  1007. pTemp += ( ( m_nHeight - 1 - y ) * nNewWidthBytes );
  1008. for( x=0; x<m_nWidth; x++ ){
  1009. Data1 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*4];
  1010. Data2 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*4+1];
  1011. Data3 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*4+2];
  1012. Data4 = pOldBits[(m_nWidth-1-x)*nOldWidthBytes+yy*4+3];
  1013. pTemp[x*4] = Data1;
  1014. pTemp[x*4+1] = Data2;
  1015. pTemp[x*4+2] = Data3;
  1016. pTemp[x*4+3] = Data4;
  1017. }
  1018. }
  1019. break;
  1020. }
  1021. }
  1022. BOOL CImageObject::Invert( void )
  1023. {
  1024. unsigned char *pBuffer, *pTemp1, *pTemp2;
  1025. BITMAPINFOHEADER *pBIH;
  1026. RGBQUAD *pPalette;
  1027. unsigned char *pBits;
  1028. int nWidthBytes;
  1029. int nNumColors;
  1030. int y, yy;
  1031. unsigned char *pTemp;
  1032. pBuffer = (unsigned char *) GetDIBPointer( &nWidthBytes );
  1033. if( pBuffer == NULL ) return( FALSE );
  1034. pBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  1035. nNumColors = m_nColors;
  1036. pPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  1037. pBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  1038. pTemp = new unsigned char [nWidthBytes];
  1039. if( pTemp != NULL ){
  1040. yy = pBIH->biHeight;
  1041. if( !( yy & 1 ) ) yy /= 2;
  1042. else yy = ( yy / 2 ) + 1;
  1043. for( y=0; y<yy; y++ ){
  1044. pTemp1 = pBits;
  1045. pTemp1 += ( ( pBIH->biHeight - 1 - y ) * nWidthBytes );
  1046. pTemp2 = pBits;
  1047. pTemp2 += y * nWidthBytes;
  1048. memcpy( pTemp, pTemp1, nWidthBytes );
  1049. memcpy( pTemp1, pTemp2, nWidthBytes );
  1050. memcpy( pTemp2, pTemp, nWidthBytes );
  1051. }
  1052. delete [] pTemp;
  1053. }
  1054. ::GlobalUnlock( m_hDib );
  1055. m_nLastError = IMAGELIB_SUCCESS;
  1056. return( TRUE );
  1057. }
  1058. BOOL CImageObject::Reverse( void )
  1059. {
  1060. unsigned char *pBuffer, *pTemp;
  1061. BITMAPINFOHEADER *pBIH;
  1062. RGBQUAD *pPalette;
  1063. unsigned char *pBits;
  1064. int nWidthBytes;
  1065. int nNumColors;
  1066. int y, x, xx, xt, nWidth;
  1067. unsigned char Data, Tmp, Data1, Tmp1;
  1068. pBuffer = (unsigned char *) GetDIBPointer( &nWidthBytes );
  1069. if( pBuffer == NULL ) return( FALSE );
  1070. pBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  1071. nNumColors = m_nColors;
  1072. pPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  1073. pBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  1074. xx = pBIH->biWidth;
  1075. if( !( xx & 1 ) ) xx /= 2;
  1076. else xx = ( xx / 2 ) + 1;
  1077. nWidth = pBIH->biWidth;
  1078. if( m_nBits == 4 ){
  1079. xx = pBIH->biWidth;
  1080. xx = ( xx + 3 ) / 4;
  1081. nWidth = ( pBIH->biWidth + 1 ) / 2;
  1082. }
  1083. else if( m_nBits == 1 ){
  1084. xx = pBIH->biWidth;
  1085. xx = ( xx + 15 ) / 16;
  1086. nWidth = ( pBIH->biWidth + 7 ) / 8;
  1087. }
  1088. for( y=0; y<pBIH->biHeight; y++ ){
  1089. pTemp = pBits;
  1090. pTemp += y * nWidthBytes;
  1091. switch( m_nBits ){
  1092. case 1:
  1093. for( x=0; x<xx; x++ ){
  1094. xt = nWidth - 1 - x;
  1095. Data = pTemp[x];
  1096. Data1 = Data << 7;
  1097. Data1 |= ( ( Data & 0x02 ) << 5 );
  1098. Data1 |= ( ( Data & 0x04 ) << 3 );
  1099. Data1 |= ( ( Data & 0x08 ) << 1 );
  1100. Data1 |= ( ( Data & 0x10 ) >> 1 );
  1101. Data1 |= ( ( Data & 0x20 ) >> 3 );
  1102. Data1 |= ( ( Data & 0x40 ) >> 5 );
  1103. Data1 |= ( ( Data & 0x80 ) >> 7 );
  1104. Tmp = pTemp[xt];
  1105. Tmp1 = Tmp << 7;
  1106. Tmp1 |= ( ( Tmp & 0x02 ) << 5 );
  1107. Tmp1 |= ( ( Tmp & 0x04 ) << 3 );
  1108. Tmp1 |= ( ( Tmp & 0x08 ) << 1 );
  1109. Tmp1 |= ( ( Tmp & 0x10 ) >> 1 );
  1110. Tmp1 |= ( ( Tmp & 0x20 ) >> 3 );
  1111. Tmp1 |= ( ( Tmp & 0x40 ) >> 5 );
  1112. Tmp1 |= ( ( Tmp & 0x80 ) >> 7 );
  1113. pTemp[x] = Tmp1;
  1114. pTemp[xt] = Data1;
  1115. }
  1116. break;
  1117. case 4:
  1118. for( x=0; x<xx; x++ ){
  1119. xt = nWidth - 1 - x;
  1120. Data = pTemp[x];
  1121. Tmp = pTemp[xt];
  1122. Data = ( Data << 4 ) | ( Data >> 4 );
  1123. Tmp = ( Tmp << 4 ) | ( Tmp >> 4 );
  1124. pTemp[x] = Tmp;
  1125. pTemp[xt] = Data;
  1126. }
  1127. break;
  1128. case 8:
  1129. for( x=0; x<xx; x++ ){
  1130. xt = nWidth - 1 - x;
  1131. Data = pTemp[x];
  1132. pTemp[x] = pTemp[xt];
  1133. pTemp[xt] = Data;
  1134. }
  1135. break;
  1136. case 16:
  1137. for( x=0; x<xx; x++ ){
  1138. xt = nWidth - 1 - x;
  1139. Data = pTemp[x*2];
  1140. pTemp[x*2] = pTemp[xt*2];
  1141. pTemp[xt*2] = Data;
  1142. Data = pTemp[x*2+1];
  1143. pTemp[x*2+1] = pTemp[xt*2+1];
  1144. pTemp[xt*2+1] = Data;
  1145. }
  1146. break;
  1147. case 24:
  1148. for( x=0; x<xx; x++ ){
  1149. xt = nWidth - 1 - x;
  1150. Data = pTemp[x*3];
  1151. pTemp[x*3] = pTemp[xt*3];
  1152. pTemp[xt*3] = Data;
  1153. Data = pTemp[x*3+1];
  1154. pTemp[x*3+1] = pTemp[xt*3+1];
  1155. pTemp[xt*3+1] = Data;
  1156. Data = pTemp[x*3+2];
  1157. pTemp[x*3+2] = pTemp[xt*3+2];
  1158. pTemp[xt*3+2] = Data;
  1159. }
  1160. break;
  1161. case 32:
  1162. for( x=0; x<xx; x++ ){
  1163. xt = nWidth - 1 - x;
  1164. Data = pTemp[x*4];
  1165. pTemp[x*4] = pTemp[xt*4];
  1166. pTemp[xt*4] = Data;
  1167. Data = pTemp[x*4+1];
  1168. pTemp[x*4+1] = pTemp[xt*4+1];
  1169. pTemp[xt*4+1] = Data;
  1170. Data = pTemp[x*4+2];
  1171. pTemp[x*4+2] = pTemp[xt*4+2];
  1172. pTemp[xt*4+2] = Data;
  1173. Data = pTemp[x*4+3];
  1174. pTemp[x*4+3] = pTemp[xt*4+3];
  1175. pTemp[xt*4+3] = Data;
  1176. }
  1177. break;
  1178. }
  1179. }
  1180. ::GlobalUnlock( m_hDib );
  1181. m_nLastError = IMAGELIB_SUCCESS;
  1182. return( TRUE );
  1183. }
  1184. BOOL CImageObject::ChangeFormat( int nNewBitsPerPixel )
  1185. {
  1186. m_nLastError = IMAGELIB_SUCCESS;
  1187. if( nNewBitsPerPixel == m_nBits ) return( TRUE );
  1188. int nOldWidthBytes, nNewWidthBytes;
  1189. char *pBuffer = (char *) GetDIBPointer( &nOldWidthBytes, nNewBitsPerPixel, &nNewWidthBytes );
  1190. if( pBuffer == NULL ) return( FALSE );
  1191. BITMAPINFOHEADER *pOldBIH, *pNewBIH;
  1192. BITMAPFILEHEADER *pOldBFH, *pNewBFH;
  1193. RGBQUAD *pOldRGBPalette, *pNewRGBPalette;
  1194. unsigned char *pOldBits, *pNewBits;
  1195. int nNumColors, nNumNewColors;
  1196. pOldBFH = (BITMAPFILEHEADER *) pBuffer;
  1197. pOldBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  1198. pOldRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  1199. nNumColors = m_nColors;
  1200. nNumNewColors = 1 << nNewBitsPerPixel;
  1201. if( nNewBitsPerPixel > 8 ) nNumNewColors = 0;
  1202. pOldBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumColors*sizeof(RGBQUAD)];
  1203. if( m_nBits >= 16 && nNewBitsPerPixel < 16 ){
  1204. if( m_pLogPal != NULL ) delete [] m_pLogPal;
  1205. m_pLogPal = CreatePaletteFromBitmap( nNumNewColors, pOldBits, m_nBits, m_nWidth, m_nHeight );
  1206. }
  1207. HGLOBAL hGlobal;
  1208. DWORD dwSize;
  1209. dwSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + m_nHeight * nNewWidthBytes;
  1210. hGlobal = ::GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize );
  1211. if( hGlobal == NULL ){
  1212. ::GlobalUnlock( m_hDib );
  1213. return( FALSE );
  1214. }
  1215. pBuffer = (char *) ::GlobalLock( hGlobal );
  1216. if( pBuffer == NULL ){
  1217. ::GlobalFree( hGlobal );
  1218. ::GlobalUnlock( m_hDib );
  1219. return( FALSE );
  1220. }
  1221. pNewBFH = (BITMAPFILEHEADER *) pBuffer;
  1222. pNewBIH = (BITMAPINFOHEADER *) &pBuffer[sizeof(BITMAPFILEHEADER)];
  1223. pNewRGBPalette = (RGBQUAD *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)];
  1224. *pNewBFH = *pOldBFH;
  1225. *pNewBIH = *pOldBIH;
  1226. int i, j = nNumNewColors;
  1227. if( m_nBits < 16 && nNewBitsPerPixel < 16 ){
  1228. for( i=0; i<j; i++ ) pNewRGBPalette[i] = pOldRGBPalette[i];
  1229. }
  1230. else if( m_nBits >= 16 ){
  1231.   for( i=0; i<j; i++ ){
  1232. pNewRGBPalette[i].rgbRed = m_pLogPal->palPalEntry[i].peRed;
  1233. pNewRGBPalette[i].rgbGreen = m_pLogPal->palPalEntry[i].peGreen;
  1234. pNewRGBPalette[i].rgbBlue = m_pLogPal->palPalEntry[i].peBlue;
  1235. }
  1236. }
  1237. pNewBIH->biBitCount = nNewBitsPerPixel;
  1238. pNewBIH->biSizeImage = nNewWidthBytes * m_nHeight;
  1239. pNewBIH->biClrUsed = nNumNewColors;
  1240. pNewBFH->bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD ) + pNewBIH->biSizeImage;
  1241. pNewBFH->bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + nNumNewColors * sizeof( RGBQUAD );
  1242. pNewBits = (unsigned char *) &pBuffer[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nNumNewColors*sizeof(RGBQUAD)];
  1243. m_nPaletteBytes = nNumNewColors * sizeof( RGBQUAD );
  1244. for( int y=0; y<m_nHeight; y++ ){
  1245. unsigned char ucRed, ucGreen, ucBlue;
  1246. unsigned char *pSrc, *pDest;
  1247. pSrc = pOldBits;
  1248. pSrc += ( nOldWidthBytes * y );
  1249. pDest = pNewBits;
  1250. pDest += ( nNewWidthBytes * y );
  1251. for( int x=0; x<m_nWidth; x++ ){
  1252. switch( m_nBits ){
  1253. case 1:
  1254. if( pSrc[x/8] & ( 0x80 >> ( x & 7 ) ) )
  1255. ucRed = ucGreen = ucBlue = 0xff;
  1256. else
  1257. ucRed = ucGreen = ucBlue = 0x00;
  1258. break;
  1259. case 4:
  1260. if( !( x & 1 ) ){
  1261. ucRed = pOldRGBPalette[pSrc[x/2]>>4].rgbRed;
  1262. ucGreen = pOldRGBPalette[pSrc[x/2]>>4].rgbGreen;
  1263. ucBlue = pOldRGBPalette[pSrc[x/2]>>4].rgbBlue;
  1264. }
  1265. else{
  1266. ucRed = pOldRGBPalette[pSrc[x/2]&15].rgbRed;
  1267. ucGreen = pOldRGBPalette[pSrc[x/2]&15].rgbGreen;
  1268. ucBlue = pOldRGBPalette[pSrc[x/2]&15].rgbBlue;
  1269. }
  1270. break;
  1271. case 8:
  1272. ucRed = pOldRGBPalette[pSrc[x]].rgbRed;
  1273. ucGreen = pOldRGBPalette[pSrc[x]].rgbGreen;
  1274. ucBlue = pOldRGBPalette[pSrc[x]].rgbBlue;
  1275. break;
  1276. case 16:
  1277. GETRGB555( ucRed, ucGreen, ucBlue, &pSrc[x*2] );
  1278. break;
  1279. case 24:
  1280. ucRed = pSrc[x*3+2];
  1281. ucGreen = pSrc[x*3+1];
  1282. ucBlue = pSrc[x*3];
  1283. break;
  1284. case 32:
  1285. GETRGB888( ucRed, ucGreen, ucBlue, &pSrc[x*4] );
  1286. break;
  1287. }
  1288. switch( nNewBitsPerPixel ){
  1289. case 1:
  1290. if( !( x & 7 ) ) pDest[x/8] = 0;
  1291. pDest[x/8] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << ( x & 7 );
  1292. break;
  1293. case 4:
  1294. if( !( x & 1 ) )
  1295. pDest[x/2] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors ) << 4;
  1296. else
  1297. pDest[x/2] |= (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
  1298. break;
  1299. case 8:
  1300. pDest[x] = (unsigned char) GetNearestIndex( ucRed, ucGreen, ucBlue, pNewRGBPalette, nNumNewColors );
  1301. break;
  1302. case 16:
  1303. PUTRGB555( ucRed, ucGreen, ucBlue, &pDest[x*2] );
  1304. break;
  1305. case 24:
  1306. pDest[x*3+2] = ucRed;
  1307. pDest[x*3+1] = ucGreen;
  1308. pDest[x*3] = ucBlue;
  1309. break;
  1310. case 32:
  1311. PUTRGB888( ucRed, ucGreen, ucBlue, &pDest[x*4] );
  1312. break;
  1313. }
  1314. }
  1315. }
  1316. ::GlobalUnlock( m_hDib );
  1317. ::GlobalFree( m_hDib );
  1318. ::GlobalUnlock( hGlobal );
  1319. m_hDib = hGlobal;
  1320. ProcessImageHeader();
  1321. return( TRUE );
  1322. }
  1323. LOGPALETTE *CImageObject::CreatePaletteFromBitmap( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
  1324. {
  1325. RGBQUAD *pRGBPalette;
  1326. if( nBits != 8 && m_nPaletteCreationType == POPULARITY_PALETTE ) pRGBPalette = MakePopularityPalette( nNumColors, pBits, nBits, nWidth, nHeight );
  1327. else if( nBits != 8 && m_nPaletteCreationType == MEDIAN_CUT_PALETTE ) pRGBPalette = MakeMedianCutPalette( nNumColors, pBits, nBits, nWidth, nHeight );
  1328. else if( m_nPaletteCreationType == FIXED_PALETTE ) pRGBPalette = MakeFixedPalette( nNumColors );
  1329. if( pRGBPalette == NULL ) return( NULL );
  1330. LOGPALETTE *pLogPal = CreateLogPalette( pRGBPalette, nNumColors );
  1331. delete [] pRGBPalette;
  1332. return( pLogPal );
  1333. }
  1334. void CImageObject::SetPaletteCreationType( int nType )
  1335. {
  1336. m_nPaletteCreationType = nType;
  1337. }
  1338. int CImageObject::GetPaletteCreationType( void )
  1339. {
  1340. return( m_nPaletteCreationType );
  1341. }
  1342. RGBQUAD *CImageObject::MakePopularityPalette( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
  1343. {
  1344. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1345. if( pRGBQuad == NULL ) return( MakeFixedPalette( nNumColors ) );
  1346. memset( pRGBQuad, 0, nNumColors * sizeof( RGBQUAD ) );
  1347. BYTE ColMap[256][3];
  1348. if( !Popularity( pBits, nBits, nWidth, nHeight, ColMap ) ){
  1349. delete [] pRGBQuad;
  1350. return( MakeFixedPalette( nNumColors ) );
  1351. }
  1352. for( int i=0; i<nNumColors; i++ ){
  1353. pRGBQuad[i].rgbRed = ColMap[i][0];
  1354. pRGBQuad[i].rgbGreen = ColMap[i][1];
  1355. pRGBQuad[i].rgbBlue = ColMap[i][2];
  1356. }
  1357. return( pRGBQuad );
  1358. }
  1359. RGBQUAD *CImageObject::MakeMedianCutPalette( int nNumColors, unsigned char *pBits, int nBits, int nWidth, int nHeight )
  1360. {
  1361. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1362. if( pRGBQuad == NULL ) return( MakeFixedPalette( nNumColors ) );
  1363. memset( pRGBQuad, 0, nNumColors * sizeof( RGBQUAD ) );
  1364. BYTE ColMap[256][3];
  1365. WORD *Hist = new WORD[32768];
  1366. if( Hist == NULL ){
  1367. delete [] pRGBQuad;
  1368. return( MakeFixedPalette( nNumColors ) );
  1369. }
  1370. memset( Hist, 0, 32768 * sizeof( WORD ) );
  1371. int nWidthBytes = WidthBytes( nBits, nWidth );
  1372. for( int y=0; y<nHeight; y++ ){
  1373. unsigned char *pData = pBits;
  1374. unsigned char ucRed, ucGreen, ucBlue;
  1375. WORD color;
  1376. pData += ( y * nWidthBytes );
  1377. for( int x=0; x<nWidth; x++ ){
  1378. switch( nBits ){
  1379. case 16:
  1380. GETRGB555( ucRed, ucGreen, ucBlue, &pData[x*2] );
  1381. break;
  1382. case 24:
  1383. ucRed = pData[x*3+2];
  1384. ucGreen = pData[x*3+1];
  1385. ucBlue = pData[x*3];
  1386. break;
  1387. case 32:
  1388. GETRGB888( ucRed, ucGreen, ucBlue, &pData[x*4] );
  1389. break;
  1390. }
  1391. color = _RGB( ucRed, ucGreen, ucBlue );
  1392. if( Hist[color] < 65535 ) Hist[color]++;
  1393. }
  1394. }
  1395. MedianCut( Hist, ColMap, (int) 256 );
  1396. for( int i=0; i<nNumColors; i++ ){
  1397. pRGBQuad[i].rgbRed = ColMap[i][0];
  1398. pRGBQuad[i].rgbGreen = ColMap[i][1];
  1399. pRGBQuad[i].rgbBlue = ColMap[i][2];
  1400. }
  1401. delete [] Hist;
  1402. return( pRGBQuad );
  1403. }
  1404. RGBQUAD *CImageObject::MakeFixedPalette( int nNumColors )
  1405. {
  1406. RGBQUAD *pRGBQuad = new RGBQUAD[nNumColors];
  1407. if( pRGBQuad == NULL ) return( NULL );
  1408. static int colors[] = {
  1409. 255, 255, 255,
  1410. 0, 0, 0,
  1411. 255, 0, 0,
  1412. 0, 0, 255,
  1413. 0, 255, 0,
  1414. 150, 150, 150,
  1415. 255, 255, 0,
  1416. 0, 150, 150,
  1417. 150, 0, 150,
  1418. 150, 150, 0,
  1419. 0, 255, 255,
  1420. 255, 0, 255,
  1421. 255, 120, 120,
  1422. 120, 255, 120,
  1423. 120, 120, 255,
  1424. 90, 90, 90 };
  1425. int nSteps = ( ( nNumColors + 15 ) / 16 );
  1426. for( int i=0; i<nSteps; i++ ){
  1427. for( int j=0; j<16; j++ ){
  1428. if( i * 16 + j < nNumColors ){
  1429. int r, g, b;
  1430. r = colors[j*3];
  1431. g = colors[j*3+1];
  1432. b = colors[j*3+2];
  1433. r = ( ( nSteps - i ) * r ) / nSteps;
  1434. g = ( ( nSteps - i ) * g ) / nSteps;
  1435. b = ( ( nSteps - i ) * b ) / nSteps;
  1436. pRGBQuad[i*16+j].rgbRed = (unsigned char) r;
  1437. pRGBQuad[i*16+j].rgbGreen = (unsigned char) g;
  1438. pRGBQuad[i*16+j].rgbBlue = (unsigned char) b;
  1439. }
  1440. }
  1441. }
  1442. return( pRGBQuad );
  1443. }
  1444. int CImageObject::GetPaletteBytes( void )
  1445. {
  1446. return( m_nPaletteBytes );
  1447. }
  1448. HGLOBAL CImageObject::GetDib( void )
  1449. {
  1450. return( m_hDib );
  1451. }
  1452. CPalette *CImageObject::GetPalette( void )
  1453. {
  1454. return( &m_Palette );
  1455. }
  1456. LOGPALETTE *CImageObject::GetLogPal( void )
  1457. {
  1458. return( m_pLogPal );
  1459. }