Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
giftorle.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 /* +------------------------------------------------------------------+ */
19 /* | Copyright 1989, David Koblas. | */
20 /* | You may copy this file in whole or in part as long as you | */
21 /* | don't try to make money off it, or pretend that you wrote it. | */
22 /* +------------------------------------------------------------------+ */
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include "rle.h"
28 
29 #ifndef lint
30 static char rcsid[] = "$Id: giftorle.c,v 3.0.1.4 1992/04/30 13:56:24 spencer Exp spencer $";
31 #endif
32 /*
33 giftorle() Tag the file.
34 */
35 
36 #define MAXCOLORMAPSIZE 256
37 
38 #define TRUE 1
39 #define FALSE 0
40 
41 #define CM_RED 0
42 #define CM_GREEN 1
43 #define CM_BLUE 2
44 
45 #define MAX_LWZ_BITS 12
46 
47 #define ReadOK(file,buffer,len) (fread(buffer,len,1,file)!=0)
48 #define EasyFail(str,status) {fprintf(stderr,str);return(status);}
49 #define HardFail(str,status) {fprintf(stderr,str);exit (status);}
50 
51 #define LM_to_uint(a,b) (((b)<<8)|(a))
52 
53 int ReadGIF();
54 int ReadColorMap(), IgnoreExtention(), GetCode(), LWZReadByte();
55 int ReadRaster();
56 
57 static rle_map out_map[3*(1<<8)];
58 
59 CONST_DECL char *MY_NAME = "giftorle";
60 
61 FILE *outfile;
62 
63 struct {
64  unsigned int Width;
65  unsigned int Height;
66  unsigned char ColorMap[3][MAXCOLORMAPSIZE];
67  unsigned int BitPixel;
68  unsigned int ColorResolution;
69  unsigned int Background;
70 } Screen;
71 
72 static int output_colormap = FALSE;
73 
74 void
76 int argc;
77 char **argv;
78 {
79  int oflag = 0, nfname = 0;
80  char *outfname = NULL, **infname = NULL;
81 
82  MY_NAME = cmd_name( argv );
83 
84  if ( scanargs( argc, argv, "% c%- o%-outfile.rle!s infile.gif%*s",
85  &output_colormap, &oflag, &outfname,
86  &nfname, &infname ) == 0 )
87  exit( 1 );
88 
89  outfile = rle_open_f( MY_NAME, outfname, "w" );
90  /* Questionable practice. Modifies default values for headers. */
91  rle_addhist( argv, (rle_hdr *)0, &rle_dflt_hdr );
92 
93  /* Always read at least one (standard input). */
94  if ( nfname == 0 )
95  (void)ReadGIF( NULL );
96 
97  while ( nfname-- > 0 )
98  (void)ReadGIF( *infname++ );
99  exit( 0 );
100 }
101 
102 int
103 ReadGIF(filename)
104 char *filename;
105 {
106  unsigned char buf[16];
107  unsigned char c;
108  unsigned char LocalColorMap[3][MAXCOLORMAPSIZE];
109  FILE *fd;
110  int use_global_colormap;
111  int bit_pixel;
112  int count=0;
113 
114  fd = rle_open_f( MY_NAME, filename, "r" );
115 
116  if (! ReadOK(fd,buf,6))
117  EasyFail("error reading magic number\n",TRUE);
118  if (strncmp((char *)buf,"GIF87a",6)!=0)
119  EasyFail("bad magic number (version mismatch?)\n",TRUE);
120  if (! ReadOK(fd,buf,7))
121  EasyFail("error reading screen descriptor\n",TRUE);
122  Screen.Width = LM_to_uint(buf[0],buf[1]);
123  Screen.Height = LM_to_uint(buf[2],buf[3]);
124  Screen.BitPixel = 2<<(buf[4]&0x07);
125  Screen.ColorResolution = (((buf[4]&0x70)>>3)+1);
126  Screen.Background = buf[5];
127  if ((buf[4]&0x80)==0x80) {
128  if (ReadColorMap(fd,Screen.BitPixel,Screen.ColorMap))
129  return (TRUE);
130  }
131 
132  while (1) {
133  if (! ReadOK(fd,&c,1))
134  EasyFail("No image data -- EOF\n",TRUE);
135  if (c == ';')
136  return FALSE;
137  if (c == '!') {
138  if (! ReadOK(fd,&c,1))
139  EasyFail("No extention function code -- EOF\n",TRUE);
140  if (IgnoreExtention(fd))
141  return(TRUE);
142  continue;
143  }
144  if (c != ',') {
145  fprintf(stderr,"Bogus character ignoring '%c'\n",c);
146  continue;
147  }
148 /*
149  if (count == 1)
150  HardFail("This file contains more than one image! FAILING\n",1);
151 */
152  count++;
153 
154  if (! ReadOK(fd,buf,9))
155  EasyFail("Couldn't read left/top/width/height\n",TRUE);
156  if ((buf[8]&0x80)==0x80)
157  use_global_colormap = FALSE ;
158  else
159  use_global_colormap = TRUE ;
160 
161  bit_pixel = 1<<((buf[8]&0x07)+1);
162 
163  if (! use_global_colormap) {
164  if (ReadColorMap(fd,bit_pixel,LocalColorMap))
165  return TRUE;
166  }
167 
168  if (ReadRaster((buf[8]&0x40)==0x40, fd,LM_to_uint(buf[4],buf[5]),
169  LM_to_uint(buf[6],buf[7]),
170  use_global_colormap?Screen.ColorMap:LocalColorMap))
171  return TRUE;
172  }
173 }
174 
175 int
176 ReadColorMap(fd,number,buffer)
177 FILE *fd;
178 int number;
179 unsigned char buffer[3][MAXCOLORMAPSIZE];
180 {
181  int i;
182  unsigned char rgb[3];
183 
184  for (i=0;i<number;i++) {
185  if (! ReadOK(fd,rgb,sizeof(rgb)))
186  EasyFail("Bogus colormap\n",TRUE);
187  buffer[CM_RED][i] = rgb[0] ;
188  buffer[CM_GREEN][i] = rgb[1] ;
189  buffer[CM_BLUE][i] = rgb[2] ;
190  }
191  return FALSE;
192 }
193 
194 int
195 IgnoreExtention(fd)
196 FILE *fd;
197 {
198  static char buf[256];
199  unsigned char c;
200 
201  while (1) {
202  if (! ReadOK(fd,&c,1))
203  EasyFail("EOF in extention\n",TRUE);
204  if (c == 0)
205  return FALSE;
206  if (read(fd,buf,(int) c)!=(int) c)
207  EasyFail("EOF in extention\n",TRUE);
208  }
209 }
210 
211 int
212 GetCode(fd, code_size, flag)
213 FILE *fd;
214 int code_size;
215 int flag;
216 {
217  static unsigned char buf[280];
218  static int curbit,lastbit,done,last_byte;
219  int i, j, ret;
220  unsigned char count;
221 
222  if (flag) {
223  curbit = 0;
224  lastbit = 0;
225  done = FALSE;
226  return 0;
227  }
228 
229  if ( (curbit+code_size) >= lastbit) {
230  if (done) {
231  if (curbit>=lastbit)
232  EasyFail("Ran off the end of my bits\n",-1);
233  }
234  buf[0] = buf[last_byte-2];
235  buf[1] = buf[last_byte-1];
236  if (! ReadOK(fd,&count,1)) {
237  EasyFail("Error in getting buffer size\n",-1);
238  }
239  if (count == 0) {
240  done = TRUE;
241  } else if (! ReadOK(fd,&buf[2],count))
242  EasyFail("Error in getting buffer\n",-1);
243  last_byte = 2 + count;
244  curbit = (curbit - lastbit) + 16;
245  lastbit = (2+count)*8 ;
246  }
247 
248  ret = 0;
249  for( i = curbit, j = 0; j < code_size; i++, j++ )
250  ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j;
251 
252  curbit += code_size;
253 
254  return ret;
255 }
256 
257 int
258 LWZReadByte(fd,flag,input_code_size)
259 FILE *fd;
260 int flag;
261 int input_code_size;
262 {
263  static int fresh=FALSE;
264  int code,incode;
265  static int code_size,set_code_size;
266  static int max_code,max_code_size;
267  static int firstcode,oldcode;
268  static int clear_code,end_code;
269  static int table[2][(1<< MAX_LWZ_BITS)];
270  static int stack[(1<<(MAX_LWZ_BITS))*2],*sp;
271  register int i;
272 
273  if (flag) {
274  set_code_size = input_code_size;
275  code_size = set_code_size+1;
276  clear_code = 1 << set_code_size ;
277  end_code = clear_code + 1;
278  max_code_size = 2*clear_code;
279  max_code = clear_code+2;
280 
281  GetCode(fd,NULL,TRUE);
282 
283  fresh=TRUE;
284 
285  for (i=0;i<clear_code;i++) {
286  table[0][i] = 0;
287  table[1][i] = i;
288  }
289  for (;i<(1<<MAX_LWZ_BITS);i++)
290  table[0][i] = table[1][0] = 0;
291 
292  sp=stack;
293 
294  return 0;
295  } else if (fresh) {
296  fresh = FALSE;
297  do {
298  firstcode=oldcode=
299  GetCode(fd, code_size, FALSE);
300  } while (firstcode == clear_code);
301  return firstcode;
302  }
303 
304  if (sp > stack)
305  return *--sp;
306 
307  while ((code=GetCode(fd,code_size,FALSE))>=0) {
308  if (code == clear_code) {
309  for (i=0;i<clear_code;i++) {
310  table[0][i] = 0;
311  table[1][i] = i;
312  }
313  for (;i<(1<<MAX_LWZ_BITS);i++)
314  table[0][i] = table[1][i] = 0;
315  code_size = set_code_size+1;
316  max_code_size = 2*clear_code;
317  max_code = clear_code+2;
318  sp=stack;
319  firstcode=oldcode=
320  GetCode(fd,code_size,FALSE);
321  return firstcode;
322  } else if (code == end_code) {
323  unsigned char count;
324  unsigned char junk;
325 
326  while (ReadOK(fd,&count,1) && (count!=0))
327  while (count-->0 && ReadOK(fd,&junk,1));
328  if (count!=0)
329  EasyFail("missing EOD in data stream (common occurance)\n",-3);
330  return -2;
331  }
332 
333  incode = code;
334 
335  if (code >= max_code) {
336  *sp++ = firstcode;
337  code = oldcode;
338  }
339 
340  while (code >= clear_code) {
341  *sp++ = table[1][code];
342  if (code == table[0][code])
343  EasyFail("Circular table entry BIG ERROR\n",-1);
344  code = table[0][code];
345  }
346 
347  *sp++ = firstcode = table[1][code];
348 
349  if ((code=max_code)<(1<<MAX_LWZ_BITS)) {
350  table[0][code] = oldcode;
351  table[1][code] = firstcode;
352  max_code++;
353  if ((max_code >= max_code_size) &&
354  (max_code_size < (1<<MAX_LWZ_BITS))) {
355  max_code_size *= 2;
356  code_size++;
357  }
358  }
359 
360  oldcode = incode;
361 
362  if (sp > stack)
363  return *--sp;
364  }
365  return code;
366 }
367 
368 int
369 ReadRaster(interlace,fd,len,height,cmap)
370 int interlace;
371 FILE *fd;
372 int len,height;
373 char cmap[3][MAXCOLORMAPSIZE];
374 {
375  unsigned char c;
376  int v;
377  int xpos=0;
378  rle_pixel **scanline[3];
379  rle_pixel *ptr[3] ;
380  rle_hdr hdr;
381  int i,j;
382  int ypos=0, pass=interlace ? 0 : 4;
383 
384 
385  for (j=0;j<(output_colormap?1:3);j++) {
386  if ((scanline[j]=(rle_pixel **)
387  malloc(height*sizeof(rle_pixel *)))==NULL)
388  EasyFail("Unable to malloc space for pixels #1\n",1);
389  for (i=0;i<height;i++) {
390  if ((scanline[j][i]=(rle_pixel *)
391  malloc(len*sizeof(rle_pixel)))==NULL) {
392  for (;j>=0;j--)
393  for (;i>=0;i--)
394  if (scanline[j][i]!=NULL) free(scanline[i]);
395  EasyFail("Unable to malloc space for pixels #2\n",1);
396  }
397  }
398  }
399 
400  hdr = *rle_hdr_init( (rle_hdr *)NULL );
401  rle_names( &hdr, "giftorle", NULL, 0 );
402 
403  if (output_colormap) {
404  hdr.ncolors = 1;
405  hdr.ncmap = 3;
406  hdr.cmaplen = 8;
407  hdr.cmap = out_map;
408  for (i=0;i<(1<<8);i++) {
409  out_map[i+(0<<8)] = cmap[CM_RED][i] << 8;
410  out_map[i+(1<<8)] = cmap[CM_GREEN][i] << 8;
411  out_map[i+(2<<8)] = cmap[CM_BLUE][i] << 8;
412  }
413  } else {
414  RLE_SET_BIT(hdr, RLE_RED);
415  RLE_SET_BIT(hdr, RLE_GREEN);
416  RLE_SET_BIT(hdr, RLE_BLUE);
417  hdr.ncolors = 3;
418  }
419  hdr.rle_file = outfile ;
420  hdr.xmax = len - 1;
421  hdr.ymax = height - 1;
422 
423  rle_put_setup(&hdr);
424 
425  if (! ReadOK(fd,&c,1))
426  EasyFail("Bogus image data -- EOF\n",TRUE);
427  if (LWZReadByte(fd,TRUE,c)<0)
428  return TRUE;
429 
430  while ((v=LWZReadByte(fd,FALSE,c))>=0) {
431  if (output_colormap) {
432  scanline[RLE_RED][ypos][xpos] = v ;
433  } else {
434  scanline[RLE_RED][ypos][xpos] = cmap[CM_RED][v] ;
435  scanline[RLE_GREEN][ypos][xpos] = cmap[CM_GREEN][v] ;
436  scanline[RLE_BLUE][ypos][xpos] = cmap[CM_BLUE][v] ;
437  }
438  xpos++;
439  if (xpos==len) {
440  xpos = 0;
441  switch (pass) {
442  case 0:
443  case 1:
444  ypos += 8; break;
445  case 2:
446  ypos += 4; break;
447  case 3:
448  ypos += 2; break;
449  case 4: /* Not interlaced */
450  ypos++; break;
451  default:
452  fprintf( stderr, "%s: Data past end of image.\n", hdr.cmd );
453  break;
454  }
455  if (ypos >= height) {
456  pass++;
457  switch (pass) {
458  case 1:
459  ypos = 4; break;
460  case 2:
461  ypos = 2; break;
462  case 3:
463  ypos = 1; break;
464  default: /* Shouldn't happen. */
465  ypos = 0; break;
466  }
467  }
468  }
469  }
470 
471  for ( i = height - 1; i >= 0; i-- ) {
472  ptr[0] = scanline[RLE_RED][i] ;
473  if (! output_colormap) {
474  ptr[1] = scanline[RLE_GREEN][i] ;
475  ptr[2] = scanline[RLE_BLUE][i] ;
476  }
477  rle_putrow(ptr,len,&hdr);
478  }
479 
480  rle_puteof(&hdr);
481 
482  for (i=0;i<height;i++) {
483  if (scanline[0][i]!=NULL) free(scanline[0][i]);
484  if (output_colormap) continue;
485 
486  if (scanline[1][i]!=NULL) free(scanline[1][i]);
487  if (scanline[2][i]!=NULL) free(scanline[2][i]);
488  }
489  free(scanline[0]);
490  if (! output_colormap) {
491  free(scanline[1]);
492  free(scanline[2]);
493  }
494 
495  if (v == -2)
496  return FALSE;
497  return TRUE;
498 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
static int output_colormap
Definition: giftorle.c:72
#define MAX_LWZ_BITS
Definition: giftorle.c:45
#define RLE_SET_BIT(glob, bit)
Definition: rle.h:122
FILE * outfile
Definition: giftorle.c:61
static char rcsid[]
Definition: giftorle.c:30
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
#define EasyFail(str, status)
Definition: giftorle.c:48
char * cmd_name(char **argv)
Definition: cmd_name.c:31
void main(int argc, char **argv)
Definition: aliastorle.c:121
#define FALSE
Definition: giftorle.c:39
rle_map * cmap
Definition: rle.h:112
#define ReadOK(file, buffer, len)
Definition: giftorle.c:47
#define RLE_GREEN
Definition: rle.h:63
#define RLE_BLUE
Definition: rle.h:64
#define CM_BLUE
Definition: giftorle.c:43
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
#define LM_to_uint(a, b)
Definition: giftorle.c:51
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
const char * MY_NAME
Definition: rletogif.c:35
static rle_map out_map[3 *(1<< 8)]
Definition: giftorle.c:57
#define CONST_DECL
Definition: rle_config.h:42
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
#define TRUE
Definition: giftorle.c:38
#define CM_GREEN
Definition: giftorle.c:42
int ncmap
Definition: rle.h:100
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
int cmaplen
Definition: rle.h:100
#define MAXCOLORMAPSIZE
Definition: giftorle.c:36
unsigned short rle_map
Definition: rle.h:57
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
rle_hdr rle_dflt_hdr
Definition: rle_global.c:66
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define CM_RED
Definition: giftorle.c:41