comparison mupdf-source/source/fitz/load-jbig2.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-2021 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 "pixmap-imp.h"
26
27 #include <jbig2.h>
28
29 struct info
30 {
31 int width, height;
32 int xres, yres;
33 int pages;
34 fz_colorspace *cspace;
35 };
36
37 struct fz_jbig2_allocator
38 {
39 Jbig2Allocator super;
40 fz_context *ctx;
41 };
42
43 static void
44 error_callback(void *data, const char *msg, Jbig2Severity severity, uint32_t seg_idx)
45 {
46 fz_context *ctx = data;
47 if (severity == JBIG2_SEVERITY_FATAL)
48 fz_warn(ctx, "jbig2dec error: %s (segment %u)", msg, seg_idx);
49 else if (severity == JBIG2_SEVERITY_WARNING)
50 fz_warn(ctx, "jbig2dec warning: %s (segment %u)", msg, seg_idx);
51 #ifdef JBIG2_DEBUG
52 else if (severity == JBIG2_SEVERITY_INFO)
53 fz_warn(ctx, "jbig2dec info: %s (segment %u)", msg, seg_idx);
54 else if (severity == JBIG2_SEVERITY_DEBUG)
55 fz_warn(ctx, "jbig2dec debug: %s (segment %u)", msg, seg_idx);
56 #endif
57 }
58
59 static void *fz_jbig2_alloc(Jbig2Allocator *allocator, size_t size)
60 {
61 fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
62 return fz_malloc_no_throw(ctx, size);
63 }
64
65 static void fz_jbig2_free(Jbig2Allocator *allocator, void *p)
66 {
67 fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
68 fz_free(ctx, p);
69 }
70
71 static void *fz_jbig2_realloc(Jbig2Allocator *allocator, void *p, size_t size)
72 {
73 fz_context *ctx = ((struct fz_jbig2_allocator *) allocator)->ctx;
74 if (size == 0)
75 {
76 fz_free(ctx, p);
77 return NULL;
78 }
79 if (p == NULL)
80 return Memento_label(fz_malloc(ctx, size), "jbig2_realloc");
81 return Memento_label(fz_realloc_no_throw(ctx, p, size), "jbig2_realloc");
82 }
83
84 static fz_pixmap *
85 jbig2_read_image(fz_context *ctx, struct info *jbig2, const unsigned char *buf, size_t len, int only_metadata, int subimage)
86 {
87 Jbig2Ctx *jctx = NULL;
88 Jbig2Image *page = NULL;
89 struct fz_jbig2_allocator allocator;
90 fz_pixmap *pix = NULL;
91
92 allocator.super.alloc = fz_jbig2_alloc;
93 allocator.super.free = fz_jbig2_free;
94 allocator.super.realloc = fz_jbig2_realloc;
95 allocator.ctx = ctx;
96
97 fz_var(jctx);
98 fz_var(page);
99 fz_var(pix);
100
101 fz_try(ctx)
102 {
103 jctx = jbig2_ctx_new((Jbig2Allocator *) &allocator, 0, NULL, error_callback, ctx);
104 if (jctx == NULL)
105 fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot create jbig2 context");
106 if (jbig2_data_in(jctx, buf, len) < 0)
107 fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot decode jbig2 image");
108 if (jbig2_complete_page(jctx) < 0)
109 fz_throw(ctx, FZ_ERROR_LIBRARY, "cannot complete jbig2 image");
110
111 if (only_metadata && subimage < 0)
112 {
113 while ((page = jbig2_page_out(jctx)) != NULL)
114 {
115 jbig2_release_page(jctx, page);
116 jbig2->pages++;
117 }
118 }
119 else if (only_metadata && subimage >= 0)
120 {
121 while ((page = jbig2_page_out(jctx)) != NULL && subimage > 0)
122 {
123 jbig2_release_page(jctx, page);
124 subimage--;
125 }
126
127 if (page == NULL)
128 fz_throw(ctx, FZ_ERROR_LIBRARY, "no jbig2 image decoded");
129
130 jbig2->cspace = fz_device_gray(ctx);
131 jbig2->width = page->width;
132 jbig2->height = page->height;
133 jbig2->xres = 72;
134 jbig2->yres = 72;
135 }
136 else if (subimage >= 0)
137 {
138 while ((page = jbig2_page_out(jctx)) != NULL && subimage > 0)
139 {
140 jbig2_release_page(jctx, page);
141 subimage--;
142 }
143
144 if (page == NULL)
145 fz_throw(ctx, FZ_ERROR_LIBRARY, "no jbig2 image decoded");
146
147 jbig2->cspace = fz_device_gray(ctx);
148 jbig2->width = page->width;
149 jbig2->height = page->height;
150 jbig2->xres = 72;
151 jbig2->yres = 72;
152
153 pix = fz_new_pixmap(ctx, jbig2->cspace, jbig2->width, jbig2->height, NULL, 0);
154 fz_unpack_tile(ctx, pix, page->data, 1, 1, page->stride, 0);
155 fz_invert_pixmap(ctx, pix);
156 }
157 }
158 fz_always(ctx)
159 {
160 jbig2_release_page(jctx, page);
161 jbig2_ctx_free(jctx);
162 }
163 fz_catch(ctx)
164 {
165 fz_drop_pixmap(ctx, pix);
166 fz_rethrow(ctx);
167 }
168
169 return pix;
170 }
171
172 int
173 fz_load_jbig2_subimage_count(fz_context *ctx, const unsigned char *buf, size_t len)
174 {
175 struct info jbig2 = { 0 };
176 int subimage_count = 0;
177
178 fz_try(ctx)
179 {
180 jbig2_read_image(ctx, &jbig2, buf, len, 1, -1);
181 subimage_count = jbig2.pages;
182 }
183 fz_catch(ctx)
184 fz_rethrow(ctx);
185
186 return subimage_count;
187 }
188
189 void
190 fz_load_jbig2_info_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep, int subimage)
191 {
192 struct info jbig2 = { 0 };
193
194 jbig2_read_image(ctx, &jbig2, buf, len, 1, subimage);
195 *cspacep = fz_keep_colorspace(ctx, jbig2.cspace);
196 *wp = jbig2.width;
197 *hp = jbig2.height;
198 *xresp = jbig2.xres;
199 *yresp = jbig2.yres;
200 }
201
202 fz_pixmap *
203 fz_load_jbig2_subimage(fz_context *ctx, const unsigned char *buf, size_t len, int subimage)
204 {
205 struct info jbig2 = { 0 };
206 return jbig2_read_image(ctx, &jbig2, buf, len, 0, subimage);
207 }
208
209 fz_pixmap *
210 fz_load_jbig2(fz_context *ctx, const unsigned char *buf, size_t len)
211 {
212 return fz_load_jbig2_subimage(ctx, buf, len, 0);
213 }
214
215 void
216 fz_load_jbig2_info(fz_context *ctx, const unsigned char *buf, size_t len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
217 {
218 fz_load_jbig2_info_subimage(ctx, buf, len, wp, hp, xresp, yresp, cspacep, 0);
219 }