ImageHandle_Tga.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Copyright (C) =USTC= Fu Li
  3. *
  4. * Author : Fu Li
  5. * Create : 2004-4-9
  6. * Home : http://www.crazy-bit.com/
  7. * Mail : crazybit@263.net
  8. * History :
  9. */
  10. #ifndef __FOO_IMAGE_HANDLE_TGA__2004_04_09__H__
  11. #define __FOO_IMAGE_HANDLE_TGA__2004_04_09__H__
  12. #include "../ObjImage.h"
  13. #include "../compress/Rle.h"
  14. //class FCImageHandle ;
  15. class FCImageHandle_Tga ;
  16. //=============================================================================
  17. /**
  18. * Read/Write TGA image.
  19. */
  20. class FCImageHandle_Tga : public FCImageHandleBase
  21. {
  22. // Definitions for TGA image types.
  23. enum
  24. {
  25. TGA_NULL = 0,
  26. TGA_UCPAL = 1,
  27. TGA_UCRGB = 2,
  28. TGA_UCMONO = 3,
  29. TGA_RLEPAL = 9,
  30. TGA_RLERGB = 10,
  31. TGA_RLEMONO = 11,
  32. };
  33. // TGA file header (same as BMP format, pixel store from left-bottom)
  34. #pragma pack(1)
  35. struct TGAHEAD
  36. {
  37. BYTE byID_Length ; // Number of Characters in Identification Field
  38. BYTE byPalType ; // 00 : no-palette 01 : has-palette
  39. BYTE byImageType ;
  40. WORD wPalFirstNdx ; // 调色板起始索引
  41. WORD wPalLength ; // number of color in palette
  42. BYTE byPalBits ; // 调色板中每一颜色所占位数
  43. WORD wLeft ;
  44. WORD wBottom ;
  45. WORD wWidth ; // width
  46. WORD wHeight ; // height
  47. BYTE byColorBits ; // bpp
  48. struct
  49. {
  50. BYTE AlphaBits : 4 ; // number of attribute bits associated with each pixel
  51. BYTE HorMirror : 1 ; // 1: from right to left
  52. BYTE VerMirror : 1 ; // 为1表示图像数据上下颠倒存储
  53. BYTE Reserved : 2 ;
  54. } Descriptor ;
  55. }; // 18 - Bytes
  56. #pragma pack()
  57. /// Load TGA image.
  58. virtual bool LoadImageMemory (const BYTE* pStart, int nMemSize,
  59. PCL_Interface_Composite<FCObjImage>& rImageList,
  60. std::auto_ptr<FCImageProperty>& rImageProp)
  61. {
  62. const TGAHEAD * pTga = (TGAHEAD*)pStart ;
  63. if (!pStart || (nMemSize <= sizeof(TGAHEAD)))
  64. return false ;
  65. if ((pTga->byPalBits == 15) || (pTga->byPalBits == 16))
  66. return false ; // not support 15 or 16 bit palette
  67. // create image
  68. FCObjImage * pImg = new FCObjImage ;
  69. if (!pImg->Create (pTga->wWidth, pTga->wHeight, (pTga->byColorBits == 15) ? 16 : pTga->byColorBits))
  70. {
  71. delete pImg; return false ;
  72. }
  73. // set palette
  74. const BYTE * pCurr = pStart + sizeof(TGAHEAD) + pTga->byID_Length ;
  75. if (pTga->byPalType == 1)
  76. {
  77. if (pTga->wPalFirstNdx + pTga->wPalLength > 256)
  78. {
  79. delete pImg; return false ;
  80. }
  81. RGBQUAD pPal[256] = {0} ;
  82. for (int i=0 ; i < pTga->wPalLength ; i++)
  83. {
  84. PCL_B(&pPal[pTga->wPalFirstNdx + i]) = *pCurr++ ;
  85. PCL_G(&pPal[pTga->wPalFirstNdx + i]) = *pCurr++ ;
  86. PCL_R(&pPal[pTga->wPalFirstNdx + i]) = *pCurr++ ;
  87. if (pTga->byPalBits == 32)
  88. PCL_A(&pPal[pTga->wPalFirstNdx + i]) = *pCurr++ ;
  89. }
  90. pImg->SetColorTable (0, 256, pPal) ;
  91. }
  92. // start decode
  93. for (int i=0 ; i < pImg->Height() ; i++)
  94. {
  95. BYTE * pDest ;
  96. if (pStart[17] & 0x20)
  97. pDest = pImg->GetBits(i) ; // top to bottom
  98. else
  99. pDest = pImg->GetBits(pImg->Height() - 1 - i) ; // bottom to top
  100. if ((pTga->byImageType == TGA_RLEPAL) || (pTga->byImageType == TGA_RLERGB) || (pTga->byImageType == TGA_RLEMONO))
  101. {
  102. pCurr = FCCompress::RLE_TGA_DecodeLine (pCurr, pImg->ColorBits(), pImg->Width(), pDest) ;
  103. }
  104. else // not-compressed
  105. {
  106. int nPitch = pImg->Width() * pImg->ColorBits() / 8 ;
  107. memcpy (pDest, pCurr, nPitch) ;
  108. pCurr += nPitch ;
  109. }
  110. }
  111. // image's property
  112. rImageProp = std::auto_ptr<FCImageProperty>(new FCImageProperty) ;
  113. if ((pTga->byImageType == TGA_RLEPAL) || (pTga->byImageType == TGA_RLERGB) || (pTga->byImageType == TGA_RLEMONO))
  114. {
  115. rImageProp->SetPropertyValue (PROPERTY_TAG_TGA_USERLE, "1") ;
  116. }
  117. else
  118. {
  119. rImageProp->SetPropertyValue (PROPERTY_TAG_TGA_USERLE, "-1") ;
  120. }
  121. // add to list
  122. rImageList.PCL_PushObject (pImg) ;
  123. return true ;
  124. }
  125. /// @param nFlag : 1(use RLE compress) / -1(not use), default(not use)
  126. virtual bool SaveImageFile (const char* szFileName,
  127. const std::deque<const FCObjImage*>& rImageList,
  128. const FCImageProperty& rImageProp)
  129. {
  130. if (rImageList.empty() || !rImageList[0]->IsValidImage())
  131. return false ;
  132. const FCObjImage &img = *rImageList[0] ;
  133. // validate
  134. if ((img.ColorBits() != 8) && (img.ColorBits() != 16) && (img.ColorBits() != 24) && (img.ColorBits() != 32))
  135. return false ;
  136. // create image file
  137. FILE * pf = fopen (szFileName, "wb") ;
  138. if (!pf)
  139. return false ;
  140. // Initialize TGA Header
  141. const char * pTgaInfo = "PhoXo -- TGA" ;
  142. TGAHEAD TgaHead ;
  143. memset (&TgaHead, 0, sizeof(TgaHead)) ;
  144. TgaHead.byID_Length = strlen(pTgaInfo) ; // tga size
  145. TgaHead.byPalType = ((img.ColorBits() == 8) ? 1 : 0) ;
  146. if (TgaSaveUseRLE(rImageProp))
  147. TgaHead.byImageType = ((img.ColorBits() == 8) ? TGA_RLEPAL : TGA_RLERGB) ;
  148. else
  149. TgaHead.byImageType = ((img.ColorBits() == 8) ? TGA_UCPAL : TGA_UCRGB) ;
  150. TgaHead.wPalFirstNdx = 0 ;
  151. TgaHead.wPalLength = 256 ;
  152. TgaHead.byPalBits = 24 ; // palette's bit
  153. TgaHead.wWidth = img.Width() ;
  154. TgaHead.wHeight = img.Height() ;
  155. TgaHead.byColorBits = (BYTE)img.ColorBits() ;
  156. ((BYTE*)&TgaHead)[17] = 0x20 ; // top to bottom
  157. fwrite (&TgaHead, 1, sizeof(TgaHead), pf) ;
  158. fwrite (pTgaInfo, 1, TgaHead.byID_Length, pf) ;
  159. // write palette
  160. if (img.ColorBits() == 8)
  161. {
  162. PCL_array<RGBQUAD> pPal (256) ;
  163. img.GetColorTable (0, 256, pPal.get()) ;
  164. for (int i=0 ; i < 256 ; i++)
  165. fwrite (&pPal[i], 1, 3, pf) ;
  166. }
  167. // write pixels
  168. const int nLineByte = img.ColorBits() * img.Width() / 8 ;
  169. if (TgaSaveUseRLE(rImageProp))
  170. {
  171. // RLE compress
  172. PCL_array<BYTE> pStart (nLineByte * 2 + 4096) ;
  173. for (int y=0 ; y < img.Height() ; y++)
  174. {
  175. BYTE * pEn = FCCompress::RLE_TGA_EncodeLine (img.GetBits(y), img.ColorBits(), img.Width(), pStart.get()) ;
  176. fwrite (pStart.get(), 1, (int)(pEn - pStart.get()), pf) ;
  177. }
  178. }
  179. else
  180. {
  181. // not compress
  182. for (int y=0 ; y < img.Height() ; y++)
  183. fwrite (img.GetBits(y), 1, nLineByte, pf) ;
  184. }
  185. fclose (pf) ;
  186. return true ;
  187. }
  188. };
  189. #endif