From c61d6ad686c2845583eb45f9424622635e201188 Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Thu, 6 May 2021 16:07:58 -0400 Subject: [PATCH] Save work on streams. --- pdfio-object.c | 4 +- pdfio-private.h | 2 + pdfio-stream.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ pdfio.h | 13 +++++- 4 files changed, 120 insertions(+), 3 deletions(-) diff --git a/pdfio-object.c b/pdfio-object.c index fe972bb..6a7c834 100644 --- a/pdfio-object.c +++ b/pdfio-object.c @@ -197,10 +197,12 @@ _pdfioObjLoad(pdfio_obj_t *obj) // I - Object // pdfio_stream_t * // O - Stream or `NULL` on error -pdfioObjOpenStream(pdfio_obj_t *obj) // I - Object +pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object + bool decode) // I - Decode/decompress data? { // TODO: Implement me (void)obj; + (void)decode; return (NULL); } diff --git a/pdfio-private.h b/pdfio-private.h index a30de60..e7f79c9 100644 --- a/pdfio-private.h +++ b/pdfio-private.h @@ -224,7 +224,9 @@ extern bool _pdfioFileWrite(pdfio_file_t *pdf, const void *buffer, size_t bytes extern void _pdfioObjDelete(pdfio_obj_t *obj) PDFIO_INTERNAL; extern bool _pdfioObjLoad(pdfio_obj_t *obj) PDFIO_INTERNAL; +extern pdfio_stream_t *_pdfioStreamCreate(pdfio_obj_t *obj, pdfio_filter_t compression) PDFIO_INTERNAL; extern void _pdfioStreamDelete(pdfio_stream_t *st) PDFIO_INTERNAL; +extern pdfio_stream_t *_pdfioStreamOpen(pdfio_obj_t *obj, bool decode) PDFIO_INTERNAL; extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) PDFIO_INTERNAL; diff --git a/pdfio-stream.c b/pdfio-stream.c index 1daf28f..0f0715d 100644 --- a/pdfio-stream.c +++ b/pdfio-stream.c @@ -27,6 +27,25 @@ pdfioStreamClose(pdfio_stream_t *st) // I - Stream } +// +// '_pdfioStreamCreate()' - Create a stream for writing. +// +// Note: pdfioObjCreateStream handles writing the object and its dictionary. +// + +pdfio_stream_t * // O - Stream or `NULL` on error +_pdfioStreamCreate( + pdfio_obj_t *obj, // I - Object + pdfio_filter_t compression) // I - Compression to apply +{ + // TODO: Implement me + (void)obj; + (void)compression; + + return (NULL); +} + + // // 'pdfioStreamConsume()' - Consume bytes from the stream. // @@ -76,6 +95,91 @@ pdfioStreamGetToken( } +// +// '_pdfioStreamOpen()' - Create a stream for reading. +// +// Note: pdfioObjOpenStream handles loading the object's dictionary and +// getting the start of the stream data. +// + +pdfio_stream_t * // O - Stream or `NULL` on error +_pdfioStreamOpen(pdfio_obj_t *obj, // I - Object + bool decode) // I - Decode/decompress the stream? +{ + pdfio_stream_t *st; // Stream + + + // Allocate a new stream object... + if ((st = (pdfio_stream_t *)calloc(1, sizeof(pdfio_stream_t))) == NULL) + { + _pdfioFileError(obj->pdf, "Unable to allocate memory for a stream."); + return (NULL); + } + + st->pdf = obj->pdf; + st->obj = obj; + + _pdfioFileSeek(st->pdf, obj->stream_offset, SEEK_SET); + + if (decode) + { + // Try to decode/decompress the contents of this object... + pdfio_dict_t *dict = pdfioObjGetDict(obj); + // Object dictionary + const char *filter = pdfioDictGetName(dict, "Filter"); + // Filter value + + if (!filter) + { + // No single filter name, do we have a compound filter? + if (pdfioDictGetArray(dict, "Filter")) + { + // TODO: Implement compound filters... + _pdfioFileError(st->pdf, "Unsupported compound stream filter."); + free(st); + return (NULL); + } + + // No filter, read as-is... + st->filter = PDFIO_FILTER_NONE; + } + else if (!strcmp(filter, "FlateDecode")) + { + // Flate compression + int bpc = (int)pdfioDictGetNumber(dict, "BitsPerComponent"); + // Bits per component + int colors = (int)pdfioDictGetNumber(dict, "Colors"); + // Number of colors + int columns = (int)pdfioDictGetNumber(dict, "Columns"); + // Number of columns + int predictor = (int)pdfioDictGetNumber(dict, "Predictor"); + // Predictory value, if any + + st->filter = PDFIO_FILTER_FLATE; + } + else if (!strcmp(filter, "LZWDecode")) + { + // LZW compression + st->filter = PDFIO_FILTER_LZW; + } + else + { + // Something else we don't support + _pdfioFileError(st->pdf, "Unsupported stream filter '/%s'.", filter); + free(st); + return (NULL); + } + } + else + { + // Just return the stream data as-is... + st->filter = PDFIO_FILTER_NONE; + } + + return (st); +} + + // // 'pdfioStreamPeek()' - Peek at data in a stream. // diff --git a/pdfio.h b/pdfio.h index ad00b8d..10aa672 100644 --- a/pdfio.h +++ b/pdfio.h @@ -58,7 +58,16 @@ typedef bool (*pdfio_error_cb_t)(pdfio_file_t *pdf, const char *message, void *d typedef enum pdfio_filter_e // Compression/decompression filters for streams { PDFIO_FILTER_NONE, // No filter - PDFIO_FILTER_FLATE // Flate filter + PDFIO_FILTER_ASCIIHEX, // ASCIIHexDecode filter (reading only) + PDFIO_FILTER_ASCII85, // ASCII85Decode filter (reading only) + PDFIO_FILTER_CCITTFAX, // CCITTFaxDecode filter + PDFIO_FILTER_CRYPT, // Encryption filter + PDFIO_FILTER_DCT, // DCTDecode (JPEG) filter + PDFIO_FILTER_FLATE, // FlateDecode filter + PDFIO_FILTER_JBIG2, // JBIG2Decode filter + PDFIO_FILTER_JPX, // JPXDecode filter (reading only) + PDFIO_FILTER_LZW, // LZWDecode filter (reading only) + PDFIO_FILTER_RUNLENGTH, // RunLengthDecode filter (reading only) } pdfio_filter_t; typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file typedef struct pdfio_rect_s // PDF rectangle @@ -157,7 +166,7 @@ extern pdfio_dict_t *pdfioObjGetDict(pdfio_obj_t *obj) PDFIO_PUBLIC; extern unsigned short pdfioObjGetGeneration(pdfio_obj_t *obj) PDFIO_PUBLIC; extern size_t pdfioObjGetNumber(pdfio_obj_t *obj) PDFIO_PUBLIC; extern const char *pdfioObjGetType(pdfio_obj_t *obj) PDFIO_PUBLIC; -extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj) PDFIO_PUBLIC; +extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj, bool decode) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioPageCopy(pdfio_file_t *pdf, pdfio_obj_t *src) PDFIO_PUBLIC;