ImageInfo.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Graphics/ImageInfo.h>
  14. #include <Engine/Graphics/Color.h>
  15. #include <Engine/Base/Stream.h>
  16. #include <Engine/Base/Memory.h>
  17. #include <Engine/Math/Functions.h>
  18. extern void FlipBitmap( UBYTE *pubSrc, UBYTE *pubDst, PIX pixWidth, PIX pixHeight, INDEX iFlipType, BOOL bAlphaChannel);
  19. // Order of CroTeam true color pixel components
  20. #define COMPONENT_1 red
  21. #define COMPONENT_2 green
  22. #define COMPONENT_3 blue
  23. #define COMPONENT_4 alpha
  24. // and vice versa
  25. #define RED_COMPONENT 0
  26. #define GREEN_COMPONENT 1
  27. #define BLUE_COMPONENT 2
  28. #define ALPHA_COMPONENT 3
  29. // PCX header structure
  30. struct PCXHeader
  31. {
  32. SBYTE MagicID;
  33. SBYTE Version;
  34. SBYTE Encoding;
  35. SBYTE PixelBits;
  36. SWORD Xmin, Ymin, Xmax, Ymax;
  37. SWORD Hres, Vres;
  38. UBYTE Palette[16*3];
  39. SBYTE Reserved;
  40. SBYTE Planes;
  41. UWORD BytesPerLine;
  42. SWORD PaletteInfo;
  43. SWORD HscreenSize, VscreenSize;
  44. SBYTE Filler[54];
  45. };
  46. // TARGA header structure
  47. struct TGAHeader
  48. {
  49. UBYTE IdLenght;
  50. UBYTE ColorMapType;
  51. UBYTE ImageType;
  52. UBYTE ColorMapSpec[5];
  53. UWORD Xorigin;
  54. UWORD Yorigin;
  55. UWORD Width;
  56. UWORD Height;
  57. UBYTE BitsPerPixel;
  58. UBYTE Descriptor;
  59. };
  60. /******************************************************
  61. * Routines for manipulating CroTeam picture raw format
  62. */
  63. CImageInfo::CImageInfo() {
  64. Detach();
  65. }
  66. CImageInfo::~CImageInfo() {
  67. Clear();
  68. }
  69. // reads image info raw format from file
  70. void CImageInfo::Read_t( CTStream *inFile) // throw char *
  71. {
  72. Clear();
  73. // read image info header
  74. inFile->ExpectID_t( CChunkID("CTII"));
  75. if( inFile->GetSize_t() != 5*4) throw( "Invalid image info file.");
  76. *inFile >> (PIX)ii_Width;
  77. *inFile >> (PIX)ii_Height;
  78. *inFile >> (SLONG)ii_BitsPerPixel;
  79. // read image contents (all channels)
  80. ULONG pic_size = ii_Width*ii_Height * ii_BitsPerPixel/8;
  81. ii_Picture = (UBYTE*)AllocMemory( pic_size);
  82. inFile->ReadFullChunk_t( CChunkID("IPIC"), ii_Picture, pic_size);
  83. }
  84. // writes image info raw format to file
  85. void CImageInfo::Write_t( CTStream *outFile) const // throw char *
  86. {
  87. // write image info header
  88. outFile->WriteID_t( CChunkID("CTII"));
  89. outFile->WriteSize_t( 5*4);
  90. *outFile << (PIX)ii_Width;
  91. *outFile << (PIX)ii_Height;
  92. *outFile << (SLONG)ii_BitsPerPixel;
  93. // write image contents (all channels)
  94. ULONG pic_size = ii_Width*ii_Height * ii_BitsPerPixel/8;
  95. outFile->WriteFullChunk_t( CChunkID("IPIC"), ii_Picture, pic_size);
  96. }
  97. // initializes structure members and attaches pointer to image
  98. void CImageInfo::Attach( UBYTE *pPicture, PIX pixWidth, PIX pixHeight, SLONG slBitsPerPixel)
  99. {
  100. // parameters must be meaningful
  101. ASSERT( (pPicture != NULL) && (pixWidth>0) && (pixHeight>0));
  102. ASSERT( (slBitsPerPixel == 24) || (slBitsPerPixel == 32));
  103. // do it ...
  104. ii_Picture = pPicture;
  105. ii_Width = pixWidth;
  106. ii_Height = pixHeight;
  107. ii_BitsPerPixel = slBitsPerPixel;
  108. }
  109. // clears the content of an image info structure but does not free allocated memory
  110. void CImageInfo::Detach(void)
  111. {
  112. ii_Picture = NULL;
  113. ii_Width = 0;
  114. ii_Height = 0;
  115. ii_BitsPerPixel = 0;
  116. }
  117. // clears the content of an image info structure and frees allocated memory (if any)
  118. void CImageInfo::Clear()
  119. {
  120. // if allocated, release picture memory
  121. if( ii_Picture != NULL) FreeMemory( ii_Picture);
  122. Detach();
  123. }
  124. // expand image edges
  125. void CImageInfo::ExpandEdges( INDEX ctPasses/*=8192*/)
  126. {
  127. // do nothing if image is too small or doesn't have an alpha channel
  128. if( ii_Width<3 || ii_Height<3 || ii_BitsPerPixel!=32) return;
  129. // allocate some memory for spare picture and wipe it clean
  130. SLONG slSize = ii_Width*ii_Height*ii_BitsPerPixel/8;
  131. ULONG *pulSrc = (ULONG*)ii_Picture;
  132. ULONG *pulDst = (ULONG*)AllocMemory(slSize);
  133. memcpy( pulDst, pulSrc, slSize);
  134. // loop while there are some more pixels to be processed or for specified number of passes
  135. for( INDEX iPass=0; iPass<ctPasses; iPass++)
  136. {
  137. BOOL bAllPixelsVisible = TRUE;
  138. // loop thru rows
  139. for( PIX pixV=1; pixV<ii_Height-1; pixV++)
  140. { // loop thru pixels in row
  141. for( PIX pixU=1; pixU<ii_Width-1; pixU++)
  142. { // determine pixel location
  143. const PIX pixOffset = pixV*ii_Width + pixU;
  144. // do nothing if it is already visible
  145. COLOR col = ByteSwap(pulSrc[pixOffset]);
  146. if( ((col&CT_AMASK)>>CT_ASHIFT)>3) continue;
  147. bAllPixelsVisible = FALSE;
  148. // average all surrounding pixels that are visible
  149. ULONG ulRa=0, ulGa=0, ulBa=0;
  150. INDEX ctVisible=0;
  151. for( INDEX j=-1; j<=1; j++) {
  152. for( INDEX i=-1; i<=1; i++) {
  153. const PIX pixSurrOffset = pixOffset + j*ii_Width + i;
  154. col = ByteSwap(pulSrc[pixSurrOffset]);
  155. if( ((col&CT_AMASK)>>CT_ASHIFT)<4) continue; // skip non-visible pixels
  156. UBYTE ubR, ubG, ubB;
  157. ColorToRGB( col, ubR,ubG,ubB);
  158. ulRa+=ubR; ulGa+=ubG; ulBa += ubB;
  159. ctVisible++;
  160. }
  161. } // if there were some visible pixels around
  162. if( ctVisible>0) {
  163. // calc average
  164. ulRa/=ctVisible; ulGa/=ctVisible; ulBa/=ctVisible;
  165. col = RGBAToColor( ulRa,ulGa,ulBa,255);
  166. // put it to center pixel
  167. pulDst[pixOffset] = ByteSwap(col);
  168. }
  169. }
  170. } // copy resulting picture over source
  171. memcpy( pulSrc, pulDst, slSize);
  172. // done if all pixels are visible
  173. if( bAllPixelsVisible) break;
  174. }
  175. // free temp memory
  176. FreeMemory(pulDst);
  177. }
  178. // sets image info structure members with info form file of any supported graphic format
  179. // (CT RAW, PCX8, PCX24, TGA32 uncompressed), but does not load picture content nor palette
  180. INDEX CImageInfo::GetGfxFileInfo_t( const CTFileName &strFileName) // throw char *
  181. {
  182. CTFileStream GfxFile;
  183. TGAHeader TGAhdr;
  184. PCXHeader PCXhdr;
  185. // lets assume it's a TGA file
  186. GfxFile.Open_t( strFileName, CTStream::OM_READ);
  187. GfxFile.Read_t( &TGAhdr, sizeof( struct TGAHeader));
  188. GfxFile.Close();
  189. // check for supported targa format
  190. if( (TGAhdr.ImageType==2 || TGAhdr.ImageType==10) && TGAhdr.BitsPerPixel>=24) {
  191. // targa it is, so clear image info and set new values
  192. Clear();
  193. ii_Width = TGAhdr.Width;
  194. ii_Height = TGAhdr.Height;
  195. ii_BitsPerPixel = TGAhdr.BitsPerPixel;
  196. // we done here, no need to check further
  197. return TGA_FILE;
  198. }
  199. // we miss Targa, so lets check for supported PCX format
  200. GfxFile.Open_t( strFileName, CTStream::OM_READ);
  201. GfxFile.Read_t( &PCXhdr, sizeof( struct PCXHeader));
  202. GfxFile.Close();
  203. // check for supported PCX format
  204. if( (PCXhdr.MagicID == 10) && (PCXhdr.PixelBits == 8)) {
  205. // PCX it is, so clear image info and set new values
  206. Clear();
  207. ii_Width = PCXhdr.Xmax - PCXhdr.Xmin + 1;
  208. ii_Height = PCXhdr.Ymax - PCXhdr.Ymin + 1;
  209. ii_BitsPerPixel = PCXhdr.PixelBits * PCXhdr.Planes;
  210. // we done here, no need to check further
  211. return PCX_FILE;
  212. }
  213. // we didn't found a supported gfx format, sorry ...
  214. return UNSUPPORTED_FILE;
  215. }
  216. /* TGA *********************************************************************************
  217. * Routines that load and save true color (24 or 32 bit per pixel) uncompressed targa file
  218. */
  219. void CImageInfo::LoadTGA_t( const CTFileName &strFileName) // throw char *
  220. {
  221. TGAHeader *pTGAHdr;
  222. UBYTE *pTGABuffer, *pTGAImage;
  223. SLONG slFileSize;
  224. CTFileStream TGAFile;
  225. Clear();
  226. // determine file size
  227. TGAFile.Open_t( strFileName, CTStream::OM_READ);
  228. slFileSize = TGAFile.GetStreamSize();
  229. // load entire TGA file to memory, as is, and close it (no further usage)
  230. pTGABuffer = (UBYTE*)AllocMemory( slFileSize);
  231. TGAFile.Read_t( pTGABuffer, slFileSize);
  232. TGAFile.Close();
  233. // TGA header starts at the begining of the TGA file
  234. pTGAHdr = (struct TGAHeader*)pTGABuffer;
  235. // TGA image bytes definition follows up
  236. pTGAImage = pTGABuffer + sizeof(struct TGAHeader) + pTGAHdr->IdLenght;
  237. // detremine picture size dimensions
  238. ii_Width = (SLONG)pTGAHdr->Width;
  239. ii_Height = (SLONG)pTGAHdr->Height;
  240. ii_BitsPerPixel = (SLONG)pTGAHdr->BitsPerPixel;
  241. SLONG slBytesPerPixel = ii_BitsPerPixel/8;
  242. PIX pixBitmapSize = ii_Width*ii_Height;
  243. BOOL bAlphaChannel = (slBytesPerPixel==4);
  244. // check for supported file types
  245. ASSERT( slBytesPerPixel==3 || slBytesPerPixel==4);
  246. if( slBytesPerPixel!=3 && slBytesPerPixel!=4) throw( TRANS("Unsupported BitsPerPixel in TGA format."));
  247. // allocate memory for image content
  248. ii_Picture = (UBYTE*)AllocMemory( ii_Width*ii_Height *slBytesPerPixel);
  249. UBYTE *pubSrc = pTGAImage; // need 'walking' pointers
  250. UBYTE *pubDst = ii_Picture;
  251. // determine TGA image type
  252. if( pTGAHdr->ImageType==10) {
  253. // RLE encoded
  254. UBYTE ubControl;
  255. INDEX iBlockSize;
  256. BOOL bRepeat;
  257. PIX pixCurrentSize=0;
  258. // loop thru blocks
  259. while( pixCurrentSize<pixBitmapSize)
  260. { // readout control byte
  261. ubControl = *pubSrc++;
  262. bRepeat = ubControl&0x80;
  263. iBlockSize = (ubControl&0x7F) +1;
  264. // repeat or copy color values
  265. for( INDEX i=0; i<iBlockSize; i++) {
  266. *pubDst++ = pubSrc[0];
  267. *pubDst++ = pubSrc[1];
  268. *pubDst++ = pubSrc[2];
  269. if( bAlphaChannel) *pubDst++ = pubSrc[3];
  270. if( !bRepeat) pubSrc += slBytesPerPixel;
  271. }
  272. // advance for next block if repeated
  273. if( bRepeat) pubSrc += slBytesPerPixel;
  274. // update image size
  275. pixCurrentSize += iBlockSize;
  276. }
  277. // mark that image was encoded to ImageInfo buffer
  278. pTGAImage = ii_Picture;
  279. }
  280. // not true-colored?
  281. else if( pTGAHdr->ImageType!=2) {
  282. // whoops!
  283. ASSERTALWAYS("Unsupported TGA format.");
  284. throw( TRANS("Unsupported TGA format."));
  285. }
  286. // determine image flipping
  287. INDEX iFlipType;
  288. switch( (pTGAHdr->Descriptor&0x30)>>4) {
  289. case 0: iFlipType = 1; break; // vertical flipping
  290. case 1: iFlipType = 3; break; // diagonal flipping
  291. case 3: iFlipType = 2; break; // horizontal flipping
  292. default: iFlipType = 0; break; // no flipping (just copying)
  293. }
  294. // do flipping
  295. FlipBitmap( pTGAImage, ii_Picture, ii_Width, ii_Height, iFlipType, bAlphaChannel);
  296. // convert TGA pixel format to CroTeam
  297. pubSrc = ii_Picture; // need 'walking' pointer again
  298. for( INDEX iPix=0; iPix<pixBitmapSize; iPix++)
  299. { // flip bytes
  300. Swap( pubSrc[0], pubSrc[2]); // R & B channels
  301. pubSrc += slBytesPerPixel;
  302. }
  303. // free temorary allocated memory for TGA image format
  304. FreeMemory( pTGABuffer);
  305. }
  306. // save TGA routine
  307. void CImageInfo::SaveTGA_t( const CTFileName &strFileName) const // throw char *
  308. {
  309. TGAHeader *pTGAHdr;
  310. UBYTE *pTGABuffer, *pTGAImage;
  311. SLONG slFileSize;
  312. PIX pixBitmapSize = ii_Width*ii_Height;
  313. CTFileStream TGAFile;
  314. // determine and check image info format
  315. SLONG slBytesPerPixel = ii_BitsPerPixel/8;
  316. ASSERT( slBytesPerPixel==3 || slBytesPerPixel==4);
  317. if( slBytesPerPixel!=3 && slBytesPerPixel!=4) throw( TRANS( "Unsupported BitsPerPixel in ImageInfo header."));
  318. // determine TGA file size and allocate memory
  319. slFileSize = sizeof(struct TGAHeader) + pixBitmapSize *slBytesPerPixel;
  320. pTGABuffer = (UBYTE*)AllocMemory( slFileSize);
  321. pTGAHdr = (struct TGAHeader*)pTGABuffer;
  322. pTGAImage = pTGABuffer + sizeof(struct TGAHeader);
  323. // set TGA picture size dimensions
  324. memset( pTGABuffer, 0x0, sizeof(struct TGAHeader));
  325. pTGAHdr->Width = (UWORD)ii_Width;
  326. pTGAHdr->Height = (UWORD)ii_Height;
  327. pTGAHdr->BitsPerPixel = (UBYTE)ii_BitsPerPixel;
  328. pTGAHdr->ImageType = 2;
  329. // flip image vertically
  330. BOOL bAlphaChannel = (slBytesPerPixel==4);
  331. FlipBitmap( ii_Picture, pTGAImage, ii_Width, ii_Height, 1, bAlphaChannel);
  332. // convert CroTeam's pixel format to TGA format
  333. UBYTE *pubTmp = pTGAImage; // need 'walking' pointer
  334. for( INDEX iPix=0; iPix<pixBitmapSize; iPix++)
  335. { // flip bytes
  336. Swap( pubTmp[0], pubTmp[2]); // R & B channels
  337. pubTmp += slBytesPerPixel;
  338. }
  339. // save entire TGA memory to file and close it
  340. TGAFile.Create_t( strFileName);
  341. TGAFile.Write_t( pTGABuffer, slFileSize);
  342. TGAFile.Close();
  343. // free temorary allocated memory for TGA image format
  344. FreeMemory( pTGABuffer);
  345. }
  346. /* PCX ***********************************************************************
  347. * This routine reads file with given file name and if it is valid PCX file it
  348. * loads it into given ImageInfo structure in CroTeam true-color format.
  349. * (and, if the one exists, loads the palette)
  350. */
  351. void CImageInfo::LoadPCX_t( const CTFileName &strFileName) // throw char *
  352. {
  353. PCXHeader *pPCXHdr;
  354. UBYTE *pPCXBuffer, *pPCXImage, *pPCXDecodedImage, *pTmp;
  355. UBYTE data, counter;
  356. SLONG pic_size, PCX_size, slFileSize;
  357. CTFileStream PCXFile;
  358. Clear();
  359. // inconvinent way to determine file size
  360. PCXFile.Open_t( strFileName, CTStream::OM_READ);
  361. slFileSize = PCXFile.GetStreamSize();
  362. // load entire PCX file to memory, as is, and close it (no further usage)
  363. pPCXBuffer = (UBYTE*)AllocMemory( slFileSize);
  364. PCXFile.Read_t( pPCXBuffer, slFileSize);
  365. PCXFile.Close();
  366. // PCX header starts at the begining of the PCX file
  367. pPCXHdr = (struct PCXHeader*)pPCXBuffer;
  368. // PCX image bytes definition follows up
  369. pPCXImage = pPCXBuffer + sizeof( struct PCXHeader);
  370. // detremine picture size dimensions
  371. ii_Width = (SLONG)(pPCXHdr->Xmax - pPCXHdr->Xmin +1);
  372. ii_Height = (SLONG)(pPCXHdr->Ymax - pPCXHdr->Ymin +1);
  373. ii_BitsPerPixel = (SLONG)pPCXHdr->Planes*8;
  374. pic_size = ii_Width * ii_Height * ii_BitsPerPixel/8;
  375. // allocate memory for image content
  376. ii_Picture = (UBYTE*)AllocMemory( pic_size);
  377. // allocate memory for decoded PCX file that hasn't been converted to CT RAW Image format
  378. PCX_size = (SLONG)(pPCXHdr->BytesPerLine * ii_Height * ii_BitsPerPixel/8);
  379. pPCXDecodedImage = (UBYTE*)AllocMemory( PCX_size);
  380. pTmp = pPCXDecodedImage; // save pointer for latter usage
  381. // decode PCX file
  382. for( INDEX i=0; i<PCX_size; ) // i is incremented by counter value at the and of the loop
  383. {
  384. // read one byte from PCX image in memory
  385. data = *pPCXImage++;
  386. // check byte-run mark
  387. if( (data & 0xC0) == 0xC0) {
  388. counter = data & 0x3F; // determine repeat value
  389. data = *pPCXImage++; // read repeated data
  390. // put several bytes of PCX image to decoded image area in memory
  391. for( INDEX j=0; j<counter; j++)
  392. *pPCXDecodedImage++ = data;
  393. } else {
  394. // put just one byte from PCX image to decoded image area in memory
  395. counter = 1;
  396. *pPCXDecodedImage++ = data;
  397. }
  398. // increment encoded image counter
  399. i += counter;
  400. }
  401. pPCXDecodedImage = pTmp; // reset pointer
  402. // convert decoded PCX image to CroTeam RAW Image Info format
  403. SLONG slBytesPerPixel = ii_BitsPerPixel/8;
  404. for( INDEX y=0; y<ii_Height; y++)
  405. {
  406. SLONG slYSrcOfs = y * ii_Width * slBytesPerPixel;
  407. SLONG slYDstOfs = y * pPCXHdr->BytesPerLine * slBytesPerPixel;
  408. // channel looper
  409. for( INDEX p=0; p<slBytesPerPixel; p++)
  410. {
  411. SLONG slPOffset = p * pPCXHdr->BytesPerLine;
  412. // byte looper
  413. for( INDEX x=0; x<ii_Width; x++)
  414. *(ii_Picture + slYSrcOfs + x*slBytesPerPixel + p) =
  415. *(pPCXDecodedImage + slYDstOfs + slPOffset + x);
  416. }
  417. }
  418. // free temorary allocated memory for PCX encoded and decoded image
  419. FreeMemory( pPCXBuffer);
  420. FreeMemory( pPCXDecodedImage);
  421. }
  422. // check for the supported gfx format file and invokes corresponding routine to load it
  423. void CImageInfo::LoadAnyGfxFormat_t( const CTFileName &strFileName) // throw char *
  424. {
  425. INDEX iFileFormat = GetGfxFileInfo_t( strFileName);
  426. if( iFileFormat == PCX_FILE) LoadPCX_t( strFileName);
  427. if( iFileFormat == TGA_FILE) LoadTGA_t( strFileName);
  428. if( iFileFormat == UNSUPPORTED_FILE) throw( "Gfx format not supported.");
  429. }