Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "fitz.h"
  2.  
  3. /* TODO: check if this works with 16bpp images */
  4.  
  5. enum { MAXC = 32 };
  6.  
  7. typedef struct fz_predict_s fz_predict;
  8.  
  9. struct fz_predict_s
  10. {
  11.         fz_stream *chain;
  12.  
  13.         int predictor;
  14.         int columns;
  15.         int colors;
  16.         int bpc;
  17.  
  18.         int stride;
  19.         int bpp;
  20.         unsigned char *in;
  21.         unsigned char *out;
  22.         unsigned char *ref;
  23.         unsigned char *rp, *wp;
  24. };
  25.  
  26. static inline int getcomponent(unsigned char *line, int x, int bpc)
  27. {
  28.         switch (bpc)
  29.         {
  30.         case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
  31.         case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
  32.         case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
  33.         case 8: return line[x];
  34.         }
  35.         return 0;
  36. }
  37.  
  38.  
  39. static inline void putcomponent(unsigned char *buf, int x, int bpc, int value)
  40. {
  41.         switch (bpc)
  42.         {
  43.         case 1: buf[x >> 3] |= value << (7 - (x & 7)); break;
  44.         case 2: buf[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
  45.         case 4: buf[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
  46.         case 8: buf[x] = value; break;
  47.         }
  48. }
  49.  
  50. static inline int paeth(int a, int b, int c)
  51. {
  52.         /* The definitions of ac and bc are correct, not a typo. */
  53.         int ac = b - c, bc = a - c, abcc = ac + bc;
  54.         int pa = ABS(ac);
  55.         int pb = ABS(bc);
  56.         int pc = ABS(abcc);
  57.         return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
  58. }
  59.  
  60. static void
  61. fz_predict_tiff(fz_predict *state, unsigned char *out, unsigned char *in, int len)
  62. {
  63.         int left[MAXC];
  64.         int i, k;
  65.  
  66.         for (k = 0; k < state->colors; k++)
  67.                 left[k] = 0;
  68.  
  69.         for (i = 0; i < state->columns; i++)
  70.         {
  71.                 for (k = 0; k < state->colors; k++)
  72.                 {
  73.                         int a = getcomponent(in, i * state->colors + k, state->bpc);
  74.                         int b = a + left[k];
  75.                         int c = b % (1 << state->bpc);
  76.                         putcomponent(out, i * state->colors + k, state->bpc, c);
  77.                         left[k] = c;
  78.                 }
  79.         }
  80. }
  81.  
  82. static void
  83. fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor)
  84. {
  85.         int bpp = state->bpp;
  86.         int i;
  87.         unsigned char *ref = state->ref;
  88.  
  89.         switch (predictor)
  90.         {
  91.         case 0:
  92.                 memcpy(out, in, len);
  93.                 break;
  94.         case 1:
  95.                 for (i = bpp; i > 0; i--)
  96.                 {
  97.                         *out++ = *in++;
  98.                 }
  99.                 for (i = len - bpp; i > 0; i--)
  100.                 {
  101.                         *out = *in++ + out[-bpp];
  102.                         out++;
  103.                 }
  104.                 break;
  105.         case 2:
  106.                 for (i = bpp; i > 0; i--)
  107.                 {
  108.                         *out++ = *in++ + *ref++;
  109.                 }
  110.                 for (i = len - bpp; i > 0; i--)
  111.                 {
  112.                         *out++ = *in++ + *ref++;
  113.                 }
  114.                 break;
  115.         case 3:
  116.                 for (i = bpp; i > 0; i--)
  117.                 {
  118.                         *out++ = *in++ + (*ref++) / 2;
  119.                 }
  120.                 for (i = len - bpp; i > 0; i--)
  121.                 {
  122.                         *out = *in++ + (out[-bpp] + *ref++) / 2;
  123.                         out++;
  124.                 }
  125.                 break;
  126.         case 4:
  127.                 for (i = bpp; i > 0; i--)
  128.                 {
  129.                         *out++ = *in++ + paeth(0, *ref++, 0);
  130.                 }
  131.                 for (i = len - bpp; i > 0; i --)
  132.                 {
  133.                         *out = *in++ + paeth(out[-bpp], *ref, ref[-bpp]);
  134.                         ref++;
  135.                         out++;
  136.                 }
  137.                 break;
  138.         }
  139. }
  140.  
  141. static int
  142. read_predict(fz_stream *stm, unsigned char *buf, int len)
  143. {
  144.         fz_predict *state = stm->state;
  145.         unsigned char *p = buf;
  146.         unsigned char *ep = buf + len;
  147.         int ispng = state->predictor >= 10;
  148.         int n;
  149.  
  150.         while (state->rp < state->wp && p < ep)
  151.                 *p++ = *state->rp++;
  152.  
  153.         while (p < ep)
  154.         {
  155.                 n = fz_read(state->chain, state->in, state->stride + ispng);
  156.                 if (n < 0)
  157.                         return fz_rethrow(n, "read error in prediction filter");
  158.                 if (n == 0)
  159.                         return p - buf;
  160.  
  161.                 if (state->predictor == 1)
  162.                         memcpy(state->out, state->in, n);
  163.                 else if (state->predictor == 2)
  164.                         fz_predict_tiff(state, state->out, state->in, n);
  165.                 else
  166.                 {
  167.                         fz_predict_png(state, state->out, state->in + 1, n - 1, state->in[0]);
  168.                         memcpy(state->ref, state->out, state->stride);
  169.                 }
  170.  
  171.                 state->rp = state->out;
  172.                 state->wp = state->out + n - ispng;
  173.  
  174.                 while (state->rp < state->wp && p < ep)
  175.                         *p++ = *state->rp++;
  176.         }
  177.  
  178.         return p - buf;
  179. }
  180.  
  181. static void
  182. close_predict(fz_stream *stm)
  183. {
  184.         fz_predict *state = stm->state;
  185.         fz_close(state->chain);
  186.         fz_free(state->in);
  187.         fz_free(state->out);
  188.         fz_free(state->ref);
  189.         fz_free(state);
  190. }
  191.  
  192. fz_stream *
  193. fz_open_predict(fz_stream *chain, fz_obj *params)
  194. {
  195.         fz_predict *state;
  196.         fz_obj *obj;
  197.  
  198.         state = fz_malloc(sizeof(fz_predict));
  199.         state->chain = chain;
  200.  
  201.         state->predictor = 1;
  202.         state->columns = 1;
  203.         state->colors = 1;
  204.         state->bpc = 8;
  205.  
  206.         obj = fz_dict_gets(params, "Predictor");
  207.         if (obj)
  208.                 state->predictor = fz_to_int(obj);
  209.  
  210.         if (state->predictor != 1 && state->predictor != 2 &&
  211.                 state->predictor != 10 && state->predictor != 11 &&
  212.                 state->predictor != 12 && state->predictor != 13 &&
  213.                 state->predictor != 14 && state->predictor != 15)
  214.         {
  215.                 fz_warn("invalid predictor: %d", state->predictor);
  216.                 state->predictor = 1;
  217.         }
  218.  
  219.         obj = fz_dict_gets(params, "Columns");
  220.         if (obj)
  221.                 state->columns = fz_to_int(obj);
  222.  
  223.         obj = fz_dict_gets(params, "Colors");
  224.         if (obj)
  225.                 state->colors = fz_to_int(obj);
  226.  
  227.         obj = fz_dict_gets(params, "BitsPerComponent");
  228.         if (obj)
  229.                 state->bpc = fz_to_int(obj);
  230.  
  231.         state->stride = (state->bpc * state->colors * state->columns + 7) / 8;
  232.         state->bpp = (state->bpc * state->colors + 7) / 8;
  233.  
  234.         state->in = fz_malloc(state->stride + 1);
  235.         state->out = fz_malloc(state->stride);
  236.         state->ref = fz_malloc(state->stride);
  237.         state->rp = state->out;
  238.         state->wp = state->out;
  239.  
  240.         memset(state->ref, 0, state->stride);
  241.  
  242.         return fz_new_stream(state, read_predict, close_predict);
  243. }
  244.