17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <draw.h>
57dd7cddfSDavid du Colombier #include <event.h>
67dd7cddfSDavid du Colombier #include "imagefile.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier int cflag = 0;
97dd7cddfSDavid du Colombier int dflag = 0;
107dd7cddfSDavid du Colombier int eflag = 0;
117dd7cddfSDavid du Colombier int nineflag = 0;
127dd7cddfSDavid du Colombier int threeflag = 0;
137dd7cddfSDavid du Colombier int output = 0;
147dd7cddfSDavid du Colombier ulong outchan = CMAP8;
157dd7cddfSDavid du Colombier Image **allims;
167dd7cddfSDavid du Colombier Image **allmasks;
17*42860f21SDavid du Colombier Rawimage **allimages;
187dd7cddfSDavid du Colombier int which;
197dd7cddfSDavid du Colombier int defaultcolor = 1;
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier enum{
227dd7cddfSDavid du Colombier Border = 2,
237dd7cddfSDavid du Colombier Edge = 5
247dd7cddfSDavid du Colombier };
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier char *show(int, char*);
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier Rectangle
imager(void)297dd7cddfSDavid du Colombier imager(void)
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier Rectangle r;
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier if(allims==nil || allims[0]==nil)
347dd7cddfSDavid du Colombier return screen->r;
357dd7cddfSDavid du Colombier r = insetrect(screen->clipr, Edge+Border);
367dd7cddfSDavid du Colombier r.max.x = r.min.x+Dx(allims[0]->r);
377dd7cddfSDavid du Colombier r.max.y = r.min.y+Dy(allims[0]->r);
387dd7cddfSDavid du Colombier return r;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier void
eresized(int new)427dd7cddfSDavid du Colombier eresized(int new)
437dd7cddfSDavid du Colombier {
447dd7cddfSDavid du Colombier Rectangle r;
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier if(new && getwindow(display, Refnone) < 0){
477dd7cddfSDavid du Colombier fprint(2, "gif: can't reattach to window\n");
487dd7cddfSDavid du Colombier exits("resize");
497dd7cddfSDavid du Colombier }
507dd7cddfSDavid du Colombier if(allims==nil || allims[which]==nil)
517dd7cddfSDavid du Colombier return;
527dd7cddfSDavid du Colombier r = imager();
537dd7cddfSDavid du Colombier border(screen, r, -Border, nil, ZP);
5459cc4ca5SDavid du Colombier r.min.x += allims[which]->r.min.x - allims[0]->r.min.x;
5559cc4ca5SDavid du Colombier r.min.y += allims[which]->r.min.y - allims[0]->r.min.y;
56*42860f21SDavid du Colombier if(which > 0 && allimages[which]->gifflags & TRANSP)
57*42860f21SDavid du Colombier drawop(screen, r, allims[which], allmasks[which],
58*42860f21SDavid du Colombier allims[which]->r.min, SoverD);
59*42860f21SDavid du Colombier else
60*42860f21SDavid du Colombier drawop(screen, r, allims[which], allmasks[which],
61*42860f21SDavid du Colombier allims[which]->r.min, S);
627dd7cddfSDavid du Colombier flushimage(display, 1);
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier void
main(int argc,char * argv[])667dd7cddfSDavid du Colombier main(int argc, char *argv[])
677dd7cddfSDavid du Colombier {
687dd7cddfSDavid du Colombier int fd, i;
697dd7cddfSDavid du Colombier char *err;
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier ARGBEGIN{
727dd7cddfSDavid du Colombier case '3': /* produce encoded, compressed, three-color bitmap file; no display by default */
737dd7cddfSDavid du Colombier threeflag++;
747dd7cddfSDavid du Colombier /* fall through */
757dd7cddfSDavid du Colombier case 't': /* produce encoded, compressed, true-color bitmap file; no display by default */
767dd7cddfSDavid du Colombier cflag++;
777dd7cddfSDavid du Colombier dflag++;
787dd7cddfSDavid du Colombier output++;
797dd7cddfSDavid du Colombier defaultcolor = 0;
807dd7cddfSDavid du Colombier outchan = RGB24;
817dd7cddfSDavid du Colombier break;
827dd7cddfSDavid du Colombier case 'c': /* produce encoded, compressed, bitmap file; no display by default */
837dd7cddfSDavid du Colombier cflag++;
847dd7cddfSDavid du Colombier dflag++;
857dd7cddfSDavid du Colombier output++;
867dd7cddfSDavid du Colombier if(defaultcolor)
877dd7cddfSDavid du Colombier outchan = CMAP8;
887dd7cddfSDavid du Colombier break;
897dd7cddfSDavid du Colombier case 'd': /* suppress display of image */
907dd7cddfSDavid du Colombier dflag++;
917dd7cddfSDavid du Colombier break;
927dd7cddfSDavid du Colombier case 'e': /* disable floyd-steinberg error diffusion */
937dd7cddfSDavid du Colombier eflag++;
947dd7cddfSDavid du Colombier break;
957dd7cddfSDavid du Colombier case 'k': /* force black and white */
967dd7cddfSDavid du Colombier defaultcolor = 0;
977dd7cddfSDavid du Colombier outchan = GREY8;
987dd7cddfSDavid du Colombier break;
997dd7cddfSDavid du Colombier case 'v': /* force RGBV */
1007dd7cddfSDavid du Colombier defaultcolor = 0;
1017dd7cddfSDavid du Colombier outchan = CMAP8;
1027dd7cddfSDavid du Colombier break;
1037dd7cddfSDavid du Colombier case '9': /* produce plan 9, uncompressed, bitmap file; no display by default */
1047dd7cddfSDavid du Colombier nineflag++;
1057dd7cddfSDavid du Colombier dflag++;
1067dd7cddfSDavid du Colombier output++;
1077dd7cddfSDavid du Colombier if(defaultcolor)
1087dd7cddfSDavid du Colombier outchan = CMAP8;
1097dd7cddfSDavid du Colombier break;
1107dd7cddfSDavid du Colombier default:
1117dd7cddfSDavid du Colombier fprint(2, "usage: gif -39cdektv [file.gif ...]\n");
1127dd7cddfSDavid du Colombier exits("usage");
1137dd7cddfSDavid du Colombier }ARGEND;
1147dd7cddfSDavid du Colombier
1157dd7cddfSDavid du Colombier err = nil;
1167dd7cddfSDavid du Colombier if(argc == 0)
1177dd7cddfSDavid du Colombier err = show(0, "<stdin>");
1187dd7cddfSDavid du Colombier else{
1197dd7cddfSDavid du Colombier for(i=0; i<argc; i++){
1207dd7cddfSDavid du Colombier fd = open(argv[i], OREAD);
1217dd7cddfSDavid du Colombier if(fd < 0){
1227dd7cddfSDavid du Colombier fprint(2, "gif: can't open %s: %r\n", argv[i]);
1237dd7cddfSDavid du Colombier err = "open";
1247dd7cddfSDavid du Colombier }else{
1257dd7cddfSDavid du Colombier err = show(fd, argv[i]);
1267dd7cddfSDavid du Colombier close(fd);
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier if(output && argc>1 && err==nil){
1297dd7cddfSDavid du Colombier fprint(2, "gif: exiting after one file\n");
1307dd7cddfSDavid du Colombier break;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier exits(err);
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier
1377dd7cddfSDavid du Colombier Image*
transparency(Rawimage * r,char * name)1387dd7cddfSDavid du Colombier transparency(Rawimage *r, char *name)
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier Image *i;
1417dd7cddfSDavid du Colombier int j, index;
1427dd7cddfSDavid du Colombier uchar *pic, *mpic, *mask;
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier if((r->gifflags&TRANSP) == 0)
1457dd7cddfSDavid du Colombier return nil;
1467dd7cddfSDavid du Colombier i = allocimage(display, r->r, GREY8, 0, 0);
1477dd7cddfSDavid du Colombier if(i == nil){
1487dd7cddfSDavid du Colombier fprint(2, "gif: allocimage for mask of %s failed: %r\n", name);
1497dd7cddfSDavid du Colombier return nil;
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier pic = r->chans[0];
1527dd7cddfSDavid du Colombier mask = malloc(r->chanlen);
1537dd7cddfSDavid du Colombier if(mask == nil){
1547dd7cddfSDavid du Colombier fprint(2, "gif: malloc for mask of %s failed: %r\n", name);
1557dd7cddfSDavid du Colombier freeimage(i);
1567dd7cddfSDavid du Colombier return nil;
1577dd7cddfSDavid du Colombier }
1587dd7cddfSDavid du Colombier index = r->giftrindex;
1597dd7cddfSDavid du Colombier mpic = mask;
1607dd7cddfSDavid du Colombier for(j=0; j<r->chanlen; j++)
1617dd7cddfSDavid du Colombier if(*pic++ == index)
1627dd7cddfSDavid du Colombier *mpic++ = 0;
1637dd7cddfSDavid du Colombier else
1647dd7cddfSDavid du Colombier *mpic++ = 0xFF;
1657dd7cddfSDavid du Colombier if(loadimage(i, i->r, mask, r->chanlen) < 0){
1667dd7cddfSDavid du Colombier fprint(2, "gif: loadimage for mask of %s failed: %r\n", name);
1677dd7cddfSDavid du Colombier free(mask);
1687dd7cddfSDavid du Colombier freeimage(i);
1697dd7cddfSDavid du Colombier return nil;
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier free(mask);
1727dd7cddfSDavid du Colombier return i;
1737dd7cddfSDavid du Colombier }
1747dd7cddfSDavid du Colombier
17559cc4ca5SDavid du Colombier /* interleave alpha values of 0xFF in data stream. alpha value comes first, then b g r */
17659cc4ca5SDavid du Colombier uchar*
expand(uchar * u,int chanlen,int nchan)17759cc4ca5SDavid du Colombier expand(uchar *u, int chanlen, int nchan)
17859cc4ca5SDavid du Colombier {
17959cc4ca5SDavid du Colombier int j, k;
18059cc4ca5SDavid du Colombier uchar *v, *up, *vp;
18159cc4ca5SDavid du Colombier
18259cc4ca5SDavid du Colombier v = malloc(chanlen*(nchan+1));
18359cc4ca5SDavid du Colombier if(v == nil){
18459cc4ca5SDavid du Colombier fprint(2, "gif: malloc fails: %r\n");
18559cc4ca5SDavid du Colombier exits("malloc");
18659cc4ca5SDavid du Colombier }
18759cc4ca5SDavid du Colombier up = u;
18859cc4ca5SDavid du Colombier vp = v;
18959cc4ca5SDavid du Colombier for(j=0; j<chanlen; j++){
19059cc4ca5SDavid du Colombier *vp++ = 0xFF;
19159cc4ca5SDavid du Colombier for(k=0; k<nchan; k++)
19259cc4ca5SDavid du Colombier *vp++ = *up++;
19359cc4ca5SDavid du Colombier }
19459cc4ca5SDavid du Colombier return v;
19559cc4ca5SDavid du Colombier }
19659cc4ca5SDavid du Colombier
19759cc4ca5SDavid du Colombier void
addalpha(Rawimage * i)19859cc4ca5SDavid du Colombier addalpha(Rawimage *i)
19959cc4ca5SDavid du Colombier {
20059cc4ca5SDavid du Colombier char buf[32];
20159cc4ca5SDavid du Colombier
20259cc4ca5SDavid du Colombier switch(outchan){
20359cc4ca5SDavid du Colombier case CMAP8:
20459cc4ca5SDavid du Colombier i->chans[0] = expand(i->chans[0], i->chanlen/1, 1);
20559cc4ca5SDavid du Colombier i->chanlen = 2*(i->chanlen/1);
20659cc4ca5SDavid du Colombier i->chandesc = CRGBVA16;
20759cc4ca5SDavid du Colombier outchan = CHAN2(CMap, 8, CAlpha, 8);
20859cc4ca5SDavid du Colombier break;
20959cc4ca5SDavid du Colombier
21059cc4ca5SDavid du Colombier case GREY8:
21159cc4ca5SDavid du Colombier i->chans[0] = expand(i->chans[0], i->chanlen/1, 1);
21259cc4ca5SDavid du Colombier i->chanlen = 2*(i->chanlen/1);
21359cc4ca5SDavid du Colombier i->chandesc = CYA16;
21459cc4ca5SDavid du Colombier outchan = CHAN2(CGrey, 8, CAlpha, 8);
21559cc4ca5SDavid du Colombier break;
21659cc4ca5SDavid du Colombier
21759cc4ca5SDavid du Colombier case RGB24:
21859cc4ca5SDavid du Colombier i->chans[0] = expand(i->chans[0], i->chanlen/3, 3);
21959cc4ca5SDavid du Colombier i->chanlen = 4*(i->chanlen/3);
22059cc4ca5SDavid du Colombier i->chandesc = CRGBA32;
22159cc4ca5SDavid du Colombier outchan = RGBA32;
22259cc4ca5SDavid du Colombier break;
22359cc4ca5SDavid du Colombier
22459cc4ca5SDavid du Colombier default:
22559cc4ca5SDavid du Colombier chantostr(buf, outchan);
22659cc4ca5SDavid du Colombier fprint(2, "gif: can't add alpha to type %s\n", buf);
22759cc4ca5SDavid du Colombier exits("err");
22859cc4ca5SDavid du Colombier }
22959cc4ca5SDavid du Colombier }
23059cc4ca5SDavid du Colombier
2317dd7cddfSDavid du Colombier /*
23259cc4ca5SDavid du Colombier * Called only when writing output. If the output is RGBA32,
23359cc4ca5SDavid du Colombier * we must write four bytes per pixel instead of two.
23459cc4ca5SDavid du Colombier * There's always at least two: data plus alpha.
23559cc4ca5SDavid du Colombier * r is used only for reference; the image is already in c.
2367dd7cddfSDavid du Colombier */
2377dd7cddfSDavid du Colombier void
blackout(Rawimage * r,Rawimage * c)238*42860f21SDavid du Colombier blackout(Rawimage *r, Rawimage *c)
2397dd7cddfSDavid du Colombier {
2407dd7cddfSDavid du Colombier int i, trindex;
2417dd7cddfSDavid du Colombier uchar *rp, *cp;
2427dd7cddfSDavid du Colombier
2437dd7cddfSDavid du Colombier rp = r->chans[0];
2447dd7cddfSDavid du Colombier cp = c->chans[0];
2457dd7cddfSDavid du Colombier trindex = r->giftrindex;
24659cc4ca5SDavid du Colombier if(outchan == RGBA32)
2477dd7cddfSDavid du Colombier for(i=0; i<r->chanlen; i++){
2487dd7cddfSDavid du Colombier if(*rp == trindex){
24959cc4ca5SDavid du Colombier *cp++ = 0x00;
250*42860f21SDavid du Colombier *cp++ = 0x00;
251*42860f21SDavid du Colombier *cp++ = 0x00;
252*42860f21SDavid du Colombier *cp++ = 0x00;
25359cc4ca5SDavid du Colombier }else{
25459cc4ca5SDavid du Colombier *cp++ = 0xFF;
25559cc4ca5SDavid du Colombier cp += 3;
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier rp++;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier else
2607dd7cddfSDavid du Colombier for(i=0; i<r->chanlen; i++){
26159cc4ca5SDavid du Colombier if(*rp == trindex){
26259cc4ca5SDavid du Colombier *cp++ = 0x00;
263*42860f21SDavid du Colombier *cp++ = 0x00;
26459cc4ca5SDavid du Colombier }else{
26559cc4ca5SDavid du Colombier *cp++ = 0xFF;
2667dd7cddfSDavid du Colombier cp++;
2677dd7cddfSDavid du Colombier }
26859cc4ca5SDavid du Colombier rp++;
26959cc4ca5SDavid du Colombier }
2707dd7cddfSDavid du Colombier }
2717dd7cddfSDavid du Colombier
2727dd7cddfSDavid du Colombier int
init(void)2737dd7cddfSDavid du Colombier init(void)
2747dd7cddfSDavid du Colombier {
2757dd7cddfSDavid du Colombier static int inited;
2767dd7cddfSDavid du Colombier
2777dd7cddfSDavid du Colombier if(inited == 0){
2787dd7cddfSDavid du Colombier if(initdraw(0, 0, 0) < 0){
2797dd7cddfSDavid du Colombier fprint(2, "gif: initdraw failed: %r\n");
2807dd7cddfSDavid du Colombier return -1;
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier einit(Ekeyboard|Emouse);
2837dd7cddfSDavid du Colombier inited++;
2847dd7cddfSDavid du Colombier }
2857dd7cddfSDavid du Colombier return 1;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier
2887dd7cddfSDavid du Colombier char*
show(int fd,char * name)2897dd7cddfSDavid du Colombier show(int fd, char *name)
2907dd7cddfSDavid du Colombier {
2917dd7cddfSDavid du Colombier Rawimage **images, **rgbv;
2927dd7cddfSDavid du Colombier Image **ims, **masks;
29359cc4ca5SDavid du Colombier int j, k, n, ch, nloop, loopcount, dt;
2947dd7cddfSDavid du Colombier char *err;
2957dd7cddfSDavid du Colombier char buf[32];
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier err = nil;
2987dd7cddfSDavid du Colombier images = readgif(fd, CRGB);
2997dd7cddfSDavid du Colombier if(images == nil){
3007dd7cddfSDavid du Colombier fprint(2, "gif: decode %s failed: %r\n", name);
3017dd7cddfSDavid du Colombier return "decode";
3027dd7cddfSDavid du Colombier }
3037dd7cddfSDavid du Colombier for(n=0; images[n]; n++)
3047dd7cddfSDavid du Colombier ;
3057dd7cddfSDavid du Colombier ims = malloc((n+1)*sizeof(Image*));
3067dd7cddfSDavid du Colombier masks = malloc((n+1)*sizeof(Image*));
3077dd7cddfSDavid du Colombier rgbv = malloc((n+1)*sizeof(Rawimage*));
3087dd7cddfSDavid du Colombier if(masks==nil || rgbv==nil || ims==nil){
3097dd7cddfSDavid du Colombier fprint(2, "gif: malloc of masks for %s failed: %r\n", name);
3107dd7cddfSDavid du Colombier err = "malloc";
3117dd7cddfSDavid du Colombier goto Return;
3127dd7cddfSDavid du Colombier }
3137dd7cddfSDavid du Colombier memset(masks, 0, (n+1)*sizeof(Image*));
3147dd7cddfSDavid du Colombier memset(ims, 0, (n+1)*sizeof(Image*));
3157dd7cddfSDavid du Colombier memset(rgbv, 0, (n+1)*sizeof(Rawimage*));
3167dd7cddfSDavid du Colombier if(!dflag){
3177dd7cddfSDavid du Colombier if(init() < 0){
3187dd7cddfSDavid du Colombier err = "initdraw";
3197dd7cddfSDavid du Colombier goto Return;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier if(defaultcolor && screen->depth>8)
3227dd7cddfSDavid du Colombier outchan = RGB24;
3237dd7cddfSDavid du Colombier }
3247dd7cddfSDavid du Colombier
3257dd7cddfSDavid du Colombier for(k=0; k<n; k++){
3267dd7cddfSDavid du Colombier if(outchan == CMAP8)
3277dd7cddfSDavid du Colombier rgbv[k] = torgbv(images[k], !eflag);
3287dd7cddfSDavid du Colombier else{
3297dd7cddfSDavid du Colombier if(outchan==GREY8 || (images[k]->chandesc==CY && threeflag==0))
3307dd7cddfSDavid du Colombier rgbv[k] = totruecolor(images[k], CY);
3317dd7cddfSDavid du Colombier else
3327dd7cddfSDavid du Colombier rgbv[k] = totruecolor(images[k], CRGB24);
3337dd7cddfSDavid du Colombier }
3347dd7cddfSDavid du Colombier if(rgbv[k] == nil){
3357dd7cddfSDavid du Colombier fprint(2, "gif: converting %s to local format failed: %r\n", name);
3367dd7cddfSDavid du Colombier err = "torgbv";
3377dd7cddfSDavid du Colombier goto Return;
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier if(!dflag){
3407dd7cddfSDavid du Colombier masks[k] = transparency(images[k], name);
3417dd7cddfSDavid du Colombier if(rgbv[k]->chandesc == CY)
3427dd7cddfSDavid du Colombier ims[k] = allocimage(display, rgbv[k]->r, GREY8, 0, 0);
3437dd7cddfSDavid du Colombier else
3447dd7cddfSDavid du Colombier ims[k] = allocimage(display, rgbv[k]->r, outchan, 0, 0);
3457dd7cddfSDavid du Colombier if(ims[k] == nil){
3467dd7cddfSDavid du Colombier fprint(2, "gif: allocimage %s failed: %r\n", name);
3477dd7cddfSDavid du Colombier err = "allocimage";
3487dd7cddfSDavid du Colombier goto Return;
3497dd7cddfSDavid du Colombier }
3507dd7cddfSDavid du Colombier if(loadimage(ims[k], ims[k]->r, rgbv[k]->chans[0], rgbv[k]->chanlen) < 0){
3517dd7cddfSDavid du Colombier fprint(2, "gif: loadimage %s failed: %r\n", name);
3527dd7cddfSDavid du Colombier err = "loadimage";
3537dd7cddfSDavid du Colombier goto Return;
3547dd7cddfSDavid du Colombier }
3557dd7cddfSDavid du Colombier }
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier
358*42860f21SDavid du Colombier allimages = images;
3597dd7cddfSDavid du Colombier allims = ims;
3607dd7cddfSDavid du Colombier allmasks = masks;
3617dd7cddfSDavid du Colombier loopcount = images[0]->gifloopcount;
3627dd7cddfSDavid du Colombier if(!dflag){
3637dd7cddfSDavid du Colombier nloop = 0;
3647dd7cddfSDavid du Colombier do{
3657dd7cddfSDavid du Colombier for(k=0; k<n; k++){
3667dd7cddfSDavid du Colombier which = k;
3677dd7cddfSDavid du Colombier eresized(0);
36859cc4ca5SDavid du Colombier dt = images[k]->gifdelay*10;
36959cc4ca5SDavid du Colombier if(dt < 50)
37059cc4ca5SDavid du Colombier dt = 50;
3717dd7cddfSDavid du Colombier while(n==1 || ecankbd()){
3727dd7cddfSDavid du Colombier if((ch=ekbd())=='q' || ch==0x7F || ch==0x04) /* an odd, democratic list */
3737dd7cddfSDavid du Colombier exits(nil);
3747dd7cddfSDavid du Colombier if(ch == '\n')
3757dd7cddfSDavid du Colombier goto Out;
37659cc4ca5SDavid du Colombier }sleep(dt);
3777dd7cddfSDavid du Colombier }
3787dd7cddfSDavid du Colombier /* loopcount -1 means no loop (this code's rule), loopcount 0 means loop forever (netscape's rule)*/
3797dd7cddfSDavid du Colombier }while(loopcount==0 || ++nloop<loopcount);
3807dd7cddfSDavid du Colombier /* loop count has run out */
3817dd7cddfSDavid du Colombier ekbd();
3827dd7cddfSDavid du Colombier Out:
3836b6b9ac8SDavid du Colombier drawop(screen, screen->clipr, display->white, nil, ZP, S);
3847dd7cddfSDavid du Colombier }
3857dd7cddfSDavid du Colombier if(n>1 && output)
3867dd7cddfSDavid du Colombier fprint(2, "gif: warning: only writing first image in %d-image GIF %s\n", n, name);
3877dd7cddfSDavid du Colombier if(nineflag){
38859cc4ca5SDavid du Colombier if(images[0]->gifflags&TRANSP){
38959cc4ca5SDavid du Colombier addalpha(rgbv[0]);
390*42860f21SDavid du Colombier blackout(images[0], rgbv[0]);
39159cc4ca5SDavid du Colombier }
3927dd7cddfSDavid du Colombier chantostr(buf, outchan);
3937dd7cddfSDavid du Colombier print("%11s %11d %11d %11d %11d ", buf,
3947dd7cddfSDavid du Colombier rgbv[0]->r.min.x, rgbv[0]->r.min.y, rgbv[0]->r.max.x, rgbv[0]->r.max.y);
3957dd7cddfSDavid du Colombier if(write(1, rgbv[0]->chans[0], rgbv[0]->chanlen) != rgbv[0]->chanlen){
3967dd7cddfSDavid du Colombier fprint(2, "gif: %s: write error %r\n", name);
3977dd7cddfSDavid du Colombier return "write";
3987dd7cddfSDavid du Colombier }
3997dd7cddfSDavid du Colombier }else if(cflag){
40059cc4ca5SDavid du Colombier if(images[0]->gifflags&TRANSP){
40159cc4ca5SDavid du Colombier addalpha(rgbv[0]);
402*42860f21SDavid du Colombier blackout(images[0], rgbv[0]);
40359cc4ca5SDavid du Colombier }
4047dd7cddfSDavid du Colombier if(writerawimage(1, rgbv[0]) < 0){
4057dd7cddfSDavid du Colombier fprint(2, "gif: %s: write error: %r\n", name);
4067dd7cddfSDavid du Colombier return "write";
4077dd7cddfSDavid du Colombier }
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier
4107dd7cddfSDavid du Colombier Return:
4117dd7cddfSDavid du Colombier allims = nil;
4127dd7cddfSDavid du Colombier allmasks = nil;
413*42860f21SDavid du Colombier allimages = nil;
4147dd7cddfSDavid du Colombier for(k=0; images[k]; k++){
4157dd7cddfSDavid du Colombier for(j=0; j<images[k]->nchans; j++)
4167dd7cddfSDavid du Colombier free(images[k]->chans[j]);
4177dd7cddfSDavid du Colombier free(images[k]->cmap);
4187dd7cddfSDavid du Colombier if(rgbv[k])
4197dd7cddfSDavid du Colombier free(rgbv[k]->chans[0]);
4207dd7cddfSDavid du Colombier freeimage(ims[k]);
4217dd7cddfSDavid du Colombier freeimage(masks[k]);
4227dd7cddfSDavid du Colombier free(images[k]);
4237dd7cddfSDavid du Colombier free(rgbv[k]);
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier free(images);
4267dd7cddfSDavid du Colombier free(masks);
4277dd7cddfSDavid du Colombier free(ims);
4287dd7cddfSDavid du Colombier return err;
4297dd7cddfSDavid du Colombier }
430