readpng.c (8713B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ctype.h> 4 #include <bio.h> 5 #include <flate.h> 6 #include <draw.h> 7 #include "imagefile.h" 8 9 int debug; 10 11 enum{ IDATSIZE=1000000, 12 /* filtering algorithms, supposedly increase compression */ 13 FilterNone = 0, /* new[x][y] = buf[x][y] */ 14 FilterSub = 1, /* new[x][y] = buf[x][y] + new[x-1][y] */ 15 FilterUp = 2, /* new[x][y] = buf[x][y] + new[x][y-1] */ 16 FilterAvg = 3, /* new[x][y] = buf[x][y] + (new[x-1][y]+new[x][y-1])/2 */ 17 FilterPaeth= 4, /* new[x][y] = buf[x][y] + paeth(new[x-1][y],new[x][y-1],new[x-1][y-1]) */ 18 FilterLast = 5, 19 PropertyBit = 1<<5 20 }; 21 22 23 typedef struct ZlibW{ 24 uchar *chan[4]; /* Rawimage channels */ 25 uchar *scan; /* new scanline */ 26 uchar *pscan; /* previous scanline */ 27 int scanl; /* scan len */ 28 int scanp; /* scan pos */ 29 int nchan; /* number of input chans */ 30 int npix; /* pixels read so far */ 31 int chanl; /* number of bytes allocated to chan[x] */ 32 int scanpix; 33 int bpp; /* bits per sample */ 34 int palsize; 35 int row; /* current scanline number */ 36 uchar palette[3*256]; 37 } ZlibW; 38 39 typedef struct ZlibR{ 40 Biobuf *bi; 41 uchar *buf; 42 uchar *b; /* next byte to decompress */ 43 uchar *e; /* past end of buf */ 44 ZlibW *w; 45 } ZlibR; 46 47 static uint32 *crctab; 48 static uchar PNGmagic[] = {137,80,78,71,13,10,26,10}; 49 static char memerr[] = "ReadPNG: malloc failed: %r"; 50 51 static uint32 52 get4(uchar *a) 53 { 54 return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3]; 55 } 56 57 static 58 void 59 pnginit(void) 60 { 61 static int inited; 62 63 if(inited) 64 return; 65 inited = 1; 66 crctab = mkcrctab(0xedb88320); 67 if(crctab == nil) 68 sysfatal("mkcrctab error"); 69 inflateinit(); 70 } 71 72 static 73 void* 74 pngmalloc(ulong n, int clear) 75 { 76 void *p; 77 78 p = malloc(n); 79 if(p == nil) 80 sysfatal(memerr); 81 if(clear) 82 memset(p, 0, n); 83 return p; 84 } 85 86 static int 87 getchunk(Biobuf *b, char *type, uchar *d, int m) 88 { 89 uchar buf[8]; 90 uint32 crc = 0, crc2; 91 int n, nr; 92 93 if(Bread(b, buf, 8) != 8) 94 return -1; 95 n = get4(buf); 96 memmove(type, buf+4, 4); 97 type[4] = 0; 98 if(n > m) 99 sysfatal("getchunk needed %d, had %d", n, m); 100 nr = Bread(b, d, n); 101 if(nr != n) 102 sysfatal("getchunk read %d, expected %d", nr, n); 103 crc = blockcrc(crctab, crc, type, 4); 104 crc = blockcrc(crctab, crc, d, n); 105 if(Bread(b, buf, 4) != 4) 106 sysfatal("getchunk tlr failed"); 107 crc2 = get4(buf); 108 if(crc != crc2) 109 sysfatal("getchunk crc failed"); 110 return n; 111 } 112 113 static int 114 zread(void *va) 115 { 116 ZlibR *z = va; 117 char type[5]; 118 int n; 119 120 if(z->b >= z->e){ 121 refill_buffer: 122 z->b = z->buf; 123 n = getchunk(z->bi, type, z->b, IDATSIZE); 124 if(n < 0 || strcmp(type, "IEND") == 0) 125 return -1; 126 z->e = z->b + n; 127 if(!strcmp(type,"PLTE")) { 128 if (n < 3 || n > 3*256 || n%3) 129 sysfatal("invalid PLTE chunk len %d", n); 130 memcpy(z->w->palette, z->b, n); 131 z->w->palsize = n/3; 132 goto refill_buffer; 133 } 134 if(type[0] & PropertyBit) 135 goto refill_buffer; /* skip auxiliary chunks for now */ 136 if(strcmp(type,"IDAT")) { 137 sysfatal("unrecognized mandatory chunk %s", type); 138 goto refill_buffer; 139 } 140 } 141 return *z->b++; 142 } 143 144 static uchar 145 paeth(uchar a, uchar b, uchar c) 146 { 147 int p, pa, pb, pc; 148 149 p = (int)a + (int)b - (int)c; 150 pa = abs(p - (int)a); 151 pb = abs(p - (int)b); 152 pc = abs(p - (int)c); 153 154 if(pa <= pb && pa <= pc) 155 return a; 156 else if(pb <= pc) 157 return b; 158 return c; 159 } 160 161 static void 162 unfilter(int alg, uchar *buf, uchar *up, int len, int bypp) 163 { 164 int i; 165 switch(alg){ 166 case FilterNone: 167 break; 168 169 case FilterSub: 170 for (i = bypp; i < len; ++i) 171 buf[i] += buf[i-bypp]; 172 break; 173 174 case FilterUp: 175 for (i = 0; i < len; ++i) 176 buf[i] += up[i]; 177 break; 178 179 case FilterAvg: 180 for (i = 0; i < bypp; ++i) 181 buf[i] += (0+up[i])/2; 182 for (; i < len; ++i) 183 buf[i] += (buf[i-bypp]+up[i])/2; 184 break; 185 186 case FilterPaeth: 187 for (i = 0; i < bypp; ++i) 188 buf[i] += paeth(0, up[i], 0); 189 for (; i < len; ++i) 190 buf[i] += paeth(buf[i-bypp], up[i], up[i-bypp]); 191 break; 192 default: 193 sysfatal("unknown filtering scheme %d\n", alg); 194 } 195 } 196 197 static void 198 convertpix(ZlibW *z, uchar *pixel, uchar *r, uchar *g, uchar *b) 199 { 200 int off; 201 switch (z->nchan) { 202 case 1: /* gray or indexed */ 203 case 2: /* gray+alpha */ 204 if (z->bpp < 8) 205 pixel[0] >>= 8-z->bpp; 206 if (pixel[0] > z->palsize) 207 sysfatal("index %d out of bounds %d", pixel[0], z->palsize); 208 off = 3*pixel[0]; 209 *r = z->palette[off]; 210 *g = z->palette[off+1]; 211 *b = z->palette[off+2]; 212 break; 213 case 3: /* rgb */ 214 case 4: /* rgb+alpha */ 215 *r = pixel[0]; 216 *g = pixel[1]; 217 *b = pixel[2]; 218 break; 219 default: 220 sysfatal("bad number of channels: %d", z->nchan); 221 } 222 } 223 224 static void 225 scan(ZlibW *z) 226 { 227 uchar *p; 228 int i, bit, n, ch, nch, pd; 229 uchar cb; 230 uchar pixel[4]; 231 232 p = z->scan; 233 nch = z->nchan; 234 235 unfilter(p[0], p+1, z->pscan+1, z->scanl-1, (nch*z->bpp+7)/8); 236 /* 237 * Adam7 interlace order. 238 * 1 6 4 6 2 6 4 6 239 * 7 7 7 7 7 7 7 7 240 * 5 6 5 6 5 6 5 6 241 * 7 7 7 7 7 7 7 7 242 * 3 6 4 6 3 6 4 6 243 * 7 7 7 7 7 7 7 7 244 * 5 6 5 6 5 6 5 6 245 * 7 7 7 7 7 7 7 7 246 */ 247 ch = 0; 248 n = 0; 249 cb = 128; 250 pd = z->row * z->scanpix; 251 for (i = 1; i < z->scanl; ++i) 252 for (bit = 128; bit > 0; bit /= 2) { 253 254 pixel[ch] &= ~cb; 255 if (p[i] & bit) 256 pixel[ch] |= cb; 257 258 cb >>= 1; 259 260 if (++n == z->bpp) { 261 cb = 128; 262 n = 0; 263 ch++; 264 } 265 if (ch == nch) { 266 if (z->npix++ < z->chanl) 267 convertpix(z,pixel,z->chan[0]+pd,z->chan[1]+pd,z->chan[2]+pd); 268 pd++; 269 if (pd % z->scanpix == 0) 270 goto out; 271 ch = 0; 272 } 273 } 274 out: ; 275 } 276 277 static int 278 zwrite(void *va, void *vb, int n) 279 { 280 ZlibW *z = va; 281 uchar *buf = vb; 282 int i, j; 283 284 j = z->scanp; 285 for (i = 0; i < n; ++i) { 286 z->scan[j++] = buf[i]; 287 if (j == z->scanl) { 288 uchar *tp; 289 scan(z); 290 291 tp = z->scan; 292 z->scan = z->pscan; 293 z->pscan = tp; 294 z->row++; 295 j = 0; 296 } 297 } 298 z->scanp = j; 299 300 return n; 301 } 302 303 static Rawimage* 304 readslave(Biobuf *b) 305 { 306 ZlibR zr; 307 ZlibW zw; 308 Rawimage *image; 309 char type[5]; 310 uchar *buf, *h; 311 int k, n, nrow, ncol, err, bpp, nch; 312 313 zr.w = &zw; 314 315 buf = pngmalloc(IDATSIZE, 0); 316 Bread(b, buf, sizeof PNGmagic); 317 if(memcmp(PNGmagic, buf, sizeof PNGmagic) != 0) 318 sysfatal("bad PNGmagic"); 319 320 n = getchunk(b, type, buf, IDATSIZE); 321 if(n < 13 || strcmp(type,"IHDR") != 0) 322 sysfatal("missing IHDR chunk"); 323 h = buf; 324 ncol = get4(h); h += 4; 325 nrow = get4(h); h += 4; 326 if(ncol <= 0 || nrow <= 0) 327 sysfatal("impossible image size nrow=%d ncol=%d", nrow, ncol); 328 if(debug) 329 fprint(2, "readpng nrow=%d ncol=%d\n", nrow, ncol); 330 331 bpp = *h++; 332 nch = 0; 333 switch (*h++) { 334 case 0: /* grey */ 335 nch = 1; 336 break; 337 case 2: /* rgb */ 338 nch = 3; 339 break; 340 case 3: /* indexed rgb with PLTE */ 341 nch = 1; 342 break; 343 case 4: /* grey+alpha */ 344 nch = 2; 345 break; 346 case 6: /* rgb+alpha */ 347 nch = 4; 348 break; 349 default: 350 sysfatal("unsupported color scheme %d", h[-1]); 351 } 352 353 /* generate default palette for grayscale */ 354 zw.palsize = 256; 355 if (nch < 3 && bpp < 9) 356 zw.palsize = 1<<bpp; 357 for (k = 0; k < zw.palsize; ++k) { 358 zw.palette[3*k] = (k*255)/(zw.palsize-1); 359 zw.palette[3*k+1] = (k*255)/(zw.palsize-1); 360 zw.palette[3*k+2] = (k*255)/(zw.palsize-1); 361 } 362 363 if(*h++ != 0) 364 sysfatal("only deflate supported for now [%d]", h[-1]); 365 if(*h++ != FilterNone) 366 sysfatal("only FilterNone supported for now [%d]", h[-1]); 367 if(*h != 0) 368 sysfatal("only non-interlaced supported for now [%d]", h[-1]); 369 370 image = pngmalloc(sizeof(Rawimage), 1); 371 image->r = Rect(0, 0, ncol, nrow); 372 image->cmap = nil; 373 image->cmaplen = 0; 374 image->chanlen = ncol*nrow; 375 image->fields = 0; 376 image->gifflags = 0; 377 image->gifdelay = 0; 378 image->giftrindex = 0; 379 image->chandesc = CRGB; 380 image->nchans = 3; 381 382 zw.chanl = ncol*nrow; 383 zw.npix = 0; 384 for(k=0; k<4; k++) 385 image->chans[k] = zw.chan[k] = pngmalloc(ncol*nrow, 1); 386 387 zr.bi = b; 388 zr.buf = buf; 389 zr.b = zr.e = buf + IDATSIZE; 390 391 zw.scanp = 0; 392 zw.row = 0; 393 zw.scanpix = ncol; 394 zw.scanl = (nch*ncol*bpp+7)/8+1; 395 zw.scan = pngmalloc(zw.scanl, 1); 396 zw.pscan = pngmalloc(zw.scanl, 1); 397 zw.nchan = nch; 398 zw.bpp = bpp; 399 400 err = inflatezlib(&zw, zwrite, &zr, zread); 401 402 if (zw.npix > zw.chanl) 403 fprint(2, "tried to overflow by %d pix\n", zw.npix - zw.chanl); 404 405 406 if(err) 407 sysfatal("inflatezlib %s\n", flateerr(err)); 408 409 free(image->chans[3]); 410 image->chans[3] = nil; 411 free(buf); 412 free(zw.scan); 413 free(zw.pscan); 414 return image; 415 } 416 417 Rawimage** 418 Breadpng(Biobuf *b, int colorspace) 419 { 420 Rawimage *r, **array; 421 char buf[ERRMAX]; 422 423 buf[0] = '\0'; 424 if(colorspace != CRGB){ 425 errstr(buf, sizeof buf); /* throw it away */ 426 werrstr("ReadPNG: unknown color space %d", colorspace); 427 return nil; 428 } 429 pnginit(); 430 array = malloc(2*sizeof(*array)); 431 if(array==nil) 432 return nil; 433 errstr(buf, sizeof buf); /* throw it away */ 434 r = readslave(b); 435 array[0] = r; 436 array[1] = nil; 437 return array; 438 } 439 440 Rawimage** 441 readpng(int fd, int colorspace) 442 { 443 Rawimage** a; 444 Biobuf b; 445 446 if(Binit(&b, fd, OREAD) < 0) 447 return nil; 448 a = Breadpng(&b, colorspace); 449 Bterm(&b); 450 return a; 451 }