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