Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2. #include "muxps.h"
  3.  
  4. #include <zlib.h>
  5.  
  6. struct info
  7. {
  8.         int width, height, depth, n;
  9.         int interlace, indexed;
  10.         int size;
  11.         unsigned char *samples;
  12.         unsigned char palette[256*4];
  13.         int transparency;
  14.         int trns[3];
  15.         int xres, yres;
  16. };
  17.  
  18. static inline int getint(unsigned char *p)
  19. {
  20.         return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
  21. }
  22.  
  23. static inline int getcomp(unsigned char *line, int x, int bpc)
  24. {
  25.         switch (bpc)
  26.         {
  27.         case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
  28.         case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
  29.         case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
  30.         case 8: return line[x];
  31.         case 16: return line[x << 1] << 8 | line[(x << 1) + 1];
  32.         }
  33.         return 0;
  34. }
  35.  
  36. static inline void putcomp(unsigned char *line, int x, int bpc, int value)
  37. {
  38.         int maxval = (1 << bpc) - 1;
  39.  
  40.         switch (bpc)
  41.         {
  42.         case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break;
  43.         case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break;
  44.         case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break;
  45.         }
  46.  
  47.         switch (bpc)
  48.         {
  49.         case 1: line[x >> 3] |= value << (7 - (x & 7)); break;
  50.         case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
  51.         case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
  52.         case 8: line[x] = value; break;
  53.         case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break;
  54.         }
  55. }
  56.  
  57. static const unsigned char png_signature[8] =
  58. {
  59.         137, 80, 78, 71, 13, 10, 26, 10
  60. };
  61.  
  62. static void *zalloc(void *opaque, unsigned int items, unsigned int size)
  63. {
  64.         return fz_calloc(items, size);
  65. }
  66.  
  67. static void zfree(void *opaque, void *address)
  68. {
  69.         fz_free(address);
  70. }
  71.  
  72. static inline int paeth(int a, int b, int c)
  73. {
  74.         /* The definitions of ac and bc are correct, not a typo. */
  75.         int ac = b - c, bc = a - c, abcc = ac + bc;
  76.         int pa = (ac < 0 ? -ac : ac);
  77.         int pb = (bc < 0 ? -bc : bc);
  78.         int pc = (abcc < 0 ? -abcc : abcc);
  79.         return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
  80. }
  81.  
  82. static void
  83. png_predict(unsigned char *samples, int width, int height, int n, int depth)
  84. {
  85.         int stride = (width * n * depth + 7) / 8;
  86.         int bpp = (n * depth + 7) / 8;
  87.         int i, row;
  88.  
  89.         for (row = 0; row < height; row ++)
  90.         {
  91.                 unsigned char *src = samples + (stride + 1) * row;
  92.                 unsigned char *dst = samples + stride * row;
  93.  
  94.                 unsigned char *a = dst;
  95.                 unsigned char *b = dst - stride;
  96.                 unsigned char *c = dst - stride;
  97.  
  98.                 switch (*src++)
  99.                 {
  100.                 default:
  101.                 case 0: /* None */
  102.                         for (i = 0; i < stride; i++)
  103.                                 *dst++ = *src++;
  104.                         break;
  105.  
  106.                 case 1: /* Sub */
  107.                         for (i = 0; i < bpp; i++)
  108.                                 *dst++ = *src++;
  109.                         for (i = bpp; i < stride; i++)
  110.                                 *dst++ = *src++ + *a++;
  111.                         break;
  112.  
  113.                 case 2: /* Up */
  114.                         if (row == 0)
  115.                                 for (i = 0; i < stride; i++)
  116.                                         *dst++ = *src++;
  117.                         else
  118.                                 for (i = 0; i < stride; i++)
  119.                                         *dst++ = *src++ + *b++;
  120.                         break;
  121.  
  122.                 case 3: /* Average */
  123.                         if (row == 0)
  124.                         {
  125.                                 for (i = 0; i < bpp; i++)
  126.                                         *dst++ = *src++;
  127.                                 for (i = bpp; i < stride; i++)
  128.                                         *dst++ = *src++ + (*a++ >> 1);
  129.                         }
  130.                         else
  131.                         {
  132.                                 for (i = 0; i < bpp; i++)
  133.                                         *dst++ = *src++ + (*b++ >> 1);
  134.                                 for (i = bpp; i < stride; i++)
  135.                                         *dst++ = *src++ + ((*b++ + *a++) >> 1);
  136.                         }
  137.                         break;
  138.  
  139.                 case 4: /* Paeth */
  140.                         if (row == 0)
  141.                         {
  142.                                 for (i = 0; i < bpp; i++)
  143.                                         *dst++ = *src++ + paeth(0, 0, 0);
  144.                                 for (i = bpp; i < stride; i++)
  145.                                         *dst++ = *src++ + paeth(*a++, 0, 0);
  146.                         }
  147.                         else
  148.                         {
  149.                                 for (i = 0; i < bpp; i++)
  150.                                         *dst++ = *src++ + paeth(0, *b++, 0);
  151.                                 for (i = bpp; i < stride; i++)
  152.                                         *dst++ = *src++ + paeth(*a++, *b++, *c++);
  153.                         }
  154.                         break;
  155.                 }
  156.         }
  157. }
  158.  
  159. static const int adam7_ix[7] = { 0, 4, 0, 2, 0, 1, 0 };
  160. static const int adam7_dx[7] = { 8, 8, 4, 4, 2, 2, 1 };
  161. static const int adam7_iy[7] = { 0, 0, 4, 0, 2, 0, 1 };
  162. static const int adam7_dy[7] = { 8, 8, 8, 4, 4, 2, 2 };
  163.  
  164. static void
  165. png_deinterlace_passes(struct info *info, int *w, int *h, int *ofs)
  166. {
  167.         int p, bpp = info->depth * info->n;
  168.         ofs[0] = 0;
  169.         for (p = 0; p < 7; p++)
  170.         {
  171.                 w[p] = (info->width + adam7_dx[p] - adam7_ix[p] - 1) / adam7_dx[p];
  172.                 h[p] = (info->height + adam7_dy[p] - adam7_iy[p] - 1) / adam7_dy[p];
  173.                 if (w[p] == 0) h[p] = 0;
  174.                 if (h[p] == 0) w[p] = 0;
  175.                 if (w[p] && h[p])
  176.                         ofs[p + 1] = ofs[p] + h[p] * (1 + (w[p] * bpp + 7) / 8);
  177.                 else
  178.                         ofs[p + 1] = ofs[p];
  179.         }
  180. }
  181.  
  182. static void
  183. png_deinterlace(struct info *info, int *passw, int *passh, int *passofs)
  184. {
  185.         int n = info->n;
  186.         int depth = info->depth;
  187.         int stride = (info->width * n * depth + 7) / 8;
  188.         unsigned char *output;
  189.         int p, x, y, k;
  190.  
  191.         output = fz_calloc(info->height, stride);
  192.  
  193.         for (p = 0; p < 7; p++)
  194.         {
  195.                 unsigned char *sp = info->samples + passofs[p];
  196.                 int w = passw[p];
  197.                 int h = passh[p];
  198.  
  199.                 png_predict(sp, w, h, n, depth);
  200.                 for (y = 0; y < h; y++)
  201.                 {
  202.                         for (x = 0; x < w; x++)
  203.                         {
  204.                                 int outx = x * adam7_dx[p] + adam7_ix[p];
  205.                                 int outy = y * adam7_dy[p] + adam7_iy[p];
  206.                                 unsigned char *dp = output + outy * stride;
  207.                                 for (k = 0; k < n; k++)
  208.                                 {
  209.                                         int v = getcomp(sp, x * n + k, depth);
  210.                                         putcomp(dp, outx * n + k, depth, v);
  211.                                 }
  212.                         }
  213.                         sp += (w * depth * n + 7) / 8;
  214.                 }
  215.         }
  216.  
  217.         fz_free(info->samples);
  218.         info->samples = output;
  219. }
  220.  
  221. static int
  222. png_read_ihdr(struct info *info, unsigned char *p, int size)
  223. {
  224.         int color, compression, filter;
  225.  
  226.         if (size != 13)
  227.                 return fz_throw("IHDR chunk is the wrong size");
  228.  
  229.         info->width = getint(p + 0);
  230.         info->height = getint(p + 4);
  231.         info->depth = p[8];
  232.  
  233.         color = p[9];
  234.         compression = p[10];
  235.         filter = p[11];
  236.         info->interlace = p[12];
  237.  
  238.         if (info->width <= 0)
  239.                 return fz_throw("image width must be > 0");
  240.         if (info->height <= 0)
  241.                 return fz_throw("image height must be > 0");
  242.  
  243.         if (info->depth != 1 && info->depth != 2 && info->depth != 4 &&
  244.                         info->depth != 8 && info->depth != 16)
  245.                 return fz_throw("image bit depth must be one of 1, 2, 4, 8, 16");
  246.         if (color == 2 && info->depth < 8)
  247.                 return fz_throw("illegal bit depth for truecolor");
  248.         if (color == 3 && info->depth > 8)
  249.                 return fz_throw("illegal bit depth for indexed");
  250.         if (color == 4 && info->depth < 8)
  251.                 return fz_throw("illegal bit depth for grayscale with alpha");
  252.         if (color == 6 && info->depth < 8)
  253.                 return fz_throw("illegal bit depth for truecolor with alpha");
  254.  
  255.         info->indexed = 0;
  256.         if (color == 0) /* gray */
  257.                 info->n = 1;
  258.         else if (color == 2) /* rgb */
  259.                 info->n = 3;
  260.         else if (color == 4) /* gray alpha */
  261.                 info->n = 2;
  262.         else if (color == 6) /* rgb alpha */
  263.                 info->n = 4;
  264.         else if (color == 3) /* indexed */
  265.         {
  266.                 info->indexed = 1;
  267.                 info->n = 1;
  268.         }
  269.         else
  270.                 return fz_throw("unknown color type");
  271.  
  272.         if (compression != 0)
  273.                 return fz_throw("unknown compression method");
  274.         if (filter != 0)
  275.                 return fz_throw("unknown filter method");
  276.         if (info->interlace != 0 && info->interlace != 1)
  277.                 return fz_throw("interlace method not supported");
  278.  
  279.         return fz_okay;
  280. }
  281.  
  282. static int
  283. png_read_plte(struct info *info, unsigned char *p, int size)
  284. {
  285.         int n = size / 3;
  286.         int i;
  287.  
  288.         if (n > 256 || n > (1 << info->depth))
  289.                 return fz_throw("too many samples in palette");
  290.  
  291.         for (i = 0; i < n; i++)
  292.         {
  293.                 info->palette[i * 4] = p[i * 3];
  294.                 info->palette[i * 4 + 1] = p[i * 3 + 1];
  295.                 info->palette[i * 4 + 2] = p[i * 3 + 2];
  296.         }
  297.  
  298.         return fz_okay;
  299. }
  300.  
  301. static int
  302. png_read_trns(struct info *info, unsigned char *p, int size)
  303. {
  304.         int i;
  305.  
  306.         info->transparency = 1;
  307.  
  308.         if (info->indexed)
  309.         {
  310.                 if (size > 256 || size > (1 << info->depth))
  311.                         return fz_throw("too many samples in transparency table");
  312.                 for (i = 0; i < size; i++)
  313.                         info->palette[i * 4 + 3] = p[i];
  314.         }
  315.         else
  316.         {
  317.                 if (size != info->n * 2)
  318.                         return fz_throw("tRNS chunk is the wrong size");
  319.                 for (i = 0; i < info->n; i++)
  320.                         info->trns[i] = (p[i * 2] << 8 | p[i * 2 + 1]) & ((1 << info->depth) - 1);
  321.         }
  322.  
  323.         return fz_okay;
  324. }
  325.  
  326. static int
  327. png_read_idat(struct info *info, unsigned char *p, int size, z_stream *stm)
  328. {
  329.         int code;
  330.  
  331.         stm->next_in = p;
  332.         stm->avail_in = size;
  333.  
  334.         code = inflate(stm, Z_SYNC_FLUSH);
  335.         if (code != Z_OK && code != Z_STREAM_END)
  336.                 return fz_throw("zlib error: %s", stm->msg);
  337.         if (stm->avail_in != 0)
  338.         {
  339.                 if (stm->avail_out == 0)
  340.                         return fz_throw("ran out of output before input");
  341.                 return fz_throw("inflate did not consume buffer (%d remaining)", stm->avail_in);
  342.         }
  343.  
  344.         return fz_okay;
  345. }
  346.  
  347. static int
  348. png_read_phys(struct info *info, unsigned char *p, int size)
  349. {
  350.         if (size != 9)
  351.                 return fz_throw("pHYs chunk is the wrong size");
  352.         if (p[8] == 1)
  353.         {
  354.                 info->xres = getint(p) * 254 / 10000;
  355.                 info->yres = getint(p + 4) * 254 / 10000;
  356.         }
  357.         return fz_okay;
  358. }
  359.  
  360. static int
  361. png_read_image(struct info *info, unsigned char *p, int total)
  362. {
  363.         int passw[7], passh[7], passofs[8];
  364.         int code, size;
  365.         z_stream stm;
  366.  
  367.         memset(info, 0, sizeof (struct info));
  368.         memset(info->palette, 255, sizeof(info->palette));
  369.         info->xres = 96;
  370.         info->yres = 96;
  371.  
  372.         /* Read signature */
  373.  
  374.         if (total < 8 + 12 || memcmp(p, png_signature, 8))
  375.                 return fz_throw("not a png image (wrong signature)");
  376.  
  377.         p += 8;
  378.         total -= 8;
  379.  
  380.         /* Read IHDR chunk (must come first) */
  381.  
  382.         size = getint(p);
  383.  
  384.         if (size + 12 > total)
  385.                 return fz_throw("premature end of data in png image");
  386.  
  387.         if (!memcmp(p + 4, "IHDR", 4))
  388.         {
  389.                 code = png_read_ihdr(info, p + 8, size);
  390.                 if (code)
  391.                         return fz_rethrow(code, "cannot read png header");
  392.         }
  393.         else
  394.                 return fz_throw("png file must start with IHDR chunk");
  395.  
  396.         p += size + 12;
  397.         total -= size + 12;
  398.  
  399.         /* Prepare output buffer */
  400.  
  401.         if (!info->interlace)
  402.         {
  403.                 info->size = info->height * (1 + (info->width * info->n * info->depth + 7) / 8);
  404.         }
  405.         else
  406.         {
  407.                 png_deinterlace_passes(info, passw, passh, passofs);
  408.                 info->size = passofs[7];
  409.         }
  410.  
  411.         info->samples = fz_malloc(info->size);
  412.  
  413.         stm.zalloc = zalloc;
  414.         stm.zfree = zfree;
  415.         stm.opaque = NULL;
  416.  
  417.         stm.next_out = info->samples;
  418.         stm.avail_out = info->size;
  419.  
  420.         code = inflateInit(&stm);
  421.         if (code != Z_OK)
  422.                 return fz_throw("zlib error: %s", stm.msg);
  423.  
  424.         /* Read remaining chunks until IEND */
  425.  
  426.         while (total > 8)
  427.         {
  428.                 size = getint(p);
  429.  
  430.                 if (size + 12 > total)
  431.                         return fz_throw("premature end of data in png image");
  432.  
  433.                 if (!memcmp(p + 4, "PLTE", 4))
  434.                 {
  435.                         code = png_read_plte(info, p + 8, size);
  436.                         if (code)
  437.                                 return fz_rethrow(code, "cannot read png palette");
  438.                 }
  439.  
  440.                 if (!memcmp(p + 4, "tRNS", 4))
  441.                 {
  442.                         code = png_read_trns(info, p + 8, size);
  443.                         if (code)
  444.                                 return fz_rethrow(code, "cannot read png transparency");
  445.                 }
  446.  
  447.                 if (!memcmp(p + 4, "pHYs", 4))
  448.                 {
  449.                         code = png_read_phys(info, p + 8, size);
  450.                         if (code)
  451.                                 return fz_rethrow(code, "cannot read png resolution");
  452.                 }
  453.  
  454.                 if (!memcmp(p + 4, "IDAT", 4))
  455.                 {
  456.                         code = png_read_idat(info, p + 8, size, &stm);
  457.                         if (code)
  458.                                 return fz_rethrow(code, "cannot read png image data");
  459.                 }
  460.  
  461.                 if (!memcmp(p + 4, "IEND", 4))
  462.                         break;
  463.  
  464.                 p += size + 12;
  465.                 total -= size + 12;
  466.         }
  467.  
  468.         code = inflateEnd(&stm);
  469.         if (code != Z_OK)
  470.                 return fz_throw("zlib error: %s", stm.msg);
  471.  
  472.         /* Apply prediction filter and deinterlacing */
  473.  
  474.         if (!info->interlace)
  475.                 png_predict(info->samples, info->width, info->height, info->n, info->depth);
  476.         else
  477.                 png_deinterlace(info, passw, passh, passofs);
  478.  
  479.         return fz_okay;
  480. }
  481.  
  482. static fz_pixmap *
  483. png_expand_palette(struct info *info, fz_pixmap *src)
  484. {
  485.         fz_pixmap *dst = fz_new_pixmap(fz_device_rgb, src->w, src->h);
  486.         unsigned char *sp = src->samples;
  487.         unsigned char *dp = dst->samples;
  488.         int x, y;
  489.  
  490.         dst->xres = src->xres;
  491.         dst->yres = src->yres;
  492.  
  493.         for (y = 0; y < info->height; y++)
  494.         {
  495.                 for (x = 0; x < info->width; x++)
  496.                 {
  497.                         int v = *sp << 2;
  498.                         *dp++ = info->palette[v];
  499.                         *dp++ = info->palette[v + 1];
  500.                         *dp++ = info->palette[v + 2];
  501.                         *dp++ = info->palette[v + 3];
  502.                         sp += 2;
  503.                 }
  504.         }
  505.  
  506.         fz_drop_pixmap(src);
  507.         return dst;
  508. }
  509.  
  510. static void
  511. png_mask_transparency(struct info *info, fz_pixmap *dst)
  512. {
  513.         int stride = (info->width * info->n * info->depth + 7) / 8;
  514.         int depth = info->depth;
  515.         int n = info->n;
  516.         int x, y, k, t;
  517.  
  518.         for (y = 0; y < info->height; y++)
  519.         {
  520.                 unsigned char *sp = info->samples + y * stride;
  521.                 unsigned char *dp = dst->samples + y * dst->w * dst->n;
  522.                 for (x = 0; x < info->width; x++)
  523.                 {
  524.                         t = 1;
  525.                         for (k = 0; k < n; k++)
  526.                                 if (getcomp(sp, x * n + k, depth) != info->trns[k])
  527.                                         t = 0;
  528.                         if (t)
  529.                                 dp[x * dst->n + dst->n - 1] = 0;
  530.                 }
  531.         }
  532. }
  533.  
  534. int
  535. xps_decode_png(fz_pixmap **imagep, byte *p, int total)
  536. {
  537.         fz_pixmap *image;
  538.         fz_colorspace *colorspace;
  539.         struct info png;
  540.         int code;
  541.         int stride;
  542.  
  543.         code = png_read_image(&png, p, total);
  544.         if (code)
  545.                 return fz_rethrow(code, "cannot read png image");
  546.  
  547.         if (png.n == 3 || png.n == 4)
  548.                 colorspace = fz_device_rgb;
  549.         else
  550.                 colorspace = fz_device_gray;
  551.  
  552.         stride = (png.width * png.n * png.depth + 7) / 8;
  553.  
  554.         image = fz_new_pixmap_with_limit(colorspace, png.width, png.height);
  555.         if (!image)
  556.         {
  557.                 fz_free(png.samples);
  558.                 return fz_throw("out of memory");
  559.         }
  560.  
  561.         image->xres = png.xres;
  562.         image->yres = png.yres;
  563.  
  564.         fz_unpack_tile(image, png.samples, png.n, png.depth, stride, png.indexed);
  565.  
  566.         if (png.indexed)
  567.                 image = png_expand_palette(&png, image);
  568.         else if (png.transparency)
  569.                 png_mask_transparency(&png, image);
  570.  
  571.         if (png.transparency || png.n == 2 || png.n == 4)
  572.                 fz_premultiply_pixmap(image);
  573.  
  574.         fz_free(png.samples);
  575.  
  576.         *imagep = image;
  577.         return fz_okay;
  578. }
  579.