From 209cae2445ec4b9770d6419ce7be844d5ec1ed16 Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Tue, 11 Aug 2026 13:14:30 +0200 Subject: [PATCH 1/2] pclmtoraster.c: Fix getting MediaBox from input The affected function had logic inverted - error handling happened when MediaBox was found - which caused no output was generated. The PR fixes it and adds logic to get MediaBox from parent object, because per PDF specification MediaBox can be inherited from parent. Assisted-By: Claude Code --- cupsfilters/pclmtoraster.c | 42 ++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/cupsfilters/pclmtoraster.c b/cupsfilters/pclmtoraster.c index 896dbc2bc..62c74768f 100644 --- a/cupsfilters/pclmtoraster.c +++ b/cupsfilters/pclmtoraster.c @@ -210,27 +210,39 @@ parse_opts(cf_filter_data_t *data, // I - Job and Print data } // -// 'media_box_lookup()' - Helper function look up MediaBox from PDF dictionary +// 'media_box_lookup()' - Helper function to look up MediaBox from a page +// object, walking parent nodes if needed (MediaBox is +// an inheritable attribute in PDF). // -static bool // O - 1 if mediabox is found, 0 if not -media_box_lookup(pdfio_obj_t *object, // I - Page Object to look for mediabox - float rect[4]) // O - rectangle for mediabox output +static bool // O - true if found, false if not +media_box_lookup(pdfio_obj_t *object, // I - Page object + float rect[4]) // O - MediaBox rectangle { - pdfio_rect_t mediaBox; - pdfio_dict_t *object_dict = pdfioObjGetDict(object); - if(pdfioDictGetRect(object_dict, "MediaBox", &mediaBox)) - return false; + pdfio_rect_t mediaBox; // MediaBox value + pdfio_dict_t *dict; // Current dictionary - pdfioDictGetRect(object_dict, "MediaBox", &mediaBox); + // Walk the page tree up through Parent nodes to find an inherited MediaBox + while (object) + { + dict = pdfioObjGetDict(object); + if (!dict) + break; - rect[0] = mediaBox.x1; - rect[1] = mediaBox.y1; - rect[2] = mediaBox.x2; - rect[3] = mediaBox.y2; + if (pdfioDictGetRect(dict, "MediaBox", &mediaBox)) + { + rect[0] = mediaBox.x1; + rect[1] = mediaBox.y1; + rect[2] = mediaBox.x2; + rect[3] = mediaBox.y2; + return (true); + } - return true; -} + object = pdfioDictGetObj(dict, "Parent"); + } + + return (false); +} // // 'rotate_bitmap()' - Function to rotate a bitmap From 98423c1bedb0a4d39ed9096c653fe91787664a0a Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Tue, 11 Aug 2026 16:23:57 +0200 Subject: [PATCH 2/2] pclmtoraster.c: Fix processing image in PCLm Fixed several issues in PCLm processing 1. The input PCLm might not have /Type set for images, because it is optional key, filter has to look for subtype Image (fixed typo image -> Image). 2. PDFIO read stream function can return -1, so it has to be saved in ssize_t to get correct interpretation - otherwise the filter aborts on alloc of large number. 3. buffer was array of pointers to char instead of array of chars - saves memory 4. making code straight, adding return value checks, grouping local vars at the beginning Assisted-By: Claude Code by Anthropic --- cupsfilters/pclmtoraster.c | 79 +++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/cupsfilters/pclmtoraster.c b/cupsfilters/pclmtoraster.c index 62c74768f..d1ca90149 100644 --- a/cupsfilters/pclmtoraster.c +++ b/cupsfilters/pclmtoraster.c @@ -851,40 +851,65 @@ process_image(pdfio_dict_t *dict, // I - dictionary where images are there const char *key, // I - key names of xobjects void *cb_data) // I - conversion data { - pclmtoraster_data_t *data = (pclmtoraster_data_t *)cb_data; - char *buffer[4096]; - pdfio_obj_t *image = pdfioDictGetObj(dict, key); + const char *subtype; + pclmtoraster_data_t *data; + pdfio_obj_t *image; + pdfio_dict_t *imgdict; + pdfio_stream_t *img_str; + ssize_t bytes; + unsigned char buffer[8192]; - if (strcmp(pdfioObjGetType(image), "image") == 0) - { - pdfio_dict_t *imgdict = pdfioObjGetDict(image); - if (!imgdict) - return true; - // Read the raw image stream - pdfio_stream_t *img_str = pdfioObjOpenStream(image, true); - size_t bufsize = pdfioStreamRead(img_str, buffer, sizeof(buffer)); + data = (pclmtoraster_data_t *)cb_data; + + if ((image = pdfioDictGetObj(dict, key)) == NULL) + return (true); + + if ((subtype = pdfioObjGetSubtype(image)) == NULL) + return (true); + + if (strcmp(subtype, "Image")) + return (true); - int width = pdfioDictGetNumber(imgdict, "Width"); - int height = pdfioDictGetNumber(imgdict, "Height"); + if ((imgdict = pdfioObjGetDict(image)) == NULL) + return (true); - data->header.cupsHeight += height; + int width = (int)pdfioDictGetNumber(imgdict, "Width"); + int height = (int)pdfioDictGetNumber(imgdict, "Height"); + + // Read the complete decoded image stream + if ((img_str = pdfioObjOpenStream(image, true)) == NULL) + return (true); + + while ((bytes = pdfioStreamRead(img_str, buffer, sizeof(buffer))) > 0) + { + unsigned char *tmp; - // Allocate memory for the bitmap data if (data->pixel_count == 0) - data->bitmap = (unsigned char *)malloc(bufsize); + tmp = (unsigned char *)malloc(bytes); else - data->bitmap = (unsigned char *)realloc(data->bitmap, - data->pixel_count + bufsize); + tmp = (unsigned char *)realloc(data->bitmap, + data->pixel_count + bytes); - memcpy(data->bitmap + data->pixel_count, buffer, bufsize); - data->pixel_count += bufsize; + if (!tmp) + { + pdfioStreamClose(img_str); + return (false); + } - // Track maximum width - if (width > data->header.cupsWidth) - data->header.cupsWidth = width; + data->bitmap = tmp; + memcpy(data->bitmap + data->pixel_count, buffer, bytes); + data->pixel_count += bytes; } + pdfioStreamClose(img_str); + + data->header.cupsHeight += height; + + // Track maximum width + if (width > (int)data->header.cupsWidth) + data->header.cupsWidth = width; + return (true); } @@ -1297,13 +1322,7 @@ cfFilterPCLmToRaster(int inputfd, // I - File descriptor input stream if (log) log(ld, CF_LOGLEVEL_INFO, "cfFilterPCLmToRaster: Starting page %d.", i + 1); - if (out_page(raster, pages, i, log, ld, &pclmtoraster_data,data, - &convert) != 0) - break; - - if (log) log(ld, CF_LOGLEVEL_INFO, - "cfFilterPCLmToRaster: Starting page %d.", (i + 1)); - if (out_page(raster, pages, i, log, ld, &pclmtoraster_data,data, + if (out_page(raster, pages, i, log, ld, &pclmtoraster_data, data, &convert) != 0) break; }