diff options
| author | cinap_lenrek <cinap_lenrek@rei2.9hal> | 2011-10-06 22:49:12 +0200 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@rei2.9hal> | 2011-10-06 22:49:12 +0200 |
| commit | 7e744bda2bfe0c664890b0f844591793fb08c976 (patch) | |
| tree | ee9f99cf43a8329880a6303825b6e022af9b45dd | |
| parent | 2fdb279101563f0e72a11a83e29c40ccda924667 (diff) | |
| download | plan9front-7e744bda2bfe0c664890b0f844591793fb08c976.tar.xz | |
gif: implement dispose method for animations, do composing offscreen for speed
| -rw-r--r-- | sys/src/cmd/jpg/gif.c | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/sys/src/cmd/jpg/gif.c b/sys/src/cmd/jpg/gif.c index cf54a0989..f059c750c 100644 --- a/sys/src/cmd/jpg/gif.c +++ b/sys/src/cmd/jpg/gif.c @@ -13,7 +13,6 @@ int threeflag = 0; int output = 0; ulong outchan = CMAP8; Image **allims; -Image **allmasks; int which; int defaultcolor = 1; @@ -50,9 +49,7 @@ eresized(int new) return; r = imager(); border(screen, r, -Border, nil, ZP); - r.min.x += allims[which]->r.min.x - allims[0]->r.min.x; - r.min.y += allims[which]->r.min.y - allims[0]->r.min.y; - drawop(screen, r, allims[which], allmasks[which], allims[which]->r.min, SoverD); + draw(screen, r, allims[which], nil, allims[which]->r.min); flushimage(display, 1); } @@ -283,7 +280,8 @@ char* show(int fd, char *name) { Rawimage **images, **rgbv; - Image **ims, **masks; + Image *tmp, *msk, *img, *dst, **ims; + Rectangle r; int j, k, n, ch, nloop, loopcount, dt; char *err; char buf[32]; @@ -295,16 +293,18 @@ show(int fd, char *name) return "decode"; } for(n=0; images[n]; n++) - ; + if(n == 0) + r = images[n]->r; + else + combinerect(&r, images[n]->r); + tmp = nil; ims = malloc((n+1)*sizeof(Image*)); - masks = malloc((n+1)*sizeof(Image*)); rgbv = malloc((n+1)*sizeof(Rawimage*)); - if(masks==nil || rgbv==nil || ims==nil){ + if(rgbv==nil || ims==nil){ fprint(2, "gif: malloc of masks for %s failed: %r\n", name); err = "malloc"; goto Return; } - memset(masks, 0, (n+1)*sizeof(Image*)); memset(ims, 0, (n+1)*sizeof(Image*)); memset(rgbv, 0, (n+1)*sizeof(Rawimage*)); if(!dflag){ @@ -331,26 +331,46 @@ show(int fd, char *name) goto Return; } if(!dflag){ - masks[k] = transparency(images[k], name); + msk = transparency(images[k], name); if(rgbv[k]->chandesc == CY) - ims[k] = allocimage(display, rgbv[k]->r, GREY8, 0, 0); + img = allocimage(display, rgbv[k]->r, GREY8, 0, 0); else - ims[k] = allocimage(display, rgbv[k]->r, outchan, 0, 0); - if(ims[k] == nil){ + img = allocimage(display, rgbv[k]->r, outchan, 0, 0); + if(tmp == nil) + tmp = allocimage(display, r, img->chan, 0, DWhite); + ims[k]= dst = allocimage(display, r, tmp->chan, 0, DWhite); + if(tmp == nil || img == nil || dst == nil){ fprint(2, "gif: allocimage %s failed: %r\n", name); err = "allocimage"; goto Return; } - if(loadimage(ims[k], ims[k]->r, rgbv[k]->chans[0], rgbv[k]->chanlen) < 0){ + if(loadimage(img, img->r, rgbv[k]->chans[0], rgbv[k]->chanlen) < 0){ fprint(2, "gif: loadimage %s failed: %r\n", name); err = "loadimage"; goto Return; } + switch((images[k]->gifflags>>2)&7){ + case 0: + case 1: + draw(tmp, img->r, img, msk, img->r.min); + draw(dst, tmp->r, tmp, nil, tmp->r.min); + break; + case 2: + draw(tmp, img->r, display->white, msk, img->r.min); + /* no break */ + case 3: + draw(dst, tmp->r, tmp, nil, tmp->r.min); + draw(dst, img->r, img, msk, img->r.min); + break; + } + freeimage(msk); + freeimage(img); } } + if(tmp) + freeimage(tmp); allims = ims; - allmasks = masks; loopcount = images[0]->gifloopcount; if(!dflag){ nloop = 0; @@ -362,7 +382,8 @@ show(int fd, char *name) if(dt < 50) dt = 50; while(n==1 || ecankbd()){ - if((ch=ekbd())=='q' || ch==0x7F || ch==0x04) /* an odd, democratic list */ + /* an odd, democratic list */ + if((ch=ekbd())=='q' || ch==0x7F || ch==0x04) exits(nil); if(ch == '\n') goto Out; @@ -373,7 +394,7 @@ show(int fd, char *name) /* loop count has run out */ ekbd(); Out: - drawop(screen, screen->clipr, display->white, nil, ZP, S); + draw(screen, screen->clipr, display->white, nil, ZP); } if(n>1 && output) fprint(2, "gif: warning: only writing first image in %d-image GIF %s\n", n, name); @@ -402,7 +423,6 @@ show(int fd, char *name) Return: allims = nil; - allmasks = nil; for(k=0; images[k]; k++){ for(j=0; j<images[k]->nchans; j++) free(images[k]->chans[j]); @@ -410,12 +430,10 @@ show(int fd, char *name) if(rgbv[k]) free(rgbv[k]->chans[0]); freeimage(ims[k]); - freeimage(masks[k]); free(images[k]); free(rgbv[k]); } free(images); - free(masks); free(ims); return err; } |
