Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/pdf/pdf-recolor.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2024 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/pdf.h" | |
| 24 | |
| 25 typedef struct { | |
| 26 fz_colorspace *outcs; | |
| 27 pdf_obj *outcs_obj; | |
| 28 } recolor_data; | |
| 29 | |
| 30 static void | |
| 31 color_rewrite(fz_context *ctx, void *opaque, pdf_obj **cs_obj, int *n, float color[FZ_MAX_COLORS]) | |
| 32 { | |
| 33 recolor_data *rd = (recolor_data *)opaque; | |
| 34 fz_colorspace *cs; | |
| 35 float cols[4] = { 0 }; | |
| 36 | |
| 37 if (pdf_name_eq(ctx, *cs_obj, PDF_NAME(Pattern))) | |
| 38 return; | |
| 39 if (pdf_name_eq(ctx, pdf_dict_get(ctx, *cs_obj, PDF_NAME(Type)), PDF_NAME(Pattern))) | |
| 40 return; | |
| 41 | |
| 42 if (*n != 0) | |
| 43 { | |
| 44 cs = pdf_load_colorspace(ctx, *cs_obj); | |
| 45 | |
| 46 fz_try(ctx) | |
| 47 { | |
| 48 fz_convert_color(ctx, cs, color, rd->outcs, cols, NULL, fz_default_color_params); | |
| 49 } | |
| 50 fz_always(ctx) | |
| 51 fz_drop_colorspace(ctx, cs); | |
| 52 fz_catch(ctx) | |
| 53 fz_rethrow(ctx); | |
| 54 *n = rd->outcs->n; | |
| 55 } | |
| 56 | |
| 57 pdf_drop_obj(ctx, *cs_obj); | |
| 58 *cs_obj = rd->outcs_obj; | |
| 59 memcpy(color, cols, sizeof(color[0])*4); | |
| 60 } | |
| 61 | |
| 62 static void | |
| 63 image_rewrite(fz_context *ctx, void *opaque, fz_image **image, fz_matrix ctm, pdf_obj *im_obj) | |
| 64 { | |
| 65 recolor_data *rd = (recolor_data *)opaque; | |
| 66 fz_image *orig = *image; | |
| 67 fz_pixmap *pix = NULL; | |
| 68 fz_colorspace* dst_cs; | |
| 69 | |
| 70 fz_var(pix); | |
| 71 | |
| 72 if ((*image)->imagemask) | |
| 73 return; | |
| 74 | |
| 75 dst_cs = rd->outcs; | |
| 76 pix = fz_get_unscaled_pixmap_from_image(ctx, orig); | |
| 77 | |
| 78 fz_try(ctx) | |
| 79 { | |
| 80 if (pix->colorspace != dst_cs) | |
| 81 { | |
| 82 fz_pixmap *pix2 = fz_convert_pixmap(ctx, pix, dst_cs, NULL, NULL, fz_default_color_params, 1); | |
| 83 fz_drop_pixmap(ctx, pix); | |
| 84 pix = pix2; | |
| 85 } | |
| 86 | |
| 87 *image = fz_new_image_from_pixmap(ctx, pix, orig->mask); | |
| 88 fz_drop_image(ctx, orig); | |
| 89 } | |
| 90 fz_always(ctx) | |
| 91 fz_drop_pixmap(ctx, pix); | |
| 92 fz_catch(ctx) | |
| 93 fz_rethrow(ctx); | |
| 94 } | |
| 95 | |
| 96 static void | |
| 97 vertex_rewrite(fz_context *ctx, void *opaque, fz_colorspace *dst_cs, float *d, fz_colorspace *src_cs, const float *s) | |
| 98 { | |
| 99 recolor_data *rd = (recolor_data *)opaque; | |
| 100 | |
| 101 fz_convert_color(ctx, src_cs, s, rd->outcs, d, NULL, fz_default_color_params); | |
| 102 } | |
| 103 | |
| 104 static pdf_recolor_vertex * | |
| 105 shade_rewrite(fz_context *ctx, void *opaque, fz_colorspace *src_cs, fz_colorspace **dst_cs) | |
| 106 { | |
| 107 recolor_data *rd = (recolor_data *)opaque; | |
| 108 | |
| 109 *dst_cs = rd->outcs; | |
| 110 | |
| 111 return vertex_rewrite; | |
| 112 } | |
| 113 | |
| 114 static void | |
| 115 rewrite_page_streams(fz_context *ctx, pdf_document *doc, int page_num, recolor_data *rd) | |
| 116 { | |
| 117 pdf_page *page = pdf_load_page(ctx, doc, page_num); | |
| 118 pdf_filter_options options = { 0 }; | |
| 119 pdf_filter_factory list[2] = { 0 }; | |
| 120 pdf_color_filter_options copts = { 0 }; | |
| 121 pdf_annot *annot; | |
| 122 | |
| 123 copts.opaque = rd; | |
| 124 copts.color_rewrite = color_rewrite; | |
| 125 copts.image_rewrite = image_rewrite; | |
| 126 copts.shade_rewrite = shade_rewrite; | |
| 127 options.filters = list; | |
| 128 options.recurse = 1; | |
| 129 list[0].filter = pdf_new_color_filter; | |
| 130 list[0].options = &copts; | |
| 131 | |
| 132 fz_try(ctx) | |
| 133 { | |
| 134 pdf_filter_page_contents(ctx, doc, page, &options); | |
| 135 | |
| 136 for (annot = pdf_first_annot(ctx, page); annot != NULL; annot = pdf_next_annot(ctx, annot)) | |
| 137 pdf_filter_annot_contents(ctx, doc, annot, &options); | |
| 138 } | |
| 139 fz_always(ctx) | |
| 140 fz_drop_page(ctx, &page->super); | |
| 141 fz_catch(ctx) | |
| 142 fz_rethrow(ctx); | |
| 143 } | |
| 144 | |
| 145 | |
| 146 void pdf_recolor_page(fz_context *ctx, pdf_document *doc, int pagenum, const pdf_recolor_options *opts) | |
| 147 { | |
| 148 recolor_data rd = { 0 }; | |
| 149 | |
| 150 if (opts == NULL) | |
| 151 fz_throw(ctx, FZ_ERROR_ARGUMENT, "Options must be supplied"); | |
| 152 | |
| 153 switch (opts->num_comp) | |
| 154 { | |
| 155 case 1: | |
| 156 rd.outcs = fz_device_gray(ctx); | |
| 157 rd.outcs_obj = PDF_NAME(DeviceGray); | |
| 158 break; | |
| 159 case 3: | |
| 160 rd.outcs = fz_device_rgb(ctx); | |
| 161 rd.outcs_obj = PDF_NAME(DeviceRGB); | |
| 162 break; | |
| 163 case 4: | |
| 164 rd.outcs = fz_device_cmyk(ctx); | |
| 165 rd.outcs_obj = PDF_NAME(DeviceCMYK); | |
| 166 break; | |
| 167 default: | |
| 168 fz_throw(ctx, FZ_ERROR_ARGUMENT, "Unsupported number of components"); | |
| 169 } | |
| 170 | |
| 171 rewrite_page_streams(ctx, doc, pagenum, &rd); | |
| 172 } | |
| 173 | |
| 174 void pdf_remove_output_intents(fz_context *ctx, pdf_document *doc) | |
| 175 { | |
| 176 pdf_dict_del(ctx, pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root)), PDF_NAME(OutputIntents)); | |
| 177 } |
