mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2024-12-27 05:48:20 +01:00
Fix PNG predictor 12, 14, and 15.
This commit is contained in:
parent
2856b440d1
commit
3efb4f800b
@ -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));
|
||||||
|
Loading…
Reference in New Issue
Block a user