-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello,

I made another patch version for the prediction filter:

I have done some more bug fixes:
* PNG predictor filters processed streams byte
after byte. This is wrong, because the corresponding bytes per pixel
have to be processed (1st byte of pixel x with 1st byte of pixel x+1,
2nd ... with 2nd ...,  and so on). I introduced a new state variable
"bpp" (bits per pixel) and corrected all PNG predictors like they are
described in PNG RFC-2083.
* In the decoder it can happen that there is still something in the
input buffer but output is full. I think what I have overseen this
because it only happens if multiple filters are connected (I have not
tested predictor filter with another filter before). So I added the
same main loop condition as in the encoder:
+  while (!pdf_buffer_eob_p (in) && !pdf_buffer_full_p (out));
+
+  if (pdf_buffer_full_p (out) && !pdf_buffer_eob_p (in))
+    return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
* It was possible to jump from PNG to TIFF prediction in the same
image decoding call. I caught this and decoding now fails with an
error message.

And some refactoring:
* changed all (pdf_char_t*)  to (pdf_uchar_t*)
* added a paeth predictor function, to beautify enc/decode_row_paeth

I have tested these changes with following pictures (PDFs produced by
pdflatex and tested against mupdfs pdfshow):
* 8x8 Pixel, 1 color/component,   4 bits per component
* 8x8 Pixel, 1 colors/components, 8 bits per component
* 8x8 Pixel, 3 colors/components, 24 bits per component
* 32x32 Pixel, 3 colors/components, 24 bits per component
* 1555x633 Pixel, 3 colors/components, 24 bits per component
(all encoded with gimp, which uses optimum prediction and thus uses
different predictors; in fact all but row_up, which is the only one I
didn't change because it works already on corresponding pixels)

Please merge the patch.

Regards,
Georg

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk7FVKYACgkQ5sLITM1qIaJ3jwCgo351nvJaWEvtKuC782bHrEzq
BXAAn3R2b1Namk7xYcbUzn/MAh50wZbi
=EfUg
-----END PGP SIGNATURE-----
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: georg.gottleu...@uni-ulm.de-20111117183509-\
#   11j9s27lbhng6ba2
# target_branch: bzr://bzr.savannah.gnu.org/pdf/libgnupdf/trunk/
# testament_sha1: 3daa95922e536e842c729f3acec153b66eba5172
# timestamp: 2011-11-17 19:36:18 +0100
# base_revision_id: jema...@gnu.org-20111011211752-3goterimb0gpbqq7
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog	2011-10-11 21:17:52 +0000
+++ ChangeLog	2011-11-17 18:35:09 +0000
@@ -1,3 +1,10 @@
+2011-11-17  Georg Gottleuber <georg.gottleu...@uni-ulm.de>
+
+	base,stm: Bugfixes and refactored prediction filter.
+	* src/base/pdf-stm-f-pred.c: predictor type inside PNG with offset,
+	PNG predictor functions now process the corresponding bytes; refactored
+	paeth predictor function
+
 2011-10-11  Jose E. Marchesi  <jema...@gnu.org>
 
 	prmgt: converters to html reverted to a previous revision.

=== modified file 'src/base/pdf-stm-f-pred.c'
--- src/base/pdf-stm-f-pred.c	2011-07-30 21:08:22 +0000
+++ src/base/pdf-stm-f-pred.c	2011-11-17 18:35:09 +0000
@@ -107,7 +107,10 @@
   pdf_size_t columns;             /* The number of samples in each
                                      row. Default value: 1 */
 
-  pdf_size_t scanline_len;        /* will be calculated from params */
+  /* will be calculated from params */
+  pdf_size_t scanline_len;        /* length of one image row in bytes */ 
+
+  pdf_size_t bpp;                 /* bits per pixel in bytes */
 
   /* previous and current buffers for scanlines (rows) 
      encoder uses prev_row_buf for last input row to the filter
@@ -148,7 +151,7 @@
  */
 typedef struct pred_bit_ptr_s 
 {
-  pdf_char_t* ptr;
+  pdf_uchar_t* ptr;
   int offset;
   int mask;
   int block_size;
@@ -156,7 +159,7 @@
 
 static void
 pred_bit_ptr_init (pred_bit_ptr_t* bp, 
-              pdf_char_t* ptr, 
+              pdf_uchar_t* ptr, 
               int block_size)
 {
   bp->ptr = ptr;
@@ -190,7 +193,7 @@
                  pdf_error_t      **error)
 {
   pdf_size_t actual_len;
-  pdf_stm_f_pred_t* filter_state;
+  pdf_stm_f_pred_t* fstate;
 
   /* Predictor decides if we need more paramters; so check it first */
   if (!params || !pdf_hash_key_p (params, PRED_PARAM_PREDICTOR))
@@ -226,9 +229,9 @@
         }
     }
 
-  /* Create the private filter_state storage */
-  filter_state = pdf_alloc (sizeof (struct pdf_stm_f_pred_s));
-  if (!filter_state)
+  /* Create the private filter state storage */
+  fstate = pdf_alloc (sizeof (struct pdf_stm_f_pred_s));
+  if (!fstate)
     {
       pdf_set_error (error,
                      PDF_EDOMAIN_BASE_STM,
@@ -239,25 +242,25 @@
       return PDF_FALSE;
     }
 
-  filter_state->predictor = pdf_hash_get_size (params, PRED_PARAM_PREDICTOR);
-  filter_state->colors = pdf_hash_get_size (params, PRED_PARAM_COLORS);
-  filter_state->bits_per_component = pdf_hash_get_size (params, PRED_PARAM_BPC);
-  filter_state->columns = pdf_hash_get_size (params, PRED_PARAM_COLUMNS);
+  fstate->predictor = pdf_hash_get_size (params, PRED_PARAM_PREDICTOR);
+  fstate->colors = pdf_hash_get_size (params, PRED_PARAM_COLORS);
+  fstate->bits_per_component = pdf_hash_get_size (params, PRED_PARAM_BPC);
+  fstate->columns = pdf_hash_get_size (params, PRED_PARAM_COLUMNS);
 
   /* as no parameters for predictor 1 (NO_PREDICTION) is needed */
-  if (filter_state->predictor == PDF_STM_F_PREDENC_NO_PREDICTION)
+  if (fstate->predictor == PDF_STM_F_PREDENC_NO_PREDICTION)
     {
       /* set default values */
-      filter_state->colors = 1;
-      filter_state->bits_per_component = 1;
-      filter_state->columns = 1;
+      fstate->colors = 1;
+      fstate->bits_per_component = 1;
+      fstate->columns = 1;
     }
   /* else wise check for bad parameter values */
   else
     {
-      if (filter_state->colors < 1
-          || filter_state->columns < 1
-          || filter_state->bits_per_component < 1)
+      if (fstate->colors < 1
+          || fstate->columns < 1
+          || fstate->bits_per_component < 1)
         {
           pdf_set_error (error,
                          PDF_EDOMAIN_BASE_STM,
@@ -265,11 +268,11 @@
                          "cannot initialize predictor encoder/decoder: "
                          "bad parameter values ('"PRED_PARAM_COLORS"': %s, "
                          "'"PRED_PARAM_BPC"': %s, '"PRED_PARAM_COLUMNS"': %s)",
-                         ((filter_state->colors < 1) ?
-                          "bad" : "ok"),
-                         ((filter_state->bits_per_component < 1) ?
-                          "bad" : "ok"),
-                         ((filter_state->columns < 1) ?
+                         ((fstate->colors < 1) ?
+                          "bad" : "ok"),
+                         ((fstate->bits_per_component < 1) ?
+                          "bad" : "ok"),
+                         ((fstate->columns < 1) ?
                           "bad" : "ok"));
           return PDF_FALSE;
         }
@@ -278,89 +281,96 @@
   /* We need the number of full bytes that each row has. As defined in the
    * PNG standard we can assume that if greater than 8 the bits per component
    * is multiplier of eight. */
-  actual_len = filter_state->columns * filter_state->colors * 
-               filter_state->bits_per_component;
-  filter_state->scanline_len = (actual_len >> 3) + (actual_len & 7); 
+  actual_len = fstate->columns * fstate->colors * 
+               fstate->bits_per_component;
+  fstate->scanline_len = (actual_len >> 3) + (actual_len & 7); 
+
+  fstate->bpp = (fstate->colors * fstate->bits_per_component + 7) / 8;
 
   /* one extra byte for PNG predictor */
-  filter_state->prev_row_buf = pdf_buffer_new (filter_state->scanline_len + 1,
+  fstate->prev_row_buf = pdf_buffer_new (fstate->scanline_len + 1,
                                                error);
-  if (!(filter_state->prev_row_buf))
+  if (!(fstate->prev_row_buf))
     {
       pdf_set_error (error,
                      PDF_EDOMAIN_BASE_STM,
                      PDF_ENOMEM,
                      "cannot create predictor encoder/decoder internal buffer: "
                      "couldn't allocate %lu bytes",
-                     (unsigned long) filter_state->scanline_len);
+                     (unsigned long) fstate->scanline_len);
       return PDF_FALSE;
     }
 
   /* hint for further optimizing (if necessary): if scanlines are smaller than 
      in and out buffers, curr_row_buf and out_row_buf are not needed and two 
      memcpys per scanline can be omitted */
-  filter_state->curr_row_buf = pdf_buffer_new (filter_state->scanline_len + 1, 
+  fstate->curr_row_buf = pdf_buffer_new (fstate->scanline_len + 1, 
                                                error);
-  if (!(filter_state->curr_row_buf))
+  if (!(fstate->curr_row_buf))
     {
       pdf_set_error (error,
                      PDF_EDOMAIN_BASE_STM,
                      PDF_ENOMEM,
                      "cannot create predictor encoder/decoder internal buffer: "
                      "couldn't allocate %lu bytes",
-                     (unsigned long) filter_state->scanline_len);
+                     (unsigned long) fstate->scanline_len);
       return PDF_FALSE;
     }
-  filter_state->out_row_buf = pdf_buffer_new (filter_state->scanline_len + 1, 
+  fstate->out_row_buf = pdf_buffer_new (fstate->scanline_len + 1, 
                                               error);
-  if (!(filter_state->out_row_buf))
+  if (!(fstate->out_row_buf))
     {
       pdf_set_error (error,
                      PDF_EDOMAIN_BASE_STM,
                      PDF_ENOMEM,
                      "cannot create predictor encoder/decoder internal buffer: "
                      "couldn't allocate %lu bytes",
-                     (unsigned long) filter_state->scanline_len + 1);
+                     (unsigned long) fstate->scanline_len + 1);
       return PDF_FALSE;
     }
 
-  *state = filter_state;
+  *state = fstate;
   return PDF_TRUE;
 }
 
-
 static void
-encode_row_none(pdf_char_t* cur, 
-                pdf_char_t* prev, 
-                pdf_char_t* out,
+encode_row_none(pdf_uchar_t* cur, 
+                pdf_uchar_t* prev, 
+                pdf_uchar_t* out,
                 pdf_stm_f_pred_t* state) 
 {
   memcpy(out, cur, state->scanline_len);
 }
 
 static void
-encode_row_sub(pdf_char_t* cur, 
-               pdf_char_t* prev, 
-               pdf_char_t* out,
+encode_row_sub(pdf_uchar_t* cur, 
+               pdf_uchar_t* prev, 
+               pdf_uchar_t* out,
                pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
-  *out++ = *cur++;
-  for (i = 1; i < state->scanline_len; i++) 
-    {
-      *out++ = *cur - *(cur-1);
+
+  for( i = 0 ; i < state->bpp ; i++ )
+    {
+      *out++ = *cur++;
+    }
+
+  for (i = 0; i < state->scanline_len - state->bpp; i++)
+    {
+      *out++ = *cur - *(cur - state->bpp);
       cur++;
     }
 }
 
 static void
-encode_row_up(pdf_char_t* cur, 
-              pdf_char_t* prev, 
-              pdf_char_t* out,
+encode_row_up(pdf_uchar_t* cur, 
+              pdf_uchar_t* prev, 
+              pdf_uchar_t* out,
               pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
-  if (prev != NULL) 
+
+  if (prev != NULL)
     {
       for (i = 0; i < state->scanline_len; i++)
         {
@@ -374,96 +384,104 @@
 }
 
 static void
-encode_row_average(pdf_char_t* cur,
-                   pdf_char_t* prev,
-                   pdf_char_t* out,
+encode_row_average(pdf_uchar_t* cur,
+                   pdf_uchar_t* prev,
+                   pdf_uchar_t* out,
                    pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
+  pdf_size_t bpp = state->bpp;
+
   if (prev != NULL)
     {
-      *out++ = *cur++ - (*prev++ >> 1);
+      for( i = 0 ; i < bpp ; i++ )
+        {
+          *out++ = *cur++ - (*prev++ >> 1);
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *out++ = *cur - (pdf_char_t)(((int)*(cur-1) + (int)*prev) >> 1);
+          *out++ = *cur - (pdf_uchar_t) (((int) cur[-bpp] + (int) *prev) >> 1);
           cur++;
           prev++;
         }
-    } 
-  else 
+    }
+  else
     {
-      *out++ = *cur++;
+      for( i = 0 ; i < bpp ; i++ )
+        {
+          *out++ = *cur++;
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *out++ = *cur - (*(cur-1) >> 1);
+          *out++ = *cur - (cur[-bpp] >> 1);
           cur++;
         }
     }
 }
 
+static int
+paeth_predictor(int a, int b, int c)
+{
+    int p = a + b - c;
+    int pa = abs(p - a);
+    int pb = abs(p - b);
+    int pc = abs(p - c);
+
+    if (pa <= pb && pa <= pc)
+      return a;
+    if (pb <= pc)
+      return b;
+
+    return c;
+}
+
+
 static void
-encode_row_paeth (pdf_char_t* cur, 
-                  pdf_char_t* prev, 
-                  pdf_char_t* out,
+encode_row_paeth (pdf_uchar_t* cur, 
+                  pdf_uchar_t* prev, 
+                  pdf_uchar_t* out,
                   pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
-  int p;
-  int pa;
-  int pb;
-  int pc;
+  pdf_size_t bpp = state->bpp;
 
-  if (prev != NULL) 
+  if (prev != NULL)
     {
-      *out++ = *cur++ - *prev++; 
-
-      for (i = 0; i < state->scanline_len; i++) 
-        {
-          p = *(cur-1) + *(prev) - *(prev-1);
-          pa = abs(p - *(cur-1));
-          pb = abs(p - *(prev));
-          pc = abs(p - *(prev-1));
-
-          if (pa <= pb && pa <= pc) 
-            {
-              *out++ = *cur - *(cur-1);
-            }
-          else 
-            {
-              if (pb <= pc) 
-                {
-                  *out++ = *cur - *(prev);
-                }
-              else 
-                { 
-                  *out++ = *cur - *(prev-1);
-                }
-            }
-
-          cur++;
+      for (i = 0; i < bpp; i++)
+        {
+          *out++ = *cur++ - *prev++;
+        }
+
+      for (i = 0; i < state->scanline_len - bpp; i++)
+        {
+          *out++ = *cur - paeth_predictor (cur[-bpp], prev[0], prev[-bpp]);
           prev++;
+          cur++;
         }
-    } 
-  else 
+    }
+  else
     {
-      *out++ = *cur++;
+      for (i = 0; i < bpp; i++)
+        {
+          *out++ = *cur++;
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *out++ = *cur - *(cur-1);
+          *out++ = *cur - cur[-bpp];
           cur++;
         }
     }
 }
 
 static void
-encode_row_sub_color16 (pdf_char_t* cur, 
-                        pdf_char_t* prev, 
-                        pdf_char_t* out,
+encode_row_sub_color16 (pdf_uchar_t* cur,
+                        pdf_uchar_t* prev,
+                        pdf_uchar_t* out,
                         pdf_stm_f_pred_t* state)
-{  
+{
   pdf_size_t i;
   pdf_size_t j;
 
@@ -490,16 +508,16 @@
 }
 
 static void
-encode_row_sub_color8 (pdf_char_t* cur, 
-                       pdf_char_t* prev, 
-                       pdf_char_t* out,
+encode_row_sub_color8 (pdf_uchar_t* cur,
+                       pdf_uchar_t* prev,
+                       pdf_uchar_t* out,
                        pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
   pdf_size_t j;
-  pdf_char_t *this;
-  pdf_char_t *next;
-  pdf_char_t *sout;
+  pdf_uchar_t *this;
+  pdf_uchar_t *next;
+  pdf_uchar_t *sout;
 
   this = cur; 
   next = cur;
@@ -519,9 +537,9 @@
 }
 
 static void
-encode_row_sub_colorl8 (pdf_char_t *cur, 
-                        pdf_char_t *prev, 
-                        pdf_char_t *out,
+encode_row_sub_colorl8 (pdf_uchar_t *cur,
+                        pdf_uchar_t *prev,
+                        pdf_uchar_t *out,
                         pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
@@ -529,11 +547,11 @@
   pred_bit_ptr_t this;
   pred_bit_ptr_t next;
   pred_bit_ptr_t sout;
-  
+
   pred_bit_ptr_init (&this, cur, state->bits_per_component);
   pred_bit_ptr_init (&next, cur, state->bits_per_component);
   pred_bit_ptr_init (&sout, out, state->bits_per_component);
-  
+
   for (j = 0; j < state->colors; j++) 
     {
       PRED_BIT_PTR_SET(sout, PRED_BIT_PTR_GET(next));
@@ -554,9 +572,9 @@
 }
 
 static int
-encode_row (pdf_char_t *cur,
-            pdf_char_t *prev,
-            pdf_char_t *out,
+encode_row (pdf_uchar_t *cur,
+            pdf_uchar_t *prev,
+            pdf_uchar_t *out,
             pdf_stm_f_pred_t* state,
             pdf_error_t **error)
 {
@@ -639,35 +657,38 @@
 }
 
 static void
-decode_row_none (pdf_char_t* in, 
-                 pdf_char_t* cur, 
-                 pdf_char_t* prev,
+decode_row_none (pdf_uchar_t* in, 
+                 pdf_uchar_t* cur, 
+                 pdf_uchar_t* prev,
                  pdf_stm_f_pred_t* state)
 {
   memcpy (cur, in, state->scanline_len);
 }
 
 static void
-decode_row_sub (pdf_char_t* in, 
-                pdf_char_t* cur, 
-                pdf_char_t* prev,
+decode_row_sub (pdf_uchar_t* in,
+                pdf_uchar_t* cur,
+                pdf_uchar_t* prev,
                 pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
 
-  *cur++ = *in++;
+  for( i = 0 ; i < state->bpp ; i++)
+  {
+      *cur++ = *in++;
+  }
 
-  for (i = 1; i < state->scanline_len; i++) 
+  for (i = 0; i < state->scanline_len - state->bpp; i++)
     {
-      *cur = *in++ + *(cur-1);
-      cur++; 
+      *cur = *in++ + cur[-state->bpp];
+      cur++;
     }
 }
 
 static void
-decode_row_up (pdf_char_t* in, 
-               pdf_char_t* cur, 
-               pdf_char_t* prev,
+decode_row_up (pdf_uchar_t* in, 
+               pdf_uchar_t* cur, 
+               pdf_uchar_t* prev,
                pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
@@ -687,94 +708,84 @@
 }
 
 static void
-decode_row_average (pdf_char_t* in, 
-                    pdf_char_t* cur, 
-                    pdf_char_t* prev,
+decode_row_average (pdf_uchar_t* in, 
+                    pdf_uchar_t* cur, 
+                    pdf_uchar_t* prev,
                     pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
+  pdf_size_t bpp = state->bpp;
 
   if (prev != NULL) 
     {
-      *cur++ = *in++ + (*prev++ >> 1);
+      for (i = 0; i < bpp; i++)
+        {
+          *cur++ = *in++ + (*prev++ >> 1);
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *cur = *in++ + (pdf_char_t)(((int)*(cur-1) + (int)*prev) >> 1);
+          *cur = *in++ + (pdf_uchar_t) (((int) cur[-bpp] + (int) *prev) >> 1);
           cur++;
           prev++;
         }
-    } 
-  else 
+    }
+  else
     {
-      *cur++ = *in++;
+      for (i = 0; i < bpp; i++)
+        {
+          *cur++ = *in++;
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *cur = *in++ + (*(cur-1) >> 1);
+          *cur = *in++ + (cur[-bpp] >> 1);
           cur++;
         }
     }
 }
 
 static void
-decode_row_paeth (pdf_char_t* in, 
-                  pdf_char_t* cur, 
-                  pdf_char_t* prev,
+decode_row_paeth (pdf_uchar_t* in,
+                  pdf_uchar_t* cur,
+                  pdf_uchar_t* prev,
                   pdf_stm_f_pred_t* state)
 {
-  int p;
-  int pa;
-  int pb;
-  int pc;
   pdf_size_t i;
+  pdf_size_t bpp = state->bpp;
 
-  if (prev != NULL) 
+  if (prev != NULL)
     {
-      *cur++ = *in++ + *prev++; 
-
-      for (i = 0; i < state->scanline_len; i++) 
-        {
-          p = *(cur-1) + *(prev) - *(prev-1);
-          pa = abs(p - *(cur-1));
-          pb = abs(p - *(prev));
-          pc = abs(p - *(prev-1));
-
-          if (pa <= pb && pa <= pc) 
-            {
-              *cur = *in + *(cur-1);
-            }
-          else 
-            {
-              if (pb <= pc) 
-                {
-                  *cur = *in + *(prev);
-                }
-              else 
-                {
-                  *cur = *in + *(prev-1);
-                }
-            }
-
-          in++;
+      for (i = 0; i < bpp; i++)
+        {
+          *cur = *in++ + paeth_predictor (0, *prev++, 0);
+          cur++;
+        }
+
+      for (i = 0; i < state->scanline_len - bpp; i++)
+        {
+          *cur = *in++ + paeth_predictor (cur[-bpp], prev[0], prev[-bpp]);
           prev++;
           cur++;
         }
-    } 
-  else 
+    }
+  else
     {
-      *cur++ = *in++;
+      for (i = 0; i < bpp; i++)
+        {
+          *cur++ = *in++;
+        }
 
-      for (i = 1; i < state->scanline_len; i++) 
+      for (i = 0; i < state->scanline_len - bpp; i++)
         {
-          *cur = *in++ + *(cur-1);
-          cur++; 
+          *cur = *in++ + cur[-bpp];
+          cur++;
         }
     }
 }
 
 static void
-decode_row_sub_color16 (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev,
+decode_row_sub_color16 (pdf_uchar_t* in, pdf_uchar_t* cur, pdf_uchar_t* prev,
                         pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
@@ -801,16 +812,16 @@
 }
 
 static void
-decode_row_sub_color8  (pdf_char_t* in, 
-                        pdf_char_t* cur, 
-                        pdf_char_t* prev,
+decode_row_sub_color8  (pdf_uchar_t* in, 
+                        pdf_uchar_t* cur, 
+                        pdf_uchar_t* prev,
                         pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
   pdf_size_t j;
-  pdf_char_t *this;
-  pdf_char_t *next;
-  pdf_char_t *sin;
+  pdf_uchar_t *this;
+  pdf_uchar_t *next;
+  pdf_uchar_t *sin;
 
   this = cur;
   next = cur;
@@ -832,9 +843,9 @@
 
 
 static void
-decode_row_sub_colorl8 (pdf_char_t* in, 
-                        pdf_char_t* cur, 
-                        pdf_char_t* prev,
+decode_row_sub_colorl8 (pdf_uchar_t* in, 
+                        pdf_uchar_t* cur, 
+                        pdf_uchar_t* prev,
                         pdf_stm_f_pred_t* state)
 {
   pdf_size_t i;
@@ -867,9 +878,9 @@
 }
 
 static int
-decode_row (pdf_char_t* in,
-            pdf_char_t* cur,
-            pdf_char_t* prev,
+decode_row (pdf_uchar_t* in,
+            pdf_uchar_t* cur,
+            pdf_uchar_t* prev,
             pdf_stm_f_pred_t* state,
             pdf_error_t **error)
 {
@@ -964,11 +975,12 @@
   pdf_bool_t is_png_predictor;
   is_png_predictor = PNG_ENC_PREDICTOR_P(fs->predictor);
 
-  pdf_char_t *curr_row;
-  pdf_char_t *prev_row = NULL;
-  pdf_char_t *out_buf;
+  pdf_uchar_t *curr_row;
+  pdf_uchar_t *prev_row = NULL;
+  pdf_uchar_t *out_buf;
 
   pdf_size_t in_size;
+  pdf_uchar_t png_pred_type;
   PDF_ASSERT (in->wp >= in->rp);
 
   size_t tocpy;
@@ -1008,17 +1020,20 @@
             {
               /* write/read PNG predictor at first byte of a row */
               if (is_png_predictor)
-                fs->out_row_buf->data[fs->out_row_buf->wp++] = fs->predictor;
+                {
+                  /* predictor numbers inside PNG start with 0 (see RFC-2083) */
+                  png_pred_type = fs->predictor - PDF_STM_F_PREDDEC_PNG_NONE;
+                  fs->out_row_buf->data[fs->out_row_buf->wp++] = png_pred_type;
+                }
 
-              curr_row = (pdf_char_t*) fs->curr_row_buf->data;
-              out_buf  = (pdf_char_t*) fs->out_row_buf->data 
-                                       + fs->out_row_buf->wp;
+              curr_row = fs->curr_row_buf->data;
+              out_buf  = fs->out_row_buf->data + fs->out_row_buf->wp;
 
               /* at first row encode_row expects prev_row to be NULL */
               if (fs->prev_row_buf->wp == 0)
                 prev_row = NULL;
               else
-                prev_row = (pdf_char_t*) fs->prev_row_buf->data;
+                prev_row = fs->prev_row_buf->data;
 
               if (encode_row (curr_row, prev_row, out_buf, fs, error) 
                   == PDF_ERROR)
@@ -1096,9 +1111,9 @@
   pdf_bool_t is_png_predictor;
   is_png_predictor = PNG_DEC_PREDICTOR_P(fs->predictor);
 
-  pdf_char_t *curr_row;
-  pdf_char_t *prev_row = NULL;
-  pdf_char_t *out_buf;
+  pdf_uchar_t *curr_row;
+  pdf_uchar_t *prev_row = NULL;
+  pdf_uchar_t *out_buf;
 
   pdf_size_t in_size;
   PDF_ASSERT (in->wp >= in->rp);
@@ -1143,18 +1158,34 @@
             {
               /* write/read PNG predictor at first byte of a row */
               if (is_png_predictor)
-                fs->predictor = fs->curr_row_buf->data[fs->curr_row_buf->rp++];
-
-              curr_row = (pdf_char_t*) fs->curr_row_buf->data 
-                                       + fs->curr_row_buf->rp;
-              out_buf  = (pdf_char_t*) fs->out_row_buf->data 
-                                       + fs->out_row_buf->wp;
+                {
+                  fs->predictor = fs->curr_row_buf->data[fs->curr_row_buf->rp];
+                  fs->curr_row_buf->rp++;
+                  /* predictor numbers inside PNG start with 0 (see RFC-2083) */
+                  fs->predictor += PDF_STM_F_PREDDEC_PNG_NONE;
+
+                  /* this prevents jumping from PNG prediction to TIFF
+                   * in the same image */
+                  if (fs->predictor < PDF_STM_F_PREDDEC_PNG_NONE)
+                    {
+                      pdf_set_error (error,
+                             PDF_EDOMAIN_BASE_STM,
+                             PDF_EBADDATA,
+                             "bad predictor value for decoding a PNG image: "
+                             "expected 10, 11, 12, 13, 14 got %d",
+                             (fs->predictor));
+                      return PDF_STM_FILTER_APPLY_STATUS_ERROR;
+                    }
+                }
+
+              curr_row = fs->curr_row_buf->data + fs->curr_row_buf->rp;
+              out_buf  = fs->out_row_buf->data + fs->out_row_buf->wp;
 
               /* at first row decode_row expects prev_row to be NULL */
               if (fs->prev_row_buf->wp == 0)
                 prev_row = NULL;
               else
-                prev_row = (pdf_char_t*) fs->prev_row_buf->data;
+                prev_row = fs->prev_row_buf->data;
 
               if (decode_row (curr_row, out_buf, prev_row, fs, error)
                   == PDF_ERROR)
@@ -1189,7 +1220,10 @@
           pdf_buffer_rewind (fs->out_row_buf);
         }
     }
-  while (!pdf_buffer_eob_p (in));
+  while (!pdf_buffer_eob_p (in) && !pdf_buffer_full_p (out));
+
+  if (pdf_buffer_full_p (out) && !pdf_buffer_eob_p (in))
+    return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT;
 
   /* final call of this filter; empty out_row_buf */
   if (finish && in->wp - in->rp < 1)

# Begin bundle
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
P/0+YrYWUcKrVZh/8XckU4UJD7dPB/A=

Reply via email to