From f40284df08ca4b2f87f91f3a45ae59affbef215b Mon Sep 17 00:00:00 2001 From: Till Kamppeter Date: Mon, 28 Mar 2022 13:04:07 +0200 Subject: [PATCH] libcupsfilters: Allow mupdftoraster() be used for all raster formats The mupdftoraster() filter function only produces PWG Raster, due to the fact that mutool of MuPDF produces PWG Raster but not Apple Raster, CUPS Raster, or PCLm. To obtain the other formats one needs post-filtering with pwgtoraster and rastertopclm. To make this working in the best possible way and to make it working at all with any PPD file (also those which do not have information for generating the inbetween PWG Raster format) we have prepared mupdftoraster appropriately. Changes done: - Get final output format via parameters - Call cupsRasterPrepareHeader() with PWG Raster as header format and the final output format as final format - If the final format is not PWG Raster we need post-filtering. In this case let mutool only generate output with a maximum of 3 color channels (no CMYK) as the post filters pwgtoraster and rastertopclm only support 1- or 3-color-channel input. - Add explicit support for the RGBW color space (#17, used by HPLIP's hpcups driver). - On an unknown final output color space default to color instead of mono output. A post filter can turn color into monochrome but not vice-versa. - Let the CUPS filter wrapper read the final output format from the FINAL_CONTENT_TYPE environment variable. Default to CUPS Raster on an unknown format, as those formats typically come from CUPS Raster ("rasterto...") drivers. - Do not pass in the full list of environment variables any more. We do not manipulate these. Instead we call mutool with execvp() to simply use the caller's environment instead of execvpe() with a supplied environment. - Update the MIME rules: Remove rule telling that mupdftoraster outputs CUPS Raster, add rules for pwgtoraster, and also rules to reflect that rastertopclm also accepts Apple Raster or PWG Raster as input. --- cupsfilters/filter.h | 11 +++++++ cupsfilters/mupdftoraster.c | 52 ++++++++++++++++++++----------- filter/mupdftoraster.c | 13 +++++++- mime/cupsfilters-individual.convs | 8 ++++- mime/cupsfilters-mupdf.convs | 1 - 5 files changed, 64 insertions(+), 21 deletions(-) diff --git a/cupsfilters/filter.h b/cupsfilters/filter.h index 637cf5109..1d0d46014 100644 --- a/cupsfilters/filter.h +++ b/cupsfilters/filter.h @@ -273,6 +273,17 @@ extern int mupdftoraster(int inputfd, filter_data_t *data, void *parameters); +/* Parameters: filter_out_format_t* + Ouput format: CUPS Raster, PWG Raster, Apple Raster, PCLm + Note: With CUPS Raster, Apple Raster, or PCLm selections the output + is actually PWG Raster but information about available color spaces + and depths is taken from the pseudo-PostScript in the PPDs options, + urf-supported printer IPP attribute or the appropriate PPD file + attribute (PCLM is always sRGB 8-bit). These modes are for further + processing with pwgtoraster or rastertopclm. This can change in the + future when MuPDF adds further output formats. */ + + extern int pclmtoraster(int inputfd, int outputfd, int inputseekable, diff --git a/cupsfilters/mupdftoraster.c b/cupsfilters/mupdftoraster.c index d0d8d7ac3..8c3d43125 100644 --- a/cupsfilters/mupdftoraster.c +++ b/cupsfilters/mupdftoraster.c @@ -118,8 +118,9 @@ parse_pdf_header_options(FILE *fp, mupdf_page_header *h) } static void -add_pdf_header_options(mupdf_page_header *h, - cups_array_t *mupdf_args) +add_pdf_header_options(mupdf_page_header *h, + filter_out_format_t outformat, + cups_array_t *mupdf_args) { char tmpstr[1024]; @@ -141,20 +142,26 @@ add_pdf_header_options(mupdf_page_header *h, switch (h->cupsColorSpace) { case CUPS_CSPACE_RGB: case CUPS_CSPACE_CMY: + case CUPS_CSPACE_RGBW: case CUPS_CSPACE_SRGB: case CUPS_CSPACE_ADOBERGB: + default: snprintf(tmpstr, sizeof(tmpstr), "-crgb"); break; case CUPS_CSPACE_CMYK: - snprintf(tmpstr, sizeof(tmpstr), "-ccmyk"); + if (outformat == OUTPUT_FORMAT_PWG_RASTER) /* No post-filtering needed */ + snprintf(tmpstr, sizeof(tmpstr), "-ccmyk"); + else + snprintf(tmpstr, sizeof(tmpstr), "-crgb"); /* Post-filtering needed, only + 3-color modes supported as + input for the post filters*/ break; case CUPS_CSPACE_SW: snprintf(tmpstr, sizeof(tmpstr), "-cgray"); break; - default: case CUPS_CSPACE_K: case CUPS_CSPACE_W: snprintf(tmpstr, sizeof(tmpstr), "-cmono"); @@ -166,7 +173,6 @@ add_pdf_header_options(mupdf_page_header *h, static int mutool_spawn (const char *filename, cups_array_t *mutool_args, - char **envp, int outputfd, filter_logfunc_t log, void *ld, @@ -209,10 +215,6 @@ mutool_spawn (const char *filename, " %s%s%s", apos, mutoolargv[i], apos); } log(ld, FILTER_LOGLEVEL_DEBUG, "%s", buf); - - for (i = 0; envp[i]; i ++) - log(ld, FILTER_LOGLEVEL_DEBUG, - "mupdftoraster: envp[%d]=\"%s\"", i, envp[i]); } /* Create a pipe for stderr output of mutool */ @@ -288,7 +290,7 @@ mutool_spawn (const char *filename, } /* Execute mutool command line ... */ - execvpe(filename, mutoolargv, envp); + execvp(filename, mutoolargv); if (log) log(ld, FILTER_LOGLEVEL_ERROR, "mupdftoraster: Unable to launch mutool: %s: %s", filename, strerror(errno)); @@ -392,6 +394,7 @@ mupdftoraster (int inputfd, /* I - File descriptor input stream */ filter_data_t *data, /* I - Job and printer data */ void *parameters) /* I - Filter-specific parameters */ { + filter_out_format_t outformat; char buf[BUFSIZ]; char *icc_profile = NULL; char tmpstr[1024]; @@ -413,17 +416,30 @@ mupdftoraster (int inputfd, /* I - File descriptor input stream */ void *ld = data->logdata; filter_iscanceledfunc_t iscanceled = data->iscanceledfunc; void *icd = data->iscanceleddata; - char **envp; cups_cspace_t cspace = -1; #ifdef HAVE_CUPS_1_7 ppd_attr_t *attr; #endif /* HAVE_CUPS_1_7 */ - if(parameters) - envp = (char**)(parameters); - else - envp = NULL; + (void)inputseekable; + + if (parameters) { + outformat = *(filter_out_format_t *)parameters; + if (outformat != OUTPUT_FORMAT_CUPS_RASTER && + outformat != OUTPUT_FORMAT_PWG_RASTER && + outformat != OUTPUT_FORMAT_APPLE_RASTER && + outformat != OUTPUT_FORMAT_PCLM) + outformat = OUTPUT_FORMAT_PWG_RASTER; + } else + outformat = OUTPUT_FORMAT_PWG_RASTER; + + if (log) log(ld, FILTER_LOGLEVEL_DEBUG, + "mupdftoraster: Output format: %s", + (outformat == OUTPUT_FORMAT_CUPS_RASTER ? "CUPS Raster" : + (outformat == OUTPUT_FORMAT_PWG_RASTER ? "PWG Raster" : + (outformat == OUTPUT_FORMAT_APPLE_RASTER ? "Apple Raster" : + "PCLM")))); memset(&sa, 0, sizeof(sa)); /* Ignore SIGPIPE and have write return an error instead */ @@ -522,7 +538,7 @@ mupdftoraster (int inputfd, /* I - File descriptor input stream */ Raster header then, no extra manipulation needed. From the header h only cupsWidth/cupsHeight (dimensions in pixels), resolution, and color space are used here. */ - cupsRasterPrepareHeader(&h, data, OUTPUT_FORMAT_PWG_RASTER, + cupsRasterPrepareHeader(&h, data, outformat, OUTPUT_FORMAT_PWG_RASTER, 1, &cspace); if ((h.HWResolution[0] == 100) && (h.HWResolution[1] == 100)) { @@ -555,7 +571,7 @@ mupdftoraster (int inputfd, /* I - File descriptor input stream */ h.Orientation = CUPS_ORIENT_0; /* get all the data from the header and pass it to mutool */ - add_pdf_header_options (&h, mupdf_args); + add_pdf_header_options (&h, outformat, mupdf_args); snprintf(tmpstr, sizeof(tmpstr), "%s", infilename); cupsArrayAdd(mupdf_args, strdup(tmpstr)); @@ -564,7 +580,7 @@ mupdftoraster (int inputfd, /* I - File descriptor input stream */ snprintf(tmpstr, sizeof(tmpstr), "%s", CUPS_MUTOOL); /* call mutool */ - status = mutool_spawn (tmpstr, mupdf_args, envp, outputfd, log, ld, + status = mutool_spawn (tmpstr, mupdf_args, outputfd, log, ld, iscanceled, icd); if (status != 0) status = 1; diff --git a/filter/mupdftoraster.c b/filter/mupdftoraster.c index 2b38aa47d..8684412e8 100644 --- a/filter/mupdftoraster.c +++ b/filter/mupdftoraster.c @@ -53,7 +53,18 @@ main(int argc, /* I - Number of command-line arguments */ * Fire up the mupdftoraster() filter function */ - ret = filterCUPSWrapper(argc, argv, mupdftoraster, envp, &JobCanceled); + filter_out_format_t outformat = OUTPUT_FORMAT_CUPS_RASTER; + char *t = getenv("FINAL_CONTENT_TYPE"); + if (t) { + if (strcasestr(t, "pwg")) + outformat = OUTPUT_FORMAT_PWG_RASTER; + else if (strcasestr(t, "urf")) + outformat = OUTPUT_FORMAT_APPLE_RASTER; + else if (strcasestr(t, "pclm")) + outformat = OUTPUT_FORMAT_PCLM; + } + + ret = filterCUPSWrapper(argc, argv, mupdftoraster, &outformat, &JobCanceled); if (ret) fprintf(stderr, "ERROR: mupdftoraster filter function failed.\n"); diff --git a/mime/cupsfilters-individual.convs b/mime/cupsfilters-individual.convs index faed81535..c3809d02a 100644 --- a/mime/cupsfilters-individual.convs +++ b/mime/cupsfilters-individual.convs @@ -60,7 +60,6 @@ image/x-xwindowdump application/vnd.cups-pdf 65 imagetopdf image/x-sun-raster application/vnd.cups-pdf 65 imagetopdf application/vnd.cups-pdf-banner application/pdf 32 bannertopdf image/urf application/pdf 0 rastertopdf -application/vnd.cups-raster application/PCLm 32 rastertopclm ######################################################################## # @@ -102,3 +101,10 @@ image/x-sgi-rgb application/vnd.cups-raster 100 imagetoraster image/x-xbitmap application/vnd.cups-raster 100 imagetoraster image/x-xpixmap application/vnd.cups-raster 100 imagetoraster image/x-sun-raster application/vnd.cups-raster 100 imagetoraster +image/pwg-raster application/vnd.cups-raster 100 pwgtoraster +image/urf application/vnd.cups-raster 100 pwgtoraster +image/pwg-raster image/urf 100 pwgtoraster +image/urf image/pwg-raster 100 pwgtoraster +image/pwg-raster application/PCLm 100 rastertopclm +image/urf application/PCLm 100 rastertopclm +application/vnd.cups-raster application/PCLm 100 rastertopclm diff --git a/mime/cupsfilters-mupdf.convs b/mime/cupsfilters-mupdf.convs index 20a68beb4..de110c75d 100644 --- a/mime/cupsfilters-mupdf.convs +++ b/mime/cupsfilters-mupdf.convs @@ -15,5 +15,4 @@ # MuPDF-based filters... # -application/vnd.cups-pdf application/vnd.cups-raster 101 mupdftoraster application/vnd.cups-pdf image/pwg-raster 101 mupdftoraster -- 2.47.3