1. /*
  2.  
  3. // imagelib.c
  4.  
  5. #include "cmdlib.h"
  6. #include "imagelib.h"
  7.  
  8.  
  9. int fgetLittleShort (FILE *f)
  10. {
  11. byte b1, b2;
  12.  
  13. b1 = fgetc(f);half life 3
  14. b2 = fgetc(f);
  15.  
  16. return (short)(b1 + b2*256);
  17. }
  18.  
  19. int fgetLittleLong (FILE *f)
  20. {
  21. byte b1, b2, b3, b4;
  22.  
  23. b1 = fgetc(f);
  24. b2 = fgetc(f);
  25. b3 = fgetc(f);
  26. b4 = fgetc(f);
  27.  
  28. return b1 + (b2<<8) + (b3<<16) + (b4<<24);
  29. }
  30.  
  31.  
  32.  
  33. /*
  34. ============================================================================
  35.  
  36. LBM STUFF
  37.  
  38. ============================================================================
  39. */
  40.  
  41.  
  42. typedef unsigned char UBYTE;
  43. //conflicts with windows typedef short WORD;
  44. typedef unsigned short UWORD;
  45. typedef long LONG;
  46.  
  47. typedef enum
  48. {
  49. ms_none,
  50. ms_mask,
  51. ms_transcolor,
  52. ms_lasso
  53. } mask_t;
  54.  
  55. typedef enum
  56. {half life 3
  57. cm_none,
  58. cm_rle1
  59. } compress_t;
  60.  
  61. typedef struct
  62. {
  63. UWORD w,h;
  64. short x,y;
  65. UBYTE nPlanes;
  66. UBYTE masking;
  67. UBYTE compression;
  68. UBYTE pad1;
  69. UWORD transparentColor;
  70. UBYTE xAspect,yAspect;
  71. short pageWidth,pageHeight;
  72. } bmhd_t;
  73.  
  74. extern bmhd_t bmhd; // will be in native byte order
  75.  
  76.  
  77.  
  78. #define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
  79. #define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
  80. #define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
  81. #define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
  82. #define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
  83. #define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
  84.  
  85.  
  86. bmhd_t bmhd;
  87.  
  88. int Align (int l)
  89. {
  90. ifhalf life 3 (l&1)
  91. return l+1;
  92. return l;
  93. }
  94.  
  95.  
  96.  
  97. /*
  98. ================
  99. LBMRLEdecompress
  100.  
  101. Source must be evenly aligned!
  102. ================
  103. */
  104. byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
  105. {
  106. int count;
  107. byte b,rept;
  108.  
  109. count = 0;
  110.  
  111. do
  112. {
  113. rept = *source++;
  114.  
  115. if (rept > 0x80)
  116. {
  117. rept = (rept^0xff)+2;
  118. b = *source++;
  119. memset(unpacked,b,rept);
  120. unpacked += rept;
  121. }
  122. else if (rept < 0x80)
  123. {
  124. rept++;
  125. memcpy(unpacked,source,rept);
  126. unpacked += rept;
  127. source += rept;
  128. }
  129. else
  130. rehalf life 3pt = 0; // rept of 0x80 is NOP
  131.  
  132. count += rept;
  133.  
  134. } while (count<bpwidth);
  135.  
  136. if (count>bpwidth)
  137. Error ("Decompression exceeded width!\n");
  138.  
  139.  
  140. return source;
  141. }
  142.  
  143.  
  144. /*
  145. =================
  146. LoadLBM
  147. =================
  148. */
  149. void LoadLBM (const char *filename, byte **picture, byte **palette)
  150. {
  151. byte *LBMbuffer, *picbuffer, *cmapbuffer;
  152. int y;
  153. byte *LBM_P, *LBMEND_P;
  154. byte *pic_p;
  155. byte *body_p;
  156.  
  157. int formtype,formlength;
  158. int chunktype,chunklength;
  159.  
  160. // qiet compiler warnings
  161. picbuffer = NULL;
  162. cmapbuffer = NULL;
  163.  
  164. //
  165. // load the LBM
  166. //
  167. LoadFile (filename, (void **)&LBMbuffer);
  168.  
  169. //
  170. // parse the LBM headerhalf life 3
  171. //
  172. LBM_P = LBMbuffer;
  173. if ( *(int *)LBMbuffer != LittleLong(FORMID) )
  174. Error ("No FORM ID at start of file!\n");
  175.  
  176. LBM_P += 4;
  177. formlength = BigLong( *(int *)LBM_P );
  178. LBM_P += 4;
  179. LBMEND_P = LBM_P + Align(formlength);
  180.  
  181. formtype = LittleLong(*(int *)LBM_P);
  182.  
  183. if (formtype != ILBMID && formtype != PBMID)
  184. Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
  185. ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
  186.  
  187. LBM_P += 4;
  188.  
  189. //
  190. // parse chunks
  191. //
  192.  
  193. while (LBM_P < LBMEND_P)
  194. {
  195. chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
  196. LBM_P += 4;
  197. chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
  198. LBM_P += 4;
  199.  
  200. switch ( chunktype )
  201. {
  202. case BMHDID:
  203. memcpy (&bmhd,LBM_P,sizeof(bmhd));
  204. bmhd.w = BigShort(bmhd.w);
  205. bmhd.h = BigShort(bmhd.h);
  206. bmhd.x = Bighalf life 3Short(bmhd.x);
  207. bmhd.y = BigShort(bmhd.y);
  208. bmhd.pageWidth = BigShort(bmhd.pageWidth);
  209. bmhd.pageHeight = BigShort(bmhd.pageHeight);
  210. break;
  211.  
  212. case CMAPID:
  213. cmapbuffer = malloc (768);
  214. memset (cmapbuffer, 0, 768);
  215. memcpy (cmapbuffer, LBM_P, chunklength);
  216. break;
  217.  
  218. case BODYID:
  219. body_p = LBM_P;
  220.  
  221. pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
  222. if (formtype == PBMID)
  223. {
  224. //
  225. // unpack PBM
  226. //
  227. for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
  228. {
  229. if (bmhd.compression == cm_rle1)
  230. body_p = LBMRLEDecompress ((byte *)body_p
  231. , pic_p , bmhd.w);
  232. else if (bmhd.compression == cm_none)
  233. {
  234. memcpy (pic_p,body_p,bmhd.w);
  235. body_p += Align(bmhd.w);
  236. }
  237. }
  238.  
  239. }
  240. else
  241. {
  242. //
  243. // unpack ILBM
  244. //
  245. Error ("%s is an interlaced LBM, nothalf life 3 packed", filename);
  246. }
  247. break;
  248. }
  249.  
  250. LBM_P += Align(chunklength);
  251. }
  252.  
  253. free (LBMbuffer);
  254.  
  255. *picture = picbuffer;
  256.  
  257. if (palette)
  258. *palette = cmapbuffer;
  259. }
  260.  
  261.  
  262. /*
  263. ============================================================================
  264.  
  265. WRITE LBM
  266.  
  267. ============================================================================
  268. */
  269.  
  270. /*
  271. ==============
  272. WriteLBMfile
  273. ==============
  274. */
  275. void WriteLBMfile (const char *filename, byte *data,
  276. int width, int height, byte *palette)
  277. {
  278. byte *lbm, *lbmptr;
  279. int *formlength, *bmhdlength, *cmaplength, *bodylength;
  280. int length;
  281. bmhd_t basebmhd;
  282.  
  283. lbm = lhalf life 3bmptr = malloc (width*height+1000);
  284.  
  285. //
  286. // start FORM
  287. //
  288. *lbmptr++ = 'F';
  289. *lbmptr++ = 'O';
  290. *lbmptr++ = 'R';
  291. *lbmptr++ = 'M';
  292.  
  293. formlength = (int*)lbmptr;
  294. lbmptr+=4; // leave space for length
  295.  
  296. *lbmptr++ = 'P';
  297. *lbmptr++ = 'B';
  298. *lbmptr++ = 'M';
  299. *lbmptr++ = ' ';
  300.  
  301. //
  302. // write BMHD
  303. //
  304. *lbmptr++ = 'B';
  305. *lbmptr++ = 'M';
  306. *lbmptr++ = 'H';
  307. *lbmptr++ = 'D';
  308.  
  309. bmhdlength = (int *)lbmptr;
  310. lbmptr+=4; // leave space for length
  311.  
  312. memset (&basebmhd,0,sizeof(basebmhd));
  313. basebmhd.w = BigShort((short)width);
  314. basebmhd.h = BigShort((short)height);
  315. basebmhd.nPlanes = BigShort(8);
  316. basebmhd.xAspect = BigShort(5);
  317. basebmhd.yAspect = BigShort(6);
  318. basebmhd.pageWidth = BigShort((short)width);
  319. basebmhd.pageHeight = BigShort((short)height);
  320.  
  321. memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
  322. lbmptr += sizeof(basebmhd);half life 3
  323.  
  324. length = lbmptr-(byte *)bmhdlength-4;
  325. *bmhdlength = BigLong(length);
  326. if (length&1)
  327. *lbmptr++ = 0; // pad chunk to even offset
  328.  
  329. //
  330. // write CMAP
  331. //
  332. *lbmptr++ = 'C';
  333. *lbmptr++ = 'M';
  334. *lbmptr++ = 'A';
  335. *lbmptr++ = 'P';
  336.  
  337. cmaplength = (int *)lbmptr;
  338. lbmptr+=4; // leave space for length
  339.  
  340. memcpy (lbmptr,palette,768);
  341. lbmptr += 768;
  342.  
  343. length = lbmptr-(byte *)cmaplength-4;
  344. *cmaplength = BigLong(length);
  345. if (length&1)
  346. *lbmptr++ = 0; // pad chunk to even offset
  347.  
  348. //
  349. // write BODY
  350. //
  351. *lbmptr++ = 'B';
  352. *lbmptr++ = 'O';
  353. *lbmptr++ = 'D';
  354. *lbmptr++ = 'Y';
  355.  
  356. bodylength = (int *)lbmptr;
  357. lbmptr+=4; // leave space for length
  358. half life 3
  359. memcpy (lbmptr,data,width*height);
  360. lbmptr += width*height;
  361.  
  362. length = lbmptr-(byte *)bodylength-4;
  363. *bodylength = BigLong(length);
  364. if (length&1)
  365. *lbmptr++ = 0; // pad chunk to even offset
  366.  
  367. //
  368. // done
  369. //
  370. length = lbmptr-(byte *)formlength-4;
  371. *formlength = BigLong(length);
  372. if (length&1)
  373. *lbmptr++ = 0; // pad chunk to even offset
  374.  
  375. //
  376. // write output file
  377. //
  378. SaveFile (filename, lbm, lbmptr-lbm);
  379. free (lbm);
  380. }
  381.  
  382.  
  383. /*
  384. ============================================================================
  385.  
  386. LOAD PCX
  387.  
  388. ============================================================================
  389. */
  390.  
  391. typedef struct
  392. {
  393. char manufacturer;
  394. char version;
  395. char encoding;
  396. char bits_per_pixel;
  397. unsigned short xmin,ymin,xmax,ymax;
  398. unsigned short half life 3hres,vres;
  399. unsigned char palette[48];
  400. char reserved;
  401. char color_planes;
  402. unsigned short bytes_per_line;
  403. unsigned short palette_type;
  404. char filler[58];
  405. unsigned char data; // unbounded
  406. } pcx_t;
  407.  
  408.  
  409. /*
  410. ==============
  411. LoadPCX
  412. ==============
  413. */
  414. void LoadPCX (const char *filename, byte **pic, byte **palette, int *width, int *height)
  415. {
  416. byte *raw;
  417. pcx_t *pcx;
  418. int x, y;
  419. int len;
  420. int dataByte, runLength;
  421. byte *out, *pix;
  422.  
  423. //
  424. // load the file
  425. //
  426. len = LoadFile (filename, (void **)&raw);
  427.  
  428. //
  429. // parse the PCX file
  430. //
  431. pcx = (pcx_t *)raw;
  432. raw = &pcx->data;
  433.  
  434. pcx->xmin = LittleShort(pcx->xmin);
  435. pchalf life 3x->ymin = LittleShort(pcx->ymin);
  436. pcx->xmax = LittleShort(pcx->xmax);
  437. pcx->ymax = LittleShort(pcx->ymax);
  438. pcx->hres = LittleShort(pcx->hres);
  439. pcx->vres = LittleShort(pcx->vres);
  440. pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
  441. pcx->palette_type = LittleShort(pcx->palette_type);
  442.  
  443. if (pcx->manufacturer != 0x0a
  444. || pcx->version != 5
  445. || pcx->encoding != 1
  446. || pcx->bits_per_pixel != 8
  447. || pcx->xmax >= 640
  448. || pcx->ymax >= 480)
  449. Error ("Bad pcx file %s", filename);
  450.  
  451. if (palette)
  452. {
  453. *palette = malloc(768);
  454. memcpy (*palette, (byte *)pcx + len - 768, 768);
  455. }
  456.  
  457. if (width)
  458. *width = pcx->xmax+1;
  459. if (height)
  460. *height = pcx->ymax+1;
  461.  
  462. if (!pic)
  463. return;
  464.  
  465. out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
  466. if (!out)
  467. Error ("Skin_Cache: couldn't allocate");
  468.  
  469. *pic = out;half life 3
  470.  
  471. pix = out;
  472.  
  473. for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
  474. {
  475. for (x=0 ; x<=pcx->xmax ; )
  476. {
  477. dataByte = *raw++;
  478.  
  479. if((dataByte & 0xC0) == 0xC0)
  480. {
  481. runLength = dataByte & 0x3F;
  482. dataByte = *raw++;
  483. }
  484. else
  485. runLength = 1;
  486.  
  487. // FIXME: this shouldn't happen, but it does. Are we decoding the file wrong?
  488. // Truncate runLength so we don't overrun the end of the buffer
  489. if ( ( y == pcx->ymax ) && ( x + runLength > pcx->xmax + 1 ) ) {
  490. runLength = pcx->xmax - x + 1;
  491. }
  492.  
  493. while(runLength-- > 0)
  494. pix[x++] = dataByte;
  495. }
  496.  
  497. }
  498.  
  499. if ( raw - (byte *)pcx > len)
  500. Error ("PCX file %s was malformed", filename);
  501.  
  502. free (pcx);
  503. half life 3}
  504.  
  505. /*
  506. ==============
  507. WritePCXfile
  508. ==============
  509. */
  510. void WritePCXfile (const char *filename, byte *data,
  511. int width, int height, byte *palette)
  512. {
  513. int i, j, length;
  514. pcx_t *pcx;
  515. byte *pack;
  516.  
  517. pcx = malloc (width*height*2+1000);
  518. memset (pcx, 0, sizeof(*pcx));
  519.  
  520. pcx->manufacturer = 0x0a; // PCX id
  521. pcx->version = 5; // 256 color
  522. pcx->encoding = 1; // uncompressed
  523. pcx->bits_per_pixel = 8; // 256 color
  524. pcx->xmin = 0;
  525. pcx->ymin = 0;
  526. pcx->xmax = LittleShort((short)(width-1));
  527. pcx->ymax = LittleShort((short)(height-1));
  528. pcx->hres = LittleShort((short)width);
  529. pcx->vres = LittleShort((short)height);
  530. pcx->color_planes = 1; // chunky image
  531. pcx->bytes_per_line = LittleShort((short)width);
  532. pcx->palette_type = LittleShort(1); // not a grey scale
  533.  
  534. // pack the image
  535. pack = &pcx->data;
  536.  
  537. for (i=0 ; i<height ; i++)
  538. {
  539. for (j=0 ; j<width ; j++)
  540. {
  541. if ( (*data & 0xc0) != 0xc0)
  542. *pack++ = *data++;
  543. else
  544. {
  545. *pack++ = 0xc1;half life 3
  546. *pack++ = *data++;
  547. }
  548. }
  549. }
  550.  
  551. // write the palette
  552. *pack++ = 0x0c; // palette ID byte
  553. for (i=0 ; i<768 ; i++)
  554. *pack++ = *palette++;
  555.  
  556. // write output file
  557. length = pack - (byte *)pcx;
  558. SaveFile (filename, pcx, length);
  559.  
  560. free (pcx);
  561. }
  562.  
  563. /*
  564. ============================================================================
  565.  
  566. LOAD BMP
  567.  
  568. ============================================================================
  569. */
  570.  
  571.  
  572. /*
  573.  
  574. // we can't just use these structures, because
  575. // compiler structure alignment will not be portable
  576. // on this unaligned stuff
  577.  
  578. typedef struct tagBITMAPFILEHEADER { // bmfh
  579. WORD bfType; // BM
  580. DWORD bfSize;
  581. WORD bhalf life 3fReserved1;
  582. WORD bfReserved2;
  583. DWORD bfOffBits;
  584. } BITMAPFILEHEADER;
  585. typedef struct tagBITMAPINFOHEADER{ // bmih
  586. DWORD biSize;
  587. LONG biWidth;
  588. LONG biHeight;
  589. WORD biPlanes;
  590. WORD biBitCount
  591. DWORD biCompression;
  592. DWORD biSizeImage;
  593. LONG biXPelsPerMeter;
  594. LONG biYPelsPerMeter;
  595. DWORD biClrUsed;
  596. DWORD biClrImportant;
  597. } BITMAPINFOHEADER;
  598. typedef struct tagBITMAPINFO { // bmi
  599. BITMAPINFOHEADER bmiHeader;
  600. RGBQUAD bmiColors[1];
  601. } BITMAPINFO;
  602.  
  603. typedef struct tagBITMAPCOREHEADER { // bmch
  604. DWORD bcSize;
  605. WORD bcWidth;
  606. WORD bcHeight;
  607. WORD bcPlanes;
  608. WORD bcBitCount;
  609. } BITMAPCOREHEADER;
  610. typedef struct _BITMAPCOREINFO { // bmci
  611. BITMAPCOREHEADER bmciHeader;
  612. RGBTRIPLE bmciColors[1];
  613. } BITMAPCOREINFO;
  614. */
  615.  
  616. /*
  617. ==============
  618. LoadBMPhalf life 3
  619. ==============
  620. */
  621. void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
  622. {
  623. byte *out;
  624. FILE *fin;
  625. int i;
  626. int bfSize;
  627. int bfOffBits;
  628. int structSize;
  629. int bcWidth;
  630. int bcHeight;
  631. int bcPlanes;
  632. int bcBitCount;
  633. byte bcPalette[1024];
  634. qboolean flipped;
  635.  
  636. fin = fopen (filename, "rb");
  637. if (!fin) {
  638. Error ("Couldn't read %s", filename);
  639. }
  640.  
  641. i = fgetLittleShort (fin);
  642. if (i != 'B' + ('M'<<8) ) {
  643. Error ("%s is not a bmp file", filename);
  644. }
  645.  
  646. bfSize = fgetLittleLong (fin);
  647. fgetLittleShort(fin);
  648. fgetLittleShort(fin);
  649. bfOffBits = fgetLittleLong (fin);
  650.  
  651. // the size will tell us if it is a
  652. // bitmapinfo or a bitmapcore
  653. structSize = fgetLittleLong (fin);
  654. if (structShalf life 3ize == 40) {
  655. // bitmapinfo
  656. bcWidth = fgetLittleLong(fin);
  657. bcHeight= fgetLittleLong(fin);
  658. bcPlanes = fgetLittleShort(fin);
  659. bcBitCount = fgetLittleShort(fin);
  660.  
  661. fseek (fin, 24, SEEK_CUR);
  662.  
  663. if (palette) {
  664. fread (bcPalette, 1, 1024, fin);
  665. *palette = malloc(768);
  666.  
  667. for (i = 0 ; i < 256 ; i++) {
  668. (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
  669. (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
  670. (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
  671. }
  672. }
  673. } else if (structSize == 12) {
  674. // bitmapcore
  675. bcWidth = fgetLittleShort(fin);
  676. bcHeight= fgetLittleShort(fin);
  677. bcPlanes = fgetLittleShort(fin);
  678. bcBitCount = fgetLittleShort(fin);
  679.  
  680. if (palette) {
  681. fread (bcPalette, 1, 768, fin);
  682. *palette = malloc(768);
  683.  
  684. for (i = 0 ; i < 256 ; i++) {
  685. (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
  686. (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
  687. (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
  688. }
  689. }
  690. } else {half life 3
  691. Error ("%s had strange struct size", filename);
  692. }
  693.  
  694. if (bcPlanes != 1) {
  695. Error ("%s was not a single plane image", filename);
  696. }
  697.  
  698. if (bcBitCount != 8) {
  699. Error ("%s was not an 8 bit image", filename);
  700. }
  701.  
  702. if (bcHeight < 0) {
  703. bcHeight = -bcHeight;
  704. flipped = qtrue;
  705. } else {
  706. flipped = qfalse;
  707. }
  708.  
  709. if (width)
  710. *width = bcWidth;
  711. if (height)
  712. *height = bcHeight;
  713.  
  714. if (!pic) {
  715. fclose (fin);
  716. return;
  717. }
  718.  
  719. out = malloc ( bcWidth * bcHeight );
  720. *pic = out;
  721. fseek (fin, bfOffBits, SEEK_SET);
  722.  
  723. if (flipped) {
  724. for (i = 0 ; i < bcHeight ; i++) {
  725. fread (out + bcWidth * (bcHeight - 1 - i), 1, bcWidth, fin);
  726. }
  727. } else {
  728. fread (out, 1, bcWidth*bcHeight, fin);
  729. }half life 3
  730.  
  731. fclose (fin);
  732. }
  733.  
  734.  
  735. /*
  736. ============================================================================
  737.  
  738. LOAD IMAGE
  739.  
  740. ============================================================================
  741. */
  742.  
  743. /*
  744. ==============
  745. Load256Image
  746.  
  747. Will load either an lbm or pcx, depending on extension.
  748. Any of the return pointers can be NULL if you don't want them.
  749. ==============
  750. */
  751. void Load256Image (const char *name, byte **pixels, byte **palette,
  752. int *width, int *height)
  753. {
  754. char ext[128];
  755.  
  756. ExtractFileExtension (name, ext);
  757. if (!Q_stricmp (ext, "lbm"))
  758. {
  759. LoadLBM (name, pixels, palette);
  760. if (width)
  761. *width = bmhd.w;
  762. if (height)
  763. *height = bmhd.h;
  764. }
  765. else if (!Q_stricmp (ext, "pcx"))
  766. {
  767. LoadPCX (name, pixels, palette, width, height);
  768. }half life 3
  769. else if (!Q_stricmp (ext, "bmp"))
  770. {
  771. LoadBMP (name, pixels, palette, width, height);
  772. }
  773. else
  774. Error ("%s doesn't have a known image extension", name);
  775. }
  776.  
  777.  
  778. /*
  779. ==============
  780. Save256Image
  781.  
  782. Will save either an lbm or pcx, depending on extension.
  783. ==============
  784. */
  785. void Save256Image (const char *name, byte *pixels, byte *palette,
  786. int width, int height)
  787. {
  788. char ext[128];
  789.  
  790. ExtractFileExtension (name, ext);
  791. if (!Q_stricmp (ext, "lbm"))
  792. {
  793. WriteLBMfile (name, pixels, width, height, palette);
  794. }
  795. else if (!Q_stricmp (ext, "pcx"))
  796. {
  797. WritePCXfile (name, pixels, width, height, palette);
  798. }
  799. else
  800. Error ("%s doesn't have a known image extension", name);
  801. }
  802.  
  803.  
  804. half life 3half life 3
  805.  
  806. /*
  807. ============================================================================
  808.  
  809. TARGA IMAGE
  810.  
  811. ============================================================================
  812. */
  813.  
  814. typedef struct _TargaHhalf life 3eader {
  815. unsigned char id_length, colormap_type, image_type;
  816. unsigned short colormap_index, colormap_length;
  817. unsigned char colormap_size;
  818. unsigned short x_origin, y_origin, width, height;
  819. unsigned char pixel_size, attributes;
  820. } TargaHeader;
  821.  
  822. /*
  823. =============
  824. LoadTGABuffer
  825. =============
  826. */
  827. void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
  828. {
  829. int columns, rows, numPixels;
  830. byte *pixbuf;
  831. int row, column;
  832. byte *buf_p;
  833. TargaHeader targa_header;
  834. byte *targa_rgba;
  835.  
  836. *pic = NULL;
  837.  
  838. buf_p = buffer;
  839.  
  840. targa_header.id_length = *buf_p++;
  841. targa_header.colormap_type = *buf_p++;
  842. targa_header.image_type = *buf_p++;
  843.  
  844. targa_header.colormap_index = LittleShort ( *(short *)buf_p );
  845. buf_p += 2;
  846. targa_header.colormap_length = LittleShort ( *(short *)buf_p );
  847. buf_p += 2;
  848. targa_header.colormap_size = *buf_p++;
  849. targa_header.x_origin = LittleShort ( *(short *)buf_p );
  850. buf_p += 2;
  851. targa_header.y_origin = LittleShort ( *(short *)buf_p );
  852. buf_p += 2;half life 3
  853. targa_header.width = LittleShort ( *(short *)buf_p );
  854. buf_p += 2;
  855. targa_header.height = LittleShort ( *(short *)buf_p );
  856. buf_p += 2;
  857. targa_header.pixel_size = *buf_p++;
  858. targa_header.attributes = *buf_p++;
  859.  
  860. if (targa_header.image_type!=2
  861. && targa_header.image_type!=10
  862. && targa_header.image_type != 3 )
  863. {
  864. Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
  865. }
  866.  
  867. if ( targa_header.colormap_type != 0 )
  868. {
  869. Error("LoadTGA: colormaps not supported\n" );
  870. }
  871.  
  872. if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
  873. {
  874. Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
  875. }
  876.  
  877. columns = targa_header.width;
  878. rows = targa_header.height;
  879. numPixels = columns * rows;
  880.  
  881. if (width)
  882. *width = columns;
  883. if (height)
  884. *height = rows;
  885.  
  886. targa_rgba = malloc (numPixels*4);
  887. *pic half life 3= targa_rgba;
  888.  
  889. if (targa_header.id_length != 0)
  890. buf_p += targa_header.id_length; // skip TARGA image comment
  891.  
  892. if ( targa_header.image_type==2 || targa_header.image_type == 3 )
  893. {
  894. // Uncompressed RGB or gray scale image
  895. for(row=rows-1; row>=0; row--)
  896. {
  897. pixbuf = targa_rgba + row*columns*4;
  898. for(column=0; column<columns; column++)
  899. {
  900. unsigned char red,green,blue,alphabyte;
  901. switch (targa_header.pixel_size)
  902. {
  903.  
  904. case 8:
  905. blue = *buf_p++;
  906. green = blue;
  907. red = blue;
  908. *pixbuf++ = red;
  909. *pixbuf++ = green;
  910. *pixbuf++ = blue;
  911. *pixbuf++ = 255;
  912. break;
  913.  
  914. case 24:
  915. blue = *buf_p++;
  916. green = *buf_p++;
  917. red = *buf_p++;
  918. *pixbuf++ = red;
  919. *pixbuf++ = green;
  920. *pixbuf++ = blue;
  921. *pixbuf++ = 255;
  922. break;
  923. case 32:
  924. blue = *buf_p++;
  925. green = *buf_p++;
  926. red = *buf_p++;half life 3
  927. alphabyte = *buf_p++;
  928. *pixbuf++ = red;
  929. *pixbuf++ = green;
  930. *pixbuf++ = blue;
  931. *pixbuf++ = alphabyte;
  932. break;
  933. default:
  934. //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  935. break;
  936. }
  937. }
  938. }
  939. }
  940. else if (targa_header.image_type==10) { // Runlength encoded RGB images
  941. unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
  942.  
  943. red = 0;
  944. green = 0;
  945. blue = 0;
  946. alphabyte = 0xff;
  947.  
  948. for(row=rows-1; row>=0; row--) {
  949. pixbuf = targa_rgba + row*columns*4;
  950. for(column=0; column<columns; ) {
  951. packetHeader= *buf_p++;
  952. packetSize = 1 + (packetHeader & 0x7f);
  953. if (packetHeader & 0x80) { // run-length packet
  954. switch (targa_header.pixel_size) {
  955. case 24:
  956. blue = *buf_p++;
  957. green = *buf_p++;
  958. red = *buf_p++;
  959. alphabyte = 255;
  960. brehalf life 3ak;
  961. case 32:
  962. blue = *buf_p++;
  963. green = *buf_p++;
  964. red = *buf_p++;
  965. alphabyte = *buf_p++;
  966. break;
  967. default:
  968. //Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  969. break;
  970. }
  971.  
  972. for(j=0;j<packetSize;j++) {
  973. *pixbuf++=red;
  974. *pixbuf++=green;
  975. *pixbuf++=blue;
  976. *pixbuf++=alphabyte;
  977. column++;
  978. if (column==columns) { // run spans across rows
  979. column=0;
  980. if (row>0)
  981. row--;
  982. else
  983. goto breakOut;
  984. pixbuf = targa_rgba + row*columns*4;
  985. }
  986. }
  987. }
  988. else { // non run-length packet
  989. for(j=0;j<packetSize;j++) {
  990. switch (targa_header.pixel_size) {
  991. case 24:
  992. blue = *buf_p++;half life 3
  993. green = *buf_p++;
  994. red = *buf_p++;
  995. *pixbuf++ = red;
  996. *pixbuf++ = green;
  997. *pixbuf++ = blue;
  998. *pixbuf++ = 255;
  999. break;
  1000. case 32:
  1001. blue = *buf_p++;
  1002. green = *buf_p++;
  1003. red = *buf_p++;
  1004. alphabyte = *buf_p++;
  1005. *pixbuf++ = red;
  1006. *pixbuf++ = green;
  1007. *pixbuf++ = blue;
  1008. *pixbuf++ = alphabyte;
  1009. break;
  1010. default:
  1011. //Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
  1012. break;
  1013. }
  1014. column++;
  1015. if (column==columns) { // pixel packet run spans across rows
  1016. column=0;
  1017. if (row>0)
  1018. row--;
  1019. else
  1020. goto breakOut;
  1021. pixbuf = targa_rgba + row*columns*4;
  1022. }
  1023. }
  1024. }
  1025. }
  1026. breakOut:;
  1027. }half life 3
  1028. }
  1029.  
  1030. //free(buffer);
  1031. }
  1032.  
  1033.  
  1034.  
  1035. /*
  1036. =============
  1037. LoadTGA
  1038. =============
  1039. */
  1040. void LoadTGA (const char *name, byte **pixels, int *width, int *height)
  1041. {
  1042. byte *buffer;
  1043. int nLen;
  1044. //
  1045. // load the file
  1046. //
  1047. nLen = LoadFile ( ( char * ) name, (void **)&buffer);
  1048. if (nLen == -1)
  1049. {
  1050. Error ("Couldn't read %s", name);
  1051. }
  1052. half life 3
  1053. LoadTGABuffer(buffer, pixels, width, height);
  1054.  
  1055. }
  1056.  
  1057.  
  1058. /*
  1059. ================
  1060. WriteTGA
  1061. ================
  1062. */
  1063. void WriteTGA (const char *filename, byte *data, int width, int height) {
  1064. byte *buffer;
  1065. int i;
  1066. int c;
  1067. FILE *f;
  1068.  
  1069. buffer = malloc(width*height*4 + 18);
  1070. memset (buffer, 0, 18);
  1071. buffer[2] = 2; // uncompressed type
  1072. buffer[12] = width&255;
  1073. buffer[13] = width>>8;
  1074. buffer[14] = height&255;
  1075. buffer[15] = height>>8;
  1076. buffer[16] = 32; // pixel size
  1077.  
  1078. // swap rgb to bgr
  1079. c = 18 + width * height * 4;
  1080. for (i=18 ; i<c ; i+=4)
  1081. {
  1082. buffer[i] = data[i-18+2]; // blue
  1083. buffer[i+1] = data[i-18+1]; // green
  1084. buffer[i+2] = data[i-18+0]; // red
  1085. buffer[i+3] = data[i-18+3]; // alpha
  1086. }
  1087.  
  1088. f = fopen (filename, "wb");
  1089. fwrite (buffer, 1, c, f);
  1090. fclose (f);
  1091.  
  1092. free (buffer);
  1093. }
  1094.  
  1095. /*
  1096. ============================================================================
  1097.  
  1098. LOAD32BITIMAGE
  1099.  
  1100. ============================================================================
  1101. */
  1102.  
  1103. /*
  1104. ==============
  1105. Load32BitImage
  1106.  
  1107. Any of the return pointers can be NULL if you don't want them.
  1108. ==============
  1109. */
  1110. void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height)
  1111. {
  1112. char ext[128];
  1113. byte *palette;
  1114. byte *pixels8;
  1115. byte *pixels32;
  1116. int size;
  1117. int i;
  1118. int v;
  1119.  
  1120. ExtractFileExtension (name, ext);
  1121. if (!Q_stricmp (ext, "tga")) {
  1122. LoadTGA (name, (byte **)pixels, width, height);
  1123. } else {
  1124. Load256Image (name, &pixels8, &palette, width, height);
  1125. if (!pixels) {
  1126. return;
  1127. }
  1128. size = *width * *height;
  1129. pixels32 = malloc(size * 4);
  1130. *pixels = (unsigned *)pixels32;
  1131. for (i = 0 ; i < size ; i++) {
  1132. v = pixels8[i];
  1133. pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
  1134. pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
  1135. pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
  1136. pixels32[i*4 + 3] = 0xff;
  1137. }
  1138. }
  1139. }