/src/ghostpdl/gpdl/tifftop.c
Line | Count | Source |
1 | | /* Copyright (C) 2019-2026 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | /* tifftop.c */ |
17 | | /* Top-level API implementation of "TIF" Language Interface */ |
18 | | #ifdef TIFF_INCLUDED |
19 | | |
20 | | #include "pltop.h" |
21 | | #include "gserrors.h" |
22 | | #include "gxdevice.h" |
23 | | #include "gsstate.h" |
24 | | #include "strimpl.h" |
25 | | #include "gscoord.h" |
26 | | #include "gsicc_manage.h" |
27 | | #include "gspaint.h" |
28 | | #include "plmain.h" |
29 | | #include "tiffio.h" |
30 | | #if defined(SHARE_JPEG) && SHARE_JPEG==0 |
31 | | #include "jmemcust.h" |
32 | | #endif |
33 | | #include "gsmchunk.h" |
34 | | |
35 | | #include <limits.h> |
36 | | |
37 | | /* Forward decls */ |
38 | | |
39 | | /************************************************************/ |
40 | | /******** Language wrapper implementation (see pltop.h) *****/ |
41 | | /************************************************************/ |
42 | | |
43 | | typedef enum |
44 | | { |
45 | | ii_state_identifying = 0, |
46 | | ii_state_tiff, |
47 | | ii_state_tiff_header, |
48 | | ii_state_tiff_decode, |
49 | | ii_state_flush |
50 | | } ii_state; |
51 | | |
52 | | /* |
53 | | * Tiff interpreter instance |
54 | | */ |
55 | | typedef struct tiff_interp_instance_s { |
56 | | gs_memory_t *memory; |
57 | | gs_memory_t *cmemory; |
58 | | gx_device *dev; |
59 | | gx_device *nulldev; |
60 | | |
61 | | gs_color_space *gray; |
62 | | gs_color_space *rgb; |
63 | | gs_color_space *cmyk; |
64 | | |
65 | | /* Tiff parser state machine */ |
66 | | ii_state state; |
67 | | |
68 | | uint32_t bpp; |
69 | | uint32_t bpc; |
70 | | uint32_t pal_bpc; |
71 | | uint32_t cs; |
72 | | uint32_t width; |
73 | | uint32_t height; |
74 | | uint32_t xresolution; |
75 | | uint32_t yresolution; |
76 | | uint32_t tile_height; |
77 | | uint32_t tile_width; |
78 | | uint32_t tiled; |
79 | | uint32_t compression; |
80 | | uint32_t photometric; |
81 | | uint8_t *palette; |
82 | | |
83 | | uint32_t raw_num_comps; /* As specified in the file */ |
84 | | uint32_t num_comps; /* After processing */ |
85 | | uint32_t raw_byte_width; |
86 | | uint32_t byte_width; |
87 | | |
88 | | gs_image_t image; |
89 | | gs_image_enum *penum; |
90 | | gs_gstate *pgs; |
91 | | |
92 | | size_t buffer_full; |
93 | | size_t buffer_max; |
94 | | byte *tiff_buffer; |
95 | | size_t file_pos; |
96 | | TIFF *handle; |
97 | | int is_rgba; |
98 | | |
99 | | byte *samples; |
100 | | byte *proc_samples; |
101 | | #if defined(SHARE_JPEG) && SHARE_JPEG==0 |
102 | | jpeg_cust_mem_data jmem; |
103 | | #endif |
104 | | } tiff_interp_instance_t; |
105 | | |
106 | | static int |
107 | | tiff_detect_language(const char *s, int len) |
108 | 28.0k | { |
109 | 28.0k | const byte *hdr = (const byte *)s; |
110 | 28.0k | if (len >= 4) { |
111 | 28.0k | if (hdr[0] == 'I' && hdr[1] == 'I' && (hdr[2] == 42 || hdr[2] == 43) && hdr[3] == 0) |
112 | 4.70k | return 100; /* Intel (LSB) order */ |
113 | 23.3k | if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && (hdr[3] == 42 || hdr[3] == 43)) |
114 | 787 | return 100; /* Motorola (MSB) order */ |
115 | 23.3k | } |
116 | | |
117 | 22.5k | return 0; |
118 | 28.0k | } |
119 | | |
120 | | static const pl_interp_characteristics_t tiff_characteristics = { |
121 | | "TIFF", |
122 | | tiff_detect_language, |
123 | | }; |
124 | | |
125 | | /* Get implementation's characteristics */ |
126 | | static const pl_interp_characteristics_t * /* always returns a descriptor */ |
127 | | tiff_impl_characteristics(const pl_interp_implementation_t *impl) /* implementation of interpreter to alloc */ |
128 | 59.1k | { |
129 | 59.1k | return &tiff_characteristics; |
130 | 59.1k | } |
131 | | |
132 | | static void |
133 | | tiff_deallocate(tiff_interp_instance_t *tiff) |
134 | 16.1k | { |
135 | 16.1k | if (tiff == NULL) |
136 | 0 | return; |
137 | | |
138 | 16.1k | rc_decrement_cs(tiff->gray, "tiff_deallocate"); |
139 | 16.1k | rc_decrement_cs(tiff->rgb, "tiff_deallocate"); |
140 | 16.1k | rc_decrement_cs(tiff->cmyk, "tiff_deallocate"); |
141 | | |
142 | 16.1k | if (tiff->pgs != NULL) |
143 | 16.1k | gs_gstate_free_chain(tiff->pgs); |
144 | 16.1k | gs_free_object(tiff->memory, tiff, "tiff_impl_allocate_interp_instance"); |
145 | 16.1k | } |
146 | | |
147 | | /* Deallocate a interpreter instance */ |
148 | | static int |
149 | | tiff_impl_deallocate_interp_instance(pl_interp_implementation_t *impl) |
150 | 16.1k | { |
151 | 16.1k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
152 | | |
153 | 16.1k | tiff_deallocate(tiff); |
154 | 16.1k | impl->interp_client_data = NULL; |
155 | | |
156 | 16.1k | return 0; |
157 | 16.1k | } |
158 | | |
159 | | /* Do per-instance interpreter allocation/init. */ |
160 | | static int |
161 | | tiff_impl_allocate_interp_instance(pl_interp_implementation_t *impl, gs_memory_t *mem) |
162 | 16.1k | { |
163 | 16.1k | int code; |
164 | 16.1k | tiff_interp_instance_t *tiff |
165 | 16.1k | = (tiff_interp_instance_t *)gs_alloc_bytes(mem, |
166 | 16.1k | sizeof(tiff_interp_instance_t), |
167 | 16.1k | "tiff_impl_allocate_interp_instance"); |
168 | 16.1k | if (!tiff) |
169 | 0 | return_error(gs_error_VMerror); |
170 | 16.1k | memset(tiff, 0, sizeof(*tiff)); |
171 | | |
172 | 16.1k | tiff->memory = mem; |
173 | 16.1k | tiff->pgs = gs_gstate_alloc(mem); |
174 | 16.1k | if (tiff->pgs == NULL) |
175 | 0 | goto failVM; |
176 | | |
177 | | /* Push one save level onto the stack to assuage the memory handling */ |
178 | 16.1k | code = gs_gsave(tiff->pgs); |
179 | 16.1k | if (code < 0) |
180 | 0 | goto fail; |
181 | | |
182 | 16.1k | code = gsicc_init_iccmanager(tiff->pgs); |
183 | 16.1k | if (code < 0) |
184 | 0 | goto fail; |
185 | | |
186 | 16.1k | tiff->gray = gs_cspace_new_ICC(mem, tiff->pgs, 1); |
187 | 16.1k | tiff->rgb = gs_cspace_new_ICC(mem, tiff->pgs, 3); |
188 | 16.1k | tiff->cmyk = gs_cspace_new_ICC(mem, tiff->pgs, 4); |
189 | | |
190 | 16.1k | impl->interp_client_data = tiff; |
191 | | |
192 | 16.1k | return 0; |
193 | | |
194 | 0 | failVM: |
195 | 0 | code = gs_note_error(gs_error_VMerror); |
196 | 0 | fail: |
197 | 0 | (void)tiff_deallocate(tiff); |
198 | 0 | return code; |
199 | 0 | } |
200 | | |
201 | | /* |
202 | | * Get the allocator with which to allocate a device |
203 | | */ |
204 | | static gs_memory_t * |
205 | | tiff_impl_get_device_memory(pl_interp_implementation_t *impl) |
206 | 0 | { |
207 | 0 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
208 | |
|
209 | 0 | return tiff->dev ? tiff->dev->memory : NULL; |
210 | 0 | } |
211 | | |
212 | | #if 0 /* UNUSED */ |
213 | | static int |
214 | | tiff_impl_set_param(pl_interp_implementation_t *impl, |
215 | | pl_set_param_type type, |
216 | | const char *param, |
217 | | const void *val) |
218 | | { |
219 | | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
220 | | |
221 | | /* No params set here */ |
222 | | return 0; |
223 | | } |
224 | | |
225 | | static int |
226 | | tiff_impl_add_path(pl_interp_implementation_t *impl, |
227 | | const char *path) |
228 | | { |
229 | | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
230 | | |
231 | | /* No paths to add */ |
232 | | return 0; |
233 | | } |
234 | | |
235 | | static int |
236 | | tiff_impl_post_args_init(pl_interp_implementation_t *impl) |
237 | | { |
238 | | tiff_interp_instance_t *tiff = (jpg_interp_instance_t *)impl->interp_client_data; |
239 | | |
240 | | /* No post args processing */ |
241 | | return 0; |
242 | | } |
243 | | #endif |
244 | | |
245 | | /* Prepare interp instance for the next "job" */ |
246 | | static int |
247 | | tiff_impl_init_job(pl_interp_implementation_t *impl, |
248 | | gx_device *device) |
249 | 5.48k | { |
250 | 5.48k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
251 | | |
252 | 5.48k | tiff->dev = device; |
253 | 5.48k | tiff->state = ii_state_identifying; |
254 | 5.48k | tiff->buffer_full = 0; |
255 | | |
256 | 5.48k | return 0; |
257 | 5.48k | } |
258 | | |
259 | | #if 0 /* UNUSED */ |
260 | | static int |
261 | | tiff_impl_run_prefix_commands(pl_interp_implementation_t *impl, |
262 | | const char *prefix) |
263 | | { |
264 | | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
265 | | |
266 | | return 0; |
267 | | } |
268 | | |
269 | | static int |
270 | | tiff_impl_process_file(pl_interp_implementation_t *impl, const char *filename) |
271 | | { |
272 | | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
273 | | |
274 | | return 0; |
275 | | } |
276 | | #endif |
277 | | |
278 | | /* Do any setup for parser per-cursor */ |
279 | | static int /* ret 0 or +ve if ok, else -ve error code */ |
280 | | tiff_impl_process_begin(pl_interp_implementation_t * impl) |
281 | 5.48k | { |
282 | 5.48k | return 0; |
283 | 5.48k | } |
284 | | |
285 | | /* Ensure we have 'required' bytes to read, and further ensure |
286 | | * that we have no UEL's within those bytes. */ |
287 | | static int |
288 | | ensure_bytes(tiff_interp_instance_t *jpg, stream_cursor_read *pr, int required) |
289 | 5.48k | { |
290 | 5.48k | int n; |
291 | 5.48k | const uint8_t *p = pr->ptr+1; |
292 | 5.48k | const uint8_t *q; |
293 | 5.48k | int avail; |
294 | | |
295 | | /* Find out how many bytes we need to check */ |
296 | 5.48k | n = pr->limit - pr->ptr; |
297 | 5.48k | if (n > required) |
298 | 5.48k | n = required; |
299 | | |
300 | | /* Make sure there are no UELs in that block */ |
301 | 5.48k | q = p + n; |
302 | 5.48k | while (p != q) { |
303 | 27.4k | while (p != q && *p != '\033') |
304 | 21.9k | p++; |
305 | 5.48k | if (p == q) |
306 | 5.48k | break; |
307 | 0 | avail = pr->limit - pr->ptr; |
308 | 0 | if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) { |
309 | | /* At least a partial match to a UEL */ |
310 | 0 | return avail < 9 ? gs_error_NeedInput : gs_error_InterpreterExit; |
311 | 0 | } |
312 | 0 | p++; |
313 | 0 | } |
314 | | |
315 | | /* If we have enough bytes, great, if not, get some more */ |
316 | 5.48k | return (n < required) ? gs_error_NeedInput : 0; |
317 | 5.48k | } |
318 | | |
319 | | static int |
320 | | flush_to_uel(stream_cursor_read *pr) |
321 | 5.48k | { |
322 | 5.48k | const uint8_t *p = pr->ptr+1; |
323 | 5.48k | const uint8_t *q = pr->limit+1; |
324 | 5.48k | int avail; |
325 | | |
326 | 5.48k | while (p != q) { |
327 | 0 | while (p != q && *p != '\033') |
328 | 0 | p++; |
329 | 0 | if (p == q) |
330 | 0 | break; |
331 | 0 | avail = pr->limit - pr->ptr; |
332 | 0 | if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) { |
333 | | /* At least a partial match to a UEL. Bin everything to |
334 | | * the start of the match. */ |
335 | 0 | pr->ptr = p-1; |
336 | 0 | if (avail == 9) /* Complete match. Exit! */ |
337 | 0 | return gs_error_InterpreterExit; |
338 | | /* Partial match. Get more data. */ |
339 | 0 | return gs_error_NeedInput; |
340 | 0 | } |
341 | 0 | p++; |
342 | 0 | } |
343 | | |
344 | 5.48k | pr->ptr = pr->limit; |
345 | | |
346 | 5.48k | return 0; |
347 | 5.48k | } |
348 | | |
349 | | static int |
350 | | bytes_until_uel(const stream_cursor_read *pr) |
351 | 20.1k | { |
352 | 20.1k | const uint8_t *p = pr->ptr+1; |
353 | 20.1k | const uint8_t *q = pr->limit+1; |
354 | 20.1k | int avail; |
355 | | |
356 | 28.8k | while (p != q) { |
357 | 5.12M | while (p != q && *p != '\033') |
358 | 5.10M | p++; |
359 | 16.0k | if (p == q) |
360 | 7.31k | break; |
361 | 8.74k | avail = q - p; |
362 | 8.74k | if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) { |
363 | | /* At least a partial match to a UEL. Everything up to |
364 | | * the start of the match is up for grabs. */ |
365 | 52 | return p - (pr->ptr+1); |
366 | 52 | } |
367 | 8.69k | p++; |
368 | 8.69k | } |
369 | | |
370 | 20.1k | return pr->limit - pr->ptr; |
371 | 20.1k | } |
372 | | |
373 | | static tmsize_t tifsReadProc(thandle_t tiff_, |
374 | | void *buf, |
375 | | tmsize_t size) |
376 | 164k | { |
377 | 164k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
378 | 164k | tmsize_t available = tiff->buffer_full - tiff->file_pos; |
379 | 164k | if (available > size) |
380 | 68.8k | available = size; |
381 | | |
382 | 164k | memcpy(buf, &tiff->tiff_buffer[tiff->file_pos], available); |
383 | 164k | tiff->file_pos += available; |
384 | | |
385 | 164k | return available; |
386 | 164k | } |
387 | | |
388 | | static tmsize_t tifsWriteProc(thandle_t tiff_, |
389 | | void *buf, |
390 | | tmsize_t size) |
391 | 0 | { |
392 | 0 | return 0; |
393 | 0 | } |
394 | | |
395 | | static toff_t tifsSeekProc(thandle_t tiff_, toff_t offset, int whence) |
396 | 339k | { |
397 | 339k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
398 | 339k | size_t pos = tiff->file_pos; |
399 | | |
400 | | /* toff_t is unsigned, which kind of implies they'll never use |
401 | | * SEEK_CUR, or SEEK_END, which makes you wonder why they include |
402 | | * whence at all, but... */ |
403 | 339k | if (whence == 1) { /* SEEK_CURR */ |
404 | 0 | offset += pos; |
405 | 339k | } else if (whence == 2) { /* SEEK_END */ |
406 | 0 | offset += tiff->buffer_full; |
407 | 0 | } |
408 | | /* else assume SEEK_SET */ |
409 | | |
410 | | /* Clamp (Don't check against 0 as toff_t is unsigned) */ |
411 | 339k | if (offset > tiff->buffer_full) |
412 | 191k | offset = tiff->buffer_full; |
413 | | |
414 | 339k | tiff->file_pos = offset; |
415 | | |
416 | 339k | return offset; |
417 | 339k | } |
418 | | |
419 | | static int tifsCloseProc(thandle_t tiff_) |
420 | 1.62k | { |
421 | 1.62k | return 0; |
422 | 1.62k | } |
423 | | |
424 | | static toff_t tifsSizeProc(thandle_t tiff_) |
425 | 2.10k | { |
426 | 2.10k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
427 | | |
428 | 2.10k | return tiff->buffer_full; |
429 | 2.10k | } |
430 | | |
431 | | #if defined(SHARE_JPEG) && SHARE_JPEG==0 |
432 | | static void *gs_j_mem_alloc(j_common_ptr cinfo, size_t size) |
433 | 0 | { |
434 | 0 | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
435 | |
|
436 | 0 | return(gs_alloc_bytes(mem, size, "JPEG allocation")); |
437 | 0 | } |
438 | | |
439 | | static void gs_j_mem_free(j_common_ptr cinfo, void *object, size_t size) |
440 | 0 | { |
441 | 0 | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
442 | |
|
443 | 0 | gs_free_object(mem, object, "JPEG free"); |
444 | 0 | } |
445 | | |
446 | | static long gs_j_mem_init (j_common_ptr cinfo) |
447 | 0 | { |
448 | 0 | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
449 | 0 | gs_memory_t *cmem = NULL; |
450 | |
|
451 | 0 | if (gs_memory_chunk_wrap(&(cmem), mem) < 0) { |
452 | 0 | return (-1); |
453 | 0 | } |
454 | | |
455 | 0 | (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), cmem); |
456 | |
|
457 | 0 | return 0; |
458 | 0 | } |
459 | | |
460 | | static void gs_j_mem_term (j_common_ptr cinfo) |
461 | 0 | { |
462 | 0 | gs_memory_t *cmem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
463 | 0 | gs_memory_t *mem = gs_memory_chunk_target(cmem); |
464 | |
|
465 | 0 | gs_memory_chunk_release(cmem); |
466 | |
|
467 | 0 | (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), mem); |
468 | 0 | } |
469 | | |
470 | | static void * |
471 | | tiff_jpeg_mem_callback(thandle_t tiff_) |
472 | 0 | { |
473 | 0 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
474 | |
|
475 | 0 | (void)jpeg_cust_mem_init(&tiff->jmem, (void *)tiff->memory, |
476 | 0 | gs_j_mem_init, gs_j_mem_term, NULL, |
477 | 0 | gs_j_mem_alloc, gs_j_mem_free, |
478 | 0 | gs_j_mem_alloc, gs_j_mem_free, NULL); |
479 | |
|
480 | 0 | return &tiff->jmem; |
481 | 0 | } |
482 | | #endif /* SHARE_JPEG == 0 */ |
483 | | |
484 | | static int |
485 | | guess_pal_depth(int n, uint16_t *rmap, uint16_t *gmap, uint16_t *bmap) |
486 | 49 | { |
487 | 49 | int i; |
488 | 420 | for (i = 0; i < n; i++) { |
489 | 415 | if (rmap[i] >= 256 || gmap[i] >= 256 || bmap[i] >= 256) |
490 | 44 | return 16; |
491 | 415 | } |
492 | 5 | return 8; |
493 | 49 | } |
494 | | |
495 | | static void |
496 | | blend_alpha(tiff_interp_instance_t *tiff, size_t n, int nc, int planar) |
497 | 164 | { |
498 | 164 | int i = tiff->raw_byte_width * nc; |
499 | 164 | byte *p = tiff->samples; |
500 | 164 | const byte *q = tiff->samples + i; |
501 | | |
502 | 164 | switch (tiff->bpc) |
503 | 164 | { |
504 | 0 | case 1: |
505 | 0 | p += i*8; |
506 | 0 | do |
507 | 0 | { |
508 | 0 | byte a = *--q; |
509 | 0 | *--p = ( a & 1)*255; |
510 | 0 | *--p = ((a>>1) & 1)*255; |
511 | 0 | *--p = ((a>>2) & 1)*255; |
512 | 0 | *--p = ((a>>3) & 1)*255; |
513 | 0 | *--p = ((a>>4) & 1)*255; |
514 | 0 | *--p = ((a>>5) & 1)*255; |
515 | 0 | *--p = ((a>>6) & 1)*255; |
516 | 0 | *--p = ((a>>7) & 1)*255; |
517 | 0 | } |
518 | 0 | while (--i); |
519 | 0 | break; |
520 | 0 | case 2: |
521 | 0 | p += i*4; |
522 | 0 | do |
523 | 0 | { |
524 | 0 | byte a = *--q; |
525 | 0 | *--p = ( a & 3)*0x55; |
526 | 0 | *--p = ((a>>1) & 3)*0x55; |
527 | 0 | *--p = ((a>>2) & 3)*0x55; |
528 | 0 | *--p = ((a>>3) & 3)*0x55; |
529 | 0 | } |
530 | 0 | while (--i); |
531 | 0 | break; |
532 | 0 | case 4: |
533 | 0 | p += i*2; |
534 | 0 | do |
535 | 0 | { |
536 | 0 | byte a = *--q; |
537 | 0 | *--p = ( a & 15)*0x11; |
538 | 0 | *--p = ((a>>1) & 15)*0x11; |
539 | 0 | *--p = ((a>>2) & 15)*0x11; |
540 | 0 | *--p = ((a>>3) & 15)*0x11; |
541 | 0 | } |
542 | 0 | while (--i); |
543 | 0 | break; |
544 | 164 | default: |
545 | 164 | break; |
546 | 164 | } |
547 | | |
548 | 164 | nc--; |
549 | 164 | p = tiff->samples; |
550 | 164 | if (planar == PLANARCONFIG_CONTIG) |
551 | 160 | { |
552 | 160 | q = (const byte *)tiff->samples; |
553 | 4.06M | while (n--) { |
554 | 4.06M | byte a = q[nc]; |
555 | 16.2M | for (i = nc; i > 0; i--) { |
556 | 12.1M | int c = *q++ * a + 255*(255-a); |
557 | 12.1M | c += (c>>7); |
558 | 12.1M | *p++ = c>>8; |
559 | 12.1M | } |
560 | 4.06M | q++; |
561 | 4.06M | } |
562 | 160 | } |
563 | 4 | else |
564 | 4 | { |
565 | 4 | int next_comp = tiff->raw_byte_width; |
566 | 4 | int alpha_offset = nc * next_comp; |
567 | 130k | while (n--) { |
568 | 130k | byte a = p[alpha_offset]; |
569 | 522k | for (i = nc; i > 0; i--) { |
570 | 392k | int c = *p * a + 255*(255-a); |
571 | 392k | c += (c>>7); |
572 | 392k | *p = c>>8; |
573 | 392k | p += next_comp; |
574 | 392k | } |
575 | 130k | p -= alpha_offset; |
576 | 130k | p++; |
577 | 130k | } |
578 | 4 | } |
579 | 164 | } |
580 | | |
581 | | /* Calulate (a*b*c+d) safely */ |
582 | | static uint32_t |
583 | | safe_mla(const gs_memory_t *mem, int *code, uint32_t a, uint32_t b, uint32_t c, uint32_t d) |
584 | 1.22k | { |
585 | | /* UINT_MAX < b*a means overflow, but we can't calculate that... */ |
586 | 1.22k | if (UINT_MAX/b < a) |
587 | 0 | goto fail; |
588 | 1.22k | a *= b; |
589 | 1.22k | if (UINT_MAX/c < a) |
590 | 12 | goto fail; |
591 | 1.20k | a *= c; |
592 | 1.20k | if (UINT_MAX-c < d) |
593 | 0 | goto fail; |
594 | | |
595 | 1.20k | return a+d; |
596 | | |
597 | 12 | fail: |
598 | 12 | emprintf(mem, "Numeric overflow!\n"); |
599 | 12 | *code = gs_error_rangecheck; |
600 | | |
601 | 12 | return 0; |
602 | 1.20k | } |
603 | | |
604 | | static size_t |
605 | | size_mla(const gs_memory_t *mem, int *code, size_t a, size_t b, size_t c, size_t d) |
606 | 524k | { |
607 | | /* SIZE_MAX < b*a means overflow, but we can't calculate that... */ |
608 | 524k | if (SIZE_MAX/b < a) |
609 | 0 | goto fail; |
610 | 524k | a *= b; |
611 | 524k | if (SIZE_MAX/c < a) |
612 | 0 | goto fail; |
613 | 524k | a *= c; |
614 | 524k | if (SIZE_MAX-c < d) |
615 | 0 | goto fail; |
616 | | |
617 | 524k | return a+d; |
618 | | |
619 | 0 | fail: |
620 | 0 | emprintf(mem, "Numeric overflow!\n"); |
621 | 0 | *code = gs_error_rangecheck; |
622 | 0 | return 0; |
623 | 524k | } |
624 | | |
625 | | static int |
626 | | do_tiff_decode(tiff_interp_instance_t *tiff) |
627 | 1.64k | { |
628 | 1.64k | int code = 0; |
629 | 1.64k | int tx, ty; |
630 | 1.64k | short planar; |
631 | 1.64k | float f, scale; |
632 | 1.64k | gs_color_space *cs; |
633 | 1.64k | unsigned int used[GS_IMAGE_MAX_COMPONENTS]; |
634 | 1.64k | gs_string plane_data[GS_IMAGE_MAX_COMPONENTS]; |
635 | 1.64k | int invert = 0; |
636 | 1.64k | int alpha = 0; |
637 | | |
638 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_COMPRESSION, &tiff->compression); |
639 | 1.64k | if (tiff->compression == COMPRESSION_JPEG) { |
640 | 55 | TIFFSetField(tiff->handle, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); |
641 | 55 | } |
642 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_PHOTOMETRIC, &tiff->photometric); |
643 | 1.64k | if (tiff->photometric == PHOTOMETRIC_LOGL || |
644 | 1.63k | tiff->photometric == PHOTOMETRIC_LOGLUV) { |
645 | 210 | TIFFSetField(tiff->handle, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); |
646 | 210 | } |
647 | | |
648 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_IMAGEWIDTH, &tiff->width); |
649 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_IMAGELENGTH, &tiff->height); |
650 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_TILEWIDTH, &tiff->tile_width); |
651 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_TILELENGTH, &tiff->tile_height); |
652 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_BITSPERSAMPLE, &tiff->bpc); |
653 | 1.64k | TIFFGetField(tiff->handle, TIFFTAG_SAMPLESPERPIXEL, &tiff->num_comps); |
654 | 1.64k | if (tiff->num_comps > GS_IMAGE_MAX_COMPONENTS) { |
655 | 65 | emprintf(tiff->memory, "Unsupported TIFF format: too many components\n"); |
656 | 65 | goto fail_decode; |
657 | 65 | } |
658 | 1.57k | tiff->raw_num_comps = tiff->num_comps; |
659 | 1.57k | TIFFGetField(tiff->handle, TIFFTAG_PLANARCONFIG, &planar); |
660 | 1.57k | f = 0; |
661 | 1.57k | TIFFGetField(tiff->handle, TIFFTAG_XRESOLUTION, &f); |
662 | 1.57k | tiff->xresolution = (uint32_t)(f+0.5); |
663 | 1.57k | f = 0; |
664 | 1.57k | TIFFGetField(tiff->handle, TIFFTAG_YRESOLUTION, &f); |
665 | 1.57k | tiff->yresolution = (uint32_t)(f+0.5); |
666 | | |
667 | 1.57k | if (tiff->xresolution == 0) |
668 | 1.46k | tiff->yresolution = tiff->xresolution; |
669 | 1.57k | if (tiff->yresolution == 0) |
670 | 1.53k | tiff->xresolution = tiff->yresolution; |
671 | 1.57k | if (tiff->xresolution == 0) |
672 | 1.53k | tiff->xresolution = tiff->yresolution = 72; |
673 | 1.57k | if (tiff->width == 0 || tiff->height == 0 || tiff->bpc == 0 || tiff->num_comps == 0 || |
674 | 964 | !(planar == PLANARCONFIG_CONTIG || planar == PLANARCONFIG_SEPARATE)) { |
675 | 611 | emprintf(tiff->memory, "Unsupported TIFF format\n"); |
676 | 611 | return gs_error_unknownerror; |
677 | 611 | } |
678 | | |
679 | 964 | tiff->tiled = TIFFIsTiled(tiff->handle); |
680 | | |
681 | 964 | if (!tiff->tiled) { |
682 | 822 | tiff->tile_width = tiff->width; |
683 | 822 | tiff->tile_height = tiff->height; |
684 | 822 | } |
685 | | |
686 | 964 | if (tiff->tiled || planar == PLANARCONFIG_CONTIG) { |
687 | 910 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, tiff->num_comps, tiff->tile_width, 7)>>3; |
688 | 910 | } else { |
689 | 54 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, 1, tiff->tile_width, 7)>>3; |
690 | 54 | } |
691 | 964 | if (code < 0) { |
692 | 11 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
693 | 11 | goto fail_decode; |
694 | 11 | } |
695 | | |
696 | 953 | tiff->raw_byte_width = tiff->byte_width; |
697 | 953 | if (tiff->photometric == PHOTOMETRIC_RGB && tiff->num_comps == 4) |
698 | 4 | { |
699 | | /* RGBA, so alpha data */ |
700 | 4 | alpha = 1; |
701 | 4 | } |
702 | 953 | if (alpha && tiff->bpp < 8) |
703 | 4 | { |
704 | | /* We need to expand the data to 8bpp to blend for alpha. */ |
705 | 4 | if (tiff->bpc != 1 && tiff->bpc != 2 && tiff->bpc != 4) |
706 | 4 | { |
707 | 4 | emprintf1(tiff->memory, "Unsupported: TIFF with alpha and bpc=%d\n", tiff->bpc); |
708 | 4 | code = gs_error_unknownerror; |
709 | 4 | goto fail_decode; |
710 | 4 | } |
711 | 0 | tiff->byte_width *= 8/tiff->bpc; |
712 | 0 | } |
713 | | |
714 | | /* Allocate 'samples' to hold the raw samples values read from libtiff. |
715 | | * The exact size of this buffer depends on which of the multifarious |
716 | | * read routines we are using. (Tiled/RGBAImage/Scanlines) */ |
717 | 949 | if (tiff->compression == COMPRESSION_OJPEG || |
718 | 924 | tiff->photometric == PHOTOMETRIC_YCBCR) { |
719 | 257 | size_t z = size_mla(tiff->memory, &code, sizeof(uint32_t), tiff->width, tiff->height, 0); |
720 | 257 | if (code < 0) { |
721 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
722 | 0 | goto fail_decode; |
723 | 0 | } |
724 | 257 | tiff->is_rgba = 1; |
725 | 257 | tiff->samples = gs_alloc_bytes(tiff->memory, z, "tiff_image"); |
726 | 257 | tiff->tile_width = tiff->width; |
727 | 257 | tiff->tile_height = tiff->height; |
728 | 257 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, tiff->num_comps, tiff->tile_width, 7)>>3; |
729 | 257 | if (code < 0) { |
730 | 1 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
731 | 1 | goto fail_decode; |
732 | 1 | } |
733 | 692 | } else if (tiff->tiled) { |
734 | 96 | tiff->samples = gs_alloc_bytes(tiff->memory, TIFFTileSize(tiff->handle), "tiff_tile"); |
735 | 596 | } else if (planar == PLANARCONFIG_SEPARATE) { |
736 | 46 | tiff->samples = gs_alloc_bytes(tiff->memory, (size_t)tiff->byte_width * tiff->num_comps, "tiff_scan"); |
737 | 550 | } else { |
738 | 550 | tiff->samples = gs_alloc_bytes(tiff->memory, tiff->byte_width, "tiff_scan"); |
739 | 550 | } |
740 | 948 | if (tiff->samples == NULL) { |
741 | 6 | code = gs_error_VMerror; |
742 | 6 | goto fail_decode; |
743 | 6 | } |
744 | 942 | tiff->proc_samples = tiff->samples; |
745 | | |
746 | 942 | tiff->bpp = tiff->bpc * tiff->num_comps; |
747 | 942 | switch(tiff->photometric) { |
748 | 69 | case PHOTOMETRIC_MINISWHITE: |
749 | 69 | invert = 1; |
750 | | /* Fall through */ |
751 | 193 | case PHOTOMETRIC_MINISBLACK: |
752 | 193 | if (tiff->num_comps != 1) { |
753 | 46 | emprintf1(tiff->memory, "Unsupported: TIFF with MINISBLACK with nc=%d\n", tiff->num_comps); |
754 | 46 | code = gs_error_unknownerror; |
755 | 46 | goto fail_decode; |
756 | 46 | } |
757 | 147 | break; |
758 | 147 | case PHOTOMETRIC_RGB: |
759 | 113 | if (tiff->num_comps == 4) { |
760 | 0 | alpha = 1; |
761 | 0 | tiff->num_comps = 3; |
762 | 0 | tiff->bpp = tiff->bpp * 3/4; |
763 | 0 | tiff->byte_width = tiff->byte_width * 3/4; |
764 | 113 | } else if (tiff->num_comps != 3) { |
765 | 2 | emprintf1(tiff->memory, "Unsupported: RGB TIFF nc=%d\n", tiff->num_comps); |
766 | 2 | code = gs_error_unknownerror; |
767 | 2 | goto fail_decode; |
768 | 2 | } |
769 | 111 | break; |
770 | 111 | case PHOTOMETRIC_PALETTE: |
771 | 50 | { |
772 | 50 | uint16_t *rmap, *gmap, *bmap; |
773 | 50 | int i, n = 1<<tiff->bpc; |
774 | 50 | if (tiff->num_comps != 1) { |
775 | 1 | emprintf1(tiff->memory, "Unsupported: Paletted TIFF with nc=%d\n", tiff->num_comps); |
776 | 1 | code = gs_error_unknownerror; |
777 | 1 | goto fail_decode; |
778 | 1 | } |
779 | 49 | if (tiff->bpc > 8) { |
780 | 0 | emprintf1(tiff->memory, "Unsupported: Paletted TIFF with bpc=%d\n", tiff->bpc); |
781 | 0 | code = gs_error_unknownerror; |
782 | 0 | goto fail_decode; |
783 | 0 | } |
784 | 49 | if (!TIFFGetField(tiff->handle, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { |
785 | 0 | emprintf(tiff->memory, "Unsupported: Paletted TIFF with bad palette\n"); |
786 | 0 | code = gs_error_unknownerror; |
787 | 0 | goto fail_decode; |
788 | 0 | } |
789 | 49 | tiff->palette = gs_alloc_bytes(tiff->memory, 3*256, "palette"); |
790 | 49 | if (tiff->palette == NULL) { |
791 | 0 | code = gs_error_VMerror; |
792 | 0 | goto fail_decode; |
793 | 0 | } |
794 | 49 | memset(tiff->palette, 0, 3 * 256); |
795 | 49 | if (guess_pal_depth(n, rmap, gmap, bmap) == 8) { |
796 | 287 | for (i=0; i < n; i++) { |
797 | 282 | tiff->palette[3*i+0] = rmap[i]; |
798 | 282 | tiff->palette[3*i+1] = gmap[i]; |
799 | 282 | tiff->palette[3*i+2] = bmap[i]; |
800 | 282 | } |
801 | 44 | } else { |
802 | 5.64k | for (i=0; i < n; i++) { |
803 | 5.60k | tiff->palette[3*i+0] = rmap[i]*255/65535; |
804 | 5.60k | tiff->palette[3*i+1] = gmap[i]*255/65535; |
805 | 5.60k | tiff->palette[3*i+2] = bmap[i]*255/65535; |
806 | 5.60k | } |
807 | 44 | } |
808 | 49 | tiff->pal_bpc = tiff->bpc; |
809 | 49 | tiff->bpc = 8; |
810 | 49 | tiff->num_comps = 3; |
811 | 49 | tiff->raw_num_comps = 1; |
812 | 49 | tiff->bpp = 24; |
813 | 49 | tiff->byte_width = tiff->tile_width * 3; |
814 | 49 | tiff->raw_byte_width = tiff->byte_width; |
815 | | /* Now we need to make a "proc_samples" area to store the |
816 | | * processed samples in. */ |
817 | 49 | if (tiff->is_rgba) { |
818 | 0 | emprintf(tiff->memory, "Unsupported: Paletted TIFF with RGBA\n"); |
819 | 0 | code = gs_error_unknownerror; |
820 | 0 | goto fail_decode; |
821 | 49 | } else if (tiff->tiled) { |
822 | 5 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 3, 0); |
823 | 5 | if (code < 0) { |
824 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
825 | 0 | goto fail_decode; |
826 | 0 | } |
827 | 5 | tiff->proc_samples = gs_alloc_bytes(tiff->memory, z, "tiff_tile"); |
828 | 5 | if (tiff->proc_samples == NULL) { |
829 | 0 | emprintf(tiff->memory, "Memory allocation failure\n"); |
830 | 0 | goto fail_decode; |
831 | 0 | } |
832 | 44 | } else { |
833 | 44 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, 1, 3, 0); |
834 | 44 | tiff->proc_samples = gs_alloc_bytes(tiff->memory, z, "tiff_scan"); |
835 | 44 | if (tiff->proc_samples == NULL) { |
836 | 0 | emprintf(tiff->memory, "Memory allocation failure\n"); |
837 | 0 | goto fail_decode; |
838 | 0 | } |
839 | 44 | } |
840 | 49 | break; |
841 | 49 | } |
842 | 49 | case PHOTOMETRIC_MASK: |
843 | 7 | if (tiff->num_comps != 1) { |
844 | 1 | emprintf1(tiff->memory, "Unsupported: Mask TIFF with nc=%d\n", tiff->num_comps); |
845 | 1 | code = gs_error_unknownerror; |
846 | 1 | goto fail_decode; |
847 | 1 | } |
848 | 6 | break; |
849 | 82 | case PHOTOMETRIC_SEPARATED: |
850 | 82 | if (tiff->num_comps == 3 || tiff->num_comps == 4) |
851 | 81 | { |
852 | 81 | emprintf1(tiff->memory, "Unsupported: Separated TIFF with nc=%d\n", tiff->num_comps); |
853 | 81 | break; |
854 | 81 | } |
855 | 250 | case PHOTOMETRIC_YCBCR: |
856 | 275 | case PHOTOMETRIC_CIELAB: |
857 | 276 | case PHOTOMETRIC_ICCLAB: |
858 | 276 | case PHOTOMETRIC_ITULAB: |
859 | 276 | if (tiff->num_comps != 3) { |
860 | 6 | emprintf1(tiff->memory, "Unsupported: YUV/LAB TIFF with nc=%d\n", tiff->num_comps); |
861 | 6 | code = gs_error_unknownerror; |
862 | 6 | goto fail_decode; |
863 | 6 | } |
864 | 270 | break; |
865 | 270 | case PHOTOMETRIC_CFA: |
866 | 222 | default: |
867 | 222 | emprintf(tiff->memory, "Unsupported TIFF\n"); |
868 | 222 | tiff->state = ii_state_flush; |
869 | 222 | break; |
870 | 942 | } |
871 | 886 | switch(tiff->num_comps) { |
872 | 26 | default: |
873 | 186 | case 1: |
874 | 186 | cs = tiff->gray; |
875 | 186 | break; |
876 | 609 | case 3: |
877 | 609 | cs = tiff->rgb; |
878 | 609 | break; |
879 | 91 | case 4: |
880 | 91 | cs = tiff->cmyk; |
881 | 91 | break; |
882 | 886 | } |
883 | | |
884 | 886 | switch (tiff->bpc) |
885 | 886 | { |
886 | 24 | case 1: |
887 | 40 | case 2: |
888 | 49 | case 4: |
889 | 784 | case 8: |
890 | 875 | case 16: |
891 | | /* We can cope with all these. */ |
892 | 875 | break; |
893 | 11 | default: |
894 | 11 | emprintf1(tiff->memory, "Unsupported: TIFF with bpc=%d\n", tiff->bpc); |
895 | 11 | code = gs_error_unknownerror; |
896 | 11 | goto fail_decode; |
897 | 886 | } |
898 | | |
899 | | /* Scale to fit, if too large. */ |
900 | 875 | scale = 1.0f; |
901 | 875 | if (tiff->width * tiff->dev->HWResolution[0] > tiff->dev->width * tiff->xresolution) |
902 | 124 | scale = ((float)tiff->dev->width * tiff->xresolution) / (tiff->width * tiff->dev->HWResolution[0]); |
903 | 875 | if (scale * tiff->height * tiff->dev->HWResolution[1] > tiff->dev->height * tiff->yresolution) |
904 | 86 | scale = ((float)tiff->dev->height * tiff->yresolution) / (tiff->height * tiff->dev->HWResolution[1]); |
905 | | |
906 | 875 | code = gs_erasepage(tiff->pgs); |
907 | 875 | if (code < 0) |
908 | 0 | return code; |
909 | | |
910 | 38.4k | for (ty = 0; ty < tiff->height; ty += tiff->tile_height) { |
911 | 454k | for (tx = 0; tx < tiff->width; tx += tiff->tile_width) { |
912 | 416k | int y, s; |
913 | 416k | byte *row; |
914 | 416k | float xext, xoffset, yext, yoffset; |
915 | 416k | int tremx, tremy; |
916 | | |
917 | 416k | tiff->penum = gs_image_enum_alloc(tiff->memory, "tiff_impl_process(penum)"); |
918 | 416k | if (tiff->penum == NULL) |
919 | 0 | return_error(gs_error_VMerror); |
920 | | |
921 | | /* Centre - Extents and offsets are all calculated in points (1/72 of an inch) */ |
922 | 416k | xext = (((float)tiff->width - tx * 2) * 72 * scale / tiff->xresolution); |
923 | 416k | xoffset = (tiff->dev->width * 72 / tiff->dev->HWResolution[0] - xext)/2; |
924 | 416k | yext = (((float)tiff->height - ty * 2) * 72 * scale / tiff->yresolution); |
925 | 416k | yoffset = (tiff->dev->height * 72 / tiff->dev->HWResolution[1] - yext)/2; |
926 | | |
927 | 416k | gs_initmatrix(tiff->pgs); |
928 | | |
929 | | /* By default the ctm is set to: |
930 | | * xres/72 0 |
931 | | * 0 -yres/72 |
932 | | * 0 dev->height * yres/72 |
933 | | * i.e. it moves the origin from being top right to being bottom left. |
934 | | * We want to move it back, as without this, the image will be displayed |
935 | | * upside down. |
936 | | */ |
937 | 416k | code = gs_translate(tiff->pgs, 0.0, tiff->dev->height * 72 / tiff->dev->HWResolution[1]); |
938 | 416k | if (code >= 0) |
939 | 416k | code = gs_translate(tiff->pgs, xoffset, -yoffset); |
940 | 416k | if (code >= 0) |
941 | 416k | code = gs_scale(tiff->pgs, scale, -scale); |
942 | 416k | if (code < 0) |
943 | 0 | goto fail_decode; |
944 | | |
945 | 416k | memset(&tiff->image, 0, sizeof(tiff->image)); |
946 | 416k | gs_image_t_init(&tiff->image, cs); |
947 | 416k | tiff->image.BitsPerComponent = tiff->bpp/tiff->num_comps; |
948 | 416k | if (alpha) |
949 | 0 | tiff->image.BitsPerComponent = 8; |
950 | 416k | tiff->image.Width = tiff->tile_width; |
951 | 416k | tiff->image.Height = tiff->tile_height; |
952 | | |
953 | 416k | tiff->image.ImageMatrix.xx = tiff->xresolution / 72.0f; |
954 | 416k | tiff->image.ImageMatrix.yy = tiff->yresolution / 72.0f; |
955 | 416k | if (invert) { |
956 | 4.90k | tiff->image.Decode[0] = 1; |
957 | 4.90k | tiff->image.Decode[1] = 0; |
958 | 4.90k | tiff->image.Decode[2] = 1; |
959 | 4.90k | tiff->image.Decode[3] = 0; |
960 | 4.90k | tiff->image.Decode[4] = 1; |
961 | 4.90k | tiff->image.Decode[5] = 0; |
962 | 4.90k | tiff->image.Decode[6] = 1; |
963 | 4.90k | tiff->image.Decode[7] = 0; |
964 | 4.90k | } |
965 | | |
966 | 416k | if (tiff->is_rgba) { |
967 | 247 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 1, 0); |
968 | 247 | if (code < 0) |
969 | 0 | goto fail_decode; |
970 | 247 | if (TIFFReadRGBAImage(tiff->handle, tiff->width, tiff->height, |
971 | 247 | (uint32_t *)tiff->samples, 0) == 0) { |
972 | 83 | code = gs_error_unknownerror; |
973 | 83 | goto fail_decode; |
974 | 83 | } |
975 | 164 | blend_alpha(tiff, z, 4, planar); |
976 | 416k | } else if (tiff->tiled) { |
977 | 415k | if (TIFFReadTile(tiff->handle, tiff->samples, tx, ty, 0, 0) == 0) { |
978 | 0 | code = gs_error_unknownerror; |
979 | 0 | goto fail_decode; |
980 | 0 | } |
981 | 415k | } else if (planar != PLANARCONFIG_CONTIG) { |
982 | 39 | tiff->image.format = gs_image_format_component_planar; |
983 | 39 | } |
984 | | |
985 | 416k | if (!tiff->is_rgba && tiff->tiled) { |
986 | 415k | if (tiff->palette) { |
987 | 107k | size_t n = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 1, 0); |
988 | 107k | byte *q = tiff->samples; |
989 | 107k | byte *p = tiff->proc_samples; |
990 | 107k | if (code < 0) |
991 | 0 | goto fail_decode; |
992 | 971k | while (n--) { |
993 | 863k | byte *v = &tiff->palette[3 * *q++]; |
994 | 863k | p[0] = *v++; |
995 | 863k | p[1] = *v++; |
996 | 863k | p[2] = *v++; |
997 | 863k | p += 3; |
998 | 863k | } |
999 | 107k | } |
1000 | 415k | if (alpha) { |
1001 | 0 | blend_alpha(tiff, tiff->tile_width, tiff->num_comps, planar); |
1002 | 0 | } |
1003 | 415k | } |
1004 | | |
1005 | 416k | code = gs_image_init(tiff->penum, |
1006 | 416k | &tiff->image, |
1007 | 416k | false, |
1008 | 416k | false, |
1009 | 416k | tiff->pgs); |
1010 | 416k | if (code < 0) { |
1011 | 2 | goto fail_decode; |
1012 | 2 | } |
1013 | | |
1014 | 416k | tremx = tiff->width - tx; |
1015 | 416k | if (tremx > tiff->tile_width) |
1016 | 378k | tremx = tiff->tile_width; |
1017 | 416k | tremy = tiff->height - ty; |
1018 | 416k | if (tremy > tiff->tile_height) |
1019 | 407k | tremy = tiff->tile_height; |
1020 | 416k | { |
1021 | | /* Make sure we won't overflow in the loop. */ |
1022 | 416k | (void)size_mla(tiff->memory, &code, tiff->byte_width, tiff->tile_height, 1, 0); |
1023 | 416k | if (code < 0) |
1024 | 0 | goto fail_decode; |
1025 | 416k | } |
1026 | 4.39M | for (y = 0; y < tremy; y++) { |
1027 | 3.98M | if (tiff->is_rgba) { |
1028 | 941k | row = tiff->proc_samples + (size_t)tiff->byte_width * (tiff->tile_height-1-y); |
1029 | 3.04M | } else if (tiff->tiled) { |
1030 | 1.61M | row = tiff->proc_samples + (size_t)tiff->byte_width * y; |
1031 | 1.61M | } else if (planar == PLANARCONFIG_CONTIG) { |
1032 | 1.40M | row = tiff->proc_samples; |
1033 | 1.40M | if (TIFFReadScanline(tiff->handle, tiff->samples, ty+y, 0) == 0) { |
1034 | 0 | code = gs_error_unknownerror; |
1035 | 0 | goto fail_decode; |
1036 | 0 | } |
1037 | 1.40M | } else { |
1038 | 16.0k | int span = tiff->raw_byte_width; |
1039 | 16.0k | byte *in_row = tiff->samples; |
1040 | 16.0k | row = tiff->proc_samples; |
1041 | 37.1k | for (s = 0; s < tiff->raw_num_comps; s++) { |
1042 | 21.1k | plane_data[s].data = row; |
1043 | 21.1k | plane_data[s].size = span; |
1044 | 21.1k | if (TIFFReadScanline(tiff->handle, in_row, ty+y, s) == 0) { |
1045 | 0 | code = gs_error_unknownerror; |
1046 | 0 | goto fail_decode; |
1047 | 0 | } |
1048 | 21.1k | row += span; |
1049 | 21.1k | in_row += span; |
1050 | 21.1k | } |
1051 | 16.0k | row -= span * tiff->raw_num_comps; |
1052 | 16.0k | } |
1053 | | |
1054 | 3.98M | if (tiff->bpc == 16) |
1055 | 552k | { |
1056 | 552k | byte *p = row; |
1057 | 552k | int n = tiff->tile_width * tiff->raw_num_comps; |
1058 | 30.4M | while (n--) |
1059 | 29.8M | { |
1060 | 29.8M | byte b = p[0]; |
1061 | 29.8M | p[0] = p[1]; |
1062 | 29.8M | p[1] = b; |
1063 | 29.8M | p += 2; |
1064 | 29.8M | } |
1065 | 552k | } |
1066 | | |
1067 | 3.98M | if (!tiff->tiled) { |
1068 | 1.51M | if (tiff->palette) { |
1069 | 26.6k | int n = tiff->tile_width; |
1070 | 26.6k | const byte *q = tiff->samples; |
1071 | 26.6k | byte *p = tiff->proc_samples; |
1072 | 26.6k | switch (tiff->pal_bpc) |
1073 | 26.6k | { |
1074 | 11.1k | case 8: |
1075 | 8.93M | while (n--) { |
1076 | 8.92M | byte *v = &tiff->palette[3 * *q++]; |
1077 | 8.92M | p[0] = *v++; |
1078 | 8.92M | p[1] = *v++; |
1079 | 8.92M | p[2] = *v++; |
1080 | 8.92M | p += 3; |
1081 | 8.92M | } |
1082 | 11.1k | break; |
1083 | 15.2k | case 1: |
1084 | 15.2k | { |
1085 | 15.2k | int sh = 7; |
1086 | 14.7M | while (n--) { |
1087 | 14.6M | byte *v = &tiff->palette[3 * (((*q)>>sh) & 1)]; |
1088 | 14.6M | sh--; |
1089 | 14.6M | if (sh < 0) |
1090 | 1.83M | sh = 7, q++; |
1091 | 14.6M | p[0] = *v++; |
1092 | 14.6M | p[1] = *v++; |
1093 | 14.6M | p[2] = *v++; |
1094 | 14.6M | p += 3; |
1095 | 14.6M | } |
1096 | 15.2k | break; |
1097 | 0 | } |
1098 | 111 | case 2: |
1099 | 111 | { |
1100 | 111 | int sh = 6; |
1101 | 36.3k | while (n--) { |
1102 | 36.1k | byte *v = &tiff->palette[3 * (((*q)>>sh) & 3)]; |
1103 | 36.1k | sh -= 2; |
1104 | 36.1k | if (sh < 0) |
1105 | 9.04k | sh = 6, q++; |
1106 | 36.1k | p[0] = *v++; |
1107 | 36.1k | p[1] = *v++; |
1108 | 36.1k | p[2] = *v++; |
1109 | 36.1k | p += 3; |
1110 | 36.1k | } |
1111 | 111 | break; |
1112 | 0 | } |
1113 | 161 | case 4: |
1114 | 161 | { |
1115 | 161 | int sh = 4; |
1116 | 4.34k | while (n--) { |
1117 | 4.17k | byte *v = &tiff->palette[3 * (((*q)>>sh) & 15)]; |
1118 | 4.17k | sh ^= 4; |
1119 | 4.17k | if (sh == 4) |
1120 | 2.07k | q++; |
1121 | 4.17k | p[0] = *v++; |
1122 | 4.17k | p[1] = *v++; |
1123 | 4.17k | p[2] = *v++; |
1124 | 4.17k | p += 3; |
1125 | 4.17k | } |
1126 | 161 | break; |
1127 | 0 | } |
1128 | 26.6k | } |
1129 | 26.6k | } |
1130 | 1.51M | if (alpha) { |
1131 | 0 | blend_alpha(tiff, tiff->tile_width, tiff->raw_num_comps, planar); |
1132 | 0 | } |
1133 | 1.51M | } |
1134 | | |
1135 | 3.98M | if (tiff->image.format == gs_image_format_component_planar) { |
1136 | 16.0k | code = gs_image_next_planes(tiff->penum, (gs_const_string *)&plane_data[0], used, false); |
1137 | 3.96M | } else { |
1138 | 3.96M | code = gs_image_next(tiff->penum, row, tiff->byte_width, used); |
1139 | 3.96M | } |
1140 | 3.98M | if (code < 0) { |
1141 | 22 | code = gs_error_unknownerror; |
1142 | 22 | goto fail_decode; |
1143 | 22 | } |
1144 | 3.98M | } |
1145 | 416k | code = gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1146 | 416k | tiff->penum = NULL; |
1147 | 416k | if (code < 0) |
1148 | 0 | return code; |
1149 | 416k | } |
1150 | 37.7k | } |
1151 | 768 | tiff->state = ii_state_flush; |
1152 | 768 | (void)pl_finish_page(tiff->memory->gs_lib_ctx->top_of_system, |
1153 | 768 | tiff->pgs, 1, true); |
1154 | 768 | return 0; |
1155 | | |
1156 | 261 | fail_decode: |
1157 | 261 | if (tiff->penum) |
1158 | 107 | { |
1159 | 107 | (void)gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1160 | 107 | tiff->penum = NULL; |
1161 | 107 | } |
1162 | 261 | tiff->state = ii_state_flush; |
1163 | | |
1164 | 261 | return code; |
1165 | 875 | } |
1166 | | |
1167 | | static int |
1168 | | decode_all_tiffs(tiff_interp_instance_t *tiff) |
1169 | 1.62k | { |
1170 | 1.62k | int code; |
1171 | | |
1172 | 1.62k | tiff->nulldev = gs_currentdevice(tiff->pgs); |
1173 | 1.62k | rc_increment(tiff->nulldev); |
1174 | 1.62k | code = gs_setdevice_no_erase(tiff->pgs, tiff->dev); |
1175 | 1.62k | if (code < 0) |
1176 | 0 | return code; |
1177 | | |
1178 | 1.62k | do |
1179 | 1.64k | { |
1180 | 1.64k | code = do_tiff_decode(tiff); |
1181 | 1.64k | if (code < 0) |
1182 | 807 | return code; |
1183 | 1.64k | } |
1184 | 1.62k | while (TIFFReadDirectory(tiff->handle)); |
1185 | | |
1186 | 816 | return 0; |
1187 | 1.62k | } |
1188 | | |
1189 | | |
1190 | | static int |
1191 | | do_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr, int eof) |
1192 | 12.8k | { |
1193 | 12.8k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
1194 | 12.8k | int code = 0; |
1195 | 12.8k | ii_state ostate = (ii_state)-1; |
1196 | 12.8k | int bytes_left = 0; |
1197 | | |
1198 | 44.0k | while (tiff->state != ostate || pr->limit - pr->ptr != bytes_left) |
1199 | 36.6k | { |
1200 | 36.6k | ostate = tiff->state; |
1201 | 36.6k | bytes_left = pr->limit - pr->ptr; |
1202 | 36.6k | switch(tiff->state) |
1203 | 36.6k | { |
1204 | 5.48k | case ii_state_identifying: |
1205 | 5.48k | { |
1206 | 5.48k | const byte *hdr; |
1207 | | /* Try and get us 4 bytes */ |
1208 | 5.48k | code = ensure_bytes(tiff, pr, 4); |
1209 | 5.48k | if (code < 0) |
1210 | 0 | return code; |
1211 | 5.48k | hdr = pr->ptr+1; |
1212 | 5.48k | if (hdr[0] == 'I' && hdr[1] == 'I' && (hdr[2] == 42 || hdr[2] == 43) && hdr[3] == 0) { |
1213 | 4.69k | tiff->state = ii_state_tiff; |
1214 | 4.69k | break; |
1215 | 4.69k | } |
1216 | 787 | if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && (hdr[3] == 42 || hdr[3] == 43)) { |
1217 | 787 | tiff->state = ii_state_tiff; |
1218 | 787 | break; |
1219 | 787 | } |
1220 | 0 | tiff->state = ii_state_flush; |
1221 | 0 | break; |
1222 | 787 | } |
1223 | 20.1k | case ii_state_tiff: |
1224 | 20.1k | { |
1225 | | /* Gather data into a buffer */ |
1226 | 20.1k | int bytes = bytes_until_uel(pr); |
1227 | | |
1228 | 20.1k | if (bytes == 0 && pr->limit - pr->ptr > 9) { |
1229 | | /* No bytes until UEL, and there is space for a UEL in the buffer */ |
1230 | 0 | tiff->state = ii_state_tiff_decode; |
1231 | 0 | tiff->file_pos = 0; |
1232 | 0 | break; |
1233 | 0 | } |
1234 | 20.1k | if (bytes == 0 && eof) { |
1235 | | /* No bytes until UEL, and we are at eof */ |
1236 | 5.48k | tiff->state = ii_state_tiff_decode; |
1237 | 5.48k | tiff->file_pos = 0; |
1238 | 5.48k | break; |
1239 | 5.48k | } |
1240 | | |
1241 | 14.7k | if (tiff->buffer_full + bytes > tiff->buffer_max) { |
1242 | | /* Need to expand our buffer */ |
1243 | 5.51k | size_t proposed = tiff->buffer_full*2; |
1244 | 5.51k | if (proposed == 0) |
1245 | 5.48k | proposed = 32768; |
1246 | 5.51k | while (proposed < tiff->buffer_full + bytes) |
1247 | 0 | proposed *= 2; |
1248 | | |
1249 | 5.51k | if (tiff->tiff_buffer == NULL) { |
1250 | 5.48k | tiff->tiff_buffer = gs_alloc_bytes(tiff->memory, proposed, "tiff_buffer"); |
1251 | 5.48k | if (tiff->tiff_buffer == NULL) { |
1252 | 0 | tiff->state = ii_state_flush; |
1253 | 0 | break; |
1254 | 0 | } |
1255 | 5.48k | } else { |
1256 | 29 | void *new_buf = gs_resize_object(tiff->memory, tiff->tiff_buffer, proposed, "tiff_buffer"); |
1257 | 29 | if (new_buf == NULL) { |
1258 | 0 | tiff->state = ii_state_flush; |
1259 | 0 | break; |
1260 | 0 | } |
1261 | 29 | tiff->tiff_buffer = new_buf; |
1262 | 29 | } |
1263 | 5.51k | tiff->buffer_max = proposed; |
1264 | 5.51k | } |
1265 | | |
1266 | 14.7k | memcpy(&tiff->tiff_buffer[tiff->buffer_full], pr->ptr+1, bytes); |
1267 | 14.7k | tiff->buffer_full += bytes; |
1268 | 14.7k | pr->ptr += bytes; |
1269 | 14.7k | code = gs_error_NeedInput; |
1270 | 14.7k | break; |
1271 | 14.7k | } |
1272 | 5.48k | case ii_state_tiff_decode: |
1273 | 5.48k | { |
1274 | 5.48k | tiff->handle = TIFFClientOpen("dummy", "rm", |
1275 | 5.48k | (thandle_t)tiff, |
1276 | 5.48k | tifsReadProc, |
1277 | 5.48k | tifsWriteProc, |
1278 | 5.48k | tifsSeekProc, |
1279 | 5.48k | tifsCloseProc, |
1280 | 5.48k | tifsSizeProc, |
1281 | 5.48k | NULL, |
1282 | 5.48k | NULL); |
1283 | 5.48k | if (tiff->handle == NULL) { |
1284 | 3.86k | tiff->state = ii_state_flush; |
1285 | 3.86k | break; |
1286 | 3.86k | } |
1287 | | |
1288 | 1.62k | #if defined(SHARE_JPEG) && SHARE_JPEG==0 |
1289 | 1.62k | TIFFSetJpegMemFunction(tiff->handle, |
1290 | 1.62k | &tiff_jpeg_mem_callback); |
1291 | 1.62k | #endif |
1292 | | |
1293 | 1.62k | code = decode_all_tiffs(tiff); |
1294 | 1.62k | if (code < 0) |
1295 | 807 | { |
1296 | 807 | tiff->state = ii_state_flush; |
1297 | 807 | break; |
1298 | 807 | } |
1299 | 816 | break; |
1300 | 1.62k | } |
1301 | 816 | default: |
1302 | 5.48k | case ii_state_flush: |
1303 | | |
1304 | 5.48k | if (tiff->handle) { |
1305 | 1.62k | TIFFClose(tiff->handle); |
1306 | 1.62k | tiff->handle = NULL; |
1307 | 1.62k | } |
1308 | | |
1309 | 5.48k | if (tiff->penum) { |
1310 | 0 | (void)gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1311 | 0 | tiff->penum = NULL; |
1312 | 0 | } |
1313 | | |
1314 | 5.48k | if (tiff->proc_samples && tiff->proc_samples != tiff->samples) { |
1315 | 48 | gs_free_object(tiff->memory, tiff->proc_samples, "tiff_impl_process(samples)"); |
1316 | 48 | tiff->proc_samples = NULL; |
1317 | 48 | } |
1318 | | |
1319 | 5.48k | if (tiff->samples) { |
1320 | 927 | gs_free_object(tiff->memory, tiff->samples, "tiff_impl_process(samples)"); |
1321 | 927 | tiff->samples = NULL; |
1322 | 927 | tiff->proc_samples = NULL; |
1323 | 927 | } |
1324 | | |
1325 | 5.48k | if (tiff->palette) { |
1326 | 48 | gs_free_object(tiff->memory, tiff->palette, "tiff_impl_process(samples)"); |
1327 | 48 | tiff->palette = NULL; |
1328 | 48 | } |
1329 | | |
1330 | 5.48k | if (tiff->tiff_buffer) { |
1331 | 5.48k | gs_free_object(tiff->memory, tiff->tiff_buffer, "tiff_impl_process(tiff_buffer)"); |
1332 | 5.48k | tiff->tiff_buffer = NULL; |
1333 | 5.48k | tiff->buffer_max = 0; |
1334 | 5.48k | tiff->buffer_full = 0; |
1335 | 5.48k | } |
1336 | | /* We want to bin any data we get up to, but not including |
1337 | | * a UEL. */ |
1338 | 5.48k | return flush_to_uel(pr); |
1339 | 36.6k | } |
1340 | 36.6k | } |
1341 | | |
1342 | 7.37k | return code; |
1343 | 12.8k | } |
1344 | | |
1345 | | static int |
1346 | 7.37k | tiff_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr) { |
1347 | 7.37k | return do_impl_process(impl, pr, 0); |
1348 | 7.37k | } |
1349 | | |
1350 | | static int |
1351 | | tiff_impl_process_end(pl_interp_implementation_t * impl) |
1352 | 5.48k | { |
1353 | 5.48k | return 0; |
1354 | 5.48k | } |
1355 | | |
1356 | | /* Not implemented */ |
1357 | | static int |
1358 | | tiff_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor) |
1359 | 0 | { |
1360 | 0 | const byte *p = cursor->ptr; |
1361 | 0 | const byte *rlimit = cursor->limit; |
1362 | | |
1363 | | /* Skip to, but leave UEL in buffer for PJL to find later */ |
1364 | 0 | for (; p < rlimit; ++p) |
1365 | 0 | if (p[1] == '\033') { |
1366 | 0 | uint avail = rlimit - p; |
1367 | |
|
1368 | 0 | if (memcmp(p + 1, "\033%-12345X", min(avail, 9))) |
1369 | 0 | continue; |
1370 | 0 | if (avail < 9) |
1371 | 0 | break; |
1372 | 0 | cursor->ptr = p; |
1373 | 0 | return 1; /* found eoj */ |
1374 | 0 | } |
1375 | 0 | cursor->ptr = p; |
1376 | 0 | return 0; /* need more */ |
1377 | 0 | } |
1378 | | |
1379 | | /* Parser action for end-of-file */ |
1380 | | static int |
1381 | | tiff_impl_process_eof(pl_interp_implementation_t *impl) |
1382 | 5.48k | { |
1383 | 5.48k | stream_cursor_read r; |
1384 | | |
1385 | 5.48k | r.ptr = NULL; |
1386 | 5.48k | r.limit = NULL; |
1387 | 5.48k | return do_impl_process(impl, &r, 1); |
1388 | 5.48k | } |
1389 | | |
1390 | | /* Report any errors after running a job */ |
1391 | | static int |
1392 | | tiff_impl_report_errors(pl_interp_implementation_t *impl, /* interp instance to wrap up job in */ |
1393 | | int code, /* prev termination status */ |
1394 | | long file_position, /* file position of error, -1 if unknown */ |
1395 | | bool force_to_cout /* force errors to cout */ |
1396 | | ) |
1397 | 0 | { |
1398 | 0 | return 0; |
1399 | 0 | } |
1400 | | |
1401 | | /* Wrap up interp instance after a "job" */ |
1402 | | static int |
1403 | | tiff_impl_dnit_job(pl_interp_implementation_t *impl) |
1404 | 5.48k | { |
1405 | 5.48k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
1406 | | |
1407 | 5.48k | if (tiff->nulldev) { |
1408 | 1.62k | int code = gs_setdevice(tiff->pgs, tiff->nulldev); |
1409 | 1.62k | tiff->dev = NULL; |
1410 | 1.62k | rc_decrement(tiff->nulldev, "tiff_impl_dnit_job(nulldevice)"); |
1411 | 1.62k | tiff->nulldev = NULL; |
1412 | 1.62k | return code; |
1413 | 1.62k | } |
1414 | 3.86k | return 0; |
1415 | 5.48k | } |
1416 | | |
1417 | | /* Parser implementation descriptor */ |
1418 | | const pl_interp_implementation_t tiff_implementation = { |
1419 | | tiff_impl_characteristics, |
1420 | | tiff_impl_allocate_interp_instance, |
1421 | | tiff_impl_get_device_memory, |
1422 | | NULL, /* tiff_impl_set_param */ |
1423 | | NULL, /* tiff_impl_add_path */ |
1424 | | NULL, /* tiff_impl_post_args_init */ |
1425 | | tiff_impl_init_job, |
1426 | | NULL, /* tiff_impl_run_prefix_commands */ |
1427 | | NULL, /* tiff_impl_process_file */ |
1428 | | tiff_impl_process_begin, |
1429 | | tiff_impl_process, |
1430 | | tiff_impl_process_end, |
1431 | | tiff_impl_flush_to_eoj, |
1432 | | tiff_impl_process_eof, |
1433 | | tiff_impl_report_errors, |
1434 | | tiff_impl_dnit_job, |
1435 | | tiff_impl_deallocate_interp_instance, |
1436 | | NULL, /* tiff_impl_reset */ |
1437 | | NULL /* interp_client_data */ |
1438 | | }; |
1439 | | #endif /* TIFF_INCLUDED */ |