FS2_Open
Open source remastering of the Freespace 2 engine
tgautils.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include <string.h>
13 
14 #include "globalincs/pstypes.h"
15 #include "tgautils/tgautils.h"
16 #include "cfile/cfile.h"
17 #include "bmpman/bmpman.h"
18 #include "palman/palman.h"
19 #include "graphics/2d.h"
20 #include "cmdline/cmdline.h"
21 
22 // -----------------
23 //
24 // Defines
25 //
26 // -----------------
27 
28 const char *Xfile_ID = "TRUEVISION-XFILE.";
29 
30 #define TARGA_FOOTER_SIZE 26 // using sizeof(targa_footer) doesn't work unless we
31  // pack the struct and I don't want to do that :)
32 
33 #define MAX_TARGA_RUN_LENGTH_PACKET 128
34 #define TARGA_HEADER_LENGTH 18
35 #define ULORIGIN (header.image_descriptor & 0x20)
36 
37 // -----------------
38 //
39 // Structures
40 //
41 // -----------------
42 
43 typedef struct targa_header {
44  short xoffset;
45  short yoffset;
46  short width;
47  short height;
48  short cmap_start;
49  short cmap_length;
56 } targa_header;
57 
58 typedef struct targa_footer {
59  uint ext_offset; // file offset to extension area (we ignore it)
60  uint dev_offset; // file offset to developer area (we also ignore this)
61  char sig_string[18]; // check to see if this is new TGA format, string should be value of Xfile_ID
62 } targa_footer;
63 
64 // -----------------
65 //
66 // Internal Functions
67 //
68 // -----------------
69 
70 
71 // copy from one pixel buffer to another
72 //
73 // to - pointer to dest. buffet
74 // from - pointer to source buffer
75 // pixels - number of pixels to copy
76 // fromsize - source pixel size
77 // tosize - dest. pixel size
78 //
79 // returns - number of pixels copied to destination
80 //
81 static int targa_copy_data(char *to, char *from, int pixels, int fromsize, int tosize)
82 {
83  if ( (fromsize == 2) && (tosize==2) ) {
84  // Flip the alpha bit on 1555 format
85  ushort *src, *dst;
86 
87  src = (ushort *)from;
88  dst = (ushort *)from;
89  for (int i=0; i<pixels; i++ ) {
90  *dst++ = (ushort)((*src++) ^ 0x8000); // Flip the transparency bit
91  }
92  return tosize*pixels;
93  } else if ( (fromsize == 2) && (tosize == 3) ) {
94  ushort *src;
95 
96  src = (ushort *)from;
97  for (int i=0; i<pixels; i++ ) {
98  ushort pixel = *src++;
99 
100  *to++ = (ubyte)((pixel & 0x1f) * 8);
101  *to++ = (ubyte)(((pixel >> 5) & 63) * 4);
102  *to++ = (ubyte)(((pixel >> 11) & 0x1f) * 8);
103  }
104  return tosize*pixels;
105  } else {
106  Assert(fromsize == tosize);
107  memcpy(to, from, pixels * fromsize);
108  return tosize*pixels;
109  }
110 }
111 
112 // targa_pixels_equal -- Test if two pixels are identical
113 //
114 // pix1 - first pixel data
115 // pix2 - second pixel data
116 // pixbytes - number of bytes per pixel
117 //
118 // returns - 0 if No Match, else 1 if Match
119 static int targa_pixels_equal(char *pix1, char *pix2, int pixbytes)
120 {
121  do {
122  if ( *pix1++ != *pix2++ ) {
123  return 0;
124  }
125  } while ( --pixbytes > 0 );
126 
127  return 1;
128 }
129 
130 // Perform targa RLE on the input data
131 //
132 // out - Buffer to write it out to
133 // in - Buffer to compress
134 // outsize - Number of bytes in output buffer
135 // pixsize - Number of bytes in input pixel
136 // bytecount - Number of bytes input
137 //
138 // returns - size of compressed data
139 //
140 int targa_compress(char *out, char *in, int outsize, int pixsize, int bytecount)
141 {
142  int pixcount; // number of pixels in the current packet
143  char *inputpixel=NULL; // current input pixel position
144  char *matchpixel=NULL; // pixel value to match for a run
145  char *flagbyte=NULL; // location of last flag byte to set
146  int rlcount; // current count in r.l. string
147  int rlthresh; // minimum valid run length
148  char *copyloc; // location to begin copying at
149 
150  // set the threshold -- the minimum valid run length
151 
152  if (outsize == 1) {
153  rlthresh = 2; // for 8bpp, require a 2 pixel span before rle'ing
154  } else {
155  rlthresh = 1;
156  }
157 
158  // set the first pixel up
159 
160  flagbyte = out; // place to put next flag if run
161  inputpixel = in;
162  pixcount = 1;
163  rlcount = 0;
164  copyloc = (char *)0;
165 
166  // loop till data processing complete
167  do {
168 
169  // if we have accumulated a 128-byte packet, process it
170  if ( pixcount == 129 ) {
171  *flagbyte = 127;
172 
173  // set the run flag if this is a run
174 
175  if ( rlcount >= rlthresh ) {
176  *flagbyte |= 0x80;
177  pixcount = 2;
178  }
179 
180  // copy the data into place
181  ++flagbyte;
182  flagbyte += targa_copy_data(flagbyte, copyloc, pixcount-1, pixsize, outsize);
183  pixcount = 1;
184 
185  // set up for next packet
186  continue;
187  }
188 
189  // if zeroth byte, handle as special case
190  if ( pixcount == 1 ) {
191  rlcount = 0;
192  copyloc = inputpixel; /* point to 1st guy in packet */
193  matchpixel = inputpixel; /* set pointer to pix to match */
194  pixcount = 2;
195  inputpixel += pixsize;
196  continue;
197  }
198 
199  // assembling a packet -- look at next pixel
200 
201  // current pixel == match pixel?
202  if ( targa_pixels_equal(inputpixel, matchpixel, outsize) ) {
203 
204  // establishing a run of enough length to
205  // save space by doing it
206  // -- write the non-run length packet
207  // -- start run-length packet
208 
209  if ( ++rlcount == rlthresh ) {
210 
211  // close a non-run packet
212 
213  if ( pixcount > (rlcount+1) ) {
214  // write out length and do not set run flag
215 
216  *flagbyte++ = (char)(pixcount - 2 - rlthresh);
217 
218  flagbyte += targa_copy_data(flagbyte, copyloc, (pixcount-1-rlcount), pixsize, outsize);
219 
220  copyloc = inputpixel;
221  pixcount = rlcount + 1;
222  }
223  }
224  } else {
225 
226  // no match -- either break a run or continue without one
227  // if a run exists break it:
228  // write the bytes in the string (outsize+1)
229  // start the next string
230 
231  if ( rlcount >= rlthresh ) {
232 
233  *flagbyte++ = (char)(0x80 | rlcount);
234  flagbyte += targa_copy_data(flagbyte, copyloc, 1, pixsize, outsize);
235  pixcount = 1;
236  continue;
237  } else {
238 
239  // not a match and currently not a run
240  // - save the current pixel
241  // - reset the run-length flag
242  rlcount = 0;
243  matchpixel = inputpixel;
244  }
245  }
246  pixcount++;
247  inputpixel += pixsize;
248  } while ( inputpixel < (in + bytecount));
249 
250  // quit this buffer without loosing any data
251 
252  if ( --pixcount >= 1 ) {
253  *flagbyte = (char)(pixcount - 1);
254  if ( rlcount >= rlthresh ) {
255  *flagbyte |= 0x80;
256  pixcount = 1;
257  }
258 
259  // copy the data into place
260  ++flagbyte;
261  flagbyte += targa_copy_data(flagbyte, copyloc, pixcount, pixsize, outsize);
262  }
263  return(flagbyte-out);
264 }
265 
266 // Reads a pixel of the specified bytes_per_pixel into memory and
267 // returns the number of bytes read into memory.
268 // NOTE : for FreeSpace2, this also swizzles data into the proper screen (NOT texture) format - just like
269 // the pcxutils do.
270 //
271 // dst - A pointer to the destination. Must be at least 4 bytes long.
272 // targa_file - The file to read from.
273 // bytes_per_pixel - The bytes per pixel of the file.
274 // dest_size - bytes per pixel in destination (1 or 2. 1 == 8 bit paletted)
275 //
276 // returns - Number of byte read into memory
277 //
278 static void targa_read_pixel( int num_pixels, ubyte **dst, ubyte **src, int bytes_per_pixel, int dest_size )
279 {
280  int idx;
281  ushort pixel;
282  int pixel32;
283  ubyte pal_index;
284  ubyte r, g, b;
285  ubyte al = 0;
286 
287  for(idx=0; idx<num_pixels; idx++){
288  // 24 or 32 bit
289  if ( (bytes_per_pixel == 3) || (bytes_per_pixel == 4) ) {
290  memset( &pixel32, 0xff, sizeof(int) );
291  memcpy( &pixel32, *src, bytes_per_pixel );
292 
293 #if BYTE_ORDER == BIG_ENDIAN
294  // on big-endian it will be used as ARGB so switch it back to BGRA
295  if ( dest_size == 4 ) {
296  pixel32 = INTEL_INT(pixel32);
297  }
298 #endif
299 
300  // should have it's own alpha settings so just copy it out as is
301  memcpy( *dst, &pixel32, dest_size );
302  }
303  // 8 or 16 bit
304  else {
305  // stuff the 16 bit pixel
306  memcpy(&pixel, *src, bytes_per_pixel);
307 
308  pixel = INTEL_SHORT(pixel);
309 
310  // if the pixel is transparent, make it so...
311  if(((pixel & 0x7c00) == 0) && ((pixel & 0x03e0) == 0x03e0) && ((pixel & 0x001f) == 0)){
312  r = b = 0;
313  g = 255;
314  al = 0;
315  bm_set_components((ubyte*)&pixel, &r, &g, &b, &al);
316  } else {
317  // get the 8 bit r, g, and b values
318  r = (ubyte)(((pixel & 0x7c00) >> 10) * 8);
319  g = (ubyte)(((pixel & 0x03e0) >> 5) * 8);
320  b = (ubyte)((pixel & 0x001f) * 8);
321  al = 1;
322 
323  // now stuff these back, swizzling properly
324  pixel = 0;
325  bm_set_components((ubyte*)&pixel, &r, &g, &b, &al);
326  }
327 
328  // 16 bit destination
329  if(dest_size == 2){
330  // stuff the final pixel
331  memcpy( *dst, &pixel, bytes_per_pixel );
332  }
333  // 8 bit destination
334  else {
335  pal_index = (ubyte)palette_find((int)r, (int)g, (int)b);
336  **dst = pal_index;
337  }
338  }
339 
340  // next pixel
341  (*dst) += dest_size;
342  (*src) += bytes_per_pixel;
343  }
344 }
345 
346 // -----------------
347 //
348 // External Functions
349 //
350 // -----------------
351 
352 // Reads header information from the targa file into the bitmap pointer
353 //
354 // filename - name of the targa bitmap file
355 // w - (output) width of the bitmap
356 // h - (output) height of the bitmap
357 // bpp - (output) bits per pixel of the bitmap
358 //
359 // returns - TARGA_ERROR_NONE if successful, otherwise error code
360 //
361 int targa_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette )
362 {
364  CFILE *targa_file = NULL;
366 
367  if (img_cfp == NULL) {
368  strcpy_s( filename, real_filename );
369 
370  char *p = strchr( filename, '.' );
371 
372  if ( p )
373  *p = 0;
374 
375  strcat_s( filename, ".tga" );
376 
377  targa_file = cfopen( filename , "rb" );
378 
379  if ( !targa_file ) {
380  return TARGA_ERROR_READING;
381  }
382  } else {
383  targa_file = img_cfp;
384  }
385 
386  header.id_length = cfread_ubyte(targa_file);
387  // header.id_length=targa_file.read_char();
388 
389  header.color_map_type = cfread_ubyte(targa_file);
390  // header.color_map_type=targa_file.read_char();
391 
392  header.image_type = cfread_ubyte(targa_file);
393  // header.image_type=targa_file.read_char();
394 
395  header.cmap_start = cfread_short(targa_file);
396  // header.cmap_start=targa_file.read_short();
397 
398  header.cmap_length = cfread_short(targa_file);
399  // header.cmap_length=targa_file.read_short();
400 
401  header.cmap_depth = cfread_ubyte(targa_file);
402  // header.cmap_depth=targa_file.read_char();
403 
404  header.xoffset = cfread_short(targa_file);
405  // header.xoffset=targa_file.read_short();
406 
407  header.yoffset = cfread_short(targa_file);
408  // header.yoffset=targa_file.read_short();
409 
410  header.width = cfread_short(targa_file);
411  // header.width=targa_file.read_short();
412 
413  header.height = cfread_short(targa_file);
414  // header.height=targa_file.read_short();
415 
416  header.pixel_depth = cfread_ubyte(targa_file);
417  // header.pixel_depth=targa_file.read_char();
418 
419  header.image_descriptor = cfread_ubyte(targa_file);
420  // header.image_descriptor=targa_file.read_char();
421 
422  if (img_cfp == NULL) {
423  cfclose(targa_file);
424  targa_file = NULL;
425  }
426 
427  if ( (header.pixel_depth != 16) && (header.pixel_depth != 24) && (header.pixel_depth != 32) ) {
428  Assertion( (header.pixel_depth != 16) && (header.pixel_depth != 24) && (header.pixel_depth != 32), "Invalid colour depth (%d) in header of tga file %s\n", header.pixel_depth, real_filename );
429  return TARGA_ERROR_READING;
430  }
431 
432  if (w) *w = header.width;
433  if (h) *h = header.height;
434  if (bpp) *bpp = header.pixel_depth;
435 
436  return TARGA_ERROR_NONE;
437 }
438 
439 // Uncompresses some RLE'd TGA data
440 //
441 // dst: pointer uncompressed destination.
442 // src: pointer to source rle'd data.
443 // bitmap_width: how many pixels to uncompress.
444 // bytes_per_pixel: bytes per pixel of the data.
445 //
446 // returns: number of input bytes processed.
447 //
448 int targa_uncompress( ubyte *dst, ubyte *src, int bitmap_width, int bytes_per_pixel, int dest_size )
449 {
450  ubyte *pixdata = dst;
451  ubyte *src_pixels = src;
452 
453  int pixel_count = 0; // Initialize pixel counter
454 
455  // Main decoding loop
456  while (pixel_count < bitmap_width ) {
457 
458  // Get the pixel count
459  int run_count = *src_pixels++;
460 
461  // Make sure writing this next run will not overflow the buffer
462  Assert(pixel_count + (run_count & 0x7f) + 1 <= bitmap_width );
463 
464  // If the run is encoded...
465  if ( run_count & 0x80 ) {
466  run_count &= ~0x80; // Mask off the upper bit
467 
468  // Update total pixel count
469  pixel_count += (run_count + 1);
470 
471  ubyte pixel_value[4]; // temporary
472  ubyte *tmp = pixel_value;
473  targa_read_pixel( 1, &tmp, &src_pixels, bytes_per_pixel, dest_size );
474 
475  // Write remainder of pixel run to buffer 'run_count' times
476  do {
477  memcpy( pixdata, pixel_value, dest_size );
478  pixdata += dest_size;
479  } while (run_count--);
480 
481  } else { // ...the run is unencoded (raw)
482  // Update total pixel count
483  pixel_count += (run_count + 1);
484 
485  // Read run_count pixels
486  targa_read_pixel(run_count+1, &pixdata, &src_pixels, bytes_per_pixel, dest_size );
487  }
488  }
489 
490  Assert( pixel_count == bitmap_width );
491 
492  return src_pixels - src;
493 }
494 
495 
496 // Loads a Targa bitmap
497 //
498 // filename - name of the targa file to load
499 // image_data - allocated storage for the bitmap
500 //
501 // returns - true if succesful, false otherwise
502 //
503 int targa_read_bitmap(const char *real_filename, ubyte *image_data, ubyte *palette, int dest_size, int cf_type)
504 {
505  Assert(real_filename);
507  targa_footer footer;
508  CFILE *targa_file;
510  ubyte r, g, b;
511  int xfile_offset = 0;
512 
513  // open the file
514  strcpy_s( filename, real_filename );
515  char *p = strchr( filename, '.' );
516  if ( p ) *p = 0;
517  strcat_s( filename, ".tga" );
518 
519  targa_file = cfopen( filename , "rb", CFILE_NORMAL, cf_type );
520  if ( !targa_file ){
521  return TARGA_ERROR_READING;
522  }
523 
524  // read the footer info first
525  cfseek( targa_file, cfilelength(targa_file) - TARGA_FOOTER_SIZE, CF_SEEK_SET );
526 
527  memset( &footer, 0, sizeof(targa_footer) );
528 
529  footer.ext_offset = cfread_uint(targa_file);
530  footer.dev_offset = cfread_uint(targa_file);
531 
532  cfread_string(footer.sig_string, sizeof(footer.sig_string), targa_file);
533 
534  if ( !strcmp(footer.sig_string, Xfile_ID) ) {
535  // it's an extended file to lets be sure to skip the extra crap which comes after the
536  // image data section, dev section comes first in the file and we only need one offset
537  if (footer.dev_offset || footer.ext_offset) {
538  xfile_offset = cfilelength(targa_file) - ((footer.dev_offset) ? footer.dev_offset : footer.ext_offset);
539  }
540  }
541 
542  // done with the footer so jump back and do normal reading
543  cfseek( targa_file, 0, CF_SEEK_SET );
544 
545  header.id_length = cfread_ubyte(targa_file);
546  // header.id_length=targa_file.read_char();
547 
548  header.color_map_type = cfread_ubyte(targa_file);
549  // header.color_map_type=targa_file.read_char();
550 
551  header.image_type = cfread_ubyte(targa_file);
552  // header.image_type=targa_file.read_char();
553 
554  header.cmap_start = cfread_short(targa_file);
555  // header.cmap_start=targa_file.read_short();
556 
557  header.cmap_length = cfread_short(targa_file);
558  // header.cmap_length=targa_file.read_short();
559 
560  header.cmap_depth = cfread_ubyte(targa_file);
561  // header.cmap_depth=targa_file.read_char();
562 
563  header.xoffset = cfread_short(targa_file);
564  // header.xoffset=targa_file.read_short();
565 
566  header.yoffset = cfread_short(targa_file);
567  // header.yoffset=targa_file.read_short();
568 
569  header.width = cfread_short(targa_file);
570  // header.width=targa_file.read_short();
571 
572  header.height = cfread_short(targa_file);
573  // header.height=targa_file.read_short();
574 
575  header.pixel_depth = cfread_ubyte(targa_file);
576  // header.pixel_depth=targa_file.read_char();
577 
578  header.image_descriptor = cfread_ubyte(targa_file);
579  // header.image_descriptor=targa_file.read_char();
580 
581  int bytes_per_pixel = (header.pixel_depth>>3);
582 
583  // we're only allowing 2 bytes per pixel (16 bit compressed), unless Cmdline_jpgtga is used
584  Assert( (bytes_per_pixel == 2) || (bytes_per_pixel == 3) || (bytes_per_pixel == 4) );
585 
586  if ( (bytes_per_pixel < 2) || (bytes_per_pixel > 4) ) {
587  cfclose(targa_file);
588  Int3();
589 
590  return TARGA_ERROR_READING;
591  }
592 
593  if((header.image_type!=1)&&(header.image_type!=2)&&(header.image_type!=9)&&(header.image_type!=10)) {
594  cfclose(targa_file);
595  return TARGA_ERROR_READING;
596  }
597 
598  // skip the Image ID field -- should not be needed
599  if(header.id_length>0) {
600  if ( cfseek(targa_file, header.id_length, CF_SEEK_CUR) ) {
601  cfclose(targa_file);
602  return TARGA_ERROR_READING;
603  }
604  }
605 
606  // read palette if one present.
607 
608  if (header.color_map_type) { // non-zero indicates palette in the file
609  Int3();
610 
611  // Determine the size of the color map
612  Assert(header.cmap_depth==24);
613  Assert(header.cmap_length<=256);
614  Assert(palette);
615 
616  // Read the color map data
617  int i;
618  for (i = 0; i < header.cmap_length; i++) {
619  r = cfread_ubyte(targa_file);
620  g = cfread_ubyte(targa_file);
621  b = cfread_ubyte(targa_file);
622 
623  if(palette != NULL){
624  palette[i*3+2] = r;
625  palette[i*3+1] = g;
626  palette[i*3+0] = b;
627  }
628  }
629  // Fill out with black.
630  if(palette != NULL){
631  for (; i < 256; i++) {
632  palette[i*3+2] = 0;
633  palette[i*3+1] = 0;
634  palette[i*3+0] = 0;
635  }
636  }
637  }
638 
639  int bytes_remaining = cfilelength(targa_file) - cftell(targa_file) - xfile_offset;
640 
641  Assert(bytes_remaining > 0);
642 
643  ubyte *fileptr = (ubyte*)vm_malloc(bytes_remaining);
644  Assert(fileptr);
645  if(fileptr == NULL){
646  return TARGA_ERROR_READING;
647  }
648 
649  ubyte *src_pixels = fileptr;
650 
651  cfread(fileptr, bytes_remaining, 1, targa_file);
652 
653  int rowsize = header.width * dest_size;
654 
655  if ( (header.image_type == 1) || (header.image_type == 2) || (header.image_type == 3) ) {
656  // Uncompressed read
657 
658  for (int i = 0; i < header.height; i++) {
659  ubyte * pixptr;
660 
661  if ( ULORIGIN ) {
662  pixptr = image_data + i * rowsize;
663  } else {
664  pixptr = image_data + ((header.height - i - 1) * rowsize);
665  }
666 
667  targa_read_pixel(header.width, &pixptr, &src_pixels, bytes_per_pixel, dest_size );
668  }
669 
670  } else if (header.image_type == 9 || header.image_type == 10 || header.image_type == 11) {
671  // the following handles RLE'ed targa data.
672 
673  // targas encoded by the scanline -- loop on the height
674  for (int i = 0; i < header.height; i++) {
675  ubyte *pixdata;
676 
677  if (ULORIGIN) {
678  pixdata = image_data + i * rowsize;
679  } else {
680  pixdata = image_data + ((header.height - i - 1) * rowsize);
681  }
682 
683  src_pixels += targa_uncompress( pixdata, src_pixels, header.width, bytes_per_pixel, dest_size );
684  }
685 
686  }
687 
688  vm_free(fileptr);
689  cfclose(targa_file);
690  targa_file = NULL;
691 
692  return TARGA_ERROR_NONE;
693 }
694 
695 // Write out a Targa format bitmap. Always writes out a top-up bitmap.
696 // JAS: DOESN'T WORK WITH 8-BPP PALETTES
697 //
698 // filename: name of the Targa file, .tga extension added if not passed in
699 // data: raw image data
700 // w: width of the bitmap in pixels
701 // h: height of the bitmap in pixels
702 // bpp: bits per pixel of the bitmap
703 //
704 // returns: 0 if successful, otherwise -1
705 //
706 int targa_write_bitmap(char *real_filename, ubyte *data, ubyte *palette, int w, int h, int bpp)
707 {
708  Assert(bpp == 24);
710  CFILE *f;
711  int bytes_per_pixel = (bpp >> 3);
712 
713  // open the file
714  strcpy_s( filename, real_filename );
715  char *p = strchr( filename, '.' );
716  if ( p ) *p = 0;
717  strcat_s( filename, ".tga" );
718 
719  f = cfopen( filename , "wb" );
720  if ( !f ){
721  return TARGA_ERROR_READING;
722  }
723 
724  // Write the TGA header
725  cfwrite_ubyte(0, f);
726  // f.write_ubyte(0); // IDLength
727 
728  cfwrite_ubyte(0, f);
729  //f.write_ubyte(0); // ColorMapType
730 
731  cfwrite_ubyte(10, f);
732  // f.write_ubyte(10); // image_type: 2 = 24bpp, uncompressed, 10=24bpp rle compressed
733 
734  cfwrite_ushort(0, f);
735  // f.write_ushort(0); // CMapStart
736 
737  cfwrite_ushort(0, f);
738  // f.write_ushort(0); // CMapLength
739 
740  cfwrite_ubyte(0, f);
741  // f.write_ubyte(0); // CMapDepth
742 
743  cfwrite_ushort(0, f);
744  // f.write_ushort(0); // XOffset
745 
746  cfwrite_ushort(0, f);
747  // f.write_ushort(0); // YOffset
748 
749  cfwrite_ushort((ushort)w, f);
750  // f.write_ushort((ushort)w); // Width
751 
752  cfwrite_ushort((ushort)h, f);
753  // f.write_ushort((ushort)h); // Height
754 
755  cfwrite_ubyte(24, f);
756  // f.write_ubyte(24); // pixel_depth
757 
758  cfwrite_ubyte(0x20, f);
759  // f.write_ubyte(0x20); // ImageDesc ( 0x20 = Origin at upper left )
760 
761  ubyte *compressed_data;
762  compressed_data = (ubyte*)vm_malloc(w * h * bytes_per_pixel);
763  Assert(compressed_data);
764  if(compressed_data == NULL){
765  cfclose(f);
766  return -1;
767  }
768 
769  int compressed_data_len;
770  compressed_data_len = targa_compress((char*)compressed_data, (char*)data, 3, bytes_per_pixel, w * h * bytes_per_pixel);
771  if (compressed_data_len < 0) {
772  vm_free(compressed_data);
773  cfclose(f);
774  return -1;
775  }
776 
777  cfwrite(compressed_data, compressed_data_len, 1, f);
778  cfclose(f);
779  f = NULL;
780 
781  return 0;
782 }
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int cfwrite_ushort(ushort s, CFILE *file)
Definition: cfile.cpp:1328
#define CFILE_NORMAL
Definition: cfile.h:89
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
struct header header
ubyte image_descriptor
Definition: tgautils.cpp:55
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
int cfwrite_ubyte(ubyte b, CFILE *file)
Definition: cfile.cpp:1334
#define ULORIGIN
Definition: tgautils.cpp:35
int targa_read_header(const char *real_filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *palette)
Definition: tgautils.cpp:361
Assert(pm!=NULL)
int targa_read_bitmap(const char *real_filename, ubyte *image_data, ubyte *palette, int dest_size, int cf_type)
Definition: tgautils.cpp:503
GLclampf f
Definition: Glext.h:7097
#define INTEL_SHORT(x)
Definition: pstypes.h:389
Definition: cfile.h:28
#define Assertion(expr, msg,...)
Definition: clang.h:41
#define CF_SEEK_SET
Definition: cfile.h:24
void cfread_string(char *buf, int n, CFILE *file)
Definition: cfile.cpp:1278
#define CF_SEEK_CUR
Definition: cfile.h:25
#define Int3()
Definition: pstypes.h:292
GLuint in
Definition: Glext.h:9087
#define TARGA_FOOTER_SIZE
Definition: tgautils.cpp:30
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define TARGA_ERROR_READING
Definition: tgautils.h:24
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
unsigned int uint
Definition: pstypes.h:64
void(* bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a)
Functional pointer that references any of the bm_set_components functions.
Definition: bmpman.cpp:76
GLboolean GLboolean g
Definition: Glext.h:5781
#define cfopen(...)
Definition: cfile.h:134
GLenum GLenum dst
Definition: Glext.h:5917
ubyte image_type
Definition: tgautils.cpp:52
ubyte id_length
Definition: tgautils.cpp:50
char * filename
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
Definition: cfile.cpp:1414
short cfread_short(CFILE *file, int ver, short deflt)
Definition: cfile.cpp:1192
int idx
Definition: multiui.cpp:761
short yoffset
Definition: tgautils.cpp:45
uint palette_find(int r, int g, int b)
Definition: palman.cpp:184
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: Glext.h:5180
unsigned char ubyte
Definition: pstypes.h:62
short cmap_start
Definition: tgautils.cpp:48
ubyte color_map_type
Definition: tgautils.cpp:51
#define vm_malloc(size)
Definition: pstypes.h:547
ubyte cfread_ubyte(CFILE *file, int ver, ubyte deflt)
Definition: cfile.cpp:1220
#define INTEL_INT(x)
Definition: pstypes.h:388
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
int cftell(CFILE *fp)
int targa_write_bitmap(char *real_filename, ubyte *data, ubyte *palette, int w, int h, int bpp)
Definition: tgautils.cpp:706
#define strcat_s(...)
Definition: safe_strings.h:68
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
short height
Definition: tgautils.cpp:47
struct targa_footer targa_footer
ubyte pixel_depth
Definition: tgautils.cpp:54
unsigned short ushort
Definition: pstypes.h:63
short cmap_length
Definition: tgautils.cpp:49
GLfloat GLfloat p
Definition: Glext.h:8373
int targa_uncompress(ubyte *dst, ubyte *src, int bitmap_width, int bytes_per_pixel, int dest_size)
Definition: tgautils.cpp:448
#define TARGA_ERROR_NONE
Definition: tgautils.h:23
GLenum src
Definition: Glext.h:5917
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
short xoffset
Definition: tgautils.cpp:44
int cfclose(CFILE *cfile)
Definition: cfile.cpp:895
const char * Xfile_ID
Definition: tgautils.cpp:28
int targa_compress(char *out, char *in, int outsize, int pixsize, int bytecount)
Definition: tgautils.cpp:140
struct targa_header targa_header
int cfilelength(CFILE *cfile)
Definition: cfile.cpp:1393
short width
Definition: tgautils.cpp:46
ubyte cmap_depth
Definition: tgautils.cpp:53
uint cfread_uint(CFILE *file, int ver, uint deflt)
Definition: cfile.cpp:1178
#define strcpy_s(...)
Definition: safe_strings.h:67
int cfseek(CFILE *fp, int offset, int where)