gif: implement dispose method for animations, do composing offscreen for speed
This commit is contained in:
parent
2fdb279101
commit
7e744bda2b
1 changed files with 38 additions and 20 deletions
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue