diff options
author | rsc <devnull@localhost> | 2005-02-15 05:04:18 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-02-15 05:04:18 +0000 |
commit | 0cbccd3a0e84526d0de02d003d88c456be1f0ca7 (patch) | |
tree | 1262f4b598435d3f60611e79cb8f9c2fa3a2766e /src/cmd/jpg | |
parent | 429f8aa4c12c7fb04a0285ca31db5d0ab88b53d8 (diff) | |
download | plan9port-0cbccd3a0e84526d0de02d003d88c456be1f0ca7.tar.gz plan9port-0cbccd3a0e84526d0de02d003d88c456be1f0ca7.tar.bz2 plan9port-0cbccd3a0e84526d0de02d003d88c456be1f0ca7.zip |
add support for alpha
Diffstat (limited to 'src/cmd/jpg')
-rw-r--r-- | src/cmd/jpg/writepng.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/src/cmd/jpg/writepng.c b/src/cmd/jpg/writepng.c index fb6026d0..e280a9cc 100644 --- a/src/cmd/jpg/writepng.c +++ b/src/cmd/jpg/writepng.c @@ -21,6 +21,7 @@ typedef struct ZlibR{ int width; int nrow, ncol; int row, col; // next pixel to send + int pixwid; } ZlibR; typedef struct ZlibW{ @@ -68,19 +69,42 @@ zread(void *va, void *buf, int n) int ncol = z->ncol; uchar *b = buf, *e = b+n, *img; int pixels; // number of pixels in row that can be sent now - - while(b+3 <= e){ // loop over image rows + int i, a, pixwid; + + pixwid = z->pixwid; + while(b+pixwid <= e){ // loop over image rows if(z->row >= nrow) break; if(z->col==0) *b++ = FilterNone; - pixels = (e-b)/3; + pixels = (e-b)/pixwid; if(pixels > ncol - z->col) pixels = ncol - z->col; - img = z->data + z->width * z->row + 3 * z->col; - - memmove(b, img, 3*pixels); - b += 3*pixels; + img = z->data + z->width * z->row + pixwid * z->col; + + memmove(b, img, pixwid*pixels); + if(pixwid == 4){ + /* + * Convert to non-premultiplied alpha. + */ + for(i=0; i<pixels; i++, b+=4){ + a = b[3]; + if(a == 255 || a == 0) + ; + else{ + if(b[0] >= a) + b[0] = a; + b[0] = (b[0]*255)/a; + if(b[1] >= a) + b[1] = a; + b[1] = (b[1]*255)/a; + if(b[2] >= a) + b[2] = a; + b[2] = (b[2]*255)/a; + } + } + }else + b += pixwid*pixels; z->col += pixels; if(z->col >= ncol){ @@ -119,17 +143,25 @@ zwrite(void *va, void *buf, int n) } static Memimage* -memRGB(Memimage *i) +memRGBA(Memimage *i) { Memimage *ni; - + char buf[32]; + ulong dst; + /* - * BGR24 because we want R,G,B in big-endian order. Sigh. + * [A]BGR because we want R,G,B,[A] in big-endian order. Sigh. */ - if(i->chan == BGR24) + chantostr(buf, i->chan); + if(strchr(buf, 'a')) + dst = ABGR32; + else + dst = BGR24; + + if(i->chan == dst) return i; - ni = allocmemimage(i->r, BGR24); + ni = allocmemimage(i->r, dst); if(ni == nil) return ni; memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S); @@ -149,7 +181,7 @@ memwritepng(Biobuf *bo, Memimage *r, ImageInfo *II) Tm *tm; Memimage *rgb; - rgb = memRGB(r); + rgb = memRGBA(r); if(rgb == nil) return "allocmemimage nil"; crctab = mkcrctab(0xedb88320); @@ -163,7 +195,7 @@ memwritepng(Biobuf *bo, Memimage *r, ImageInfo *II) put4(h, ncol); h += 4; put4(h, nrow); h += 4; *h++ = 8; // bit depth = 24 bit per pixel - *h++ = 2; // color type = rgb + *h++ = rgb->chan==BGR24 ? 2 : 6; // color type = rgb *h++ = 0; // compression method = deflate *h++ = 0; // filter method *h++ = 0; // interlace method = no interlace @@ -199,6 +231,7 @@ memwritepng(Biobuf *bo, Memimage *r, ImageInfo *II) zr.width = rgb->width * sizeof(ulong); zr.data = rgb->data->bdata; zr.row = zr.col = 0; + zr.pixwid = chantodepth(rgb->chan)/8; zw.bo = bo; zw.buf = malloc(IDATSIZE); zw.b = zw.buf; |