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

Graph program

Development Platform:

Visual C++

  1. /*
  2.  * File: ximaico.cpp
  3.  * Purpose: Platform Independent ICON Image Class Loader and Writer (MS version)
  4.  * 07/Aug/2001 Davide Pizzolato - www.xdp.it
  5.  * CxImage version 5.99a 08/Feb/2004
  6.  */
  7. #include "ximaico.h"
  8. #if CXIMAGE_SUPPORT_ICO
  9. ////////////////////////////////////////////////////////////////////////////////
  10. bool CxImageICO::Decode(CxFile *hFile)
  11. {
  12. if (hFile==NULL) return false;
  13. DWORD off = hFile->Tell(); //<yuandi>
  14. int page=info.nFrame; //internal icon structure indexes
  15. // read the first part of the header
  16. ICONHEADER icon_header;
  17. hFile->Read(&icon_header,sizeof(ICONHEADER),1);
  18. // check if it's an icon or a cursor
  19. if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) {
  20. info.nNumFrames = icon_header.idCount;
  21. // load the icon descriptions
  22. ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY));
  23. int c;
  24. for (c = 0; c < icon_header.idCount; c++)
  25. hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1);
  26. if ((page>=0)&&(page<icon_header.idCount)){
  27. // get the bit count for the colors in the icon <CoreyRLucier>
  28. BITMAPINFOHEADER bih;
  29. hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);
  30. hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1);
  31. c = bih.biBitCount;
  32. // allocate memory for one icon
  33. Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO); //image creation
  34. // read the palette
  35. RGBQUAD pal[256];
  36. hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);
  37. SetPalette(pal,head.biClrUsed); //palette assign
  38. //read the icon
  39. if (c<=24){
  40. hFile->Read(info.pImage, head.biSizeImage, 1);
  41. } else { // 32 bit icon
  42. BYTE* dst = info.pImage;
  43. BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth);
  44. BYTE* src = buf;
  45. hFile->Read(buf, 4*head.biHeight*head.biWidth, 1);
  46. #if CXIMAGE_SUPPORT_ALPHA
  47. if (!AlphaIsValid()) AlphaCreate();
  48. #endif //CXIMAGE_SUPPORT_ALPHA
  49. for (long y = 0; y < head.biHeight; y++) {
  50. for(long x=0;x<head.biWidth;x++){
  51. *dst++=src[0];
  52. *dst++=src[1];
  53. *dst++=src[2];
  54. #if CXIMAGE_SUPPORT_ALPHA
  55. AlphaSet(x,y,src[3]);
  56. #endif //CXIMAGE_SUPPORT_ALPHA
  57. src+=4;
  58. }
  59. }
  60. free(buf);
  61. }
  62. // apply the AND and XOR masks
  63. int maskwdt = ((head.biWidth+31) / 32) * 4; //line width of AND mask (always 1 Bpp)
  64. int masksize = head.biHeight * maskwdt; //size of mask
  65. BYTE *mask = (BYTE *)malloc(masksize);
  66. if (hFile->Read(mask, masksize, 1)){
  67. bool bGoodMask=false;
  68. for (int im=0;im<masksize;im++){
  69. if (mask[im]!=255){
  70. bGoodMask=true;
  71. break;
  72. }
  73. }
  74. if (bGoodMask){
  75. #if CXIMAGE_SUPPORT_ALPHA
  76. bool bNeedAlpha = false;
  77. if (!AlphaIsValid()){
  78. AlphaCreate();
  79. } else { 
  80. bNeedAlpha=true; //32bit icon
  81. }
  82. for (int y = 0; y < head.biHeight; y++) {
  83. for (int x = 0; x < head.biWidth; x++) {
  84. if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){
  85. AlphaSet(x,y,0);
  86. bNeedAlpha=true;
  87. }
  88. }
  89. }
  90. if (!bNeedAlpha) AlphaDelete();
  91. #endif //CXIMAGE_SUPPORT_ALPHA
  92. if (c==24){ //check if there is only one transparent color
  93. RGBQUAD cc,ct;
  94. long* pcc = (long*)&cc;
  95. long* pct = (long*)&ct;
  96. int nTransColors=0;
  97. for (int y = 0; y < head.biHeight; y++){
  98. for (int x = 0; x < head.biWidth; x++){
  99. if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
  100. cc = GetPixelColor(x,y,false);
  101. if (nTransColors==0){
  102. nTransColors++;
  103. ct = cc;
  104. } else {
  105. if (*pct!=*pcc){
  106. nTransColors++;
  107. }
  108. }
  109. }
  110. }
  111. }
  112. if (nTransColors==1){
  113. SetTransColor(ct);
  114. SetTransIndex(0);
  115. #if CXIMAGE_SUPPORT_ALPHA
  116. AlphaDelete(); //because we have a unique transparent color in the image
  117. #endif //CXIMAGE_SUPPORT_ALPHA
  118. }
  119. }
  120. // <vho> - Transparency support w/o Alpha support
  121. if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha).
  122.   
  123. // find a color index, which is not used in the image
  124. // it is almost sure to find one, bcs. nobody uses all possible colors for an icon
  125. BYTE colorsUsed[256];
  126. memset(colorsUsed, 0, sizeof(colorsUsed));
  127. for (int y = 0; y < head.biHeight; y++){
  128. for (int x = 0; x < head.biWidth; x++){
  129. colorsUsed[GetPixelIndex(x,y)] = 1;
  130. }
  131. }
  132. int iTransIdx = -1;
  133. for (int x = 0; x < (int)head.biClrUsed; x++){
  134. if (colorsUsed[x] == 0){
  135. iTransIdx = x; // this one is not in use. we may use it as transparent color
  136. break;
  137. }
  138. }
  139. // Go thru image and set unused color as transparent index if needed
  140. if (iTransIdx >= 0){
  141. bool bNeedTrans = false;
  142. for (int y = 0; y < head.biHeight; y++){
  143. for (int x = 0; x < head.biWidth; x++){
  144. // AND mask (Each Byte represents 8 Pixels)
  145. if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
  146. // AND mask is set (!=0). This is a transparent part
  147. SetPixelIndex(x, y, iTransIdx);
  148. bNeedTrans = true;
  149. }
  150. }
  151. }
  152. // set transparent index if needed
  153. if (bNeedTrans) SetTransIndex(iTransIdx);
  154. #if CXIMAGE_SUPPORT_ALPHA
  155. AlphaDelete(); //because we have a transparent color in the palette
  156. #endif //CXIMAGE_SUPPORT_ALPHA
  157. }
  158. }
  159. } else {
  160. SetTransIndex(0); //empty mask, set black as transparent color
  161. Negative();
  162. }
  163. free(mask);
  164. free(icon_list);
  165. // icon has been loaded successfully!
  166. return true;
  167. }
  168. free(icon_list);
  169. }
  170. return false;
  171. }
  172. ////////////////////////////////////////////////////////////////////////////////
  173. #if CXIMAGE_SUPPORT_ENCODE
  174. ////////////////////////////////////////////////////////////////////////////////
  175. bool CxImageICO::Encode(CxFile * hFile)
  176. {
  177. if (EncodeSafeCheck(hFile)) return false;
  178. //check format limits
  179. if ((head.biWidth>255)||(head.biHeight>255)){
  180. strcpy(info.szLastError,"Can't save this image as icon");
  181. return false;
  182. }
  183. //prepare the palette struct
  184. RGBQUAD* pal=GetPalette();
  185. if (head.biBitCount<=8 && pal==NULL) return false;
  186. int maskwdt=((head.biWidth+31)/32)*4; //mask line width
  187. int masksize=head.biHeight * maskwdt; //size of mask
  188. int bitcount=head.biBitCount;
  189. int imagesize=head.biSizeImage;
  190. #if CXIMAGE_SUPPORT_ALPHA
  191. if (AlphaIsValid() && head.biClrUsed==0){
  192. bitcount=32;
  193. imagesize=4*head.biHeight*head.biWidth;
  194. }
  195. #endif
  196. //fill the icon headers
  197. ICONHEADER icon_header={0,1,1};
  198. ICONDIRENTRY icon_list={(BYTE)head.biWidth,(BYTE)head.biHeight,(BYTE)head.biClrUsed ,0,0,(WORD)bitcount,
  199. sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+
  200. imagesize+masksize,
  201. sizeof(ICONHEADER)+sizeof(ICONDIRENTRY)};
  202. BITMAPINFOHEADER bi={sizeof(BITMAPINFOHEADER),head.biWidth,2*head.biHeight,1,(WORD)bitcount,
  203. 0,imagesize,0,0,0,0};
  204. hFile->Write(&icon_header,sizeof(ICONHEADER),1); //write the headers
  205. hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1);
  206. hFile->Write(&bi,sizeof(BITMAPINFOHEADER),1);
  207. if (pal) hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette
  208. #if CXIMAGE_SUPPORT_ALPHA
  209. if (AlphaIsValid() && head.biClrUsed==0){
  210. BYTE* src = info.pImage;
  211. BYTE* buf=(BYTE*)malloc(imagesize);
  212. BYTE* dst = buf;
  213. for (long y = 0; y < head.biHeight; y++) {
  214. for(long x=0;x<head.biWidth;x++){
  215. *dst++=*src++;
  216. *dst++=*src++;
  217. *dst++=*src++;
  218. *dst++=AlphaGet(x,y);
  219. }
  220. }
  221. hFile->Write(buf,imagesize, 1);
  222. free(buf);
  223. } else {
  224. hFile->Write(info.pImage,imagesize,1); //write image
  225. }
  226. #else
  227. hFile->Write(info.pImage,imagesize,1); //write image
  228. #endif
  229. //save transparency mask
  230. BYTE* mask=(BYTE*)calloc(masksize,1); //create empty AND/XOR masks
  231. if (!mask) return false;
  232. //prepare the variables to build the mask
  233. BYTE* iDst;
  234. int pos,i;
  235. RGBQUAD c={0,0,0,0};
  236. RGBQUAD ct = GetTransColor();
  237. long* pc = (long*)&c;
  238. long* pct= (long*)&ct;
  239. bool bTransparent = info.nBkgndIndex != -1;
  240. #if CXIMAGE_SUPPORT_ALPHA
  241. bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
  242. bool bAlphaIsValid = AlphaIsValid();
  243. #endif
  244. //build the mask
  245. for (int y = 0; y < head.biHeight; y++) {
  246. for (int x = 0; x < head.biWidth; x++) {
  247. i=0;
  248. #if CXIMAGE_SUPPORT_ALPHA
  249. if (bAlphaIsValid && AlphaGet(x,y)==0) i=1;
  250. if (bAlphaPaletteIsValid && GetPixelColor(x,y).rgbReserved==0) i=1;
  251. #endif
  252. c=GetPixelColor(x,y,false);
  253. if (bTransparent && *pc==*pct) i=1;
  254. iDst = mask + y*maskwdt + (x>>3);
  255. pos = 7-x%8;
  256. *iDst &= ~(0x01<<pos);
  257. *iDst |= ((i & 0x01)<<pos);
  258. }
  259. }
  260. //write AND/XOR masks
  261. hFile->Write(mask,masksize,1);
  262. free(mask);
  263. return true;
  264. }
  265. ////////////////////////////////////////////////////////////////////////////////
  266. #endif // CXIMAGE_SUPPORT_ENCODE
  267. ////////////////////////////////////////////////////////////////////////////////
  268. #endif // CXIMAGE_SUPPORT_ICO