comparison mupdf-source/source/cbz/muimg.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) 2004-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/fitz.h"
24
25 #include <string.h>
26
27 #define DPI 72.0f
28
29 typedef struct
30 {
31 fz_page super;
32 fz_image *image;
33 } img_page;
34
35 typedef struct
36 {
37 fz_document super;
38 fz_buffer *buffer;
39 const char *format;
40 int page_count;
41 fz_pixmap *(*load_subimage)(fz_context *ctx, const unsigned char *p, size_t total, int subimage);
42 } img_document;
43
44 static void
45 img_drop_document(fz_context *ctx, fz_document *doc_)
46 {
47 img_document *doc = (img_document*)doc_;
48 fz_drop_buffer(ctx, doc->buffer);
49 }
50
51 static int
52 img_count_pages(fz_context *ctx, fz_document *doc_, int chapter)
53 {
54 img_document *doc = (img_document*)doc_;
55 return doc->page_count;
56 }
57
58 static fz_rect
59 img_bound_page(fz_context *ctx, fz_page *page_, fz_box_type box)
60 {
61 img_page *page = (img_page*)page_;
62 fz_image *image = page->image;
63 int xres, yres;
64 fz_rect bbox;
65 uint8_t orientation = fz_image_orientation(ctx, page->image);
66
67 fz_image_resolution(image, &xres, &yres);
68 bbox.x0 = bbox.y0 = 0;
69 if (orientation == 0 || (orientation & 1) == 1)
70 {
71 bbox.x1 = image->w * DPI / xres;
72 bbox.y1 = image->h * DPI / yres;
73 }
74 else
75 {
76 bbox.y1 = image->w * DPI / xres;
77 bbox.x1 = image->h * DPI / yres;
78 }
79 return bbox;
80 }
81
82 static void
83 img_run_page(fz_context *ctx, fz_page *page_, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
84 {
85 img_page *page = (img_page*)page_;
86 fz_image *image = page->image;
87 int xres, yres;
88 float w, h;
89 uint8_t orientation = fz_image_orientation(ctx, page->image);
90 fz_matrix immat = fz_image_orientation_matrix(ctx, page->image);
91
92 fz_image_resolution(image, &xres, &yres);
93 if (orientation == 0 || (orientation & 1) == 1)
94 {
95 w = image->w * DPI / xres;
96 h = image->h * DPI / yres;
97 }
98 else
99 {
100 h = image->w * DPI / xres;
101 w = image->h * DPI / yres;
102 }
103 immat = fz_post_scale(immat, w, h);
104 ctm = fz_concat(immat, ctm);
105 fz_fill_image(ctx, dev, image, ctm, 1, fz_default_color_params);
106 }
107
108 static void
109 img_drop_page(fz_context *ctx, fz_page *page_)
110 {
111 img_page *page = (img_page*)page_;
112 fz_drop_image(ctx, page->image);
113 }
114
115 static fz_page *
116 img_load_page(fz_context *ctx, fz_document *doc_, int chapter, int number)
117 {
118 img_document *doc = (img_document*)doc_;
119 fz_pixmap *pixmap = NULL;
120 fz_image *image = NULL;
121 img_page *page = NULL;
122
123 if (number < 0 || number >= doc->page_count)
124 fz_throw(ctx, FZ_ERROR_ARGUMENT, "invalid page number %d", number);
125
126 fz_var(pixmap);
127 fz_var(image);
128 fz_var(page);
129
130 fz_try(ctx)
131 {
132 if (doc->load_subimage)
133 {
134 size_t len;
135 unsigned char *data;
136 len = fz_buffer_storage(ctx, doc->buffer, &data);
137 pixmap = doc->load_subimage(ctx, data, len, number);
138 image = fz_new_image_from_pixmap(ctx, pixmap, NULL);
139 }
140 else
141 {
142 image = fz_new_image_from_buffer(ctx, doc->buffer);
143 }
144
145 page = fz_new_derived_page(ctx, img_page, doc_);
146 page->super.bound_page = img_bound_page;
147 page->super.run_page_contents = img_run_page;
148 page->super.drop_page = img_drop_page;
149 page->image = fz_keep_image(ctx, image);
150 }
151 fz_always(ctx)
152 {
153 fz_drop_image(ctx, image);
154 fz_drop_pixmap(ctx, pixmap);
155 }
156 fz_catch(ctx)
157 {
158 fz_free(ctx, page);
159 fz_rethrow(ctx);
160 }
161
162 return (fz_page*)page;
163 }
164
165 static int
166 img_lookup_metadata(fz_context *ctx, fz_document *doc_, const char *key, char *buf, size_t size)
167 {
168 img_document *doc = (img_document*)doc_;
169 if (!strcmp(key, FZ_META_FORMAT))
170 return 1 + (int)fz_strlcpy(buf, doc->format, size);
171 return -1;
172 }
173
174 static fz_document *
175 img_open_document(fz_context *ctx, const fz_document_handler *handler, fz_stream *file, fz_stream *accel, fz_archive *dir, void *state)
176 {
177 img_document *doc = fz_new_derived_document(ctx, img_document);
178
179 doc->super.drop_document = img_drop_document;
180 doc->super.count_pages = img_count_pages;
181 doc->super.load_page = img_load_page;
182 doc->super.lookup_metadata = img_lookup_metadata;
183
184 fz_try(ctx)
185 {
186 int fmt;
187 size_t len;
188 unsigned char *data;
189
190 doc->buffer = fz_read_all(ctx, file, 0);
191 len = fz_buffer_storage(ctx, doc->buffer, &data);
192
193 fmt = FZ_IMAGE_UNKNOWN;
194 if (len >= 8)
195 fmt = fz_recognize_image_format(ctx, data);
196 if (fmt == FZ_IMAGE_TIFF)
197 {
198 doc->page_count = fz_load_tiff_subimage_count(ctx, data, len);
199 doc->load_subimage = fz_load_tiff_subimage;
200 doc->format = "TIFF";
201 }
202 else if (fmt == FZ_IMAGE_PNM)
203 {
204 doc->page_count = fz_load_pnm_subimage_count(ctx, data, len);
205 doc->load_subimage = fz_load_pnm_subimage;
206 doc->format = "PNM";
207 }
208 else if (fmt == FZ_IMAGE_JBIG2)
209 {
210 doc->page_count = fz_load_jbig2_subimage_count(ctx, data, len);
211 if (doc->page_count > 1)
212 doc->load_subimage = fz_load_jbig2_subimage;
213 doc->format = "JBIG2";
214 }
215 else if (fmt == FZ_IMAGE_BMP)
216 {
217 doc->page_count = fz_load_bmp_subimage_count(ctx, data, len);
218 doc->load_subimage = fz_load_bmp_subimage;
219 doc->format = "BMP";
220 }
221 else
222 {
223 doc->page_count = 1;
224 doc->format = "Image";
225 }
226 }
227 fz_catch(ctx)
228 {
229 fz_drop_document(ctx, (fz_document*)doc);
230 fz_rethrow(ctx);
231 }
232
233 return (fz_document*)doc;
234 }
235
236 static int
237 img_recognize_content(fz_context *ctx, const fz_document_handler *handler, fz_stream *stream, fz_archive *dir, void **state, fz_document_recognize_state_free_fn **free_state)
238 {
239 unsigned char data[8];
240 size_t n;
241 int fmt;
242
243 if (stream == NULL)
244 return 0;
245
246 if (state)
247 *state = NULL;
248 if (free_state)
249 *free_state = NULL;
250
251 n = fz_read(ctx, stream, data, 8);
252
253 if (n != 8)
254 return 0;
255
256 fmt = fz_recognize_image_format(ctx, data);
257 if (fmt != FZ_IMAGE_UNKNOWN)
258 return 100;
259
260 return 0;
261 }
262
263 static const char *img_extensions[] =
264 {
265 "bmp",
266 "gif",
267 "hdp",
268 "j2k",
269 "jb2",
270 "jbig2",
271 "jfif",
272 "jfif-tbnl",
273 "jp2",
274 "jpe",
275 "jpeg",
276 "jpg",
277 "jpx",
278 "jxr",
279 "pam",
280 "pbm",
281 "pfm",
282 "pgm",
283 "pkm",
284 "png",
285 "pnm",
286 "ppm",
287 "psd",
288 "tif",
289 "tiff",
290 "wdp",
291 NULL
292 };
293
294 static const char *img_mimetypes[] =
295 {
296 "image/bmp",
297 "image/gif",
298 "image/jp2",
299 "image/jpeg",
300 "image/jpx",
301 "image/jxr",
302 "image/pjpeg",
303 "image/png",
304 "image/tiff",
305 "image/vnd.ms-photo",
306 "image/vnd.adobe.photoshop",
307 "image/x-jb2",
308 "image/x-jbig2",
309 "image/x-portable-anymap",
310 "image/x-portable-arbitrarymap",
311 "image/x-portable-bitmap",
312 "image/x-portable-greymap",
313 "image/x-portable-pixmap",
314 "image/x-portable-floatmap",
315 "image/x-tiff",
316 NULL
317 };
318
319 fz_document_handler img_document_handler =
320 {
321 NULL,
322 img_open_document,
323 img_extensions,
324 img_mimetypes,
325 img_recognize_content
326 };