readpng.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  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. int debug;
  9. enum
  10. {
  11. IDATSIZE = 1000000,
  12. /* filtering algorithms */
  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. typedef struct ZlibR ZlibR;
  22. typedef struct ZlibW ZlibW;
  23. struct ZlibW
  24. {
  25. uchar *data; /* Rawimage data */
  26. int ndata;
  27. int noutchan;
  28. int chandesc;
  29. int nchan;
  30. uchar *scan; /* new scanline */
  31. uchar *lastscan; /* previous scan line */
  32. int scanlen; /* scan line length */
  33. int scanpos; /* scan position */
  34. int dx; /* width of image */
  35. int dy; /* height of image */
  36. int bpc; /* bits per channel (per pixel) */
  37. int y; /* current scan line */
  38. int pass; /* adam7 pass#; 0 means no adam7 */
  39. uchar palette[3*256]; /* color palette */
  40. int palsize; /* number of palette entries */
  41. };
  42. struct ZlibR
  43. {
  44. Biobuf *io; /* input buffer */
  45. uchar *buf; /* malloc'ed staging buffer */
  46. uchar *p; /* next byte to decompress */
  47. uchar *e; /* end of buffer */
  48. ZlibW *w;
  49. };
  50. static ulong *crctab;
  51. static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
  52. static ulong
  53. get4(uchar *a)
  54. {
  55. return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
  56. }
  57. static
  58. void
  59. pnginit(void)
  60. {
  61. static int inited;
  62. if(inited)
  63. return;
  64. inited = 1;
  65. crctab = mkcrctab(0xedb88320);
  66. if(crctab == nil)
  67. sysfatal("mkcrctab error");
  68. inflateinit();
  69. }
  70. static
  71. void*
  72. pngmalloc(ulong n, int clear)
  73. {
  74. void *p;
  75. p = mallocz(n, clear);
  76. if(p == nil)
  77. sysfatal("malloc: %r");
  78. return p;
  79. }
  80. static int
  81. getchunk(Biobuf *b, char *type, uchar *d, int m)
  82. {
  83. uchar buf[8];
  84. ulong crc = 0, crc2;
  85. int n, nr;
  86. if(Bread(b, buf, 8) != 8)
  87. return -1;
  88. n = get4(buf);
  89. memmove(type, buf+4, 4);
  90. type[4] = 0;
  91. if(n > m)
  92. sysfatal("getchunk needed %d, had %d", n, m);
  93. nr = Bread(b, d, n);
  94. if(nr != n)
  95. sysfatal("getchunk read %d, expected %d", nr, n);
  96. crc = blockcrc(crctab, crc, type, 4);
  97. crc = blockcrc(crctab, crc, d, n);
  98. if(Bread(b, buf, 4) != 4)
  99. sysfatal("getchunk tlr failed");
  100. crc2 = get4(buf);
  101. if(crc != crc2)
  102. sysfatal("getchunk crc failed");
  103. return n;
  104. }
  105. static int
  106. zread(void *va)
  107. {
  108. ZlibR *z = va;
  109. char type[5];
  110. int n;
  111. if(z->p >= z->e){
  112. Again:
  113. z->p = z->buf;
  114. z->e = z->p;
  115. n = getchunk(z->io, type, z->p, IDATSIZE);
  116. if(n < 0 || strcmp(type, "IEND") == 0)
  117. return -1;
  118. z->e = z->p + n;
  119. if(!strcmp(type,"PLTE")){
  120. if(n < 3 || n > 3*256 || n%3)
  121. sysfatal("invalid PLTE chunk len %d", n);
  122. memcpy(z->w->palette, z->p, n);
  123. z->w->palsize = 256;
  124. goto Again;
  125. }
  126. if(type[0] & PropertyBit)
  127. goto Again; /* skip auxiliary chunks fornow */
  128. if(strcmp(type,"IDAT")){
  129. sysfatal("unrecognized mandatory chunk %s", type);
  130. goto Again;
  131. }
  132. }
  133. return *z->p++;
  134. }
  135. static uchar
  136. paeth(uchar a, uchar b, uchar c)
  137. {
  138. int p, pa, pb, pc;
  139. p = a + b - c;
  140. pa = abs(p - a);
  141. pb = abs(p - b);
  142. pc = abs(p - c);
  143. if(pa <= pb && pa <= pc)
  144. return a;
  145. else if(pb <= pc)
  146. return b;
  147. return c;
  148. }
  149. static void
  150. unfilter(int alg, uchar *buf, uchar *up, int len, int bypp)
  151. {
  152. int i;
  153. switch(alg){
  154. case FilterNone:
  155. break;
  156. case FilterSub:
  157. for(i = bypp; i < len; ++i)
  158. buf[i] += buf[i-bypp];
  159. break;
  160. case FilterUp:
  161. for(i = 0; i < len; ++i)
  162. buf[i] += up[i];
  163. break;
  164. case FilterAvg:
  165. for(i = 0; i < bypp; ++i)
  166. buf[i] += (0+up[i])/2;
  167. for(; i < len; ++i)
  168. buf[i] += (buf[i-bypp]+up[i])/2;
  169. break;
  170. case FilterPaeth:
  171. for(i = 0; i < bypp; ++i)
  172. buf[i] += paeth(0, up[i], 0);
  173. for(; i < len; ++i)
  174. buf[i] += paeth(buf[i-bypp], up[i], up[i-bypp]);
  175. break;
  176. default:
  177. sysfatal("unknown filtering scheme %d\n", alg);
  178. }
  179. }
  180. struct {
  181. int x;
  182. int y;
  183. int dx;
  184. int dy;
  185. } adam7[] = {
  186. {0,0,1,1}, /* eve alone */
  187. {0,0,8,8}, /* pass 1 */
  188. {4,0,8,8}, /* pass 2 */
  189. {0,4,4,8}, /* pass 3 */
  190. {2,0,4,4}, /* pass 4 */
  191. {0,2,2,4}, /* pass 5 */
  192. {1,0,2,2}, /* pass 6 */
  193. {0,1,1,2}, /* pass 7 */
  194. };
  195. static void
  196. scan(int len, ZlibW *z)
  197. {
  198. int chan, i, j, nbit, off, val;
  199. uchar pixel[4], *p, *w;
  200. unfilter(z->scan[0], z->scan+1, z->lastscan+1, len-1, (z->nchan*z->bpc+7)/8);
  201. /*
  202. * loop over raw bits extracting pixel values and converting to 8-bit
  203. */
  204. nbit = 0;
  205. chan = 0;
  206. val = 0;
  207. off = z->y*z->dx + adam7[z->pass].x;
  208. w = z->data + z->noutchan*off;
  209. p = z->scan+1; /* skip alg byte */
  210. len--;
  211. for(i=0; i<len*8; i++){
  212. val <<= 1;
  213. if(p[i>>3] & (1<<(7-(i&7))))
  214. val++;
  215. if(++nbit == z->bpc){
  216. /* finished the value */
  217. pixel[chan++] = (val*255)/((1<<z->bpc)-1);
  218. val = 0;
  219. nbit = 0;
  220. if(chan == z->nchan){
  221. /* finished the pixel */
  222. if(off < z->dx*z->dy){
  223. if(z->nchan < 3 && z->palsize){
  224. j = pixel[0];
  225. if(z->bpc < 8)
  226. j >>= 8-z->bpc;
  227. if(j >= z->palsize)
  228. sysfatal("index %d >= palette size %d", j, z->palsize);
  229. pixel[3] = pixel[1]; /* alpha */
  230. pixel[0] = z->palette[3*j];
  231. pixel[1] = z->palette[3*j+1];
  232. pixel[2] = z->palette[3*j+2];
  233. }
  234. switch(z->chandesc){
  235. case CYA16:
  236. // print("%.2x%.2x ", pixel[0], pixel[1]);
  237. *w++ = pixel[1];
  238. *w++ += (pixel[0]*pixel[1])/255;
  239. break;
  240. case CRGBA32:
  241. // print("%.2x%.2x%.2x%.2x ", pixel[0], pixel[1], pixel[2], pixel[3]);
  242. *w++ += pixel[3];
  243. *w++ += (pixel[2]*pixel[3])/255;
  244. *w++ += (pixel[1]*pixel[3])/255;
  245. *w++ += (pixel[0]*pixel[3])/255;
  246. break;
  247. case CRGB24:
  248. *w++ = pixel[2];
  249. *w++ = pixel[1];
  250. case CY:
  251. *w++ = pixel[0];
  252. break;
  253. }
  254. w += (adam7[z->pass].dx-1)*z->noutchan;
  255. }
  256. off += adam7[z->pass].dx;
  257. if(off >= (z->y+1)*z->dx){
  258. /* finished the line */
  259. return;
  260. }
  261. chan = 0;
  262. }
  263. }
  264. }
  265. sysfatal("scan line too short");
  266. }
  267. static int
  268. scanbytes(ZlibW *z)
  269. {
  270. int bits, n, adx, dx;
  271. if(adam7[z->pass].y >= z->dy || adam7[z->pass].x >= z->dx)
  272. return 0;
  273. adx = adam7[z->pass].dx;
  274. dx = z->dx - adam7[z->pass].x;
  275. if(dx <= 0)
  276. n = 1;
  277. else
  278. n = (dx+adx-1)/adx;
  279. if(n != 1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx){
  280. print("%d/%d != 1+(%d-1)/%d = %d\n",
  281. z->dx - adam7[z->pass].x - 1 + adx, adx,
  282. z->dx - (adam7[z->pass].x+1), adam7[z->pass].dx,
  283. 1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx);
  284. }
  285. bits = n*z->bpc*z->nchan;
  286. return 1 + (bits+7)/8;
  287. }
  288. static int
  289. nextpass(ZlibW *z)
  290. {
  291. int len;
  292. memset(z->lastscan, 0, z->scanlen);
  293. do{
  294. z->pass = (z->pass+1)%8;
  295. z->y = adam7[z->pass].y;
  296. len = scanbytes(z);
  297. }while(len < 2);
  298. return len;
  299. }
  300. static int
  301. zwrite(void *vz, void *vbuf, int n)
  302. {
  303. int oldn, m, len;
  304. uchar *buf, *t;
  305. ZlibW *z;
  306. z = vz;
  307. buf = vbuf;
  308. oldn = n;
  309. len = scanbytes(z);
  310. if(len < 2)
  311. len = nextpass(z);
  312. while(n > 0){
  313. m = len - z->scanpos;
  314. if(m > n){
  315. /* save final partial line */
  316. memmove(z->scan+z->scanpos, buf, n);
  317. z->scanpos += n;
  318. break;
  319. }
  320. /* fill line */
  321. memmove(z->scan+z->scanpos, buf, m);
  322. buf += m;
  323. n -= m;
  324. /* process line */
  325. scan(len, z);
  326. t = z->scan;
  327. z->scan = z->lastscan;
  328. z->lastscan = t;
  329. z->scanpos = 0;
  330. z->y += adam7[z->pass].dy;
  331. if(z->y >= z->dy)
  332. len = nextpass(z);
  333. }
  334. return oldn;
  335. }
  336. static Rawimage*
  337. readslave(Biobuf *b)
  338. {
  339. char type[5];
  340. int bpc, colorfmt, dx, dy, err, n, nchan, nout, useadam7;
  341. uchar *buf, *h;
  342. Rawimage *image;
  343. ZlibR zr;
  344. ZlibW zw;
  345. buf = pngmalloc(IDATSIZE, 0);
  346. if(Bread(b, buf, sizeof PNGmagic) != sizeof PNGmagic ||
  347. memcmp(PNGmagic, buf, sizeof PNGmagic) != 0)
  348. sysfatal("bad PNGmagic");
  349. n = getchunk(b, type, buf, IDATSIZE);
  350. if(n < 13 || strcmp(type,"IHDR") != 0)
  351. sysfatal("missing IHDR chunk");
  352. h = buf;
  353. dx = get4(h);
  354. h += 4;
  355. dy = get4(h);
  356. h += 4;
  357. if(dx <= 0 || dy <= 0)
  358. sysfatal("impossible image size %dx%d", dx, dy);
  359. if(debug)
  360. fprint(2, "readpng %dx%d\n", dx, dy);
  361. bpc = *h++;
  362. colorfmt = *h++;
  363. nchan = 0;
  364. if(*h++ != 0)
  365. sysfatal("only deflate supported for now [%d]", h[-1]);
  366. if(*h++ != FilterNone)
  367. sysfatal("only FilterNone supported for now [%d]", h[-1]);
  368. useadam7 = *h++;
  369. USED(h);
  370. image = pngmalloc(sizeof(Rawimage), 1);
  371. image->r = Rect(0, 0, dx, dy);
  372. nout = 0;
  373. switch(colorfmt){
  374. case 0: /* grey */
  375. image->nchans = 1;
  376. image->chandesc = CY;
  377. nout = 1;
  378. nchan = 1;
  379. break;
  380. case 2: /* rgb */
  381. image->nchans = 1;
  382. image->chandesc = CRGB24;
  383. nout = 3;
  384. nchan = 3;
  385. break;
  386. case 3: /* indexed rgb with PLTE */
  387. image->nchans = 1;
  388. image->chandesc = CRGB24;
  389. nout = 3;
  390. nchan = 1;
  391. break;
  392. case 4: /* grey+alpha */
  393. image->nchans = 1;
  394. image->chandesc = CYA16;
  395. nout = 2;
  396. nchan = 2;
  397. break;
  398. case 6: /* rgb+alpha */
  399. image->nchans = 1;
  400. image->chandesc = CRGBA32;
  401. nout = 4;
  402. nchan = 4;
  403. break;
  404. default:
  405. sysfatal("unsupported color scheme %d", h[-1]);
  406. }
  407. image->chanlen = dx*dy*nout;
  408. image->chans[0] = pngmalloc(image->chanlen, 0);
  409. memset(image->chans[0], 0, image->chanlen);
  410. memset(&zr, 0, sizeof zr);
  411. zr.w = &zw;
  412. zr.io = b;
  413. zr.buf = buf;
  414. memset(&zw, 0, sizeof zw);
  415. if(useadam7)
  416. zw.pass = 1;
  417. zw.data = image->chans[0];
  418. zw.ndata = image->chanlen;
  419. zw.chandesc = image->chandesc;
  420. zw.noutchan = nout;
  421. zw.dx = dx;
  422. zw.dy = dy;
  423. zw.scanlen = (nchan*dx*bpc+7)/8+1;
  424. zw.scan = pngmalloc(zw.scanlen, 1);
  425. zw.lastscan = pngmalloc(zw.scanlen, 1);
  426. zw.nchan = nchan;
  427. zw.bpc = bpc;
  428. err = inflatezlib(&zw, zwrite, &zr, zread);
  429. if(err)
  430. sysfatal("inflatezlib %s\n", flateerr(err));
  431. free(buf);
  432. free(zw.scan);
  433. free(zw.lastscan);
  434. return image;
  435. }
  436. Rawimage**
  437. Breadpng(Biobuf *b, int colorspace)
  438. {
  439. Rawimage **array, *r;
  440. if(colorspace != CRGB){
  441. werrstr("ReadPNG: unknown color space %d", colorspace);
  442. return nil;
  443. }
  444. pnginit();
  445. array = malloc(2*sizeof(*array));
  446. if(array==nil)
  447. return nil;
  448. r = readslave(b);
  449. array[0] = r;
  450. array[1] = nil;
  451. return array;
  452. }
  453. Rawimage**
  454. readpng(int fd, int colorspace)
  455. {
  456. Biobuf b;
  457. Rawimage **a;
  458. if(Binit(&b, fd, OREAD) < 0)
  459. return nil;
  460. a = Breadpng(&b, colorspace);
  461. Bterm(&b);
  462. return a;
  463. }