GSKCreateGIF.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. //GIF编码
  2. //编写者:高书克
  3. //日 期:2004-12-6
  4. #include <StdAfx.h>
  5. #include <MATH.H>
  6. #include "quantizer.h"
  7. #include "GSKCreateGIF.h"
  8. //13 byte
  9. typedef struct _GIFHEADER
  10. {
  11. BYTE Signature[6];
  12. WORD ScreenWidth;
  13. WORD ScreenHeight;
  14. BYTE GlobalFlagByte;
  15. BYTE BackGroundColor;
  16. BYTE AspectRatio;
  17. }GIFHEARD;
  18. #define HASPalette 0x80
  19. //10 byte
  20. typedef struct _GIFDATAHEARD
  21. {
  22. BYTE imageLabel;
  23. WORD imageLeft;
  24. WORD imageTop;
  25. WORD imageWidth;
  26. WORD imageHeight;
  27. BYTE localFlagByte;
  28. }GIFDATAHEARD;
  29. void addToBuf(HANDLE file,BYTE *buf,long &nUsedBits,BYTE data,int nBit)
  30. {
  31. int nIndex,nCurByteUsedBits;
  32. nIndex = nUsedBits/8;
  33. nCurByteUsedBits = nUsedBits%8;
  34. if(nIndex >= 255)
  35. {//已经产生255个字节的数据
  36. BYTE bytes = 0xFF;
  37. DWORD DwWitten=0;
  38. ::WriteFile(file,&bytes,1,&DwWitten,NULL);
  39. ::WriteFile(file,buf,bytes,&DwWitten,NULL);
  40. //file.Write(&bytes,1);
  41. //file.Write(buf,bytes);
  42. buf[0] = buf[255];
  43. nIndex = 0;
  44. nUsedBits -= 255*8;
  45. }
  46. if(nCurByteUsedBits == 0)
  47. {
  48. buf[nIndex] = data;
  49. }
  50. else
  51. {
  52. buf[nIndex] |= data<<nCurByteUsedBits;
  53. if(nBit > 8-nCurByteUsedBits)
  54. {
  55. nIndex++;
  56. buf[nIndex] = data>>(8-nCurByteUsedBits);
  57. }
  58. }
  59. nUsedBits += nBit;
  60. }
  61. void WriteData(HANDLE file,WORD *pHeard,int nDataCount,BYTE bitsPixel,BOOL bEnd)
  62. {
  63. BYTE initBits = bitsPixel+1;
  64. BYTE pByts[256];
  65. BYTE *pTmp = (BYTE*)pHeard;
  66. int nCurCodeBits=initBits;
  67. WORD nMaxCode=1;
  68. WORD nClearCode=1;
  69. WORD nEndCode;
  70. /*CStdioFile strFile;
  71. if(strFile.Open("d:\\writedata.txt",CFile::modeWrite|CFile::modeCreate|CFile::typeText))
  72. {
  73. CString sTmp;
  74. for(int i=0; i<nDataCount; i++)
  75. {
  76. sTmp.Format("%X ",pHeard[i]);
  77. strFile.WriteString(sTmp);
  78. }
  79. }
  80. */
  81. nClearCode <<= nCurCodeBits-1;
  82. nMaxCode <<= nCurCodeBits;
  83. nEndCode = nClearCode+1;
  84. memset(pByts,0,256);
  85. long nUsedBits = 0;
  86. addToBuf(file,pByts,nUsedBits,nClearCode&0xFF,min(8,nCurCodeBits));
  87. if(nCurCodeBits > 8)
  88. {
  89. addToBuf(file,pByts,nUsedBits,(nClearCode&0xFF00)>>8,nCurCodeBits-8);
  90. }
  91. int nHeardCode = nClearCode+1;
  92. for(int i=0; i<nDataCount; i++)
  93. {
  94. if(nHeardCode++ >= nMaxCode)
  95. {
  96. nCurCodeBits++;
  97. if(nCurCodeBits == 13)
  98. {
  99. //CString sMsg;
  100. //sMsg.Format("[%X,%X]",pHeard[i-1],pHeard[i]);
  101. //AfxMessageBox(sMsg);
  102. addToBuf(file,pByts,nUsedBits,nClearCode&0xFF,8);
  103. addToBuf(file,pByts,nUsedBits,(nClearCode&0xFF00)>>8,4);
  104. nCurCodeBits = initBits;
  105. nHeardCode = nClearCode+2;
  106. }
  107. nMaxCode = (WORD)1<<nCurCodeBits;
  108. }
  109. addToBuf(file,pByts,nUsedBits,pHeard[i]&0xFF,min(8,nCurCodeBits));
  110. if(nCurCodeBits > 8)
  111. {
  112. addToBuf(file,pByts,nUsedBits,(pHeard[i]&0xFF00)>>8,nCurCodeBits-8);
  113. }
  114. }
  115. if(bEnd)
  116. {
  117. addToBuf(file,pByts,nUsedBits,nEndCode&0xFF,min(8,nCurCodeBits));
  118. if(nCurCodeBits > 8)
  119. {
  120. addToBuf(file,pByts,nUsedBits,(nEndCode&0xFF00)>>8,nCurCodeBits-8);
  121. }
  122. }
  123. long nByteCount = nUsedBits/8;
  124. if(nUsedBits%8 != 0)
  125. {
  126. nByteCount++;
  127. }
  128. BYTE bytes;
  129. int nIndex = 0;
  130. DWORD DwWitten=0;
  131. while(nByteCount>0)
  132. {
  133. bytes = min(0xFF,(BYTE)nByteCount);
  134. nByteCount -= bytes;
  135. ::WriteFile(file,&bytes,1,&DwWitten,NULL);
  136. ::WriteFile(file,pByts+nIndex,bytes,&DwWitten,NULL);
  137. //file.Write(&bytes,1);
  138. //file.Write(pByts+nIndex,bytes);
  139. nIndex += bytes;
  140. }
  141. bytes = 0x0;
  142. //file.Write(&bytes,1);
  143. ::WriteFile(file,&bytes,1,&DwWitten,NULL);
  144. }
  145. BYTE GetColorIndex(RGBQUAD *pQuad, UINT nSize,BYTE r,BYTE g,BYTE b)
  146. {
  147. BYTE nIndex;
  148. long nDist,nRDist,nGDist,nBDist,nMinDist = 999999999;
  149. for(UINT i=0; i<nSize; i++)
  150. {
  151. nRDist = pQuad[i].rgbRed - r;
  152. nGDist = pQuad[i].rgbGreen - g;
  153. nBDist = pQuad[i].rgbBlue - b;
  154. nDist = nRDist*nRDist + nGDist*nGDist + nBDist*nBDist;
  155. //nDist = 0.3*abs(nRDist) + 0.59*abs(nGDist) + 0.11*abs(nBDist);
  156. if(nDist < nMinDist)
  157. {
  158. nIndex = (BYTE)i;
  159. nMinDist = nDist;
  160. if(nDist == 0)
  161. {
  162. break;
  163. }
  164. }
  165. }
  166. return nIndex;
  167. }
  168. BOOL GetData(HBITMAP hBmp,BYTE **ppPalette,BYTE **ppData,BYTE *pBitsPixel,int *pWidth,int *pHeight)
  169. {
  170. BITMAP bm;
  171. PBITMAPINFO bmpInf;
  172. if(GetObject(hBmp,sizeof(bm),&bm)==0)
  173. return FALSE;
  174. int nPaletteSize=0;
  175. if(bm.bmBitsPixel<16)
  176. nPaletteSize=(int)pow(2.0,bm.bmBitsPixel);
  177. bmpInf=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+
  178. sizeof(RGBQUAD)*nPaletteSize+((bm.bmWidth*bm.bmBitsPixel+31)/32)*4*bm.bmHeight);
  179. BYTE* buf=((BYTE*)bmpInf) +
  180. sizeof(BITMAPINFOHEADER)+
  181. sizeof(RGBQUAD)*nPaletteSize;
  182. //-----------------------------------------------
  183. bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  184. bmpInf->bmiHeader.biWidth = bm.bmWidth;
  185. bmpInf->bmiHeader.biHeight = bm.bmHeight;
  186. bmpInf->bmiHeader.biPlanes = bm.bmPlanes;
  187. bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel;
  188. bmpInf->bmiHeader.biCompression = BI_RGB;
  189. bmpInf->bmiHeader.biSizeImage = (bm.bmWidth+7)/8*bm.bmHeight*bm.bmBitsPixel;
  190. //-----------------------------------------------
  191. HDC hDC = ::GetWindowDC(NULL);
  192. if(!::GetDIBits(hDC,hBmp,0,(UINT)bm.bmHeight,buf,bmpInf,DIB_RGB_COLORS))
  193. {
  194. ::ReleaseDC(NULL,hDC);
  195. LocalFree(bmpInf);
  196. return FALSE;
  197. }
  198. ::ReleaseDC(NULL,hDC);
  199. *pWidth = bm.bmWidth;
  200. *pHeight = bm.bmHeight;
  201. *ppData = new BYTE[bm.bmWidth*bm.bmHeight];
  202. CQuantizer quan(256,8);
  203. bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*nPaletteSize;
  204. quan.ProcessImage(bmpInf);
  205. int nColorCount = quan.GetColorCount();
  206. RGBQUAD *pQuad = new RGBQUAD[nColorCount];
  207. quan.SetColorTable(pQuad);
  208. int nLnBytes;
  209. //每行数据是4字节的整数倍
  210. nLnBytes = ((bm.bmWidth*bm.bmBitsPixel+31)/32)*4;
  211. int nOffset,i,nIndex=0;
  212. BYTE r,g,b;
  213. UINT nColorIndex;
  214. switch(bm.bmBitsPixel)
  215. {
  216. case 1:
  217. case 4:
  218. case 8:
  219. {
  220. delete []pQuad;
  221. nColorCount = (int)pow(2.0,bm.bmBitsPixel);
  222. pQuad = new RGBQUAD[nColorCount];
  223. memcpy(pQuad,(BYTE*)bmpInf+sizeof(BITMAPINFOHEADER),sizeof(RGBQUAD)*nColorCount);
  224. for(i=bm.bmHeight-1; i>=0; i--)
  225. {
  226. nOffset = i*nLnBytes;
  227. for(int j=0; j<bm.bmWidth; j++)
  228. {
  229. if(bm.bmBitsPixel==8)
  230. {
  231. (*ppData)[nIndex++] = buf[nOffset+j];
  232. }
  233. else
  234. {
  235. BYTE pos;
  236. BYTE iDst= buf[nOffset + (j*bm.bmBitsPixel >> 3)];
  237. if (bm.bmBitsPixel==4)
  238. {
  239. pos = 4*(1-j%2);
  240. iDst &= (0x0F<<pos);
  241. (*ppData)[nIndex++] = iDst >> pos;
  242. }else if (bm.bmBitsPixel==1)
  243. {
  244. pos = 7-j%8;
  245. iDst &= (0x01<<pos);
  246. (*ppData)[nIndex++] = iDst >> pos;
  247. }
  248. }
  249. }
  250. }
  251. }
  252. break;
  253. case 15:
  254. case 16:
  255. for(i=bm.bmHeight-1; i>=0; i--)
  256. {
  257. nOffset = i*nLnBytes;
  258. for(int j=0; j<bm.bmWidth; j++)
  259. {
  260. b = buf[nOffset+j*2]&0x1F;
  261. g = buf[nOffset+j*2]>>5;
  262. g |= (buf[nOffset+j*2+1]&0x03)<<3;
  263. r = (buf[nOffset+j*2+1]>>2)&0x1F;
  264. r *= 8;
  265. b *= 8;
  266. g *= 8;
  267. quan.GetColorIndex(r,g,b,&nColorIndex);
  268. (*ppData)[nIndex++] = (BYTE)nColorIndex;
  269. }
  270. }
  271. break;
  272. case 24:
  273. for(i=bm.bmHeight-1; i>=0; i--)
  274. {
  275. nOffset = i*nLnBytes;
  276. for(int j=0; j<bm.bmWidth; j++)
  277. {
  278. b = buf[nOffset+j*3];
  279. g = buf[nOffset+j*3+1];
  280. r = buf[nOffset+j*3+2];
  281. quan.GetColorIndex(r,g,b,&nColorIndex);
  282. (*ppData)[nIndex++] = (BYTE)nColorIndex;
  283. //该算法效果好,但速度慢
  284. //pData[nIndex++]=GetColorIndex(pQuad,nColorCount,r,g,b);
  285. }
  286. }
  287. break;
  288. case 32:
  289. for(i=bm.bmHeight-1; i>=0; i--)
  290. {
  291. nOffset = i*nLnBytes;
  292. for(int j=0; j<bm.bmWidth; j++)
  293. {
  294. b = buf[nOffset+j*4];
  295. g = buf[nOffset+j*4+1];
  296. r = buf[nOffset+j*4+2];
  297. quan.GetColorIndex(r,g,b,&nColorIndex);
  298. (*ppData)[nIndex++] = (BYTE)nColorIndex;
  299. }
  300. }
  301. break;
  302. default:
  303. delete []pQuad;
  304. LocalFree(bmpInf);
  305. return FALSE;
  306. break;
  307. }
  308. *pBitsPixel = 8;
  309. if(nColorCount <= 8)
  310. {
  311. *pBitsPixel = 3;
  312. }
  313. else if(nColorCount <= 16)
  314. {
  315. *pBitsPixel = 4;
  316. }
  317. else if(nColorCount <= 32)
  318. {
  319. *pBitsPixel = 5;
  320. }
  321. else if(nColorCount <= 64)
  322. {
  323. *pBitsPixel = 6;
  324. }
  325. else if(nColorCount <= 128)
  326. {
  327. *pBitsPixel = 7;
  328. }
  329. int nGIFPaletteSize = (int)pow(2.0,(int)*pBitsPixel);
  330. *ppPalette = new BYTE[nGIFPaletteSize*3];
  331. memset(*ppPalette,0,nGIFPaletteSize*3);
  332. for(i=0; i<(int)nColorCount; i++)
  333. {
  334. (*ppPalette)[i*3] = pQuad[i].rgbRed;
  335. (*ppPalette)[i*3+1] = pQuad[i].rgbGreen;
  336. (*ppPalette)[i*3+2] = pQuad[i].rgbBlue;
  337. }
  338. delete []pQuad;
  339. LocalFree(bmpInf);
  340. return TRUE;
  341. }
  342. void EnCode(BYTE *pData,long nDataSize,BYTE bitsPixel,WORD **ppEnCodeData,long *pnSize)
  343. {
  344. WORD *pHeard = new WORD[4097];
  345. WORD *pEnd = new WORD[4096];
  346. int nDataBufIndex=0;
  347. //每幅图片最大1000000个像素
  348. *ppEnCodeData = new WORD[1000000];
  349. int nIndex =0;
  350. int nDataIndex = 0;
  351. pHeard[nIndex] = pData[nDataIndex];
  352. pEnd[nIndex] = pData[nDataIndex+1];
  353. nIndex++;
  354. nDataIndex++;
  355. WORD wHeard,wEnd;
  356. BOOL bEndIsValide = TRUE;
  357. WORD wBeginCode = (((WORD)1)<<bitsPixel)+2;
  358. //编码
  359. for(; nDataIndex<nDataSize; )
  360. {
  361. wHeard = pData[nDataIndex];
  362. if(nDataIndex+1 >= nDataSize)
  363. {
  364. pHeard[nIndex] = wHeard;
  365. nIndex++;
  366. bEndIsValide = FALSE;
  367. break;
  368. }
  369. wEnd = pData[nDataIndex+1];
  370. nDataIndex++;
  371. for(int i=0; i<nIndex; i++)
  372. {
  373. if( (pHeard[i] == wHeard) && (pEnd[i] == wEnd) )
  374. {
  375. wHeard = wBeginCode+i;
  376. if(nDataIndex+1 >= nDataSize)
  377. {
  378. pHeard[nIndex] = wHeard;
  379. nIndex++;
  380. bEndIsValide = FALSE;
  381. break;
  382. }
  383. wEnd = pData[nDataIndex+1];
  384. nDataIndex++;
  385. }
  386. }
  387. pHeard[nIndex] = wHeard;
  388. if(bEndIsValide)
  389. {
  390. pEnd[nIndex] = wEnd;
  391. nIndex++;
  392. }
  393. else
  394. {
  395. break;
  396. }
  397. //达到4096(12位)后,重新开始编码
  398. if(wBeginCode+nIndex-1 == 4096)
  399. {
  400. memcpy( ((BYTE*)*ppEnCodeData)+nDataBufIndex,pHeard,nIndex*2);
  401. nDataBufIndex += nIndex*2;
  402. nIndex = 0;
  403. pHeard[nIndex] = pData[nDataIndex];
  404. pEnd[nIndex] = pData[nDataIndex+1];
  405. nIndex++;
  406. nDataIndex++;
  407. }
  408. }
  409. memcpy( ((BYTE*)*ppEnCodeData)+nDataBufIndex,pHeard,nIndex*2);
  410. nDataBufIndex += nIndex*2;
  411. *pnSize = nDataBufIndex/2;
  412. delete []pHeard;
  413. delete []pEnd;
  414. }
  415. typedef struct _GraphicController
  416. {
  417. BYTE extensionIntroducer;
  418. BYTE graphicControlLabel;
  419. BYTE blockSize;
  420. BYTE packedField;
  421. WORD nDelayTime;
  422. BYTE transparentColorIndex;
  423. BYTE blockTerminator;
  424. }GraphicController;
  425. typedef struct _ApplicationExtension
  426. {
  427. BYTE extensionIntroducer;
  428. BYTE applicationLabel;
  429. BYTE blockSize;
  430. char applicationId[8];
  431. char appAuthCode[3];
  432. char cAppData[4];
  433. BYTE blockTerminator;
  434. }ApplicationExtension;
  435. void CreateGIFHeard(HANDLE file,WORD nImageWidth,WORD nImageHeight,BYTE bitsPixel)
  436. {
  437. //GIF文件头,89a格式
  438. GIFHEARD heard;
  439. memcpy(heard.Signature,"GIF89a",6);
  440. heard.ScreenWidth = nImageWidth;
  441. heard.ScreenHeight = nImageHeight;
  442. //heard.GlobalFlagByte = HASPalette|((bitsPixel-1)<<4)|0|(bitsPixel-1);全局调色板
  443. heard.GlobalFlagByte = ((bitsPixel-1)<<4);
  444. heard.BackGroundColor = 0;
  445. heard.AspectRatio = 0;
  446. DWORD DwWitten=0;
  447. ::WriteFile(file,&heard,13,&DwWitten,NULL);
  448. //file.Write(&heard,13);//不要用sizeof(GIFHEARD),除非把编译器设为1字节对齐
  449. //为了让IE循环播放,必须加入该应用程序块(如果只有一幅图片,可省略该块)
  450. ApplicationExtension appData;
  451. appData.extensionIntroducer = 0x21;
  452. appData.applicationLabel = 0xFF;
  453. appData.blockSize = 11;
  454. memcpy(appData.applicationId,"NETSCAPE",8);
  455. memcpy(appData.appAuthCode,"2.0",3);
  456. appData.cAppData[0] = 3;
  457. appData.cAppData[1] = 1;
  458. appData.cAppData[2] = 0;
  459. appData.cAppData[3] = 0;
  460. appData.blockTerminator = 0;
  461. ::WriteFile(file,&appData,sizeof(ApplicationExtension),&DwWitten,NULL);
  462. //file.Write(&appData,sizeof(ApplicationExtension));
  463. }
  464. void AddImageToGIF(HANDLE file,BYTE *pData,BYTE *palette,WORD nImageWidth,WORD nImageHeight,BYTE bitsPixel,WORD nDelay,
  465. short int nTransparentColorIndex)
  466. {
  467. //控制块
  468. GraphicController control;
  469. control.extensionIntroducer = 0x21;
  470. control.graphicControlLabel = 0xF9;
  471. control.blockSize = 4;
  472. control.packedField = (nTransparentColorIndex==-1? 4:5);
  473. control.nDelayTime = nDelay;//延迟时间
  474. control.transparentColorIndex = (BYTE)(nTransparentColorIndex==-1? 0:nTransparentColorIndex);
  475. control.blockTerminator = 0;
  476. //file.Write(&control,sizeof(GraphicController));
  477. DWORD DwWitten=0;
  478. ::WriteFile(file,&control,sizeof(GraphicController),&DwWitten,NULL);
  479. ////file.Write(palette,nGIFPaletteSize*3);全局调色板
  480. //图片数据头
  481. GIFDATAHEARD dataHeard;
  482. dataHeard.imageLabel = 0x2c;
  483. dataHeard.imageLeft = 0;
  484. dataHeard.imageTop = 0;
  485. dataHeard.imageWidth = nImageWidth;
  486. dataHeard.imageHeight = nImageHeight;
  487. dataHeard.localFlagByte = HASPalette|(bitsPixel-1);
  488. ::WriteFile(file,&dataHeard.imageLabel,1,&DwWitten,NULL);
  489. ::WriteFile(file,&dataHeard.imageLeft,2,&DwWitten,NULL);
  490. ::WriteFile(file,&dataHeard.imageTop,2,&DwWitten,NULL);
  491. ::WriteFile(file,&dataHeard.imageWidth,2,&DwWitten,NULL);
  492. ::WriteFile(file,&dataHeard.imageHeight,2,&DwWitten,NULL);
  493. ::WriteFile(file,&dataHeard.localFlagByte,1,&DwWitten,NULL);
  494. //file.Write(&dataHeard.imageLabel,1);
  495. //file.Write(&dataHeard.imageLeft,2);
  496. //file.Write(&dataHeard.imageTop,2);
  497. //file.Write(&dataHeard.imageWidth,2);
  498. //file.Write(&dataHeard.imageHeight,2);
  499. //file.Write(&dataHeard.localFlagByte,1);
  500. //调色板
  501. //file.Write(palette,(int)pow(2,bitsPixel)*3);
  502. ::WriteFile(file,palette,(int)pow(2.0,bitsPixel)*3,&DwWitten,NULL);
  503. //每像素占用位数
  504. //file.Write(&bitsPixel,1);
  505. ::WriteFile(file,&bitsPixel,1,&DwWitten,NULL);
  506. WORD *pEnCodeData = NULL;
  507. long nSize = 0;
  508. //编码
  509. EnCode(pData,nImageWidth*nImageHeight,bitsPixel,&pEnCodeData,&nSize);
  510. //写入数据
  511. WriteData(file,pEnCodeData,nSize,bitsPixel,TRUE);
  512. delete []pEnCodeData;
  513. }
  514. void CloseGIF(HANDLE file)
  515. {
  516. //写入结束标志
  517. BYTE bytes = 0x3B;
  518. //file.Write(&bytes,1);
  519. DWORD DwWitten=0;
  520. ::WriteFile(file,&bytes,1,&DwWitten,NULL);
  521. }