mirror of
				https://github.com/michaelrsweet/pdfio.git
				synced 2025-10-31 18:35:45 +01:00 
			
		
		
		
	Fix PNG predictor 12, 14, and 15.
This commit is contained in:
		| @@ -262,11 +262,11 @@ struct _pdfio_stream_s			// Stream | |||||||
| 	        *bufend;		// End of buffer | 	        *bufend;		// End of buffer | ||||||
|   z_stream	flate;			// Flate filter state |   z_stream	flate;			// Flate filter state | ||||||
|   _pdfio_predictor_t predictor;		// Predictor function, if any |   _pdfio_predictor_t predictor;		// Predictor function, if any | ||||||
|   int		pbcurrent;		// Current predictor line (0 or 1) |  | ||||||
|   size_t	pbpixel,		// Size of a pixel in bytes |   size_t	pbpixel,		// Size of a pixel in bytes | ||||||
| 		pbsize;			// Predictor buffer size, if any | 		pbsize;			// Predictor buffer size, if any | ||||||
|   unsigned char	cbuffer[4096],		// Compressed data buffer |   unsigned char	cbuffer[4096],		// Compressed data buffer | ||||||
| 		*pbuffers[2];		// Predictor buffers, as needed | 		*prbuffer,		// Raw buffer (previous line), as needed | ||||||
|  | 		*psbuffer;		// PNG filter buffer, as needed | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								pdfio-stream.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								pdfio-stream.c
									
									
									
									
									
								
							| @@ -119,8 +119,8 @@ pdfioStreamClose(pdfio_stream_t *st)	// I - Stream | |||||||
