himage.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. #ifdef JA2_PRECOMPILED_HEADERS
  2. #include "JA2 SGP ALL.H"
  3. #elif defined( WIZ8_PRECOMPILED_HEADERS )
  4. #include "WIZ8 SGP ALL.H"
  5. #else
  6. #include <math.h>
  7. #include <stdlib.h>
  8. #include "types.h"
  9. #include "string.h"
  10. #include "debug.h"
  11. #include "fileman.h"
  12. #include "himage.h"
  13. #include "impTGA.h"
  14. #include "pcx.h"
  15. #include "STCI.h"
  16. #include "wcheck.h"
  17. #include "Compression.h"
  18. #include "vobject.h"
  19. #endif
  20. // This is the color substituted to keep a 24bpp -> 16bpp color
  21. // from going transparent (0x0000) -- DB
  22. #define BLACK_SUBSTITUTE 0x0001
  23. UINT16 gusAlphaMask = 0;
  24. UINT16 gusRedMask = 0;
  25. UINT16 gusGreenMask = 0;
  26. UINT16 gusBlueMask = 0;
  27. INT16 gusRedShift = 0;
  28. INT16 gusBlueShift = 0;
  29. INT16 gusGreenShift = 0;
  30. // this funky union is used for fast 16-bit pixel format conversions
  31. typedef union
  32. {
  33. struct
  34. {
  35. UINT16 usLower;
  36. UINT16 usHigher;
  37. };
  38. UINT32 uiValue;
  39. } SplitUINT32;
  40. HIMAGE CreateImage( SGPFILENAME ImageFile, UINT16 fContents )
  41. {
  42. HIMAGE hImage = NULL;
  43. SGPFILENAME Extension;
  44. CHAR8 ExtensionSep[] = ".";
  45. STR StrPtr;
  46. UINT32 iFileLoader;
  47. // Depending on extension of filename, use different image readers
  48. // Get extension
  49. StrPtr = strstr( ImageFile, ExtensionSep );
  50. if ( StrPtr == NULL )
  51. {
  52. // No extension given, use default internal loader extension
  53. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "No extension given, using default" );
  54. strcat( ImageFile, ".PCX" );
  55. strcpy( Extension, ".PCX" );
  56. }
  57. else
  58. {
  59. strcpy( Extension, StrPtr+1 );
  60. }
  61. // Determine type from Extension
  62. do
  63. {
  64. iFileLoader = UNKNOWN_FILE_READER;
  65. if ( _stricmp( Extension, "PCX" ) == 0 )
  66. {
  67. iFileLoader = PCX_FILE_READER;
  68. break;
  69. }
  70. if ( _stricmp( Extension, "TGA" ) == 0 )
  71. {
  72. iFileLoader = TGA_FILE_READER;
  73. break;
  74. }
  75. if ( _stricmp( Extension, "STI" ) == 0 )
  76. {
  77. iFileLoader = STCI_FILE_READER;
  78. break;
  79. }
  80. } while ( FALSE );
  81. // Determine if resource exists before creating image structure
  82. if ( !FileExists( ImageFile ) )
  83. {
  84. //If in debig, make fatal!
  85. #ifdef JA2
  86. #ifdef _DEBUG
  87. //FatalError( "Resource file %s does not exist.", ImageFile );
  88. #endif
  89. #endif
  90. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, String("Resource file %s does not exist.", ImageFile) );
  91. return( NULL );
  92. }
  93. // Create memory for image structure
  94. hImage = (HIMAGE)MemAlloc( sizeof( image_type ) );
  95. AssertMsg( hImage, "Failed to allocate memory for hImage in CreateImage");
  96. // Initialize some values
  97. memset( hImage, 0, sizeof( image_type ) );
  98. //hImage->fFlags = 0;
  99. // Set data pointers to NULL
  100. //hImage->pImageData = NULL;
  101. //hImage->pPalette = NULL;
  102. //hImage->pui16BPPPalette = NULL;
  103. // Set filename and loader
  104. strcpy( hImage->ImageFile, ImageFile );
  105. hImage->iFileLoader = iFileLoader;
  106. if ( !LoadImageData( hImage, fContents ) )
  107. {
  108. return( NULL );
  109. }
  110. // All is fine, image is loaded and allocated, return pointer
  111. return( hImage );
  112. }
  113. BOOLEAN DestroyImage( HIMAGE hImage )
  114. {
  115. Assert( hImage != NULL );
  116. // First delete contents
  117. ReleaseImageData( hImage, IMAGE_ALLDATA );//hImage->fFlags );
  118. // Now free structure
  119. MemFree( hImage );
  120. return( TRUE );
  121. }
  122. BOOLEAN ReleaseImageData( HIMAGE hImage, UINT16 fContents )
  123. {
  124. Assert( hImage != NULL );
  125. if ( (fContents & IMAGE_PALETTE) && (hImage->fFlags & IMAGE_PALETTE) )
  126. {
  127. //Destroy palette
  128. if( hImage->pPalette != NULL )
  129. {
  130. MemFree( hImage->pPalette );
  131. hImage->pPalette = NULL;
  132. }
  133. if ( hImage->pui16BPPPalette != NULL )
  134. {
  135. MemFree( hImage->pui16BPPPalette );
  136. hImage->pui16BPPPalette = NULL;
  137. }
  138. // Remove contents flag
  139. hImage->fFlags = hImage->fFlags ^ IMAGE_PALETTE;
  140. }
  141. if ( (fContents & IMAGE_BITMAPDATA) && (hImage->fFlags & IMAGE_BITMAPDATA) )
  142. {
  143. //Destroy image data
  144. Assert( hImage->pImageData != NULL );
  145. MemFree( hImage->pImageData );
  146. hImage->pImageData = NULL;
  147. if (hImage->usNumberOfObjects > 0)
  148. {
  149. MemFree( hImage->pETRLEObject );
  150. }
  151. // Remove contents flag
  152. hImage->fFlags = hImage->fFlags ^ IMAGE_BITMAPDATA;
  153. }
  154. if ( (fContents & IMAGE_APPDATA) && (hImage->fFlags & IMAGE_APPDATA) )
  155. {
  156. // get rid of the APP DATA
  157. if ( hImage->pAppData != NULL )
  158. {
  159. MemFree( hImage->pAppData );
  160. hImage->fFlags &= (~IMAGE_APPDATA);
  161. }
  162. }
  163. return( TRUE );
  164. }
  165. BOOLEAN LoadImageData( HIMAGE hImage, UINT16 fContents )
  166. {
  167. BOOLEAN fReturnVal = FALSE;
  168. Assert( hImage != NULL );
  169. // Switch on file loader
  170. switch( hImage->iFileLoader )
  171. {
  172. case TGA_FILE_READER:
  173. fReturnVal = LoadTGAFileToImage( hImage, fContents );
  174. break;
  175. case PCX_FILE_READER:
  176. fReturnVal = LoadPCXFileToImage( hImage, fContents );
  177. break;
  178. case STCI_FILE_READER:
  179. fReturnVal = LoadSTCIFileToImage( hImage, fContents );
  180. break;
  181. default:
  182. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Unknown image loader was specified." );
  183. }
  184. if ( !fReturnVal )
  185. {
  186. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Error occured while reading image data." );
  187. }
  188. return( fReturnVal );
  189. }
  190. BOOLEAN CopyImageToBuffer( HIMAGE hImage, UINT32 fBufferType, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  191. {
  192. // Use blitter based on type of image
  193. Assert( hImage != NULL );
  194. if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_8BPP )
  195. {
  196. #ifndef NO_ZLIB_COMPRESSION
  197. if ( hImage->fFlags & IMAGE_COMPRESSED )
  198. {
  199. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying Compressed 8 BPP Imagery." );
  200. return( Copy8BPPCompressedImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  201. }
  202. #endif
  203. // Default do here
  204. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "Copying 8 BPP Imagery." );
  205. return ( Copy8BPPImageTo8BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  206. }
  207. if ( hImage->ubBitDepth == 8 && fBufferType == BUFFER_16BPP )
  208. {
  209. #ifndef NO_ZLIB_COMPRESSION
  210. if ( hImage->fFlags & IMAGE_COMPRESSED )
  211. {
  212. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying Compressed 8 BPP Imagery to 16BPP Buffer." );
  213. return ( Copy8BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  214. }
  215. #endif
  216. // Default do here
  217. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Copying 8 BPP Imagery to 16BPP Buffer." );
  218. return ( Copy8BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  219. }
  220. if ( hImage->ubBitDepth == 16 && fBufferType == BUFFER_16BPP )
  221. {
  222. #ifndef NO_ZLIB_COMPRESSION
  223. if ( hImage->fFlags & IMAGE_COMPRESSED )
  224. {
  225. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying Compressed 16 BPP Imagery." );
  226. return( Copy16BPPCompressedImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  227. }
  228. #endif
  229. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Automatically Copying 16 BPP Imagery." );
  230. return( Copy16BPPImageTo16BPPBuffer( hImage, pDestBuf, usDestWidth, usDestHeight, usX, usY, srcRect ) );
  231. }
  232. return( FALSE );
  233. }
  234. #ifndef NO_ZLIB_COMPRESSION
  235. BOOLEAN Copy8BPPCompressedImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  236. {
  237. UINT32 uiNumLines;
  238. UINT32 uiLineSize;
  239. UINT32 uiCnt;
  240. UINT8 * pDest;
  241. UINT32 uiDestStart;
  242. UINT8 * pScanLine;
  243. PTR pDecompPtr;
  244. UINT32 uiDecompressed;
  245. // Assertions
  246. Assert( hImage != NULL );
  247. Assert( hImage->pCompressedImageData != NULL );
  248. // Validations
  249. CHECKF( usX >= 0 );
  250. CHECKF( usX < usDestWidth );
  251. CHECKF( usY >= 0 );
  252. CHECKF( usY < usDestHeight );
  253. CHECKF( srcRect->iRight > srcRect->iLeft );
  254. CHECKF( srcRect->iBottom > srcRect->iTop );
  255. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "8BPP to 8BPP Compressed Blitter Called!" );
  256. // determine where to start Copying and rectangle size
  257. uiDestStart = usY * usDestWidth + usX;
  258. uiNumLines = srcRect->iBottom - srcRect->iTop;
  259. uiLineSize = srcRect->iRight - srcRect->iLeft;
  260. Assert( usDestWidth >= uiLineSize );
  261. Assert( usDestHeight >= uiNumLines );
  262. pDest = (UINT8 *) pDestBuf + uiDestStart;
  263. // Copying a portion of a compressed image is rather messy
  264. // because we have to decompress past all the data we want
  265. // to skip.
  266. // To keep memory requirements small and regular, we will
  267. // decompress one scanline at a time even if none of the data will
  268. // be blitted (but stop when the bottom line of the rectangle
  269. // to blit has been done).
  270. // initialize the decompression routines
  271. pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight );
  272. CHECKF( pDecompPtr );
  273. // Allocate memory for one scanline
  274. pScanLine = MemAlloc( hImage->usWidth );
  275. CHECKF( pScanLine );
  276. // go past all the scanlines we don't need to process
  277. for (uiCnt = 0; uiCnt < (UINT32) srcRect->iTop; uiCnt++)
  278. {
  279. uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
  280. Assert( uiDecompressed == hImage->usWidth );
  281. }
  282. // now we start Copying
  283. for (uiCnt = 0; uiCnt < uiNumLines - 1; uiCnt++)
  284. {
  285. // decompress a scanline
  286. uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
  287. Assert( uiDecompressed == hImage->usWidth );
  288. // and blit
  289. // memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize );
  290. pDest += usDestWidth;
  291. }
  292. // decompress the last scanline and blit
  293. uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
  294. Assert( uiDecompressed == hImage->usWidth );
  295. // memcpy( pDest, pScanLine + srcRect->iLeft, uiLineSize );
  296. DecompressFini( pDecompPtr );
  297. return( TRUE );
  298. }
  299. BOOLEAN Copy8BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  300. {
  301. UINT32 uiNumLines;
  302. UINT32 uiLineSize;
  303. UINT32 uiLine;
  304. UINT32 uiCol;
  305. UINT16 * pDest;
  306. UINT16 * pDestTemp;
  307. UINT32 uiDestStart;
  308. UINT8 * pScanLine;
  309. UINT8 * pScanLineTemp;
  310. PTR pDecompPtr;
  311. UINT32 uiDecompressed;
  312. UINT16 * p16BPPPalette;
  313. // Assertions
  314. Assert( hImage != NULL );
  315. Assert( hImage->pCompressedImageData != NULL );
  316. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Start check" );
  317. // Validations
  318. CHECKF( usX >= 0 );
  319. CHECKF( usX < usDestWidth );
  320. CHECKF( usY >= 0 );
  321. CHECKF( usY < usDestHeight );
  322. CHECKF( srcRect->iRight > srcRect->iLeft );
  323. CHECKF( srcRect->iBottom > srcRect->iTop );
  324. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "End check" );
  325. p16BPPPalette = hImage->pui16BPPPalette;
  326. // determine where to start Copying and rectangle size
  327. uiDestStart = usY * usDestWidth + usX;
  328. uiNumLines = srcRect->iBottom - srcRect->iTop;
  329. uiLineSize = srcRect->iRight - srcRect->iLeft;
  330. Assert( usDestWidth >= uiLineSize );
  331. Assert( usDestHeight >= uiNumLines );
  332. pDest = (UINT16 *) pDestBuf;
  333. pDest += uiDestStart;
  334. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) );
  335. // Copying a portion of a compressed image is rather messy
  336. // because we have to decompress past all the data we want
  337. // to skip.
  338. // To keep memory requirements small and regular, we will
  339. // decompress one scanline at a time even if none of the data will
  340. // be blitted (but stop when the bottom line of the rectangle
  341. // to blit has been done).
  342. // initialize the decompression routines
  343. pDecompPtr = DecompressInit( hImage->pCompressedImageData, hImage->usWidth * hImage->usHeight );
  344. CHECKF( pDecompPtr );
  345. // Allocate memory for one scanline
  346. pScanLine = MemAlloc( hImage->usWidth );
  347. CHECKF( pScanLine );
  348. // go past all the scanlines we don't need to process
  349. for (uiLine = 0; uiLine < (UINT32) srcRect->iTop; uiLine++)
  350. {
  351. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Skipping scanline" );
  352. uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
  353. Assert( uiDecompressed == hImage->usWidth );
  354. }
  355. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, "Actually Copying" );
  356. // now we start Copying
  357. for (uiLine = 0; uiLine < uiNumLines - 1; uiLine++)
  358. {
  359. // decompress a scanline
  360. uiDecompressed = Decompress( pDecompPtr, pScanLine, hImage->usWidth );
  361. Assert( uiDecompressed == hImage->usWidth );
  362. // set pointers and blit
  363. pDestTemp = pDest;
  364. pScanLineTemp = pScanLine + srcRect->iLeft;
  365. for (uiCol = 0; uiCol < uiLineSize; uiCol++ )
  366. {
  367. *pDestTemp = p16BPPPalette[ *pScanLineTemp ];
  368. pDestTemp++;
  369. pScanLineTemp++;
  370. }
  371. pDest += usDestWidth;
  372. }
  373. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) );
  374. DecompressFini( pDecompPtr );
  375. return( TRUE );
  376. }
  377. BOOLEAN Copy16BPPCompressedImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  378. {
  379. // 16BPP Compressed image has not been implemented yet
  380. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_2, "16BPP Compressed imagery blitter has not been implemented yet." );
  381. return( FALSE );
  382. }
  383. #endif //NO_ZLIB_COMPRESSION
  384. BOOLEAN Copy8BPPImageTo8BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  385. {
  386. UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
  387. UINT32 cnt;
  388. UINT8 *pDest, *pSrc;
  389. // Assertions
  390. Assert( hImage != NULL );
  391. Assert( hImage->p16BPPData != NULL );
  392. // Validations
  393. CHECKF( usX >= 0 );
  394. CHECKF( usX < usDestWidth );
  395. CHECKF( usY >= 0 );
  396. CHECKF( usY < usDestHeight );
  397. CHECKF( srcRect->iRight > srcRect->iLeft );
  398. CHECKF( srcRect->iBottom > srcRect->iTop );
  399. // Determine memcopy coordinates
  400. uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
  401. uiDestStart = usY * usDestWidth + usX;
  402. uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1;
  403. uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1;
  404. Assert( usDestWidth >= uiLineSize );
  405. Assert( usDestHeight >= uiNumLines );
  406. // Copy line by line
  407. pDest = ( UINT8*)pDestBuf + uiDestStart;
  408. pSrc = hImage->p8BPPData + uiSrcStart;
  409. for( cnt = 0; cnt < uiNumLines-1; cnt++ )
  410. {
  411. memcpy( pDest, pSrc, uiLineSize );
  412. pDest += usDestWidth;
  413. pSrc += hImage->usWidth;
  414. }
  415. // Do last line
  416. memcpy( pDest, pSrc, uiLineSize );
  417. return( TRUE );
  418. }
  419. BOOLEAN Copy16BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  420. {
  421. UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
  422. UINT32 cnt;
  423. UINT16 *pDest, *pSrc;
  424. Assert( hImage != NULL );
  425. Assert( hImage->p16BPPData != NULL );
  426. // Validations
  427. CHECKF( usX >= 0 );
  428. CHECKF( usX < hImage->usWidth );
  429. CHECKF( usY >= 0 );
  430. CHECKF( usY < hImage->usHeight );
  431. CHECKF( srcRect->iRight > srcRect->iLeft );
  432. CHECKF( srcRect->iBottom > srcRect->iTop );
  433. // Determine memcopy coordinates
  434. uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
  435. uiDestStart = usY * usDestWidth + usX;
  436. uiNumLines = ( srcRect->iBottom - srcRect->iTop ) + 1;
  437. uiLineSize = ( srcRect->iRight - srcRect->iLeft ) + 1;
  438. CHECKF( usDestWidth >= uiLineSize );
  439. CHECKF( usDestHeight >= uiNumLines );
  440. // Copy line by line
  441. pDest = ( UINT16*)pDestBuf + uiDestStart;
  442. pSrc = hImage->p16BPPData + uiSrcStart;
  443. for( cnt = 0; cnt < uiNumLines-1; cnt++ )
  444. {
  445. memcpy( pDest, pSrc, uiLineSize * 2 );
  446. pDest += usDestWidth;
  447. pSrc += hImage->usWidth;
  448. }
  449. // Do last line
  450. memcpy( pDest, pSrc, uiLineSize * 2 );
  451. return( TRUE );
  452. }
  453. BOOLEAN Extract8BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf )
  454. {
  455. return( FALSE );
  456. }
  457. BOOLEAN Extract16BPPCompressedImageToBuffer( HIMAGE hImage, BYTE *pDestBuf )
  458. {
  459. return( FALSE );
  460. }
  461. BOOLEAN Copy8BPPImageTo16BPPBuffer( HIMAGE hImage, BYTE *pDestBuf, UINT16 usDestWidth, UINT16 usDestHeight, UINT16 usX, UINT16 usY, SGPRect *srcRect )
  462. {
  463. UINT32 uiSrcStart, uiDestStart, uiNumLines, uiLineSize;
  464. UINT32 rows, cols;
  465. UINT8 *pSrc, *pSrcTemp;
  466. UINT16 *pDest, *pDestTemp;
  467. UINT16 *p16BPPPalette;
  468. p16BPPPalette = hImage->pui16BPPPalette;
  469. // Assertions
  470. Assert( p16BPPPalette != NULL );
  471. Assert( hImage != NULL );
  472. // Validations
  473. CHECKF( hImage->p16BPPData != NULL );
  474. CHECKF( usX >= 0 );
  475. CHECKF( usX < usDestWidth );
  476. CHECKF( usY >= 0 );
  477. CHECKF( usY < usDestHeight );
  478. CHECKF( srcRect->iRight > srcRect->iLeft );
  479. CHECKF( srcRect->iBottom > srcRect->iTop );
  480. // Determine memcopy coordinates
  481. uiSrcStart = srcRect->iTop * hImage->usWidth + srcRect->iLeft;
  482. uiDestStart = usY * usDestWidth + usX;
  483. uiNumLines = ( srcRect->iBottom - srcRect->iTop );
  484. uiLineSize = ( srcRect->iRight - srcRect->iLeft );
  485. CHECKF( usDestWidth >= uiLineSize );
  486. CHECKF( usDestHeight >= uiNumLines );
  487. // Convert to Pixel specification
  488. pDest = ( UINT16*)pDestBuf + uiDestStart;
  489. pSrc = hImage->p8BPPData + uiSrcStart;
  490. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "Start Copying at %p", pDest ) );
  491. // For every entry, look up into 16BPP palette
  492. for( rows = 0; rows < uiNumLines-1; rows++ )
  493. {
  494. pDestTemp = pDest;
  495. pSrcTemp = pSrc;
  496. for ( cols = 0; cols < uiLineSize; cols++ )
  497. {
  498. *pDestTemp = p16BPPPalette[ *pSrcTemp ];
  499. pDestTemp++;
  500. pSrcTemp++;
  501. }
  502. pDest += usDestWidth;
  503. pSrc += hImage->usWidth;
  504. }
  505. // Do last line
  506. DbgMessage( TOPIC_HIMAGE, DBG_LEVEL_3, String( "End Copying at %p", pDest ) );
  507. return( TRUE );
  508. }
  509. UINT16 *Create16BPPPalette( SGPPaletteEntry *pPalette )
  510. {
  511. UINT16 *p16BPPPalette, r16, g16, b16, usColor;
  512. UINT32 cnt;
  513. UINT8 r,g,b;
  514. Assert( pPalette != NULL );
  515. p16BPPPalette = MemAlloc( sizeof( UINT16 ) * 256 );
  516. for ( cnt = 0; cnt < 256; cnt++ )
  517. {
  518. r = pPalette[ cnt ].peRed;
  519. g = pPalette[ cnt ].peGreen;
  520. b = pPalette[ cnt ].peBlue;
  521. if(gusRedShift < 0)
  522. r16=((UINT16)r>>abs(gusRedShift));
  523. else
  524. r16=((UINT16)r<<gusRedShift);
  525. if(gusGreenShift < 0)
  526. g16=((UINT16)g>>abs(gusGreenShift));
  527. else
  528. g16=((UINT16)g<<gusGreenShift);
  529. if(gusBlueShift < 0)
  530. b16=((UINT16)b>>abs(gusBlueShift));
  531. else
  532. b16=((UINT16)b<<gusBlueShift);
  533. usColor = (r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
  534. if(usColor==0)
  535. {
  536. if((r+g+b)!=0)
  537. usColor=BLACK_SUBSTITUTE | gusAlphaMask;
  538. }
  539. else
  540. usColor |= gusAlphaMask;
  541. p16BPPPalette[ cnt ] = usColor;
  542. }
  543. return( p16BPPPalette );
  544. }
  545. /**********************************************************************************************
  546. Create16BPPPaletteShaded
  547. Creates an 8 bit to 16 bit palette table, and modifies the colors as it builds.
  548. Parameters:
  549. rscale, gscale, bscale:
  550. Color mode: Percentages (255=100%) of color to translate into destination palette.
  551. Mono mode: Color for monochrome palette.
  552. mono:
  553. TRUE or FALSE to create a monochrome palette. In mono mode, Luminance values for
  554. colors are calculated, and the RGB color is shaded according to each pixel's brightness.
  555. This can be used in several ways:
  556. 1) To "brighten" a palette, pass down RGB values that are higher than 100% ( > 255) for all
  557. three. mono=FALSE.
  558. 2) To "darken" a palette, do the same with less than 100% ( < 255) values. mono=FALSE.
  559. 3) To create a "glow" palette, select mono=TRUE, and pass the color in the RGB parameters.
  560. 4) For gamma correction, pass in weighted values for each color.
  561. **********************************************************************************************/
  562. UINT16 *Create16BPPPaletteShaded( SGPPaletteEntry *pPalette, UINT32 rscale, UINT32 gscale, UINT32 bscale, BOOLEAN mono)
  563. {
  564. UINT16 *p16BPPPalette, r16, g16, b16, usColor;
  565. UINT32 cnt, lumin;
  566. UINT32 rmod, gmod, bmod;
  567. UINT8 r,g,b;
  568. Assert( pPalette != NULL );
  569. p16BPPPalette = MemAlloc( sizeof( UINT16 ) * 256 );
  570. for ( cnt = 0; cnt < 256; cnt++ )
  571. {
  572. if(mono)
  573. {
  574. lumin=(pPalette[ cnt ].peRed*299/1000)+ (pPalette[ cnt ].peGreen*587/1000)+(pPalette[ cnt ].peBlue*114/1000);
  575. rmod=(rscale*lumin)/256;
  576. gmod=(gscale*lumin)/256;
  577. bmod=(bscale*lumin)/256;
  578. }
  579. else
  580. {
  581. rmod = (rscale*pPalette[ cnt ].peRed/256);
  582. gmod = (gscale*pPalette[ cnt ].peGreen/256);
  583. bmod = (bscale*pPalette[ cnt ].peBlue/256);
  584. }
  585. r = (UINT8)__min(rmod, 255);
  586. g = (UINT8)__min(gmod, 255);
  587. b = (UINT8)__min(bmod, 255);
  588. if(gusRedShift < 0)
  589. r16=((UINT16)r>>(-gusRedShift));
  590. else
  591. r16=((UINT16)r<<gusRedShift);
  592. if(gusGreenShift < 0)
  593. g16=((UINT16)g>>(-gusGreenShift));
  594. else
  595. g16=((UINT16)g<<gusGreenShift);
  596. if(gusBlueShift < 0)
  597. b16=((UINT16)b>>(-gusBlueShift));
  598. else
  599. b16=((UINT16)b<<gusBlueShift);
  600. // Prevent creation of pure black color
  601. usColor = (r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
  602. if(usColor==0)
  603. {
  604. if((r+g+b)!=0)
  605. usColor=BLACK_SUBSTITUTE | gusAlphaMask;
  606. }
  607. else
  608. usColor |= gusAlphaMask;
  609. p16BPPPalette[ cnt ] = usColor;
  610. }
  611. return( p16BPPPalette );
  612. }
  613. // Convert from RGB to 16 bit value
  614. UINT16 Get16BPPColor( UINT32 RGBValue )
  615. {
  616. UINT16 r16, g16, b16, usColor;
  617. UINT8 r,g,b;
  618. r = SGPGetRValue( RGBValue );
  619. g = SGPGetGValue( RGBValue );
  620. b = SGPGetBValue( RGBValue );
  621. if(gusRedShift < 0)
  622. r16=((UINT16)r>>abs(gusRedShift));
  623. else
  624. r16=((UINT16)r<<gusRedShift);
  625. if(gusGreenShift < 0)
  626. g16=((UINT16)g>>abs(gusGreenShift));
  627. else
  628. g16=((UINT16)g<<gusGreenShift);
  629. if(gusBlueShift < 0)
  630. b16=((UINT16)b>>abs(gusBlueShift));
  631. else
  632. b16=((UINT16)b<<gusBlueShift);
  633. usColor=(r16&gusRedMask)|(g16&gusGreenMask)|(b16&gusBlueMask);
  634. // if our color worked out to absolute black, and the original wasn't
  635. // absolute black, convert it to a VERY dark grey to avoid transparency
  636. // problems
  637. if(usColor==0)
  638. {
  639. if(RGBValue!=0)
  640. usColor=BLACK_SUBSTITUTE | gusAlphaMask;
  641. }
  642. else
  643. usColor |= gusAlphaMask;
  644. return(usColor);
  645. }
  646. // Convert from 16 BPP to RGBvalue
  647. UINT32 GetRGBColor( UINT16 Value16BPP )
  648. {
  649. UINT16 r16, g16, b16;
  650. UINT32 r,g,b,val;
  651. r16 = Value16BPP & gusRedMask;
  652. g16 = Value16BPP & gusGreenMask;
  653. b16 = Value16BPP & gusBlueMask;
  654. if(gusRedShift < 0)
  655. r=((UINT32)r16<<abs(gusRedShift));
  656. else
  657. r=((UINT32)r16>>gusRedShift);
  658. if(gusGreenShift < 0)
  659. g=((UINT32)g16<<abs(gusGreenShift));
  660. else
  661. g=((UINT32)g16>>gusGreenShift);
  662. if(gusBlueShift < 0)
  663. b=((UINT32)b16<<abs(gusBlueShift));
  664. else
  665. b=((UINT32)b16>>gusBlueShift);
  666. r &= 0x000000ff;
  667. g &= 0x000000ff;
  668. b &= 0x000000ff;
  669. val = FROMRGB(r,g,b);
  670. return(val);
  671. }
  672. //*****************************************************************************
  673. //
  674. // ConvertToPaletteEntry
  675. //
  676. // Parameter List : Converts from RGB to SGPPaletteEntry
  677. //
  678. // Return Value pointer to the SGPPaletteEntry
  679. //
  680. // Modification History :
  681. // Dec 15th 1996 -> modified for use by Wizardry
  682. //
  683. //*****************************************************************************
  684. SGPPaletteEntry *ConvertRGBToPaletteEntry(UINT8 sbStart, UINT8 sbEnd, UINT8 *pOldPalette)
  685. {
  686. UINT16 Index;
  687. SGPPaletteEntry *pPalEntry;
  688. SGPPaletteEntry *pInitEntry;
  689. pPalEntry = (SGPPaletteEntry *)MemAlloc(sizeof(SGPPaletteEntry) * 256);
  690. pInitEntry = pPalEntry;
  691. DbgMessage(TOPIC_HIMAGE, DBG_LEVEL_0, "Converting RGB palette to SGPPaletteEntry");
  692. for(Index=0; Index <= (sbEnd-sbStart);Index++)
  693. {
  694. pPalEntry->peRed = *(pOldPalette + (Index*3));
  695. pPalEntry->peGreen = *(pOldPalette + (Index*3) + 1);
  696. pPalEntry->peBlue = *(pOldPalette + (Index*3) + 2);
  697. pPalEntry->peFlags = 0;
  698. pPalEntry++;
  699. }
  700. return pInitEntry;
  701. }
  702. BOOLEAN GetETRLEImageData( HIMAGE hImage, ETRLEData *pBuffer )
  703. {
  704. // Assertions
  705. Assert( hImage != NULL );
  706. Assert( pBuffer != NULL );
  707. // Create memory for data
  708. pBuffer->usNumberOfObjects = hImage->usNumberOfObjects;
  709. // Create buffer for objects
  710. pBuffer->pETRLEObject = MemAlloc( sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects );
  711. CHECKF( pBuffer->pETRLEObject != NULL );
  712. // Copy into buffer
  713. memcpy( pBuffer->pETRLEObject, hImage->pETRLEObject, sizeof( ETRLEObject ) * pBuffer->usNumberOfObjects );
  714. // Allocate memory for pixel data
  715. pBuffer->pPixData = MemAlloc( hImage->uiSizePixData );
  716. CHECKF( pBuffer->pPixData != NULL );
  717. pBuffer->uiSizePixData = hImage->uiSizePixData;
  718. // Copy into buffer
  719. memcpy( pBuffer->pPixData, hImage->pPixData8, pBuffer->uiSizePixData );
  720. return( TRUE );
  721. }
  722. void ConvertRGBDistribution565To555( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
  723. {
  724. UINT16 * pPixel;
  725. UINT32 uiLoop;
  726. SplitUINT32 Pixel;
  727. pPixel = p16BPPData;
  728. for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
  729. {
  730. // If the pixel is completely black, don't bother converting it -- DB
  731. if(*pPixel!=0)
  732. {
  733. // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
  734. // right shift the blue value (at the bottom) into the LOWER word to protect it
  735. Pixel.usHigher = *pPixel;
  736. Pixel.uiValue >>= 5;
  737. // get rid of the least significant bit of green
  738. Pixel.usHigher >>= 1;
  739. // now shift back into the upper word
  740. Pixel.uiValue <<= 5;
  741. // and copy back
  742. *pPixel = Pixel.usHigher | gusAlphaMask;
  743. }
  744. pPixel++;
  745. }
  746. }
  747. void ConvertRGBDistribution565To655( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
  748. {
  749. UINT16 * pPixel;
  750. UINT32 uiLoop;
  751. SplitUINT32 Pixel;
  752. pPixel = p16BPPData;
  753. for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
  754. {
  755. // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
  756. // right shift the blue value (at the bottom) into the LOWER word to protect it
  757. Pixel.usHigher = *pPixel;
  758. Pixel.uiValue >>= 5;
  759. // get rid of the least significant bit of green
  760. Pixel.usHigher >>= 1;
  761. // shift to the right some more...
  762. Pixel.uiValue >>= 5;
  763. // so we can left-shift the red value alone to give it an extra bit
  764. Pixel.usHigher <<= 1;
  765. // now shift back and copy
  766. Pixel.uiValue <<= 10;
  767. *pPixel = Pixel.usHigher;
  768. pPixel++;
  769. }
  770. }
  771. void ConvertRGBDistribution565To556( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
  772. {
  773. UINT16 * pPixel;
  774. UINT32 uiLoop;
  775. SplitUINT32 Pixel;
  776. pPixel = p16BPPData;
  777. for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
  778. {
  779. // we put the 16 pixel bits in the UPPER word of uiPixel, so that we can
  780. // right shift the blue value (at the bottom) into the LOWER word to protect it
  781. Pixel.usHigher = *pPixel;
  782. Pixel.uiValue >>= 5;
  783. // get rid of the least significant bit of green
  784. Pixel.usHigher >>= 1;
  785. // shift back into the upper word
  786. Pixel.uiValue <<= 5;
  787. // give blue an extra bit (blank in the least significant spot)
  788. Pixel.usHigher <<= 1;
  789. // copy back
  790. *pPixel = Pixel.usHigher;
  791. pPixel++;
  792. }
  793. }
  794. void ConvertRGBDistribution565ToAny( UINT16 * p16BPPData, UINT32 uiNumberOfPixels )
  795. {
  796. UINT16 * pPixel;
  797. UINT32 uiRed, uiGreen, uiBlue, uiTemp, uiLoop;
  798. pPixel = p16BPPData;
  799. for (uiLoop = 0; uiLoop < uiNumberOfPixels; uiLoop++)
  800. {
  801. // put the 565 RGB 16-bit value into a 32-bit RGB value
  802. uiRed = (*pPixel) >> 11;
  803. uiGreen = (*pPixel & 0x07E0) >> 5;
  804. uiBlue = (*pPixel & 0x001F);
  805. uiTemp = FROMRGB(uiRed,uiGreen,uiBlue);
  806. // then convert the 32-bit RGB value to whatever 16 bit format is used
  807. *pPixel = Get16BPPColor( uiTemp );
  808. pPixel++;
  809. }
  810. }