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
BumpPixel()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
Putword(w,fp)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
GIFNextPixel(getpixel)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
GIFEncode(FName,GWidth,GHeight,GInterlace,Background,BitsPerPixel,Red,Green,Blue,GetPixel)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 }
278
279
280