Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
targatorle.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  *
18  * Copyright (c) 1986, John W. Peterson
19  */
20 
21 /*
22  * targatorle.c - Convert some Truevision TARGA images to RLE. Not all
23  * variations of the TARGA format are supported (yet).
24  *
25  * Author: Hann-Bin Chuang
26  * Department of Chemistry
27  * Boston University
28  * Date: Tue. Aug 25 1987
29  *
30  * Usage is:
31  * targatorle [-h header.lis] [-n nchannels] [-o outfile.rle] [infile.tga]
32  *
33  * -h header.lis write the targa header information to file "header.lis"
34  * -n nchannels Number of channels to write to output RLE file for
35  * color images (3 or 4), default is same as source image.
36  * -o outfile.rle instead of stdout, use outfile.rle as output.
37  *
38  * rleflip is not necessary because Targa images and RLE both use
39  * the last line (in the file) as the upper left of the image.
40  */
41 
42 /*
43  Modifications:
44 
45  Made By: Andrew Hadenfeldt
46  Department of Electrical Engineering
47  University of Nebraska-Lincoln
48 
49  Date: 16-Mar-1991
50 
51  What: Rewrote file I/O code to try to be machine and/or byte-order independent.
52  Changed pixel line arrays to use malloc to allow images wider than
53  512 pixels to be processed. Also added code to convert some 8- and 16-bit
54  TARGA image formats. For 8-bit images, a single channel is written. For
55  16-bit files, the color map is still ignored, and the 16-bit pixels
56  are converted to 24 bits. Added a swtich (-n) to specify the number of
57  channels to write to the RLE file (3 or 4) for color images, allowing the
58  alpha channel to be omitted if desired. By default, the alpha channel will
59  be copied to the RLE file.
60 
61  Also allow processing of "color" images with 8-bit pixels, but only if they
62  have no colormap data. This is sort of a hack, since our Truevision ATVista
63  software can generate this format (they don't seem to use the B/W formats).
64 
65  Date: 12-Jul-1991
66 
67  What: Added run-length compression decoding, tested with known type 10 images.
68  Type 11 *should* also work, but who knows? No support for any of the
69  colormapped formats yet. Also changed colormap code to properly read
70  and discard the colormap section if the image is in a true-color format.
71 */
72 
73 #include <stdio.h>
74 #include <sys/types.h>
75 #include "rle.h"
76 
77 #define HEADSIZE 18
78 #define GETSHORT(N) (((unsigned short)(*(N+1))<<8) + (unsigned short)(*(N)))
79 
80 /*
81  * Description of header for files containing TARGA (Truevision, Inc.) images
82  */
83 struct targafile {
84  unsigned char num_char_id, /* Number of Characters in ID Field */
85  cmap_type, /* Color Map Type */
86  image_type; /* Image Type Code */
87  unsigned short cmap_origin, /* Color Map Origin */
88  cmap_length; /* Color Map Length */
89  unsigned char cmap_size; /* Color Map Entry Size */
90  unsigned short image_x_origin, /* X-Origin of Image */
91  image_y_origin, /* Y-Origin of Image */
92  image_width, /* Width of Image */
93  image_height; /* Height of Image */
94  unsigned char image_pix_size, /* Image Pixel Size */
95  image_descriptor; /* Image Descriptor Byte */
96  unsigned char *image_id; /* Image ID Field */
97  unsigned char *cmap_data; /* color Map data */
98  };
99 
100 unsigned char *outrows[4];
101 unsigned char *redline, *grnline, *bluline, *alfline;
102 FILE *infile;
103 
104 int bwimage=0;
105 int truecolor=0;
106 int cmapped=0;
107 int rlcomp=0;
112 
113 int havedata=0;
115 int bufinx;
116 unsigned char rlbuf[4*128];
117 
118 void targa_getrow();
119 void init_comp();
120 unsigned char getbyte();
121 
122 void
124 int argc;
125 char *argv[];
126 {
127  FILE *outfile;
128  FILE *hdrfile=NULL;
129  char *infname=NULL,
130  *outfname=NULL,
131  *hdrfname=NULL;
132  int oflag=0,
133  nflag=0,
134  hflag=0;
135  int i;
136  unsigned char headbuf[HEADSIZE];
137  rle_hdr out_hdr;
138 
139  if ( scanargs( argc,argv,
140  "% h%-hdrfile!s n%-nchannels!d o%-outfile!s infile%s\n(\
141 \tConvert TARGA file to URT format.\n\
142 \t-h\tSpecify separate header file.\n\
143 \t-n\tNumber of channels to write, defaults to same as input.)",
144  &hflag, &hdrfname, &nflag, &nchannels,
145  &oflag, &outfname, &infname ) == 0 )
146  exit(1);
147 
148  out_hdr = *rle_hdr_init( (rle_hdr *)NULL );
149  rle_names( &out_hdr, cmd_name( argv ), outfname, 0 );
150 
151  infile = rle_open_f(out_hdr.cmd, infname, "r");
152  if ( hflag )
153  hdrfile = rle_open_f(out_hdr.cmd, hdrfname, "w");
154  outfile = rle_open_f(out_hdr.cmd, outfname, "w");
155 
156  /* Check that hdrfile and outfile aren't the same. */
157 
158  if ( hdrfile == outfile )
159  {
160  fprintf( stderr,
161  "%s: Can't write header and RLE data to same file.\n",
162  out_hdr.cmd );
163  exit( 1 );
164  }
165 
166  /* Read the image header */
167 
168  if (fread (headbuf, 1, HEADSIZE, infile)!=HEADSIZE)
169  {
170  fprintf(stderr,"targatorle: Read Error.\n");
171  exit(1);
172  }
173 
174  tga_head.num_char_id = headbuf[0];
175  tga_head.cmap_type = headbuf[1];
176  tga_head.image_type = headbuf[2];
177 
178  tga_head.cmap_origin = GETSHORT(headbuf+3);
179  tga_head.cmap_length = GETSHORT(headbuf+5);
180  tga_head.cmap_size = headbuf[7];
181 
182  tga_head.image_x_origin = GETSHORT(headbuf+8);
183  tga_head.image_y_origin = GETSHORT(headbuf+10);
184  tga_head.image_width = GETSHORT(headbuf+12);
185  tga_head.image_height = GETSHORT(headbuf+14);
186  tga_head.image_pix_size = headbuf[16];
187 
188  tga_head.image_descriptor = headbuf[17];
189 
190  if (hflag) {
191  fprintf (hdrfile, "num_char_id = %u \n", (unsigned)tga_head.num_char_id);
192  fprintf (hdrfile, "cmap_type = %u \n", (unsigned)tga_head.cmap_type);
193  fprintf (hdrfile, "image_type = %u \n", (unsigned)tga_head.image_type);
194  }
195 
196  /* Check Color Map Type. Currently, Truevision defines only 0 and 1 */
197 
198  if (tga_head.cmap_type==0) {
199  if (hflag) {
200  fprintf (hdrfile, "Color Map Type = 0 \n");
201  }
202  }
203  else if (tga_head.cmap_type==1) {
204  cmapped = 1;
205  if (hflag) {
206  fprintf (hdrfile, "cmap_origin = %u \n",
207  (unsigned)tga_head.cmap_origin);
208  fprintf (hdrfile, "cmap_length = %u \n",
209  (unsigned)tga_head.cmap_length);
210  fprintf (hdrfile, "cmap_size = %u \n",
211  (unsigned)tga_head.cmap_size);
212  }
213  }
214  else {
215  fprintf (stderr,
216  "%s: Invalid Color Map Type Code (%d)\n", out_hdr.cmd,
218  exit (1);
219  }
220 
221  if (hflag) {
222  fprintf (hdrfile, "image_x_origin = %u \n",
223  (unsigned)tga_head.image_x_origin);
224  fprintf (hdrfile, "image_y_origin = %u \n",
225  (unsigned)tga_head.image_y_origin);
226  fprintf (hdrfile, "image_width = %u \n",
227  (unsigned)tga_head.image_width);
228  fprintf (hdrfile, "image_height = %u \n",
229  (unsigned)tga_head.image_height);
230  fprintf (hdrfile, "image_pix_size = %u \n",
231  (unsigned)tga_head.image_pix_size);
232  }
233 
234  /* Is this a supported image type? */
235 
236  switch (tga_head.image_type)
237  {
238  /* Image type codes from imagefmt.h, */
239  /* by Truevision, Inc. */
240 
241  case 0: /* No Image Data */
242  fprintf(stderr,"%s: Image file is header only, no data.\n",
243  out_hdr.cmd);
244  exit(1);
245  break;
246 
247  case 2: /* Uncompressed Real-Color Image */
248 
249  /* Check for special case of a B/W */
250  /* pretending to be a color image */
251  if ((tga_head.image_pix_size==8) &&
253  {
254  bwimage = 1;
255  nchannels = 1;
256  }
257  else
258  {
259  truecolor = 1;
260  }
261  break;
262 
263  case 3: /* Uncompressed B/W Image */
264  bwimage = 1;
265  nchannels = 1;
266  break;
267 
268  case 10: /* Run-length Encoded, Real-Color Image */
269  truecolor = 1;
270  rlcomp = 1;
271  break;
272 
273  case 11: /* Run-length Encoded, B/W Image */
274  bwimage = 1;
275  nchannels = 1;
276  rlcomp = 1;
277  break;
278 
279  case 1: /* Uncompressed, Color-Mapped Image */
280  case 9: /* Run-length Encoded, Color-Mapped Image */
281  default:
282  fprintf(stderr,"%s: Image type (%d) not supported by this program.\n",
283  out_hdr.cmd, tga_head.image_type);
284  exit(1);
285  }
286 
287  /* Check limits on what this program can handle */
288 
289  if (bwimage)
290  {
292  {
293  fprintf(stderr,"%s: B/W image pixel size must be 8.\n", out_hdr.cmd);
294  exit(1);
295  }
296  }
297  else if (truecolor)
298  {
299  if ( !((tga_head.image_pix_size==16) ||
300  (tga_head.image_pix_size==24) ||
301  (tga_head.image_pix_size==32) ))
302  {
303  fprintf(stderr,
304  "%s: Real-color image pixel size must be 16, 24 or 32.\n",
305  out_hdr.cmd);
306  exit(1);
307  }
308  if (tga_head.image_pix_size==24) nchannels = 3;
309  }
310 
311  /* Read image ID field */
312 
313  if ((i=(unsigned)tga_head.num_char_id)>=1) {
314  tga_head.image_id = (unsigned char *)malloc(i);
315  fread (tga_head.image_id, i, 1, infile);
316  }
317 
318  /* Read Color Map, if any. Do this even if the image is "true-color", since */
319  /* Truevision and other developers use the colormap area for their own needs. */
320 
321  if ((unsigned)tga_head.cmap_type==1) {
322  switch((unsigned)tga_head.cmap_size) {
323 
324  case 15: /* Typical values for colormap width */
325  case 16:
326  cmapbytes = 2;
327  break;
328  case 24:
329  cmapbytes = 3;
330  break;
331  case 32:
332  cmapbytes = 4;
333  break;
334 
335  default:
336  fprintf (stderr,"%s: Invalid color map width (%u bits)\n",
337  out_hdr.cmd, (unsigned)tga_head.cmap_size);
338  exit(1);
339  }
341  (unsigned char *)calloc((unsigned)tga_head.cmap_length,cmapbytes);
343 
344  }
345 
346  /* Build RLE image header */
347 
348  RLE_SET_BIT(out_hdr, RLE_RED);
349 
350  if (nchannels==1)
351  {
352  out_hdr.ncolors = 1;
353  }
354  else
355  {
356  RLE_SET_BIT(out_hdr, RLE_GREEN);
357  RLE_SET_BIT(out_hdr, RLE_BLUE);
358  out_hdr.ncolors = 3;
359 
360  if (nchannels==4) /* Save the alpha channel? */
361  {
362  RLE_SET_BIT(out_hdr, RLE_ALPHA);
363  out_hdr.alpha = 1;
364  }
365  }
366 
367  out_hdr.rle_file = outfile;
368  out_hdr.xmax = (unsigned)tga_head.image_width-1;
369  out_hdr.ymax = (unsigned)tga_head.image_height-1;
370 
371  /* Allocate pixel buffers */
372 
373  alfline = (unsigned char *)malloc(tga_head.image_width);
374  redline = (unsigned char *)malloc(tga_head.image_width);
375  grnline = (unsigned char *)malloc(tga_head.image_width);
376  bluline = (unsigned char *)malloc(tga_head.image_width);
377 
378  if ((!alfline) || (!redline) || (!grnline) || (!bluline))
379  {
380  fprintf(stderr,"%s: Image is too large for this program.\n",
381  out_hdr.cmd);
382  exit(1);
383  }
384 
385  outrows[0] = alfline;
386  outrows[1] = redline;
387  outrows[2] = grnline;
388  outrows[3] = bluline;
389 
390  rle_addhist( argv, (rle_hdr *)NULL, &out_hdr );
391  rle_put_setup( &out_hdr );
392 
393  /* Read and process each of the TARGA scan lines */
394 
395  pixwidth = ((unsigned)tga_head.image_pix_size+7)/8; /* Pixel size in bytes */
396  init_comp();
397  for (i=0;i<(unsigned)tga_head.image_height;i++)
398  {
399  targa_getrow();
400  rle_putrow (&outrows[1], (unsigned)tga_head.image_width, &out_hdr);
401  }
402  rle_puteof( &out_hdr );
403 
404  free(alfline);
405  free(redline);
406  free(grnline);
407  free(bluline);
408 }
409 
410 void targa_getrow()
411 {
412  int j;
413  int numpix;
414  unsigned pxltmp;
415 
416  numpix = (unsigned)tga_head.image_width;
417 
418  switch (pixwidth) {
419 
420  case 1: /* 8-bit pixels */
421  for (j=0;j<numpix;j++) redline[j] = getbyte();
422  return;
423  break;
424 
425  case 2: /* 16-bit pixels */
426  for (j=0;j<numpix;j++)
427  {
428  pxltmp = (unsigned)getbyte();
429  pxltmp |= ((unsigned)getbyte())<<8;
430 
431  bluline[j] = (pxltmp & 0x1f) << 3;
432  grnline[j] = ((pxltmp >> 5) & 0x1f) << 3;
433  redline[j] = ((pxltmp >> 10) & 0x1f) << 3;
434  alfline[j] = ((pxltmp & 0x8000) ? 0xff : 0);
435  }
436  break;
437 
438  case 3: /* 24/32 bit pixels */
439  case 4:
440  for (j=0;j<numpix;j++)
441  {
442  bluline[j]=getbyte();
443  grnline[j]=getbyte();
444  redline[j]=getbyte();
445  if (pixwidth==4)
446  alfline[j]=getbyte();
447  }
448  break;
449 
450  default:
451  fprintf(stderr,"targatorle: Invalid pixel size (%d bytes) for this program.\n",
452  pixwidth);
453  }
454 }
455 
456 void init_comp()
457 {
458  havedata = 0;
459 }
460 
461 unsigned char getbyte()
462 {
463  int j,k;
464  int pkhdr;
465  unsigned char pixdata[4];
466  unsigned char *pp;
467  unsigned char next;
468 
469  if (!rlcomp)
470  {
471  next = (unsigned)getc(infile)&0xff;
472  return next;
473  }
474 
475  if (!havedata)
476  {
477  pkhdr = getc(infile);
478  rlcount = (pkhdr & 0x7f) + 1;
479 
480  if (pkhdr & 0x80) /* Run-length packet */
481  {
482  fread(pixdata,pixwidth,1,infile);
483  pp = rlbuf;
484  for(k=0; k<rlcount; k++)
485  for(j=0; j<pixwidth; j++)
486  *(pp++) = pixdata[j];
487  }
488  else /* Raw packet */
489  {
490  fread(rlbuf,pixwidth,rlcount,infile);
491  }
492  rlcount *= pixwidth;
493  bufinx = 0;
494  havedata = 1;
495  }
496 
497  next = rlbuf[bufinx];
498  if (++bufinx == rlcount) havedata = 0;
499 
500  return next;
501 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
int bwimage
Definition: targatorle.c:104
#define GETSHORT(N)
Definition: targatorle.c:78
#define RLE_SET_BIT(glob, bit)
Definition: rle.h:122
unsigned char * image_id
Definition: targatorle.c:96
unsigned char image_pix_size
Definition: rletotarga.c:61
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
unsigned short image_width
Definition: rletotarga.c:57
char * cmd_name(char **argv)
Definition: cmd_name.c:31
void main(int argc, char **argv)
Definition: aliastorle.c:121
unsigned char image_descriptor
Definition: rletotarga.c:61
unsigned char * bluline
Definition: targatorle.c:101
int rlcomp
Definition: targatorle.c:107
#define RLE_GREEN
Definition: rle.h:63
unsigned char rlbuf[4 *128]
Definition: targatorle.c:116
int truecolor
Definition: targatorle.c:105
#define RLE_BLUE
Definition: rle.h:64
unsigned char cmap_type
Definition: rletotarga.c:51
int bufinx
Definition: targatorle.c:115
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
unsigned char * alfline
Definition: targatorle.c:101
int cmapbytes
Definition: targatorle.c:109
const char * cmd
Definition: rle.h:133
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
#define RLE_RED
Definition: rle.h:62
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
int pixwidth
Definition: targatorle.c:110
unsigned char * grnline
Definition: targatorle.c:101
int nchannels
Definition: targatorle.c:108
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
unsigned char image_type
Definition: rletotarga.c:51
unsigned short cmap_origin
Definition: rletotarga.c:54
int havedata
Definition: targatorle.c:113
#define HEADSIZE
Definition: targatorle.c:77
FILE * infile
Definition: targatorle.c:102
int ymax
Definition: rle.h:100
unsigned short image_x_origin
Definition: rletotarga.c:57
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
unsigned char * redline
Definition: targatorle.c:101
int cmapped
Definition: targatorle.c:106
int alpha
Definition: rle.h:100
#define RLE_ALPHA
Definition: rle.h:65
unsigned short cmap_length
Definition: rletotarga.c:54
struct targafile tga_head
Definition: targatorle.c:111
unsigned char num_char_id
Definition: rletotarga.c:51
unsigned short image_height
Definition: rletotarga.c:57
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
int rlcount
Definition: targatorle.c:114
unsigned char cmap_size
Definition: rletotarga.c:56
unsigned short image_y_origin
Definition: rletotarga.c:57
FILE * rle_file
Definition: rle.h:114
unsigned char * outrows[4]
Definition: targatorle.c:100
int ncolors
Definition: rle.h:100
unsigned char * cmap_data
Definition: targatorle.c:97