ximage.cpp
Upload User: kairuinn
Upload Date: 2009-02-07
Package Size: 2922k
Code Size: 14k
Category:

Graph program

Development Platform:

Visual C++

  1. // ximage.cpp : main implementation file
  2. /* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
  3.  * CxImage version 5.99a 08/Feb/2004
  4.  */
  5. #include "ximage.h"
  6. ////////////////////////////////////////////////////////////////////////////////
  7. // CxImage 
  8. ////////////////////////////////////////////////////////////////////////////////
  9. // Initialize the internal structures
  10. void CxImage::Startup(DWORD imagetype)
  11. {
  12. //init pointers
  13. pDib = pSelection = pAlpha = NULL;
  14. pLayers = NULL;
  15. //init structures
  16. memset(&head,0,sizeof(BITMAPINFOHEADER));
  17. memset(&info,0,sizeof(CXIMAGEINFO));
  18. //init default attributes
  19.     info.dwType = imagetype;
  20. info.nQuality = 90;
  21. info.nAlphaMax = 255;
  22. info.nBkgndIndex = -1;
  23. info.bEnabled = true;
  24. SetXDPI(96);
  25. SetYDPI(96);
  26. m_hMeta = NULL;
  27. memset(&m_wmfHeader,0,sizeof(METAHEADER));
  28. memset(&m_wmfPict,0,sizeof(METAFILEPICT));
  29. }
  30. ////////////////////////////////////////////////////////////////////////////////
  31. // Empty image constructor
  32. // > imagetype: (optional) set the image format (for future use)
  33. CxImage::CxImage(DWORD imagetype)
  34. {
  35. Startup(imagetype);
  36. }
  37. ////////////////////////////////////////////////////////////////////////////////
  38. bool CxImage::Destroy()
  39. {
  40. //free this only if it's valid and it's not a ghost
  41. if (info.pGhost==NULL){
  42. if (pLayers) { 
  43. for(long n=0; n<info.nNumLayers;n++){ delete pLayers[n]; }
  44. free(pLayers); pLayers=0;
  45. }
  46. if (pSelection) {free(pSelection); pSelection=0;}
  47. if (pAlpha) {free(pAlpha); pAlpha=0;}
  48. if (pDib) {free(pDib); pDib=0;}
  49. return true;
  50. }
  51. return false;
  52. }
  53. ////////////////////////////////////////////////////////////////////////////////
  54. // Sized image constructor
  55. // > dwWidth: width
  56. // > dwHeight: height
  57. // > wBpp: bit per pixel
  58. // > imagetype: (optional) set the image format (for future use)
  59. CxImage::CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)
  60. {
  61. Startup(imagetype);
  62. Create(dwWidth,dwHeight,wBpp,imagetype);
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////
  65. // image constructor from existing source
  66. // > src: source image.
  67. // > copypixels: copy the pixels from the source image into the new image.
  68. // > copyselection: copy the selection from src
  69. CxImage::CxImage(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
  70. {
  71. Startup(src.GetType());
  72. Copy(src,copypixels,copyselection,copyalpha);
  73. }
  74. ////////////////////////////////////////////////////////////////////////////////
  75. void CxImage::Copy(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
  76. {
  77. //copy the attributes
  78. memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
  79. //rebuild the image
  80. Create(src.GetWidth(),src.GetHeight(),src.GetBpp(),src.GetType());
  81. //copy the pixels and the palette, or at least copy the palette only.
  82. if (copypixels && pDib && src.pDib) memcpy(pDib,src.pDib,GetSize());
  83. else SetPalette(src.GetPalette());
  84. long nSize = head.biWidth * head.biHeight;
  85. //copy the selection
  86. if (copyselection && src.pSelection){
  87. if (pSelection) free(pSelection);
  88. pSelection = (BYTE*)malloc(nSize);
  89. memcpy(pSelection,src.pSelection,nSize);
  90. }
  91. //copy the alpha channel
  92. if (copyalpha && src.pAlpha){
  93. if (pAlpha) free(pAlpha);
  94. pAlpha = (BYTE*)malloc(nSize);
  95. memcpy(pAlpha,src.pAlpha,nSize);
  96. }
  97. if (src.m_hMeta)
  98. m_hMeta = CopyEnhMetaFile(const_cast<HENHMETAFILE>(src.m_hMeta),NULL);
  99. memcpy(&m_wmfHeader,&src.m_wmfHeader,sizeof(METAHEADER));
  100. memcpy(&m_wmfPict,&src.m_wmfPict,sizeof(METAFILEPICT));
  101. }
  102. ////////////////////////////////////////////////////////////////////////////////
  103. // Use it before Create()
  104. void CxImage::CopyInfo(const CxImage &src)
  105. {
  106. if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
  107. if (src.m_hMeta)
  108. m_hMeta = CopyEnhMetaFile(const_cast<HENHMETAFILE>(src.m_hMeta),NULL);
  109. memcpy(&m_wmfHeader,&src.m_wmfHeader,sizeof(METAHEADER));
  110. memcpy(&m_wmfPict,&src.m_wmfPict,sizeof(METAFILEPICT));
  111. }
  112. ////////////////////////////////////////////////////////////////////////////////
  113. CxImage& CxImage::operator = (const CxImage& isrc)
  114. {
  115. if (this != &isrc) Copy(isrc);
  116. return *this;
  117. }
  118. ////////////////////////////////////////////////////////////////////////////////
  119. // Initializes or rebuilds the image.
  120. // Returns the pointer to the internal pDib object
  121. // > dwWidth: width
  122. // > dwHeight: height
  123. // > wBpp: bit per pixel
  124. // > imagetype: (optional) set the image format (for future use)
  125. void* CxImage::Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)
  126. {
  127. // destroy the existing image (if any)
  128. if (!Destroy())
  129. return NULL;
  130.     // Make sure bits per pixel is valid
  131.     if (wBpp <= 1) wBpp = 1;
  132.     else if (wBpp <= 4) wBpp = 4;
  133.     else if (wBpp <= 8) wBpp = 8;
  134.     else wBpp = 24;
  135. // limit memory requirements (and also a check for bad parameters)
  136. if (((dwWidth*dwHeight*wBpp)>>8) > CXIMAGE_MAX_MEMORY){
  137. strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded");
  138. return NULL;
  139. }
  140. // set the correct bpp value
  141.     switch (wBpp){
  142.         case 1:
  143.             head.biClrUsed = 2; break;
  144.         case 4:
  145.             head.biClrUsed = 16; break;
  146.         case 8:
  147.             head.biClrUsed = 256; break;
  148.         default:
  149.             head.biClrUsed = 0;
  150.     }
  151. //set the common image informations
  152.     info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);
  153.     info.dwType = imagetype;
  154.     // initialize BITMAPINFOHEADER
  155. head.biSize = sizeof(BITMAPINFOHEADER); //<ralphw>
  156.     head.biWidth = dwWidth; // fill in width from parameter
  157.     head.biHeight = dwHeight; // fill in height from parameter
  158.     head.biPlanes = 1; // must be 1
  159.     head.biBitCount = (WORD)wBpp; // from parameter
  160.     head.biCompression = BI_RGB;    
  161.     head.biSizeImage = info.dwEffWidth * dwHeight;
  162. //    head.biXPelsPerMeter = 0; See SetXDPI
  163. //    head.biYPelsPerMeter = 0; See SetYDPI
  164.     head.biClrImportant = 0;
  165. pDib = malloc(GetSize()); // alloc memory block to store our bitmap
  166.     if (!pDib){
  167. strcpy(info.szLastError,"CxImage::Create can't allocate memory");
  168. return NULL;
  169. }
  170. //clear the palette
  171. RGBQUAD* pal=GetPalette();
  172. if (pal) memset(pal,0,GetPaletteSize());
  173. //Destroy the existing selection
  174. #if CXIMAGE_SUPPORT_SELECTION
  175. if (pSelection) SelectionDelete();
  176. #endif //CXIMAGE_SUPPORT_SELECTION
  177. //Destroy the existing alpha channel
  178. #if CXIMAGE_SUPPORT_ALPHA
  179. if (pAlpha) AlphaDelete();
  180. #endif //CXIMAGE_SUPPORT_ALPHA
  181.     // use our bitmap info structure to fill in first part of
  182.     // our DIB with the BITMAPINFOHEADER
  183.     BITMAPINFOHEADER*  lpbi;
  184. lpbi = (BITMAPINFOHEADER*)(pDib);
  185.     *lpbi = head;
  186. info.pImage=GetBits();
  187.     return pDib; //return handle to the DIB
  188. }
  189. ////////////////////////////////////////////////////////////////////////////////
  190. // returns the pointer to the image pixels
  191. BYTE* CxImage::GetBits(DWORD row)
  192. if (pDib){
  193. if (row) {
  194. if (row<(DWORD)head.biHeight){
  195. return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row));
  196. } else {
  197. return NULL;
  198. }
  199. } else {
  200. return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize());
  201. }
  202. }
  203. return NULL;
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. // returns the whole pDib dimension
  207. long CxImage::GetSize()
  208. {
  209. return head.biSize + head.biSizeImage + GetPaletteSize();
  210. }
  211. ////////////////////////////////////////////////////////////////////////////////
  212. bool CxImage::IsInside(long x, long y)
  213. {
  214.   return (0<=y && y<head.biHeight && 0<=x && x<head.biWidth);
  215. }
  216. ////////////////////////////////////////////////////////////////////////////////
  217. void CxImage::Clear(BYTE bval)
  218. {
  219. if (pDib) memset(info.pImage,bval,head.biSizeImage);
  220. }
  221. ////////////////////////////////////////////////////////////////////////////////
  222. // moves everything from (*from) to (this), (*from) become empty
  223. bool CxImage::Transfer(CxImage &from)
  224. {
  225. if (!Destroy())
  226. return false;
  227. memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER));
  228. memcpy(&info,&from.info,sizeof(CXIMAGEINFO));
  229. pDib = from.pDib;
  230. pSelection = from.pSelection;
  231. pAlpha = from.pAlpha;
  232. pLayers = from.pLayers;
  233. memset(&from.head,0,sizeof(BITMAPINFOHEADER));
  234. memset(&from.info,0,sizeof(CXIMAGEINFO));
  235. from.pDib = from.pSelection = from.pAlpha = NULL;
  236. from.pLayers = NULL;
  237. if (from.m_hMeta)
  238. m_hMeta = CopyEnhMetaFile(from.m_hMeta,NULL);
  239. DWORD llee = ::GetLastError();
  240. memcpy(&m_wmfHeader,&from.m_wmfHeader,sizeof(METAHEADER));
  241. memcpy(&m_wmfPict,&from.m_wmfPict,sizeof(METAFILEPICT));
  242. return true;
  243. }
  244. ////////////////////////////////////////////////////////////////////////////////
  245. // (this) points to the same pDib owned by (*from), the image remains in (*from)
  246. // but (this) has the access to the pixels. Use carefully !!!
  247. void CxImage::Ghost(CxImage *from)
  248. {
  249. if (from){
  250. memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER));
  251. memcpy(&info,&from->info,sizeof(CXIMAGEINFO));
  252. pDib = from->pDib;
  253. pSelection = from->pSelection;
  254. pAlpha = from->pAlpha;
  255. pLayers = from->pLayers;
  256. info.pGhost=from;
  257. }
  258. }
  259. ////////////////////////////////////////////////////////////////////////////////
  260. // turns a 16 or 32 bit bitfield image into a RGB image
  261. void CxImage::Bitfield2RGB(BYTE *src, WORD redmask, WORD greenmask, WORD bluemask, BYTE bpp)
  262. {
  263. switch (bpp){
  264. case 16:
  265. {
  266. DWORD ns[3]={0,0,0};
  267. // compute the number of shift for each mask
  268. for (int i=0;i<16;i++){
  269. if ((redmask>>i)&0x01) ns[0]++;
  270. if ((greenmask>>i)&0x01) ns[1]++;
  271. if ((bluemask>>i)&0x01) ns[2]++;
  272. }
  273. ns[1]+=ns[0]; ns[2]+=ns[1]; ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8;
  274. // dword aligned width for 16 bit image
  275. long effwidth2=(((head.biWidth + 1) / 2) * 4);
  276. WORD w;
  277. long y2,y3,x2,x3;
  278. BYTE *p=info.pImage;
  279. // scan the buffer in reverse direction to avoid reallocations
  280. for (long y=head.biHeight-1; y>=0; y--){
  281. y2=effwidth2*y;
  282. y3=info.dwEffWidth*y;
  283. for (long x=head.biWidth-1; x>=0; x--){
  284. x2 = 2*x+y2;
  285. x3 = 3*x+y3;
  286. w = (WORD)(src[x2]+256*src[1+x2]);
  287. p[  x3]=(BYTE)((w & bluemask)<<ns[0]);
  288. p[1+x3]=(BYTE)((w & greenmask)>>ns[1]);
  289. p[2+x3]=(BYTE)((w & redmask)>>ns[2]);
  290. }
  291. }
  292. break;
  293. }
  294. case 32:
  295. {
  296. // dword aligned width for 32 bit image
  297. long effwidth4 = head.biWidth * 4;
  298. long y4,y3,x4,x3;
  299. BYTE *p=info.pImage;
  300. // scan the buffer in reverse direction to avoid reallocations
  301. for (long y=head.biHeight-1; y>=0; y--){
  302. y4=effwidth4*y;
  303. y3=info.dwEffWidth*y;
  304. for (long x=head.biWidth-1; x>=0; x--){
  305. x4 = 4*x+y4;
  306. x3 = 3*x+y3;
  307. p[  x3]=src[  x4];
  308. p[1+x3]=src[1+x4];
  309. p[2+x3]=src[2+x4];
  310. }
  311. }
  312. }
  313. }
  314. return;
  315. }
  316. ////////////////////////////////////////////////////////////////////////////////
  317. bool CxImage::CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)
  318. {
  319. if (pArray==NULL) return false;
  320. if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
  321. (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
  322. if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
  323. if (dwBitsperpixel<24) SetGrayPalette();
  324. #if CXIMAGE_SUPPORT_ALPHA
  325. if (dwBitsperpixel==32) AlphaCreate();
  326. #endif //CXIMAGE_SUPPORT_ALPHA
  327. BYTE *dst,*src;
  328. for (DWORD y = 0; y<dwHeight; y++) {
  329. dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
  330. src = pArray + y * dwBytesperline;
  331. if (dwBitsperpixel==32){
  332. for(DWORD x=0;x<dwWidth;x++){
  333. *dst++=src[0];
  334. *dst++=src[1];
  335. *dst++=src[2];
  336. #if CXIMAGE_SUPPORT_ALPHA
  337. AlphaSet(x,y,src[3]);
  338. #endif //CXIMAGE_SUPPORT_ALPHA
  339. src+=4;
  340. }
  341. } else {
  342. memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
  343. }
  344. }
  345. return true;
  346. }
  347. ////////////////////////////////////////////////////////////////////////////////
  348. bool CxImage::CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)
  349. {
  350. if (ppMatrix==NULL) return false;
  351. if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
  352. (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
  353. if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
  354. if (dwBitsperpixel<24) SetGrayPalette();
  355. #if CXIMAGE_SUPPORT_ALPHA
  356. if (dwBitsperpixel==32) AlphaCreate();
  357. #endif //CXIMAGE_SUPPORT_ALPHA
  358. BYTE *dst,*src;
  359. for (DWORD y = 0; y<dwHeight; y++) {
  360. dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
  361. src = ppMatrix[y];
  362. if (src){
  363. if (dwBitsperpixel==32){
  364. for(DWORD x=0;x<dwWidth;x++){
  365. *dst++=src[0];
  366. *dst++=src[1];
  367. *dst++=src[2];
  368. #if CXIMAGE_SUPPORT_ALPHA
  369. AlphaSet(x,y,src[3]);
  370. #endif //CXIMAGE_SUPPORT_ALPHA
  371. src+=4;
  372. }
  373. } else {
  374. memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
  375. }
  376. }
  377. }
  378. return true;
  379. }
  380. ////////////////////////////////////////////////////////////////////////////////
  381. int CxImage::CompareColors(const void *elem1, const void *elem2)
  382. {
  383. RGBQUAD* c1 = (RGBQUAD*)elem1;
  384. RGBQUAD* c2 = (RGBQUAD*)elem2;
  385. int g1 = (int)RGB2GRAY(c1->rgbRed,c1->rgbGreen,c1->rgbBlue);
  386. int g2 = (int)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue);
  387. return (g1-g2);
  388. }
  389. ////////////////////////////////////////////////////////////////////////////////
  390. RGBQUAD CxImage::GetTransColor()
  391. {
  392. if (head.biBitCount<24 && info.nBkgndIndex != -1) return GetPaletteColor((BYTE)info.nBkgndIndex);
  393. return info.nBkgndColor;
  394. }
  395. ////////////////////////////////////////////////////////////////////////////////
  396. BYTE CxImage::GetColorType()
  397. {
  398. BYTE b = (BYTE)((head.biBitCount>8) ? 2 /*COLORTYPE_COLOR*/ : 1 /*COLORTYPE_PALETTE*/);
  399. #if CXIMAGE_SUPPORT_ALPHA
  400. if (AlphaIsValid()) b = 4 /*COLORTYPE_ALPHA*/;
  401. #endif //CXIMAGE_SUPPORT_ALPHA
  402. return b;
  403. }
  404. ////////////////////////////////////////////////////////////////////////////////
  405. void CxImage::SetXDPI(long dpi)
  406. {
  407. info.xDPI = dpi;
  408. head.biXPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);
  409. }
  410. ////////////////////////////////////////////////////////////////////////////////
  411. void CxImage::SetYDPI(long dpi)
  412. {
  413. info.yDPI = dpi;
  414. head.biYPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);
  415. }
  416. ////////////////////////////////////////////////////////////////////////////////
  417. void CxImage::SetFlags(DWORD flags, bool bLockReservedFlags)
  418. {
  419. if (bLockReservedFlags) info.dwFlags = flags & 0x0000ffff;
  420. else info.dwFlags = flags;
  421. }
  422. ////////////////////////////////////////////////////////////////////////////////
  423. const TCHAR* CxImage::GetVersion()
  424. {
  425. static const TCHAR CxImageVersion[] = _T("CxImage 5.99a");
  426. return (CxImageVersion);
  427. }
  428. //EOF