|  |  | ||||||
|   done: |   done: | ||||||
|  |  | ||||||
|   free(st->pbuffers[0]); |   free(st->prbuffer); | ||||||
|   free(st->pbuffers[1]); |   free(st->psbuffer); | ||||||
|   free(st); |   free(st); | ||||||
|  |  | ||||||
|   return (ret); |   return (ret); | ||||||
| @@ -216,11 +216,11 @@ _pdfioStreamCreate( | |||||||
|       if (predictor >= 10) |       if (predictor >= 10) | ||||||
| 	st->pbsize ++;		// Add PNG predictor byte | 	st->pbsize ++;		// Add PNG predictor byte | ||||||
|  |  | ||||||
|       if ((st->pbuffers[0] = calloc(1, st->pbsize)) == NULL || (st->pbuffers[1] = calloc(1, st->pbsize)) == NULL) |       if ((st->prbuffer = calloc(1, st->pbsize - 1)) == NULL || (st->psbuffer = calloc(1, st->pbsize)) == NULL) | ||||||
|       { |       { | ||||||
| 	_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Predictor buffers.", (unsigned long)st->pbsize); | 	_pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Predictor buffers.", (unsigned long)st->pbsize); | ||||||
| 	free(st->pbuffers[0]); | 	free(st->prbuffer); | ||||||
| 	free(st->pbuffers[1]); | 	free(st->psbuffer); | ||||||
| 	free(st); | 	free(st); | ||||||
| 	return (NULL); | 	return (NULL); | ||||||
|       } |       } | ||||||
| @@ -234,8 +234,8 @@ _pdfioStreamCreate( | |||||||
|     if (deflateInit(&(st->flate), 9) != Z_OK) |     if (deflateInit(&(st->flate), 9) != Z_OK) | ||||||
|     { |     { | ||||||
|       _pdfioFileError(st->pdf, "Unable to start Flate filter."); |       _pdfioFileError(st->pdf, "Unable to start Flate filter."); | ||||||
|       free(st->pbuffers[0]); |       free(st->prbuffer); | ||||||
|       free(st->pbuffers[1]); |       free(st->psbuffer); | ||||||
|       free(st); |       free(st); | ||||||
|       return (NULL); |       return (NULL); | ||||||
|     } |     } | ||||||
| @@ -429,11 +429,11 @@ _pdfioStreamOpen(pdfio_obj_t *obj,	// I - Object | |||||||
|         if (predictor >= 10) |         if (predictor >= 10) | ||||||
|           st->pbsize ++;		// Add PNG predictor byte |           st->pbsize ++;		// Add PNG predictor byte | ||||||
|  |  | ||||||
|         if ((st->pbuffers[0] = calloc(1, st->pbsize)) == NULL || (st->pbuffers[1] = calloc(1, st->pbsize)) == NULL) |         if ((st->prbuffer = calloc(1, st->pbsize - 1)) == NULL || (st->psbuffer = calloc(1, st->pbsize)) == NULL) | ||||||
|         { |         { | ||||||
|           _pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Predictor buffers.", (unsigned long)st->pbsize); |           _pdfioFileError(st->pdf, "Unable to allocate %lu bytes for Predictor buffers.", (unsigned long)st->pbsize); | ||||||
| 	  free(st->pbuffers[0]); | 	  free(st->prbuffer); | ||||||
| 	  free(st->pbuffers[1]); | 	  free(st->psbuffer); | ||||||
| 	  free(st); | 	  free(st); | ||||||
| 	  return (NULL); | 	  return (NULL); | ||||||
|         } |         } | ||||||
| @@ -447,8 +447,8 @@ _pdfioStreamOpen(pdfio_obj_t *obj,	// I - Object | |||||||
|       if (inflateInit(&(st->flate)) != Z_OK) |       if (inflateInit(&(st->flate)) != Z_OK) | ||||||
|       { |       { | ||||||
| 	_pdfioFileError(st->pdf, "Unable to start Flate filter."); | 	_pdfioFileError(st->pdf, "Unable to start Flate filter."); | ||||||
| 	free(st->pbuffers[0]); | 	free(st->prbuffer); | ||||||
| 	free(st->pbuffers[1]); | 	free(st->psbuffer); | ||||||
| 	free(st); | 	free(st); | ||||||
| 	return (NULL); | 	return (NULL); | ||||||
|       } |       } | ||||||
| @@ -649,8 +649,8 @@ pdfioStreamWrite( | |||||||
| 					// First column bytes remaining | 					// First column bytes remaining | ||||||
|   const unsigned char	*bufptr = (const unsigned char *)buffer; |   const unsigned char	*bufptr = (const unsigned char *)buffer; | ||||||
| 					// Pointer into buffer | 					// Pointer into buffer | ||||||
|   unsigned char		*thisptr,	// Current raw buffer |   unsigned char		*sptr,		// Pointer into sbuffer | ||||||
| 			*prevptr;	// Previous raw buffer | 			*pptr;		// Previous raw buffer | ||||||
|  |  | ||||||
|  |  | ||||||
|   PDFIO_DEBUG("pdfioStreamWrite(st=%p, buffer=%p, bytes=%lu)\n", st, buffer, (unsigned long)bytes); |   PDFIO_DEBUG("pdfioStreamWrite(st=%p, buffer=%p, bytes=%lu)\n", st, buffer, (unsigned long)bytes); | ||||||
| @@ -681,13 +681,13 @@ pdfioStreamWrite( | |||||||
|   { |   { | ||||||
|     // Store the PNG predictor in the first byte of the buffer... |     // Store the PNG predictor in the first byte of the buffer... | ||||||
|     if (st->predictor == _PDFIO_PREDICTOR_PNG_AUTO) |     if (st->predictor == _PDFIO_PREDICTOR_PNG_AUTO) | ||||||
|       st->pbuffers[st->pbcurrent][0] = 4; // Use Paeth predictor for auto... |       st->psbuffer[0] = 4;		// Use Paeth predictor for auto... | ||||||
|     else |     else | ||||||
|       st->pbuffers[st->pbcurrent][0] = (unsigned char)(st->predictor - 10); |       st->psbuffer[0] = (unsigned char)(st->predictor - 10); | ||||||
|  |  | ||||||
|     // Then process the current line using the specified PNG predictor... |     // Then process the current line using the specified PNG predictor... | ||||||
|     thisptr = st->pbuffers[st->pbcurrent] + 1; |     sptr = st->psbuffer + 1; | ||||||
|     prevptr = st->pbuffers[!st->pbcurrent] + 1; |     pptr = st->prbuffer; | ||||||
|  |  | ||||||
|     switch (st->predictor) |     switch (st->predictor) | ||||||
|     { |     { | ||||||
| @@ -697,57 +697,57 @@ pdfioStreamWrite( | |||||||
|  |  | ||||||
|       case _PDFIO_PREDICTOR_PNG_NONE : |       case _PDFIO_PREDICTOR_PNG_NONE : | ||||||
|           // No PNG predictor... |           // No PNG predictor... | ||||||
|           memcpy(thisptr, buffer, pbline); |           memcpy(sptr, buffer, pbline); | ||||||
|           break; |           break; | ||||||
|  |  | ||||||
|       case _PDFIO_PREDICTOR_PNG_SUB : |       case _PDFIO_PREDICTOR_PNG_SUB : | ||||||
| 	  // Encode the difference from the previous column | 	  // Encode the difference from the previous column | ||||||
| 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, thisptr ++) | 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, sptr ++) | ||||||
| 	  { | 	  { | ||||||
| 	    if (remaining < firstcol) | 	    if (remaining < firstcol) | ||||||
| 	      *thisptr = *bufptr - thisptr[-pbpixel]; | 	      *sptr = *bufptr - bufptr[-pbpixel]; | ||||||
| 	    else | 	    else | ||||||
| 	      *thisptr = *bufptr; | 	      *sptr = *bufptr; | ||||||
| 	  } | 	  } | ||||||
| 	  break; | 	  break; | ||||||
|  |  | ||||||
|       case _PDFIO_PREDICTOR_PNG_UP : |       case _PDFIO_PREDICTOR_PNG_UP : | ||||||
| 	  // Encode the difference from the previous line | 	  // Encode the difference from the previous line | ||||||
| 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, thisptr ++, prevptr ++) | 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, sptr ++, pptr ++) | ||||||
| 	  { | 	  { | ||||||
| 	    *thisptr = *bufptr - *prevptr; | 	    *sptr = *bufptr - *pptr; | ||||||
| 	  } | 	  } | ||||||
| 	  break; | 	  break; | ||||||
|  |  | ||||||
|       case _PDFIO_PREDICTOR_PNG_AVERAGE : |       case _PDFIO_PREDICTOR_PNG_AVERAGE : | ||||||
|           // Encode the difference with the average of the previous column and line |           // Encode the difference with the average of the previous column and line | ||||||
| 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, thisptr ++, prevptr ++) | 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, sptr ++, pptr ++) | ||||||
| 	  { | 	  { | ||||||
| 	    if (remaining < firstcol) | 	    if (remaining < firstcol) | ||||||
| 	      *thisptr = *bufptr - (thisptr[-pbpixel] + *prevptr) / 2; | 	      *sptr = *bufptr - (bufptr[-pbpixel] + *pptr) / 2; | ||||||
| 	    else | 	    else | ||||||
| 	      *thisptr = *bufptr - *prevptr / 2; | 	      *sptr = *bufptr - *pptr / 2; | ||||||
| 	  } | 	  } | ||||||
| 	  break; | 	  break; | ||||||
|  |  | ||||||
|       case _PDFIO_PREDICTOR_PNG_PAETH : |       case _PDFIO_PREDICTOR_PNG_PAETH : | ||||||
|       case _PDFIO_PREDICTOR_PNG_AUTO : |       case _PDFIO_PREDICTOR_PNG_AUTO : | ||||||
|           // Encode the difference with a linear transform function |           // Encode the difference with a linear transform function | ||||||
| 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, thisptr ++, prevptr ++) | 	  for (remaining = pbline; remaining > 0; remaining --, bufptr ++, sptr ++, pptr ++) | ||||||
| 	  { | 	  { | ||||||
| 	    if (remaining < firstcol) | 	    if (remaining < firstcol) | ||||||
| 	      *thisptr = *bufptr - stream_paeth(thisptr[-pbpixel], *prevptr, prevptr[-pbpixel]); | 	      *sptr = *bufptr - stream_paeth(bufptr[-pbpixel], *pptr, pptr[-pbpixel]); | ||||||
| 	    else | 	    else | ||||||
| 	      *thisptr = *bufptr - stream_paeth(0, *prevptr, 0); | 	      *sptr = *bufptr - stream_paeth(0, *pptr, 0); | ||||||
| 	  } | 	  } | ||||||
| 	  break; | 	  break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Write the encoded line... |     // Write the encoded line... | ||||||
|     if (!stream_write(st, st->pbuffers[st->pbcurrent], st->pbsize)) |     if (!stream_write(st, st->psbuffer, st->pbsize)) | ||||||
|       return (false); |       return (false); | ||||||
|  |  | ||||||
|     st->pbcurrent = !st->pbcurrent; |     memcpy(st->prbuffer, buffer, pbline); | ||||||
|     bytes -= pbline; |     bytes -= pbline; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -850,9 +850,9 @@ stream_read(pdfio_stream_t *st,		// I - Stream | |||||||
| 					// First column bytes remaining | 					// First column bytes remaining | ||||||
|       unsigned char	*bufptr = (unsigned char *)buffer, |       unsigned char	*bufptr = (unsigned char *)buffer, | ||||||
| 					// Pointer into buffer | 					// Pointer into buffer | ||||||
| 			*thisptr = st->pbuffers[st->pbcurrent] + 1, | 			*sptr = st->psbuffer + 1, | ||||||
| 					// Current (raw) line | 					// Current (raw) line | ||||||
| 			*prevptr = st->pbuffers[!st->pbcurrent] + 1; | 			*pptr = st->prbuffer; | ||||||
| 					// Previous (raw) line | 					// Previous (raw) line | ||||||
|  |  | ||||||
|       PDFIO_DEBUG("stream_read: PNG predictor.\n"); |       PDFIO_DEBUG("stream_read: PNG predictor.\n"); | ||||||
| @@ -864,7 +864,7 @@ stream_read(pdfio_stream_t *st,		// I - Stream | |||||||
|         return (-1); |         return (-1); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       st->flate.next_out  = (Bytef *)thisptr - 1; |       st->flate.next_out  = (Bytef *)sptr - 1; | ||||||
|       st->flate.avail_out = (uInt)st->pbsize; |       st->flate.avail_out = (uInt)st->pbsize; | ||||||
|  |  | ||||||
|       while (st->flate.avail_out > 0) |       while (st->flate.avail_out > 0) | ||||||
| @@ -898,44 +898,43 @@ stream_read(pdfio_stream_t *st,		// I - Stream | |||||||
|         return (-1);				// Early end of stream |         return (-1);				// Early end of stream | ||||||
|  |  | ||||||
|       // Apply predictor for this line |       // Apply predictor for this line | ||||||
|       PDFIO_DEBUG("stream_read: Line %02X %02X %02X %02X %02X.\n", thisptr[-1], thisptr[0], thisptr[0], thisptr[2], thisptr[3]); |       PDFIO_DEBUG("stream_read: Line %02X %02X %02X %02X %02X.\n", sptr[-1], sptr[0], sptr[0], sptr[2], sptr[3]); | ||||||
|  |  | ||||||
|       switch (thisptr[-1]) |       switch (sptr[-1]) | ||||||
|       { |       { | ||||||
|         case 0 : // None |         case 0 : // None | ||||||
|             memcpy(buffer, thisptr, remaining); |             memcpy(buffer, sptr, remaining); | ||||||
|             break; |             break; | ||||||
|         case 1 : // Sub |         case 1 : // Sub | ||||||
|             for (; remaining > firstcol; remaining --, thisptr ++) |             for (; remaining > firstcol; remaining --, sptr ++) | ||||||
|               *bufptr++ = *thisptr; |               *bufptr++ = *sptr; | ||||||
|             for (; remaining > 0; remaining --, thisptr ++) |             for (; remaining > 0; remaining --, sptr ++, bufptr ++) | ||||||
|               *bufptr++ = *thisptr + thisptr[-pbpixel]; |               *bufptr = *sptr + bufptr[-pbpixel]; | ||||||
|             break; |             break; | ||||||
|         case 2 : // Up |         case 2 : // Up | ||||||
|             for (; remaining > 0; remaining --, thisptr ++, prevptr ++) |             for (; remaining > 0; remaining --, sptr ++, pptr ++) | ||||||
|               *bufptr++ = *thisptr + *prevptr; |               *bufptr++ = *sptr + *pptr; | ||||||
|             break; |             break; | ||||||
|         case 3 : // Average |         case 3 : // Average | ||||||
| 	    for (; remaining > firstcol; remaining --, thisptr ++, prevptr ++) | 	    for (; remaining > firstcol; remaining --, sptr ++, pptr ++) | ||||||
| 	      *bufptr++ = *thisptr + *prevptr / 2; | 	      *bufptr++ = *sptr + *pptr / 2; | ||||||
| 	    for (; remaining > 0; remaining --, thisptr ++, prevptr ++) | 	    for (; remaining > 0; remaining --, sptr ++, pptr ++, bufptr ++) | ||||||
| 	      *bufptr++ = *thisptr + (thisptr[-pbpixel] + *prevptr) / 2; | 	      *bufptr = *sptr + (bufptr[-pbpixel] + *pptr) / 2; | ||||||
|             break; |             break; | ||||||
|         case 4 : // Paeth |         case 4 : // Paeth | ||||||
|             for (; remaining > firstcol; remaining --, thisptr ++, prevptr ++) |             for (; remaining > firstcol; remaining --, sptr ++, pptr ++) | ||||||
|               *bufptr++ = *thisptr + stream_paeth(0, *prevptr, 0); |               *bufptr++ = *sptr + stream_paeth(0, *pptr, 0); | ||||||
|             for (; remaining > 0; remaining --, thisptr ++, prevptr ++) |             for (; remaining > 0; remaining --, sptr ++, pptr ++, bufptr ++) | ||||||
|               *bufptr++ = *thisptr + stream_paeth(thisptr[-pbpixel], *prevptr, prevptr[-pbpixel]); |               *bufptr = *sptr + stream_paeth(bufptr[-pbpixel], *pptr, pptr[-pbpixel]); | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|         default : |         default : | ||||||
|             _pdfioFileError(st->pdf, "Bad PNG filter %d in data stream.", thisptr[-1]); |             _pdfioFileError(st->pdf, "Bad PNG filter %d in data stream.", sptr[-1]); | ||||||
|             return (-1); |             return (-1); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       // Copy the computed line and swap buffers... |       // Copy the computed line and swap buffers... | ||||||
|       memcpy(st->pbuffers[st->pbcurrent] + 1, buffer, st->pbsize - 1); |       memcpy(st->prbuffer, buffer, st->pbsize - 1); | ||||||
|       st->pbcurrent = !st->pbcurrent; |  | ||||||
|  |  | ||||||
|       // Return the number of bytes we copied for this line... |       // Return the number of bytes we copied for this line... | ||||||
|       return ((ssize_t)(st->pbsize - 1)); |       return ((ssize_t)(st->pbsize - 1)); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user