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