1 28994509 2004-04-21 devnull #include <u.h>
2 28994509 2004-04-21 devnull #include <libc.h>
3 28994509 2004-04-21 devnull #include <draw.h>
4 28994509 2004-04-21 devnull #include <memdraw.h>
5 28994509 2004-04-21 devnull #include <bio.h>
6 28994509 2004-04-21 devnull #include "imagefile.h"
10 28994509 2004-04-21 devnull Nhash = 4001,
11 cbeb0b26 2006-04-01 devnull Nbuf = 300
14 28994509 2004-04-21 devnull typedef struct Entry Entry;
15 28994509 2004-04-21 devnull typedef struct IO IO;
18 28994509 2004-04-21 devnull struct Entry
20 28994509 2004-04-21 devnull int index;
21 28994509 2004-04-21 devnull int prefix;
22 28994509 2004-04-21 devnull int exten;
23 28994509 2004-04-21 devnull Entry *next;
26 28994509 2004-04-21 devnull struct IO
28 28994509 2004-04-21 devnull Biobuf *fd;
29 28994509 2004-04-21 devnull uchar buf[Nbuf];
31 28994509 2004-04-21 devnull int nbits; /* bits in right side of shift register */
32 28994509 2004-04-21 devnull int sreg; /* shift register */
35 28994509 2004-04-21 devnull static Rectangle mainrect;
36 28994509 2004-04-21 devnull static Entry tbl[4096];
37 28994509 2004-04-21 devnull static uchar *colormap[5]; /* one for each ldepth: GREY1 GREY2 GREY4 CMAP8=rgbv plus GREY8 */
38 28994509 2004-04-21 devnull #define GREYMAP 4
39 28994509 2004-04-21 devnull static int colormapsize[] = { 2, 4, 16, 256, 256 }; /* 2 for zero is an odd property of GIF */
41 28994509 2004-04-21 devnull static void writeheader(Biobuf*, Rectangle, int, ulong, int);
42 28994509 2004-04-21 devnull static void writedescriptor(Biobuf*, Rectangle);
43 28994509 2004-04-21 devnull static char* writedata(Biobuf*, Image*, Memimage*);
44 28994509 2004-04-21 devnull static void writecomment(Biobuf *fd, char*);
45 28994509 2004-04-21 devnull static void writegraphiccontrol(Biobuf *fd, int, int);
46 28994509 2004-04-21 devnull static void* gifmalloc(ulong);
47 28994509 2004-04-21 devnull static void encode(Biobuf*, Rectangle, int, uchar*, uint);
51 28994509 2004-04-21 devnull startgif0(Biobuf *fd, ulong chan, Rectangle r, int depth, int loopcount)
55 840bb968 2004-04-25 devnull for(i=0; i<nelem(tbl); i++){
56 840bb968 2004-04-25 devnull tbl[i].index = i;
57 840bb968 2004-04-25 devnull tbl[i].prefix = -1;
58 840bb968 2004-04-25 devnull tbl[i].exten = i;
61 28994509 2004-04-21 devnull switch(chan){
62 28994509 2004-04-21 devnull case GREY1:
63 28994509 2004-04-21 devnull case GREY2:
64 28994509 2004-04-21 devnull case GREY4:
65 28994509 2004-04-21 devnull case CMAP8:
66 28994509 2004-04-21 devnull case GREY8:
69 28994509 2004-04-21 devnull return "WriteGIF: can't handle channel type";
72 28994509 2004-04-21 devnull mainrect = r;
73 28994509 2004-04-21 devnull writeheader(fd, r, depth, chan, loopcount);
74 28994509 2004-04-21 devnull return nil;
78 28994509 2004-04-21 devnull startgif(Biobuf *fd, Image *image, int loopcount)
80 28994509 2004-04-21 devnull return startgif0(fd, image->chan, image->r, image->depth, loopcount);
84 28994509 2004-04-21 devnull memstartgif(Biobuf *fd, Memimage *memimage, int loopcount)
86 28994509 2004-04-21 devnull return startgif0(fd, memimage->chan, memimage->r, memimage->depth, loopcount);
91 28994509 2004-04-21 devnull writegif0(Biobuf *fd, Image *image, Memimage *memimage, ulong chan, Rectangle r, char *comment, int dt, int trans)
93 28994509 2004-04-21 devnull char *err;
95 28994509 2004-04-21 devnull switch(chan){
96 28994509 2004-04-21 devnull case GREY1:
97 28994509 2004-04-21 devnull case GREY2:
98 28994509 2004-04-21 devnull case GREY4:
99 28994509 2004-04-21 devnull case CMAP8:
100 28994509 2004-04-21 devnull case GREY8:
102 28994509 2004-04-21 devnull default:
103 28994509 2004-04-21 devnull return "WriteGIF: can't handle channel type";
106 28994509 2004-04-21 devnull writecomment(fd, comment);
107 28994509 2004-04-21 devnull writegraphiccontrol(fd, dt, trans);
108 28994509 2004-04-21 devnull writedescriptor(fd, r);
110 28994509 2004-04-21 devnull err = writedata(fd, image, memimage);
111 28994509 2004-04-21 devnull if(err != nil)
112 28994509 2004-04-21 devnull return err;
114 28994509 2004-04-21 devnull return nil;
118 28994509 2004-04-21 devnull writegif(Biobuf *fd, Image *image, char *comment, int dt, int trans)
120 28994509 2004-04-21 devnull return writegif0(fd, image, nil, image->chan, image->r, comment, dt, trans);
124 28994509 2004-04-21 devnull memwritegif(Biobuf *fd, Memimage *memimage, char *comment, int dt, int trans)
126 28994509 2004-04-21 devnull return writegif0(fd, nil, memimage, memimage->chan, memimage->r, comment, dt, trans);
130 28994509 2004-04-21 devnull * Write little-endian 16-bit integer
134 28994509 2004-04-21 devnull put2(Biobuf *fd, int i)
136 28994509 2004-04-21 devnull Bputc(fd, i);
137 28994509 2004-04-21 devnull Bputc(fd, i>>8);
141 28994509 2004-04-21 devnull * Get color map for all ldepths, in format suitable for writing out
145 28994509 2004-04-21 devnull getcolormap(void)
147 28994509 2004-04-21 devnull int i, col;
148 28994509 2004-04-21 devnull ulong rgb;
149 28994509 2004-04-21 devnull uchar *c;
151 28994509 2004-04-21 devnull if(colormap[0] != nil)
153 28994509 2004-04-21 devnull for(i=0; i<nelem(colormap); i++)
154 28994509 2004-04-21 devnull colormap[i] = gifmalloc(3* colormapsize[i]);
155 28994509 2004-04-21 devnull c = colormap[GREYMAP]; /* GREY8 */
156 28994509 2004-04-21 devnull for(i=0; i<256; i++){
157 28994509 2004-04-21 devnull c[3*i+0] = i; /* red */
158 28994509 2004-04-21 devnull c[3*i+1] = i; /* green */
159 28994509 2004-04-21 devnull c[3*i+2] = i; /* blue */
161 28994509 2004-04-21 devnull c = colormap[3]; /* RGBV */
162 28994509 2004-04-21 devnull for(i=0; i<256; i++){
163 28994509 2004-04-21 devnull rgb = cmap2rgb(i);
164 28994509 2004-04-21 devnull c[3*i+0] = (rgb>>16) & 0xFF; /* red */
165 28994509 2004-04-21 devnull c[3*i+1] = (rgb>> 8) & 0xFF; /* green */
166 28994509 2004-04-21 devnull c[3*i+2] = (rgb>> 0) & 0xFF; /* blue */
168 28994509 2004-04-21 devnull c = colormap[2]; /* GREY4 */
169 28994509 2004-04-21 devnull for(i=0; i<16; i++){
170 28994509 2004-04-21 devnull col = (i<<4)|i;
171 28994509 2004-04-21 devnull rgb = cmap2rgb(col);
172 28994509 2004-04-21 devnull c[3*i+0] = (rgb>>16) & 0xFF; /* red */
173 28994509 2004-04-21 devnull c[3*i+1] = (rgb>> 8) & 0xFF; /* green */
174 28994509 2004-04-21 devnull c[3*i+2] = (rgb>> 0) & 0xFF; /* blue */
176 28994509 2004-04-21 devnull c = colormap[1]; /* GREY2 */
177 28994509 2004-04-21 devnull for(i=0; i<4; i++){
178 28994509 2004-04-21 devnull col = (i<<6)|(i<<4)|(i<<2)|i;
179 28994509 2004-04-21 devnull rgb = cmap2rgb(col);
180 28994509 2004-04-21 devnull c[3*i+0] = (rgb>>16) & 0xFF; /* red */
181 28994509 2004-04-21 devnull c[3*i+1] = (rgb>> 8) & 0xFF; /* green */
182 28994509 2004-04-21 devnull c[3*i+2] = (rgb>> 0) & 0xFF; /* blue */
184 28994509 2004-04-21 devnull c = colormap[0]; /* GREY1 */
185 28994509 2004-04-21 devnull for(i=0; i<2; i++){
186 28994509 2004-04-21 devnull if(i == 0)
187 28994509 2004-04-21 devnull col = 0;
189 28994509 2004-04-21 devnull col = 0xFF;
190 28994509 2004-04-21 devnull rgb = cmap2rgb(col);
191 28994509 2004-04-21 devnull c[3*i+0] = (rgb>>16) & 0xFF; /* red */
192 28994509 2004-04-21 devnull c[3*i+1] = (rgb>> 8) & 0xFF; /* green */
193 28994509 2004-04-21 devnull c[3*i+2] = (rgb>> 0) & 0xFF; /* blue */
198 28994509 2004-04-21 devnull * Write header, logical screen descriptor, and color map
202 28994509 2004-04-21 devnull writeheader(Biobuf *fd, Rectangle r, int depth, ulong chan, int loopcount)
204 28994509 2004-04-21 devnull /* Header */
205 28994509 2004-04-21 devnull Bprint(fd, "%s", "GIF89a");
207 28994509 2004-04-21 devnull /* Logical Screen Descriptor */
208 28994509 2004-04-21 devnull put2(fd, Dx(r));
209 28994509 2004-04-21 devnull put2(fd, Dy(r));
211 28994509 2004-04-21 devnull /* Color table present, 4 bits per color (for RGBV best case), size of color map */
212 28994509 2004-04-21 devnull Bputc(fd, (1<<7)|(3<<4)|(depth-1)); /* not right for GREY8, but GIF doesn't let us specify enough bits */
213 28994509 2004-04-21 devnull Bputc(fd, 0xFF); /* white background (doesn't matter anyway) */
214 28994509 2004-04-21 devnull Bputc(fd, 0); /* pixel aspect ratio - unused */
216 28994509 2004-04-21 devnull /* Global Color Table */
217 28994509 2004-04-21 devnull getcolormap();
218 28994509 2004-04-21 devnull if(chan == GREY8)
219 28994509 2004-04-21 devnull depth = GREYMAP;
221 28994509 2004-04-21 devnull depth = drawlog2[depth];
222 28994509 2004-04-21 devnull Bwrite(fd, colormap[depth], 3*colormapsize[depth]);
224 28994509 2004-04-21 devnull if(loopcount >= 0){ /* hard-to-discover way to force cycled animation */
225 28994509 2004-04-21 devnull /* Application Extension with (1 loopcountlo loopcounthi) as data */
226 28994509 2004-04-21 devnull Bputc(fd, 0x21);
227 28994509 2004-04-21 devnull Bputc(fd, 0xFF);
228 28994509 2004-04-21 devnull Bputc(fd, 11);
229 28994509 2004-04-21 devnull Bwrite(fd, "NETSCAPE2.0", 11);
230 28994509 2004-04-21 devnull Bputc(fd, 3);
231 28994509 2004-04-21 devnull Bputc(fd, 1);
232 28994509 2004-04-21 devnull put2(fd, loopcount);
233 28994509 2004-04-21 devnull Bputc(fd, 0);
238 28994509 2004-04-21 devnull * Write optional comment block
242 28994509 2004-04-21 devnull writecomment(Biobuf *fd, char *comment)
246 28994509 2004-04-21 devnull if(comment==nil || comment[0]=='\0')
249 28994509 2004-04-21 devnull /* Comment extension and label */
250 28994509 2004-04-21 devnull Bputc(fd, 0x21);
251 28994509 2004-04-21 devnull Bputc(fd, 0xFE);
253 28994509 2004-04-21 devnull /* Comment data */
254 28994509 2004-04-21 devnull n = strlen(comment);
255 28994509 2004-04-21 devnull if(n > 255)
256 28994509 2004-04-21 devnull n = 255;
257 28994509 2004-04-21 devnull Bputc(fd, n);
258 28994509 2004-04-21 devnull Bwrite(fd, comment, n);
260 28994509 2004-04-21 devnull /* Block terminator */
261 28994509 2004-04-21 devnull Bputc(fd, 0x00);
265 28994509 2004-04-21 devnull * Write optional control block (sets Delay Time)
269 28994509 2004-04-21 devnull writegraphiccontrol(Biobuf *fd, int dt, int trans)
271 28994509 2004-04-21 devnull if(dt < 0 && trans < 0)
274 28994509 2004-04-21 devnull /* Comment extension and label and block size*/
275 28994509 2004-04-21 devnull Bputc(fd, 0x21);
276 28994509 2004-04-21 devnull Bputc(fd, 0xF9);
277 28994509 2004-04-21 devnull Bputc(fd, 0x04);
279 28994509 2004-04-21 devnull /* Disposal method and other flags (none) */
280 28994509 2004-04-21 devnull if(trans >= 0)
281 28994509 2004-04-21 devnull Bputc(fd, 0x01);
283 28994509 2004-04-21 devnull Bputc(fd, 0x00);
285 28994509 2004-04-21 devnull /* Delay time, in centisec (argument is millisec for sanity) */
286 28994509 2004-04-21 devnull if(dt < 0)
288 28994509 2004-04-21 devnull else if(dt < 10)
291 28994509 2004-04-21 devnull dt = (dt+5)/10;
292 28994509 2004-04-21 devnull put2(fd, dt);
294 28994509 2004-04-21 devnull /* Transparency index */
295 28994509 2004-04-21 devnull if(trans < 0)
296 28994509 2004-04-21 devnull trans = 0;
297 28994509 2004-04-21 devnull Bputc(fd, trans);
299 28994509 2004-04-21 devnull /* Block terminator */
300 28994509 2004-04-21 devnull Bputc(fd, 0x00);
304 28994509 2004-04-21 devnull * Write image descriptor
308 28994509 2004-04-21 devnull writedescriptor(Biobuf *fd, Rectangle r)
310 28994509 2004-04-21 devnull /* Image Separator */
311 28994509 2004-04-21 devnull Bputc(fd, 0x2C);
313 28994509 2004-04-21 devnull /* Left, top, width, height */
314 28994509 2004-04-21 devnull put2(fd, r.min.x-mainrect.min.x);
315 28994509 2004-04-21 devnull put2(fd, r.min.y-mainrect.min.y);
316 28994509 2004-04-21 devnull put2(fd, Dx(r));
317 28994509 2004-04-21 devnull put2(fd, Dy(r));
318 28994509 2004-04-21 devnull /* no special processing */
319 28994509 2004-04-21 devnull Bputc(fd, 0);
323 28994509 2004-04-21 devnull * Write data
327 28994509 2004-04-21 devnull writedata(Biobuf *fd, Image *image, Memimage *memimage)
329 28994509 2004-04-21 devnull char *err;
330 28994509 2004-04-21 devnull uchar *data;
331 28994509 2004-04-21 devnull int ndata, depth;
332 28994509 2004-04-21 devnull Rectangle r;
334 28994509 2004-04-21 devnull if(memimage != nil){
335 28994509 2004-04-21 devnull r = memimage->r;
336 28994509 2004-04-21 devnull depth = memimage->depth;
338 28994509 2004-04-21 devnull r = image->r;
339 28994509 2004-04-21 devnull depth = image->depth;
342 28994509 2004-04-21 devnull /* LZW Minimum code size */
343 28994509 2004-04-21 devnull if(depth == 1)
344 28994509 2004-04-21 devnull Bputc(fd, 2);
346 28994509 2004-04-21 devnull Bputc(fd, depth);
349 28994509 2004-04-21 devnull * Read image data into memory
350 28994509 2004-04-21 devnull * potentially one extra byte on each end of each scan line
352 28994509 2004-04-21 devnull ndata = Dy(r)*(2+(Dx(r)>>(3-drawlog2[depth])));
353 28994509 2004-04-21 devnull data = gifmalloc(ndata);
354 28994509 2004-04-21 devnull if(memimage != nil)
355 28994509 2004-04-21 devnull ndata = unloadmemimage(memimage, r, data, ndata);
357 28994509 2004-04-21 devnull ndata = unloadimage(image, r, data, ndata);
358 28994509 2004-04-21 devnull if(ndata < 0){
359 28994509 2004-04-21 devnull err = gifmalloc(ERRMAX);
360 28994509 2004-04-21 devnull snprint(err, ERRMAX, "WriteGIF: %r");
361 28994509 2004-04-21 devnull free(data);
362 28994509 2004-04-21 devnull return err;
365 28994509 2004-04-21 devnull /* Encode and emit the data */
366 28994509 2004-04-21 devnull encode(fd, r, depth, data, ndata);
367 28994509 2004-04-21 devnull free(data);
369 28994509 2004-04-21 devnull /* Block Terminator */
370 28994509 2004-04-21 devnull Bputc(fd, 0);
371 28994509 2004-04-21 devnull return nil;
375 28994509 2004-04-21 devnull * Write trailer
378 28994509 2004-04-21 devnull endgif(Biobuf *fd)
380 28994509 2004-04-21 devnull Bputc(fd, 0x3B);
381 28994509 2004-04-21 devnull Bflush(fd);
385 28994509 2004-04-21 devnull memendgif(Biobuf *fd)
387 28994509 2004-04-21 devnull endgif(fd);
391 28994509 2004-04-21 devnull * Put n bits of c into output at io.buf[i];
395 28994509 2004-04-21 devnull output(IO *io, int c, int n)
397 28994509 2004-04-21 devnull if(c < 0){
398 28994509 2004-04-21 devnull if(io->nbits != 0)
399 28994509 2004-04-21 devnull io->buf[io->i++] = io->sreg;
400 28994509 2004-04-21 devnull Bputc(io->fd, io->i);
401 28994509 2004-04-21 devnull Bwrite(io->fd, io->buf, io->i);
402 28994509 2004-04-21 devnull io->nbits = 0;
406 28994509 2004-04-21 devnull if(io->nbits+n >= 31){
407 28994509 2004-04-21 devnull fprint(2, "panic: WriteGIF sr overflow\n");
408 28994509 2004-04-21 devnull exits("WriteGIF panic");
410 28994509 2004-04-21 devnull io->sreg |= c<<io->nbits;
411 28994509 2004-04-21 devnull io->nbits += n;
413 28994509 2004-04-21 devnull while(io->nbits >= 8){
414 28994509 2004-04-21 devnull io->buf[io->i++] = io->sreg;
415 28994509 2004-04-21 devnull io->sreg >>= 8;
416 28994509 2004-04-21 devnull io->nbits -= 8;
419 28994509 2004-04-21 devnull if(io->i >= 255){
420 28994509 2004-04-21 devnull Bputc(io->fd, 255);
421 28994509 2004-04-21 devnull Bwrite(io->fd, io->buf, 255);
422 28994509 2004-04-21 devnull memmove(io->buf, io->buf+255, io->i-255);
423 28994509 2004-04-21 devnull io->i -= 255;
428 28994509 2004-04-21 devnull * LZW encoder
432 28994509 2004-04-21 devnull encode(Biobuf *fd, Rectangle r, int depth, uchar *data, uint ndata)
434 28994509 2004-04-21 devnull int i, c, h, csize, prefix, first, sreg, nbits, bitsperpixel;
435 28994509 2004-04-21 devnull int CTM, EOD, codesize, ld0, datai, x, ld, pm;
436 28994509 2004-04-21 devnull int nentry, maxentry, early;
437 28994509 2004-04-21 devnull Entry *e, *oe;
439 28994509 2004-04-21 devnull Entry **hash;
441 28994509 2004-04-21 devnull first = 1;
442 28994509 2004-04-21 devnull ld = drawlog2[depth];
443 28994509 2004-04-21 devnull /* ldepth 0 must generate codesize 2 with values 0 and 1 (see the spec.) */
444 28994509 2004-04-21 devnull ld0 = ld;
445 28994509 2004-04-21 devnull if(ld0 == 0)
446 28994509 2004-04-21 devnull ld0 = 1;
447 28994509 2004-04-21 devnull codesize = (1<<ld0);
448 28994509 2004-04-21 devnull CTM = 1<<codesize;
449 28994509 2004-04-21 devnull EOD = CTM+1;
451 28994509 2004-04-21 devnull io = gifmalloc(sizeof(IO));
452 28994509 2004-04-21 devnull io->fd = fd;
453 28994509 2004-04-21 devnull sreg = 0;
454 28994509 2004-04-21 devnull nbits = 0;
455 28994509 2004-04-21 devnull bitsperpixel = 1<<ld;
456 28994509 2004-04-21 devnull pm = (1<<bitsperpixel)-1;
458 28994509 2004-04-21 devnull datai = 0;
459 28994509 2004-04-21 devnull x = r.min.x;
460 28994509 2004-04-21 devnull hash = gifmalloc(Nhash*sizeof(Entry*));
463 28994509 2004-04-21 devnull memset(hash, 0, Nhash*sizeof(Entry*));
464 28994509 2004-04-21 devnull csize = codesize+1;
465 28994509 2004-04-21 devnull nentry = EOD+1;
466 28994509 2004-04-21 devnull maxentry = (1<<csize);
467 28994509 2004-04-21 devnull for(i = 0; i<nentry; i++){
468 28994509 2004-04-21 devnull e = &tbl[i];
469 28994509 2004-04-21 devnull h = (e->prefix<<24) | (e->exten<<8);
470 28994509 2004-04-21 devnull h %= Nhash;
471 28994509 2004-04-21 devnull if(h < 0)
472 28994509 2004-04-21 devnull h += Nhash;
473 28994509 2004-04-21 devnull e->next = hash[h];
474 28994509 2004-04-21 devnull hash[h] = e;
476 28994509 2004-04-21 devnull prefix = -1;
477 28994509 2004-04-21 devnull if(first)
478 28994509 2004-04-21 devnull output(io, CTM, csize);
479 28994509 2004-04-21 devnull first = 0;
482 28994509 2004-04-21 devnull * Scan over pixels. Because of partially filled bytes on ends of scan lines,
483 28994509 2004-04-21 devnull * which must be ignored in the data stream passed to GIF, this is more
484 28994509 2004-04-21 devnull * complex than we'd like.
487 28994509 2004-04-21 devnull for(;;){
488 28994509 2004-04-21 devnull if(ld != 3){
489 28994509 2004-04-21 devnull /* beginning of scan line is difficult; prime the shift register */
490 28994509 2004-04-21 devnull if(x == r.min.x){
491 28994509 2004-04-21 devnull if(datai == ndata)
493 28994509 2004-04-21 devnull sreg = data[datai++];
494 28994509 2004-04-21 devnull nbits = 8-((x&(7>>ld))<<ld);
497 28994509 2004-04-21 devnull if(x == r.max.x)
498 28994509 2004-04-21 devnull x = r.min.x;
500 28994509 2004-04-21 devnull if(nbits == 0){
501 28994509 2004-04-21 devnull if(datai == ndata)
503 28994509 2004-04-21 devnull sreg = data[datai++];
504 28994509 2004-04-21 devnull nbits = 8;
506 28994509 2004-04-21 devnull nbits -= bitsperpixel;
507 28994509 2004-04-21 devnull c = sreg>>nbits & pm;
508 28994509 2004-04-21 devnull h = prefix<<24 | c<<8;
509 28994509 2004-04-21 devnull h %= Nhash;
510 28994509 2004-04-21 devnull if(h < 0)
511 28994509 2004-04-21 devnull h += Nhash;
512 28994509 2004-04-21 devnull oe = nil;
513 28994509 2004-04-21 devnull for(e = hash[h]; e!=nil; e=e->next){
514 28994509 2004-04-21 devnull if(e->prefix == prefix && e->exten == c){
515 28994509 2004-04-21 devnull if(oe != nil){
516 28994509 2004-04-21 devnull oe->next = e->next;
517 28994509 2004-04-21 devnull e->next = hash[h];
518 28994509 2004-04-21 devnull hash[h] = e;
520 28994509 2004-04-21 devnull prefix = e->index;
521 28994509 2004-04-21 devnull goto Next;
526 28994509 2004-04-21 devnull output(io, prefix, csize);
527 28994509 2004-04-21 devnull early = 0; /* peculiar tiff feature here for reference */
528 28994509 2004-04-21 devnull if(nentry == maxentry-early){
529 28994509 2004-04-21 devnull if(csize == 12){
530 28994509 2004-04-21 devnull nbits += bitsperpixel; /* unget pixel */
532 28994509 2004-04-21 devnull if(ld != 3 && x == r.min.x)
533 28994509 2004-04-21 devnull datai--;
534 28994509 2004-04-21 devnull output(io, CTM, csize);
535 28994509 2004-04-21 devnull goto Init;
537 28994509 2004-04-21 devnull csize++;
538 28994509 2004-04-21 devnull maxentry = (1<<csize);
541 28994509 2004-04-21 devnull e = &tbl[nentry];
542 28994509 2004-04-21 devnull e->prefix = prefix;
543 28994509 2004-04-21 devnull e->exten = c;
544 28994509 2004-04-21 devnull e->next = hash[h];
545 28994509 2004-04-21 devnull hash[h] = e;
547 28994509 2004-04-21 devnull prefix = c;
548 28994509 2004-04-21 devnull nentry++;
551 28994509 2004-04-21 devnull output(io, prefix, csize);
552 28994509 2004-04-21 devnull output(io, EOD, csize);
553 28994509 2004-04-21 devnull output(io, -1, csize);
554 28994509 2004-04-21 devnull free(io);
555 28994509 2004-04-21 devnull free(hash);
560 28994509 2004-04-21 devnull gifmalloc(ulong sz)
562 28994509 2004-04-21 devnull void *v;
563 28994509 2004-04-21 devnull v = malloc(sz);
564 28994509 2004-04-21 devnull if(v == nil) {
565 28994509 2004-04-21 devnull fprint(2, "WriteGIF: out of memory allocating %ld\n", sz);
566 28994509 2004-04-21 devnull abort();
567 28994509 2004-04-21 devnull exits("mem");
569 28994509 2004-04-21 devnull memset(v, 0, sz);
570 28994509 2004-04-21 devnull return v;