|
@@ -1,6 +1,3 @@
|
|
|
-// work in progress... this version only good enough to read
|
|
|
-// non-interleaved, 24bit RGB images
|
|
|
-
|
|
|
#include <u.h>
|
|
|
#include <libc.h>
|
|
|
#include <ctype.h>
|
|
@@ -11,38 +8,57 @@
|
|
|
|
|
|
int debug;
|
|
|
|
|
|
-enum{ IDATSIZE=1000000,
|
|
|
- /* filtering algorithms, supposedly increase compression */
|
|
|
+enum
|
|
|
+{
|
|
|
+ IDATSIZE = 1000000,
|
|
|
+
|
|
|
+ /* filtering algorithms */
|
|
|
FilterNone = 0, /* new[x][y] = buf[x][y] */
|
|
|
- FilterSub = 1, /* new[x][y] = buf[x][y] + new[x-1][y] */
|
|
|
- FilterUp = 2, /* new[x][y] = buf[x][y] + new[x][y-1] */
|
|
|
- FilterAvg = 3, /* new[x][y] = buf[x][y] + (new[x-1][y]+new[x][y-1])/2 */
|
|
|
- FilterPaeth= 4, /* new[x][y] = buf[x][y] + paeth(new[x-1][y],new[x][y-1],new[x-1][y-1]) */
|
|
|
- FilterLast = 5,
|
|
|
- PropertyBit = 1<<5,
|
|
|
+ FilterSub = 1, /* new[x][y] = buf[x][y] + new[x-1][y] */
|
|
|
+ FilterUp = 2, /* new[x][y] = buf[x][y] + new[x][y-1] */
|
|
|
+ FilterAvg = 3, /* new[x][y] = buf[x][y] + (new[x-1][y]+new[x][y-1])/2 */
|
|
|
+ FilterPaeth = 4, /* new[x][y] = buf[x][y] + paeth(new[x-1][y],new[x][y-1],new[x-1][y-1]) */
|
|
|
+ FilterLast = 5,
|
|
|
+
|
|
|
+ PropertyBit = 1<<5,
|
|
|
+};
|
|
|
+
|
|
|
+typedef struct ZlibR ZlibR;
|
|
|
+typedef struct ZlibW ZlibW;
|
|
|
+
|
|
|
+struct ZlibW
|
|
|
+{
|
|
|
+ uchar *data; /* Rawimage data */
|
|
|
+ int ndata;
|
|
|
+ int noutchan;
|
|
|
+ int chandesc;
|
|
|
+ int nchan;
|
|
|
+
|
|
|
+ uchar *scan; /* new scanline */
|
|
|
+ uchar *lastscan; /* previous scan line */
|
|
|
+ int scanlen; /* scan line length */
|
|
|
+ int scanpos; /* scan position */
|
|
|
+
|
|
|
+ int dx; /* width of image */
|
|
|
+ int dy; /* height of image */
|
|
|
+ int bpc; /* bits per channel (per pixel) */
|
|
|
+ int y; /* current scan line */
|
|
|
+ int pass; /* adam7 pass#; 0 means no adam7 */
|
|
|
+ uchar palette[3*256]; /* color palette */
|
|
|
+ int palsize; /* number of palette entries */
|
|
|
};
|
|
|
|
|
|
-typedef struct ZlibR{
|
|
|
- Biobuf *bi;
|
|
|
- uchar *buf;
|
|
|
- uchar *b; // next byte to decompress
|
|
|
- uchar *e; // past end of buf
|
|
|
-} ZlibR;
|
|
|
-
|
|
|
-typedef struct ZlibW{
|
|
|
- uchar *r, *g, *b; // Rawimage channels
|
|
|
- int chan; // next channel to write
|
|
|
- int col; // column index of current pixel
|
|
|
- // -1 = one-byte pseudo-column for filter spec
|
|
|
- int row; // row index of current pixel
|
|
|
- int ncol, nrow; // image width, height
|
|
|
- int filter; // algorithm for current scanline
|
|
|
-} ZlibW;
|
|
|
+struct ZlibR
|
|
|
+{
|
|
|
+ Biobuf *io; /* input buffer */
|
|
|
+ uchar *buf; /* malloc'ed staging buffer */
|
|
|
+ uchar *p; /* next byte to decompress */
|
|
|
+ uchar *e; /* end of buffer */
|
|
|
+ ZlibW *w;
|
|
|
+};
|
|
|
|
|
|
static ulong *crctab;
|
|
|
-static uchar PNGmagic[] = {137,80,78,71,13,10,26,10};
|
|
|
-static char readerr[] = "ReadPNG: read error: %r";
|
|
|
-static char memerr[] = "ReadPNG: malloc failed: %r";
|
|
|
+static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
|
|
|
|
|
|
static ulong
|
|
|
get4(uchar *a)
|
|
@@ -71,11 +87,9 @@ pngmalloc(ulong n, int clear)
|
|
|
{
|
|
|
void *p;
|
|
|
|
|
|
- p = malloc(n);
|
|
|
+ p = mallocz(n, clear);
|
|
|
if(p == nil)
|
|
|
- sysfatal(memerr);
|
|
|
- if(clear)
|
|
|
- memset(p, 0, n);
|
|
|
+ sysfatal("malloc: %r");
|
|
|
return p;
|
|
|
}
|
|
|
|
|
@@ -113,30 +127,40 @@ zread(void *va)
|
|
|
char type[5];
|
|
|
int n;
|
|
|
|
|
|
- if(z->b >= z->e){
|
|
|
-refill_buffer:
|
|
|
- z->b = z->buf;
|
|
|
- n = getchunk(z->bi, type, z->b, IDATSIZE);
|
|
|
+ if(z->p >= z->e){
|
|
|
+ Again:
|
|
|
+ z->p = z->buf;
|
|
|
+ z->e = z->p;
|
|
|
+ n = getchunk(z->io, type, z->p, IDATSIZE);
|
|
|
if(n < 0 || strcmp(type, "IEND") == 0)
|
|
|
return -1;
|
|
|
- z->e = z->b + n;
|
|
|
+ z->e = z->p + n;
|
|
|
+ if(!strcmp(type,"PLTE")){
|
|
|
+ if(n < 3 || n > 3*256 || n%3)
|
|
|
+ sysfatal("invalid PLTE chunk len %d", n);
|
|
|
+ memcpy(z->w->palette, z->p, n);
|
|
|
+ z->w->palsize = 256;
|
|
|
+ goto Again;
|
|
|
+ }
|
|
|
if(type[0] & PropertyBit)
|
|
|
- goto refill_buffer; /* skip auxiliary chunks for now */
|
|
|
- if(strcmp(type,"IDAT") != 0)
|
|
|
+ goto Again; /* skip auxiliary chunks fornow */
|
|
|
+ if(strcmp(type,"IDAT")){
|
|
|
sysfatal("unrecognized mandatory chunk %s", type);
|
|
|
+ goto Again;
|
|
|
+ }
|
|
|
}
|
|
|
- return *z->b++;
|
|
|
+ return *z->p++;
|
|
|
}
|
|
|
|
|
|
static uchar
|
|
|
paeth(uchar a, uchar b, uchar c)
|
|
|
{
|
|
|
int p, pa, pb, pc;
|
|
|
-
|
|
|
- p = (int)a + (int)b - (int)c;
|
|
|
- pa = abs(p - (int)a);
|
|
|
- pb = abs(p - (int)b);
|
|
|
- pc = abs(p - (int)c);
|
|
|
+
|
|
|
+ p = a + b - c;
|
|
|
+ pa = abs(p - a);
|
|
|
+ pb = abs(p - b);
|
|
|
+ pc = abs(p - c);
|
|
|
|
|
|
if(pa <= pb && pa <= pc)
|
|
|
return a;
|
|
@@ -146,100 +170,223 @@ paeth(uchar a, uchar b, uchar c)
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-unfilter(int alg, uchar *buf, uchar *ebuf, int up)
|
|
|
+unfilter(int alg, uchar *buf, uchar *up, int len, int bypp)
|
|
|
{
|
|
|
+ int i;
|
|
|
+
|
|
|
switch(alg){
|
|
|
+ case FilterNone:
|
|
|
+ break;
|
|
|
+
|
|
|
case FilterSub:
|
|
|
- while (++buf < ebuf)
|
|
|
- *buf += buf[-1];
|
|
|
+ for(i = bypp; i < len; ++i)
|
|
|
+ buf[i] += buf[i-bypp];
|
|
|
break;
|
|
|
+
|
|
|
case FilterUp:
|
|
|
- if (up != 0)
|
|
|
- do
|
|
|
- *buf += buf[up];
|
|
|
- while (++buf < ebuf);
|
|
|
+ for(i = 0; i < len; ++i)
|
|
|
+ buf[i] += up[i];
|
|
|
break;
|
|
|
+
|
|
|
case FilterAvg:
|
|
|
- if (up == 0)
|
|
|
- while (++buf < ebuf)
|
|
|
- *buf += buf[-1]/2;
|
|
|
- else{
|
|
|
- *buf += buf[up]/2;
|
|
|
- while (++buf < ebuf)
|
|
|
- *buf += (buf[-1]+buf[up])/2;
|
|
|
- }
|
|
|
+ for(i = 0; i < bypp; ++i)
|
|
|
+ buf[i] += (0+up[i])/2;
|
|
|
+ for(; i < len; ++i)
|
|
|
+ buf[i] += (buf[i-bypp]+up[i])/2;
|
|
|
break;
|
|
|
+
|
|
|
case FilterPaeth:
|
|
|
- if (up == 0)
|
|
|
- while (++buf < ebuf)
|
|
|
- *buf += buf[-1];
|
|
|
- else{
|
|
|
- *buf += paeth(0, buf[up], 0);
|
|
|
- while (++buf < ebuf)
|
|
|
- *buf += paeth(buf[-1], buf[up], buf[up-1]);
|
|
|
- }
|
|
|
+ for(i = 0; i < bypp; ++i)
|
|
|
+ buf[i] += paeth(0, up[i], 0);
|
|
|
+ for(; i < len; ++i)
|
|
|
+ buf[i] += paeth(buf[i-bypp], up[i], up[i-bypp]);
|
|
|
break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ sysfatal("unknown filtering scheme %d\n", alg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-zwrite(void *va, void *vb, int n)
|
|
|
+struct {
|
|
|
+ int x;
|
|
|
+ int y;
|
|
|
+ int dx;
|
|
|
+ int dy;
|
|
|
+} adam7[] = {
|
|
|
+ {0,0,1,1}, /* eve alone */
|
|
|
+ {0,0,8,8}, /* pass 1 */
|
|
|
+ {4,0,8,8}, /* pass 2 */
|
|
|
+ {0,4,4,8}, /* pass 3 */
|
|
|
+ {2,0,4,4}, /* pass 4 */
|
|
|
+ {0,2,2,4}, /* pass 5 */
|
|
|
+ {1,0,2,2}, /* pass 6 */
|
|
|
+ {0,1,1,2}, /* pass 7 */
|
|
|
+};
|
|
|
+
|
|
|
+static void
|
|
|
+scan(int len, ZlibW *z)
|
|
|
{
|
|
|
- ZlibW *z = va;
|
|
|
- uchar *buf = vb;
|
|
|
- int i, up;
|
|
|
- for(i=0; i<n; i++){
|
|
|
- if(z->col == -1){
|
|
|
- // set filter byte
|
|
|
- z->filter = *buf++;
|
|
|
- if (z->filter >= FilterLast)
|
|
|
- sysfatal("unknown filter algorithm %d for row %d", z->row, z->filter);
|
|
|
- z->col++;
|
|
|
- continue;
|
|
|
- }
|
|
|
- switch(z->chan){
|
|
|
- case 0:
|
|
|
- *z->r++ = *buf++;
|
|
|
- z->chan = 1;
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- *z->g++ = *buf++;
|
|
|
- z->chan = 2;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- *z->b++ = *buf++;
|
|
|
- z->chan = 0;
|
|
|
- z->col++;
|
|
|
- if(z->col == z->ncol){
|
|
|
- if (z->filter){
|
|
|
- if(z->row == 0)
|
|
|
- up = 0;
|
|
|
- else
|
|
|
- up = -z->ncol;
|
|
|
- unfilter(z->filter, z->r - z->col, z->r, up);
|
|
|
- unfilter(z->filter, z->g - z->col, z->g, up);
|
|
|
- unfilter(z->filter, z->b - z->col, z->b, up);
|
|
|
+ int chan, i, j, nbit, off, val;
|
|
|
+ uchar pixel[4], *p, *w;
|
|
|
+
|
|
|
+ unfilter(z->scan[0], z->scan+1, z->lastscan+1, len-1, (z->nchan*z->bpc+7)/8);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * loop over raw bits extracting pixel values and converting to 8-bit
|
|
|
+ */
|
|
|
+ nbit = 0;
|
|
|
+ chan = 0;
|
|
|
+ val = 0;
|
|
|
+ off = z->y*z->dx + adam7[z->pass].x;
|
|
|
+ w = z->data + z->noutchan*off;
|
|
|
+ p = z->scan+1; /* skip alg byte */
|
|
|
+ len--;
|
|
|
+ for(i=0; i<len*8; i++){
|
|
|
+ val <<= 1;
|
|
|
+ if(p[i>>3] & (1<<(7-(i&7))))
|
|
|
+ val++;
|
|
|
+ if(++nbit == z->bpc){
|
|
|
+ /* finished the value */
|
|
|
+ pixel[chan++] = (val*255)/((1<<z->bpc)-1);
|
|
|
+ val = 0;
|
|
|
+ nbit = 0;
|
|
|
+ if(chan == z->nchan){
|
|
|
+ /* finished the pixel */
|
|
|
+ if(off < z->dx*z->dy){
|
|
|
+ if(z->nchan < 3 && z->palsize){
|
|
|
+ j = pixel[0];
|
|
|
+ if(z->bpc < 8)
|
|
|
+ j >>= 8-z->bpc;
|
|
|
+ if(j >= z->palsize)
|
|
|
+ sysfatal("index %d >= palette size %d", j, z->palsize);
|
|
|
+ pixel[3] = pixel[1]; /* alpha */
|
|
|
+ pixel[0] = z->palette[3*j];
|
|
|
+ pixel[1] = z->palette[3*j+1];
|
|
|
+ pixel[2] = z->palette[3*j+2];
|
|
|
+ }
|
|
|
+ switch(z->chandesc){
|
|
|
+ case CYA16:
|
|
|
+ // print("%.2x%.2x ", pixel[0], pixel[1]);
|
|
|
+ *w++ = pixel[1];
|
|
|
+ *w++ += (pixel[0]*pixel[1])/255;
|
|
|
+ break;
|
|
|
+ case CRGBA32:
|
|
|
+ // print("%.2x%.2x%.2x%.2x ", pixel[0], pixel[1], pixel[2], pixel[3]);
|
|
|
+ *w++ += pixel[3];
|
|
|
+ *w++ += (pixel[2]*pixel[3])/255;
|
|
|
+ *w++ += (pixel[1]*pixel[3])/255;
|
|
|
+ *w++ += (pixel[0]*pixel[3])/255;
|
|
|
+ break;
|
|
|
+ case CRGB24:
|
|
|
+ *w++ = pixel[2];
|
|
|
+ *w++ = pixel[1];
|
|
|
+ case CY:
|
|
|
+ *w++ = pixel[0];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ w += (adam7[z->pass].dx-1)*z->noutchan;
|
|
|
}
|
|
|
- z->col = -1;
|
|
|
- z->row++;
|
|
|
- if((z->row >= z->nrow) && (i < n-1) )
|
|
|
- sysfatal("header said %d rows; data goes further", z->nrow);
|
|
|
+ off += adam7[z->pass].dx;
|
|
|
+ if(off >= (z->y+1)*z->dx){
|
|
|
+ /* finished the line */
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ chan = 0;
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sysfatal("scan line too short");
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+scanbytes(ZlibW *z)
|
|
|
+{
|
|
|
+ int bits, n, adx, dx;
|
|
|
+
|
|
|
+ if(adam7[z->pass].y >= z->dy || adam7[z->pass].x >= z->dx)
|
|
|
+ return 0;
|
|
|
+ adx = adam7[z->pass].dx;
|
|
|
+ dx = z->dx - adam7[z->pass].x;
|
|
|
+ if(dx <= 0)
|
|
|
+ n = 1;
|
|
|
+ else
|
|
|
+ n = (dx+adx-1)/adx;
|
|
|
+ if(n != 1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx){
|
|
|
+ print("%d/%d != 1+(%d-1)/%d = %d\n",
|
|
|
+ z->dx - adam7[z->pass].x - 1 + adx, adx,
|
|
|
+ z->dx - (adam7[z->pass].x+1), adam7[z->pass].dx,
|
|
|
+ 1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx);
|
|
|
+ }
|
|
|
+ bits = n*z->bpc*z->nchan;
|
|
|
+ return 1 + (bits+7)/8;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+nextpass(ZlibW *z)
|
|
|
+{
|
|
|
+ int len;
|
|
|
+
|
|
|
+ memset(z->lastscan, 0, z->scanlen);
|
|
|
+ do{
|
|
|
+ z->pass = (z->pass+1)%8;
|
|
|
+ z->y = adam7[z->pass].y;
|
|
|
+ len = scanbytes(z);
|
|
|
+ }while(len < 2);
|
|
|
+ return len;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+zwrite(void *vz, void *vbuf, int n)
|
|
|
+{
|
|
|
+ int oldn, m, len;
|
|
|
+ uchar *buf, *t;
|
|
|
+ ZlibW *z;
|
|
|
+
|
|
|
+ z = vz;
|
|
|
+ buf = vbuf;
|
|
|
+ oldn = n;
|
|
|
+
|
|
|
+ len = scanbytes(z);
|
|
|
+ if(len < 2)
|
|
|
+ len = nextpass(z);
|
|
|
+
|
|
|
+ while(n > 0){
|
|
|
+ m = len - z->scanpos;
|
|
|
+ if(m > n){
|
|
|
+ /* save final partial line */
|
|
|
+ memmove(z->scan+z->scanpos, buf, n);
|
|
|
+ z->scanpos += n;
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ /* fill line */
|
|
|
+ memmove(z->scan+z->scanpos, buf, m);
|
|
|
+ buf += m;
|
|
|
+ n -= m;
|
|
|
+
|
|
|
+ /* process line */
|
|
|
+ scan(len, z);
|
|
|
+ t = z->scan;
|
|
|
+ z->scan = z->lastscan;
|
|
|
+ z->lastscan = t;
|
|
|
+
|
|
|
+ z->scanpos = 0;
|
|
|
+ z->y += adam7[z->pass].dy;
|
|
|
+ if(z->y >= z->dy)
|
|
|
+ len = nextpass(z);
|
|
|
}
|
|
|
- return n;
|
|
|
+ return oldn;
|
|
|
}
|
|
|
|
|
|
static Rawimage*
|
|
|
readslave(Biobuf *b)
|
|
|
{
|
|
|
- ZlibR zr;
|
|
|
- ZlibW zw;
|
|
|
- Rawimage *image;
|
|
|
char type[5];
|
|
|
+ int bpc, colorfmt, dx, dy, err, n, nchan, nout, useadam7;
|
|
|
uchar *buf, *h;
|
|
|
- int k, n, nrow, ncol, err;
|
|
|
+ Rawimage *image;
|
|
|
+ ZlibR zr;
|
|
|
+ ZlibW zw;
|
|
|
|
|
|
buf = pngmalloc(IDATSIZE, 0);
|
|
|
Bread(b, buf, sizeof PNGmagic);
|
|
@@ -250,63 +397,104 @@ readslave(Biobuf *b)
|
|
|
if(n < 13 || strcmp(type,"IHDR") != 0)
|
|
|
sysfatal("missing IHDR chunk");
|
|
|
h = buf;
|
|
|
- ncol = get4(h); h += 4;
|
|
|
- nrow = get4(h); h += 4;
|
|
|
- if(ncol <= 0 || nrow <= 0)
|
|
|
- sysfatal("impossible image size nrow=%d ncol=%d", nrow, ncol);
|
|
|
+ dx = get4(h);
|
|
|
+ h += 4;
|
|
|
+ dy = get4(h);
|
|
|
+ h += 4;
|
|
|
+ if(dx <= 0 || dy <= 0)
|
|
|
+ sysfatal("impossible image size %dx%d", dx, dy);
|
|
|
if(debug)
|
|
|
- fprint(2, "readpng nrow=%d ncol=%d\n", nrow, ncol);
|
|
|
- if(*h++ != 8)
|
|
|
- sysfatal("only 24 bit per pixel supported for now [%d]", h[-1]);
|
|
|
- if(*h++ != 2)
|
|
|
- sysfatal("only rgb supported for now [%d]", h[-1]);
|
|
|
+ fprint(2, "readpng %dx%d\n", dx, dy);
|
|
|
+
|
|
|
+ bpc = *h++;
|
|
|
+ colorfmt = *h++;
|
|
|
+ nchan = 0;
|
|
|
if(*h++ != 0)
|
|
|
sysfatal("only deflate supported for now [%d]", h[-1]);
|
|
|
if(*h++ != FilterNone)
|
|
|
sysfatal("only FilterNone supported for now [%d]", h[-1]);
|
|
|
- if(*h != 0)
|
|
|
- sysfatal("only non-interlaced supported for now [%d]", h[-1]);
|
|
|
+ useadam7 = *h++;
|
|
|
+ USED(h);
|
|
|
|
|
|
image = pngmalloc(sizeof(Rawimage), 1);
|
|
|
- image->r = Rect(0, 0, ncol, nrow);
|
|
|
- image->cmap = nil;
|
|
|
- image->cmaplen = 0;
|
|
|
- image->chanlen = ncol*nrow;
|
|
|
- image->fields = 0;
|
|
|
- image->gifflags = 0;
|
|
|
- image->gifdelay = 0;
|
|
|
- image->giftrindex = 0;
|
|
|
- image->chandesc = CRGB;
|
|
|
- image->nchans = 3;
|
|
|
- for(k=0; k<3; k++)
|
|
|
- image->chans[k] = pngmalloc(ncol*nrow, 0);
|
|
|
- zr.bi = b;
|
|
|
+ image->r = Rect(0, 0, dx, dy);
|
|
|
+ nout = 0;
|
|
|
+ switch(colorfmt){
|
|
|
+ case 0: /* grey */
|
|
|
+ image->nchans = 1;
|
|
|
+ image->chandesc = CY;
|
|
|
+ nout = 1;
|
|
|
+ nchan = 1;
|
|
|
+ break;
|
|
|
+ case 2: /* rgb */
|
|
|
+ image->nchans = 1;
|
|
|
+ image->chandesc = CRGB24;
|
|
|
+ nout = 3;
|
|
|
+ nchan = 3;
|
|
|
+ break;
|
|
|
+ case 3: /* indexed rgb with PLTE */
|
|
|
+ image->nchans = 1;
|
|
|
+ image->chandesc = CRGB24;
|
|
|
+ nout = 3;
|
|
|
+ nchan = 1;
|
|
|
+ break;
|
|
|
+ case 4: /* grey+alpha */
|
|
|
+ image->nchans = 1;
|
|
|
+ image->chandesc = CYA16;
|
|
|
+ nout = 2;
|
|
|
+ nchan = 2;
|
|
|
+ break;
|
|
|
+ case 6: /* rgb+alpha */
|
|
|
+ image->nchans = 1;
|
|
|
+ image->chandesc = CRGBA32;
|
|
|
+ nout = 4;
|
|
|
+ nchan = 4;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ sysfatal("unsupported color scheme %d", h[-1]);
|
|
|
+ }
|
|
|
+ image->chanlen = dx*dy*nout;
|
|
|
+ image->chans[0] = pngmalloc(image->chanlen, 0);
|
|
|
+ memset(image->chans[0], 0, image->chanlen);
|
|
|
+
|
|
|
+ memset(&zr, 0, sizeof zr);
|
|
|
+ zr.w = &zw;
|
|
|
+ zr.io = b;
|
|
|
zr.buf = buf;
|
|
|
- zr.b = zr.e = buf + IDATSIZE;
|
|
|
- zw.r = image->chans[0];
|
|
|
- zw.g = image->chans[1];
|
|
|
- zw.b = image->chans[2];
|
|
|
- zw.chan = 0;
|
|
|
- zw.col = -1;
|
|
|
- zw.row = 0;
|
|
|
- zw.ncol = ncol;
|
|
|
- zw.nrow = nrow;
|
|
|
+
|
|
|
+ memset(&zw, 0, sizeof zw);
|
|
|
+ if(useadam7)
|
|
|
+ zw.pass = 1;
|
|
|
+ zw.data = image->chans[0];
|
|
|
+ zw.ndata = image->chanlen;
|
|
|
+ zw.chandesc = image->chandesc;
|
|
|
+ zw.noutchan = nout;
|
|
|
+
|
|
|
+ zw.dx = dx;
|
|
|
+ zw.dy = dy;
|
|
|
+ zw.scanlen = (nchan*dx*bpc+7)/8+1;
|
|
|
+ zw.scan = pngmalloc(zw.scanlen, 1);
|
|
|
+ zw.lastscan = pngmalloc(zw.scanlen, 1);
|
|
|
+ zw.nchan = nchan;
|
|
|
+ zw.bpc = bpc;
|
|
|
+
|
|
|
err = inflatezlib(&zw, zwrite, &zr, zread);
|
|
|
+
|
|
|
if(err)
|
|
|
sysfatal("inflatezlib %s\n", flateerr(err));
|
|
|
+
|
|
|
free(buf);
|
|
|
+ free(zw.scan);
|
|
|
+ free(zw.lastscan);
|
|
|
return image;
|
|
|
}
|
|
|
|
|
|
Rawimage**
|
|
|
Breadpng(Biobuf *b, int colorspace)
|
|
|
{
|
|
|
- Rawimage *r, **array;
|
|
|
- char buf[ERRMAX];
|
|
|
+ Rawimage **array, *r;
|
|
|
|
|
|
- buf[0] = '\0';
|
|
|
if(colorspace != CRGB){
|
|
|
- errstr(buf, sizeof buf); /* throw it away */
|
|
|
werrstr("ReadPNG: unknown color space %d", colorspace);
|
|
|
return nil;
|
|
|
}
|
|
@@ -314,7 +502,6 @@ Breadpng(Biobuf *b, int colorspace)
|
|
|
array = malloc(2*sizeof(*array));
|
|
|
if(array==nil)
|
|
|
return nil;
|
|
|
- errstr(buf, sizeof buf); /* throw it away */
|
|
|
r = readslave(b);
|
|
|
array[0] = r;
|
|
|
array[1] = nil;
|
|
@@ -324,8 +511,8 @@ Breadpng(Biobuf *b, int colorspace)
|
|
|
Rawimage**
|
|
|
readpng(int fd, int colorspace)
|
|
|
{
|
|
|
- Rawimage** a;
|
|
|
Biobuf b;
|
|
|
+ Rawimage **a;
|
|
|
|
|
|
if(Binit(&b, fd, OREAD) < 0)
|
|
|
return nil;
|