Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
gifencod.c
Go to the documentation of this file.
1 
2 /*****************************************************************************
3  *
4  * GIFENCODE.C - GIF Image compression interface
5  *
6  * GIFEncode( FName, GHeight, GWidth, GInterlace, Background,
7  * BitsPerPixel, Red, Green, Blue, GetPixel )
8  *
9  * Modified for use with RLE interface, Spencer W. Thomas, June, 1990.
10  * (replaced fopen with rle_open_f).
11  *
12  *****************************************************************************/
13 
14 #include <stdio.h>
15 #include "rle.h"
16 #include "rletogif.h"
17 
18 #define TRUE 1
19 #define FALSE 0
20 
21 static int Width, Height;
22 static int curx, cury;
23 static long CountDown;
24 static int Pass = 0;
25 static int Interlace;
26 
27 
28 
29 /*
30  * Bump the 'curx' and 'cury' to point to the next pixel
31  */
32 static void
33 BumpPixel()
34 {
35  /*
36  * Bump the current X position
37  */
38  curx++;
39 
40  /*
41  * If we are at the end of a scan line, set curx back to the beginning
42  * If we are interlaced, bump the cury to the appropriate spot,
43  * otherwise, just increment it.
44  */
45  if( curx == Width ) {
46  curx = 0;
47 
48  if( !Interlace )
49  cury++;
50  else {
51  switch( Pass ) {
52 
53  case 0:
54  cury += 8;
55  if( cury >= Height ) {
56  Pass++;
57  cury = 4;
58  }
59  break;
60 
61  case 1:
62  cury += 8;
63  if( cury >= Height ) {
64  Pass++;
65  cury = 2;
66  }
67  break;
68 
69  case 2:
70  cury += 4;
71  if( cury >= Height ) {
72  Pass++;
73  cury = 1;
74  }
75  break;
76 
77  case 3:
78  cury += 2;
79  break;
80  }
81  }
82  }
83 }
84 
85 /*
86  * Write out a word to the GIF file
87  */
88 static void
89 Putword( w, fp )
90 int w;
91 FILE *fp;
92 {
93  fputc( w & 0xff, fp );
94  fputc( (w >> 8) & 0xff, fp );
95 }
96 
97 
98 /*
99  * Return the next pixel from the image
100  */
101 int
102 GIFNextPixel( getpixel )
103 ifunptr getpixel;
104 {
105  int r;
106 
107  if( CountDown == 0 )
108  return EOF;
109 
110  CountDown--;
111 
112  r = ( * getpixel )( curx, cury );
113 
114  BumpPixel();
115 
116  return r;
117 }
118 
119 /* public */
120 
121 void
122 GIFEncode( FName, GWidth, GHeight, GInterlace, Background,
123  BitsPerPixel, Red, Green, Blue, GetPixel )
124 
125 char *FName;
126 int GWidth, GHeight;
127 int GInterlace;
128 int Background;
129 int BitsPerPixel;
130 short int Red[], Green[], Blue[];
131 ifunptr GetPixel;
132 {
133  FILE *fp;
134  int B;
135  int RWidth, RHeight;
136  int LeftOfs, TopOfs;
137  int Resolution;
138  int ColorMapSize;
139  int InitCodeSize;
140  int i;
141 
142  /* doesn't support interlace yet */
143  if (GInterlace) error("no support for interlace yet");
144  Interlace = GInterlace;
145 
146  ColorMapSize = 1 << BitsPerPixel;
147 
148  RWidth = Width = GWidth;
149  RHeight = Height = GHeight;
150  LeftOfs = TopOfs = 0;
151 
152  Resolution = BitsPerPixel;
153 
154  /*
155  * Calculate number of bits we are expecting
156  */
157  CountDown = (long)Width * (long)Height;
158 
159  /*
160  * Indicate which pass we are on (if interlace)
161  */
162  Pass = 0;
163 
164  /*
165  * The initial code size
166  */
167  if( BitsPerPixel <= 1 )
168  InitCodeSize = 2;
169  else
170  InitCodeSize = BitsPerPixel;
171 
172  /*
173  * Set up the current x and y position
174  */
175  curx = cury = 0;
176 
177  /*
178  * Open the GIF file for binary write
179  */
180  fp = rle_open_f( MY_NAME, FName, "w" );
181 
182  /*
183  * Write the Magic header
184  */
185  fwrite( "GIF87a", 1, 6, fp );
186 
187  /*
188  * Write out the screen width and height
189  */
190  Putword( RWidth, fp );
191  Putword( RHeight, fp );
192 
193  /*
194  * Indicate that there is a global colour map
195  */
196  B = 0x80; /* Yes, there is a color map */
197  /*
198  * OR in the resolution
199  */
200  B |= (Resolution - 1) << 5;
201 
202  /*
203  * OR in the Bits per Pixel
204  */
205  B |= (BitsPerPixel - 1);
206 
207  /*
208  * Write it out
209  */
210  fputc( B, fp );
211 
212  /*
213  * Write out the Background colour
214  */
215  fputc( Background, fp );
216 
217  /*
218  * Byte of 0's (future expansion)
219  */
220  fputc( 0, fp );
221 
222  /*
223  * Write out the Global Colour Map
224  */
225  for( i=0; i<ColorMapSize; i++ ) {
226  fputc( Red[i]>>8, fp );
227  fputc( Green[i]>>8, fp );
228  fputc( Blue[i]>>8, fp );
229  }
230  /*
231  * Write an Image separator
232  */
233  fputc( ',', fp );
234 
235  /*
236  * Write the Image header
237  */
238 
239  Putword( LeftOfs, fp );
240  Putword( TopOfs, fp );
241  Putword( Width, fp );
242  Putword( Height, fp );
243 
244  /*
245  * Write out whether or not the image is interlaced
246  */
247 
248  if( Interlace )
249  fputc( 0x40, fp );
250  else
251  fputc( 0x00, fp );
252 
253  /*
254  * Write out the initial code size
255  */
256  fputc( InitCodeSize, fp );
257 
258  /*
259  * Go and actually compress the data
260  */
261  compgif( InitCodeSize + 1, fp, GetPixel );
262  /*
263  * Write out a Zero-length packet (to end the series)
264  */
265  fputc( 0, fp );
266 
267  /*
268  * Write the GIF file terminator
269  */
270  fputc( ';', fp );
271 
272  /*
273  * And close the file
274  */
275  fclose( fp );
276 
277 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
static int curx
Definition: gifencod.c:22
static int Interlace
Definition: gifencod.c:25
static int Width
Definition: gifencod.c:21
static int Pass
Definition: gifencod.c:24
const char * MY_NAME
Definition: rletogif.c:35
int(* ifunptr)()
Definition: rletogif.h:8
static int cury
Definition: gifencod.c:22
static long CountDown
Definition: gifencod.c:23
static int Height
Definition: gifencod.c:21