/src/ghostpdl/gpdl/tifftop.c
Line | Count | Source |
1 | | /* Copyright (C) 2019-2025 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 | 17.7k | { |
109 | 17.7k | const byte *hdr = (const byte *)s; |
110 | 17.7k | if (len >= 4) { |
111 | 17.7k | if (hdr[0] == 'I' && hdr[1] == 'I' && (hdr[2] == 42 || hdr[2] == 43) && hdr[3] == 0) |
112 | 19 | return 100; /* Intel (LSB) order */ |
113 | 17.6k | if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && (hdr[3] == 42 || hdr[3] == 43)) |
114 | 0 | return 100; /* Motorola (MSB) order */ |
115 | 17.6k | } |
116 | | |
117 | 17.7k | return 0; |
118 | 17.7k | } |
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 | 37.5k | { |
129 | 37.5k | return &tiff_characteristics; |
130 | 37.5k | } |
131 | | |
132 | | static void |
133 | | tiff_deallocate(tiff_interp_instance_t *tiff) |
134 | 8.09k | { |
135 | 8.09k | if (tiff == NULL) |
136 | 0 | return; |
137 | | |
138 | 8.09k | rc_decrement_cs(tiff->gray, "tiff_deallocate"); |
139 | 8.09k | rc_decrement_cs(tiff->rgb, "tiff_deallocate"); |
140 | 8.09k | rc_decrement_cs(tiff->cmyk, "tiff_deallocate"); |
141 | | |
142 | 8.09k | if (tiff->pgs != NULL) |
143 | 8.09k | gs_gstate_free_chain(tiff->pgs); |
144 | 8.09k | gs_free_object(tiff->memory, tiff, "tiff_impl_allocate_interp_instance"); |
145 | 8.09k | } |
146 | | |
147 | | /* Deallocate a interpreter instance */ |
148 | | static int |
149 | | tiff_impl_deallocate_interp_instance(pl_interp_implementation_t *impl) |
150 | 8.09k | { |
151 | 8.09k | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
152 | | |
153 | 8.09k | tiff_deallocate(tiff); |
154 | 8.09k | impl->interp_client_data = NULL; |
155 | | |
156 | 8.09k | return 0; |
157 | 8.09k | } |
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 | 8.09k | { |
163 | 8.09k | int code; |
164 | 8.09k | tiff_interp_instance_t *tiff |
165 | 8.09k | = (tiff_interp_instance_t *)gs_alloc_bytes(mem, |
166 | 8.09k | sizeof(tiff_interp_instance_t), |
167 | 8.09k | "tiff_impl_allocate_interp_instance"); |
168 | 8.09k | if (!tiff) |
169 | 0 | return_error(gs_error_VMerror); |
170 | 8.09k | memset(tiff, 0, sizeof(*tiff)); |
171 | | |
172 | 8.09k | tiff->memory = mem; |
173 | 8.09k | tiff->pgs = gs_gstate_alloc(mem); |
174 | 8.09k | if (tiff->pgs == NULL) |
175 | 0 | goto failVM; |
176 | | |
177 | | /* Push one save level onto the stack to assuage the memory handling */ |
178 | 8.09k | code = gs_gsave(tiff->pgs); |
179 | 8.09k | if (code < 0) |
180 | 0 | goto fail; |
181 | | |
182 | 8.09k | code = gsicc_init_iccmanager(tiff->pgs); |
183 | 8.09k | if (code < 0) |
184 | 0 | goto fail; |
185 | | |
186 | 8.09k | tiff->gray = gs_cspace_new_ICC(mem, tiff->pgs, 1); |
187 | 8.09k | tiff->rgb = gs_cspace_new_ICC(mem, tiff->pgs, 3); |
188 | 8.09k | tiff->cmyk = gs_cspace_new_ICC(mem, tiff->pgs, 4); |
189 | | |
190 | 8.09k | impl->interp_client_data = tiff; |
191 | | |
192 | 8.09k | 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 | 19 | { |
250 | 19 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
251 | | |
252 | 19 | tiff->dev = device; |
253 | 19 | tiff->state = ii_state_identifying; |
254 | 19 | tiff->buffer_full = 0; |
255 | | |
256 | 19 | return 0; |
257 | 19 | } |
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 | 19 | { |
282 | 19 | return 0; |
283 | 19 | } |
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 | 19 | { |
290 | 19 | int n; |
291 | 19 | const uint8_t *p = pr->ptr+1; |
292 | 19 | const uint8_t *q; |
293 | 19 | int avail; |
294 | | |
295 | | /* Find out how many bytes we need to check */ |
296 | 19 | n = pr->limit - pr->ptr; |
297 | 19 | if (n > required) |
298 | 18 | n = required; |
299 | | |
300 | | /* Make sure there are no UELs in that block */ |
301 | 19 | q = p + n; |
302 | 19 | while (p != q) { |
303 | 95 | while (p != q && *p != '\033') |
304 | 76 | p++; |
305 | 19 | if (p == q) |
306 | 19 | 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 | 19 | return (n < required) ? gs_error_NeedInput : 0; |
317 | 19 | } |
318 | | |
319 | | static int |
320 | | flush_to_uel(stream_cursor_read *pr) |
321 | 19 | { |
322 | 19 | const uint8_t *p = pr->ptr+1; |
323 | 19 | const uint8_t *q = pr->limit+1; |
324 | 19 | int avail; |
325 | | |
326 | 19 | 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 | 19 | pr->ptr = pr->limit; |
345 | | |
346 | 19 | return 0; |
347 | 19 | } |
348 | | |
349 | | static int |
350 | | bytes_until_uel(const stream_cursor_read *pr) |
351 | 173 | { |
352 | 173 | const uint8_t *p = pr->ptr+1; |
353 | 173 | const uint8_t *q = pr->limit+1; |
354 | 173 | int avail; |
355 | | |
356 | 478 | while (p != q) { |
357 | 131k | while (p != q && *p != '\033') |
358 | 130k | p++; |
359 | 381 | if (p == q) |
360 | 76 | break; |
361 | 305 | avail = q - p; |
362 | 305 | 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 | 0 | return p - (pr->ptr+1); |
366 | 0 | } |
367 | 305 | p++; |
368 | 305 | } |
369 | | |
370 | 173 | return pr->limit - pr->ptr; |
371 | 173 | } |
372 | | |
373 | | static tmsize_t tifsReadProc(thandle_t tiff_, |
374 | | void *buf, |
375 | | tmsize_t size) |
376 | 48 | { |
377 | 48 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
378 | 48 | tmsize_t available = tiff->buffer_full - tiff->file_pos; |
379 | 48 | if (available > size) |
380 | 38 | available = size; |
381 | | |
382 | 48 | memcpy(buf, &tiff->tiff_buffer[tiff->file_pos], available); |
383 | 48 | tiff->file_pos += available; |
384 | | |
385 | 48 | return available; |
386 | 48 | } |
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 | 22 | { |
397 | 22 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
398 | 22 | 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 | 22 | if (whence == 1) { /* SEEK_CURR */ |
404 | 0 | offset += pos; |
405 | 22 | } 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 | 22 | if (offset > tiff->buffer_full) |
412 | 10 | offset = tiff->buffer_full; |
413 | | |
414 | 22 | tiff->file_pos = offset; |
415 | | |
416 | 22 | return offset; |
417 | 22 | } |
418 | | |
419 | | static int tifsCloseProc(thandle_t tiff_) |
420 | 0 | { |
421 | 0 | return 0; |
422 | 0 | } |
423 | | |
424 | | static toff_t tifsSizeProc(thandle_t tiff_) |
425 | 10 | { |
426 | 10 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_; |
427 | | |
428 | 10 | return tiff->buffer_full; |
429 | 10 | } |
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 | 0 | { |
487 | 0 | int i; |
488 | 0 | for (i = 0; i < n; i++) { |
489 | 0 | if (rmap[i] >= 256 || gmap[i] >= 256 || bmap[i] >= 256) |
490 | 0 | return 16; |
491 | 0 | } |
492 | 0 | return 8; |
493 | 0 | } |
494 | | |
495 | | static void |
496 | | blend_alpha(tiff_interp_instance_t *tiff, size_t n, int nc, int planar) |
497 | 0 | { |
498 | 0 | int i = tiff->raw_byte_width * nc; |
499 | 0 | byte *p = tiff->samples; |
500 | 0 | const byte *q = tiff->samples + i; |
501 | |
|
502 | 0 | switch (tiff->bpc) |
503 | 0 | { |
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 | 0 | default: |
545 | 0 | break; |
546 | 0 | } |
547 | | |
548 | 0 | nc--; |
549 | 0 | p = tiff->samples; |
550 | 0 | if (planar == PLANARCONFIG_CONTIG) |
551 | 0 | { |
552 | 0 | q = (const byte *)tiff->samples; |
553 | 0 | while (n--) { |
554 | 0 | byte a = q[nc]; |
555 | 0 | for (i = nc; i > 0; i--) { |
556 | 0 | int c = *q++ * a + 255*(255-a); |
557 | 0 | c += (c>>7); |
558 | 0 | *p++ = c>>8; |
559 | 0 | } |
560 | 0 | q++; |
561 | 0 | } |
562 | 0 | } |
563 | 0 | else |
564 | 0 | { |
565 | 0 | int next_comp = tiff->raw_byte_width; |
566 | 0 | int alpha_offset = nc * next_comp; |
567 | 0 | while (n--) { |
568 | 0 | byte a = p[alpha_offset]; |
569 | 0 | for (i = nc; i > 0; i--) { |
570 | 0 | int c = *p * a + 255*(255-a); |
571 | 0 | c += (c>>7); |
572 | 0 | *p = c>>8; |
573 | 0 | p += next_comp; |
574 | 0 | } |
575 | 0 | p -= alpha_offset; |
576 | 0 | p++; |
577 | 0 | } |
578 | 0 | } |
579 | 0 | } |
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 | 0 | { |
585 | | /* UINT_MAX < b*a means overflow, but we can't calculate that... */ |
586 | 0 | if (UINT_MAX/b < a) |
587 | 0 | goto fail; |
588 | 0 | a *= b; |
589 | 0 | if (UINT_MAX/c < a) |
590 | 0 | goto fail; |
591 | 0 | a *= c; |
592 | 0 | if (UINT_MAX-c < d) |
593 | 0 | goto fail; |
594 | | |
595 | 0 | return a+d; |
596 | | |
597 | 0 | fail: |
598 | 0 | emprintf(mem, "Numeric overflow!\n"); |
599 | 0 | *code = gs_error_rangecheck; |
600 | |
|
601 | 0 | return 0; |
602 | 0 | } |
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 | 0 | { |
607 | | /* SIZE_MAX < b*a means overflow, but we can't calculate that... */ |
608 | 0 | if (SIZE_MAX/b < a) |
609 | 0 | goto fail; |
610 | 0 | a *= b; |
611 | 0 | if (SIZE_MAX/c < a) |
612 | 0 | goto fail; |
613 | 0 | a *= c; |
614 | 0 | if (SIZE_MAX-c < d) |
615 | 0 | goto fail; |
616 | | |
617 | 0 | 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 | 0 | } |
624 | | |
625 | | static int |
626 | | do_tiff_decode(tiff_interp_instance_t *tiff) |
627 | 0 | { |
628 | 0 | int code = 0; |
629 | 0 | int tx, ty; |
630 | 0 | short planar; |
631 | 0 | float f, scale; |
632 | 0 | gs_color_space *cs; |
633 | 0 | unsigned int used[GS_IMAGE_MAX_COMPONENTS]; |
634 | 0 | gs_string plane_data[GS_IMAGE_MAX_COMPONENTS]; |
635 | 0 | int invert = 0; |
636 | 0 | int alpha = 0; |
637 | |
|
638 | 0 | TIFFGetField(tiff->handle, TIFFTAG_COMPRESSION, &tiff->compression); |
639 | 0 | if (tiff->compression == COMPRESSION_JPEG) { |
640 | 0 | TIFFSetField(tiff->handle, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); |
641 | 0 | } |
642 | 0 | TIFFGetField(tiff->handle, TIFFTAG_PHOTOMETRIC, &tiff->photometric); |
643 | 0 | if (tiff->photometric == PHOTOMETRIC_LOGL || |
644 | 0 | tiff->photometric == PHOTOMETRIC_LOGLUV) { |
645 | 0 | TIFFSetField(tiff->handle, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); |
646 | 0 | } |
647 | |
|
648 | 0 | TIFFGetField(tiff->handle, TIFFTAG_IMAGEWIDTH, &tiff->width); |
649 | 0 | TIFFGetField(tiff->handle, TIFFTAG_IMAGELENGTH, &tiff->height); |
650 | 0 | TIFFGetField(tiff->handle, TIFFTAG_TILEWIDTH, &tiff->tile_width); |
651 | 0 | TIFFGetField(tiff->handle, TIFFTAG_TILELENGTH, &tiff->tile_height); |
652 | 0 | TIFFGetField(tiff->handle, TIFFTAG_BITSPERSAMPLE, &tiff->bpc); |
653 | 0 | TIFFGetField(tiff->handle, TIFFTAG_SAMPLESPERPIXEL, &tiff->num_comps); |
654 | 0 | tiff->raw_num_comps = tiff->num_comps; |
655 | 0 | TIFFGetField(tiff->handle, TIFFTAG_PLANARCONFIG, &planar); |
656 | 0 | f = 0; |
657 | 0 | TIFFGetField(tiff->handle, TIFFTAG_XRESOLUTION, &f); |
658 | 0 | tiff->xresolution = (uint32_t)(f+0.5); |
659 | 0 | f = 0; |
660 | 0 | TIFFGetField(tiff->handle, TIFFTAG_YRESOLUTION, &f); |
661 | 0 | tiff->yresolution = (uint32_t)(f+0.5); |
662 | |
|
663 | 0 | if (tiff->xresolution == 0) |
664 | 0 | tiff->yresolution = tiff->xresolution; |
665 | 0 | if (tiff->yresolution == 0) |
666 | 0 | tiff->xresolution = tiff->yresolution; |
667 | 0 | if (tiff->xresolution == 0) |
668 | 0 | tiff->xresolution = tiff->yresolution = 72; |
669 | 0 | if (tiff->width == 0 || tiff->height == 0 || tiff->bpc == 0 || tiff->num_comps == 0 || |
670 | 0 | !(planar == PLANARCONFIG_CONTIG || planar == PLANARCONFIG_SEPARATE)) { |
671 | 0 | emprintf(tiff->memory, "Unsupported TIFF format\n"); |
672 | 0 | return gs_error_unknownerror; |
673 | 0 | } |
674 | | |
675 | 0 | tiff->tiled = TIFFIsTiled(tiff->handle); |
676 | |
|
677 | 0 | if (!tiff->tiled) { |
678 | 0 | tiff->tile_width = tiff->width; |
679 | 0 | tiff->tile_height = tiff->height; |
680 | 0 | } |
681 | |
|
682 | 0 | if (tiff->tiled || planar == PLANARCONFIG_CONTIG) { |
683 | 0 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, tiff->num_comps, tiff->tile_width, 7)>>3; |
684 | 0 | } else { |
685 | 0 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, 1, tiff->tile_width, 7)>>3; |
686 | 0 | } |
687 | 0 | if (code < 0) { |
688 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
689 | 0 | goto fail_decode; |
690 | 0 | } |
691 | | |
692 | 0 | tiff->raw_byte_width = tiff->byte_width; |
693 | 0 | if (tiff->photometric == PHOTOMETRIC_RGB && tiff->num_comps == 4) |
694 | 0 | { |
695 | | /* RGBA, so alpha data */ |
696 | 0 | alpha = 1; |
697 | 0 | } |
698 | 0 | if (alpha && tiff->bpp < 8) |
699 | 0 | { |
700 | | /* We need to expand the data to 8bpp to blend for alpha. */ |
701 | 0 | if (tiff->bpc != 1 && tiff->bpc != 2 && tiff->bpc != 4) |
702 | 0 | { |
703 | 0 | emprintf1(tiff->memory, "Unsupported: TIFF with alpha and bpc=%d\n", tiff->bpc); |
704 | 0 | code = gs_error_unknownerror; |
705 | 0 | goto fail_decode; |
706 | 0 | } |
707 | 0 | tiff->byte_width *= 8/tiff->bpc; |
708 | 0 | } |
709 | | |
710 | | /* Allocate 'samples' to hold the raw samples values read from libtiff. |
711 | | * The exact size of this buffer depends on which of the multifarious |
712 | | * read routines we are using. (Tiled/RGBAImage/Scanlines) */ |
713 | 0 | if (tiff->compression == COMPRESSION_OJPEG || |
714 | 0 | tiff->photometric == PHOTOMETRIC_YCBCR) { |
715 | 0 | size_t z = size_mla(tiff->memory, &code, sizeof(uint32_t), tiff->width, tiff->height, 0); |
716 | 0 | if (code < 0) { |
717 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
718 | 0 | goto fail_decode; |
719 | 0 | } |
720 | 0 | tiff->is_rgba = 1; |
721 | 0 | tiff->samples = gs_alloc_bytes(tiff->memory, z, "tiff_image"); |
722 | 0 | tiff->tile_width = tiff->width; |
723 | 0 | tiff->tile_height = tiff->height; |
724 | 0 | tiff->byte_width = safe_mla(tiff->memory, &code, tiff->bpc, tiff->num_comps, tiff->tile_width, 7)>>3; |
725 | 0 | if (code < 0) { |
726 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
727 | 0 | goto fail_decode; |
728 | 0 | } |
729 | 0 | } else if (tiff->tiled) { |
730 | 0 | tiff->samples = gs_alloc_bytes(tiff->memory, TIFFTileSize(tiff->handle), "tiff_tile"); |
731 | 0 | } else if (planar == PLANARCONFIG_SEPARATE) { |
732 | 0 | tiff->samples = gs_alloc_bytes(tiff->memory, (size_t)tiff->byte_width * tiff->num_comps, "tiff_scan"); |
733 | 0 | } else { |
734 | 0 | tiff->samples = gs_alloc_bytes(tiff->memory, tiff->byte_width, "tiff_scan"); |
735 | 0 | } |
736 | 0 | if (tiff->samples == NULL) { |
737 | 0 | code = gs_error_VMerror; |
738 | 0 | goto fail_decode; |
739 | 0 | } |
740 | 0 | tiff->proc_samples = tiff->samples; |
741 | |
|
742 | 0 | tiff->bpp = tiff->bpc * tiff->num_comps; |
743 | 0 | switch(tiff->photometric) { |
744 | 0 | case PHOTOMETRIC_MINISWHITE: |
745 | 0 | invert = 1; |
746 | | /* Fall through */ |
747 | 0 | case PHOTOMETRIC_MINISBLACK: |
748 | 0 | if (tiff->num_comps != 1) { |
749 | 0 | emprintf1(tiff->memory, "Unsupported: TIFF with MINISBLACK with nc=%d\n", tiff->num_comps); |
750 | 0 | code = gs_error_unknownerror; |
751 | 0 | goto fail_decode; |
752 | 0 | } |
753 | 0 | break; |
754 | 0 | case PHOTOMETRIC_RGB: |
755 | 0 | if (tiff->num_comps == 4) { |
756 | 0 | alpha = 1; |
757 | 0 | tiff->num_comps = 3; |
758 | 0 | tiff->bpp = tiff->bpp * 3/4; |
759 | 0 | tiff->byte_width = tiff->byte_width * 3/4; |
760 | 0 | } else if (tiff->num_comps != 3) { |
761 | 0 | emprintf1(tiff->memory, "Unsupported: RGB TIFF nc=%d\n", tiff->num_comps); |
762 | 0 | code = gs_error_unknownerror; |
763 | 0 | goto fail_decode; |
764 | 0 | } |
765 | 0 | break; |
766 | 0 | case PHOTOMETRIC_PALETTE: |
767 | 0 | { |
768 | 0 | uint16_t *rmap, *gmap, *bmap; |
769 | 0 | int i, n = 1<<tiff->bpc; |
770 | 0 | if (tiff->num_comps != 1) { |
771 | 0 | emprintf1(tiff->memory, "Unsupported: Paletted TIFF with nc=%d\n", tiff->num_comps); |
772 | 0 | code = gs_error_unknownerror; |
773 | 0 | goto fail_decode; |
774 | 0 | } |
775 | 0 | if (tiff->bpc > 8) { |
776 | 0 | emprintf1(tiff->memory, "Unsupported: Paletted TIFF with bpc=%d\n", tiff->bpc); |
777 | 0 | code = gs_error_unknownerror; |
778 | 0 | goto fail_decode; |
779 | 0 | } |
780 | 0 | if (!TIFFGetField(tiff->handle, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) { |
781 | 0 | emprintf(tiff->memory, "Unsupported: Paletted TIFF with bad palette\n"); |
782 | 0 | code = gs_error_unknownerror; |
783 | 0 | goto fail_decode; |
784 | 0 | } |
785 | 0 | tiff->palette = gs_alloc_bytes(tiff->memory, 3*256, "palette"); |
786 | 0 | if (tiff->palette == NULL) { |
787 | 0 | code = gs_error_VMerror; |
788 | 0 | goto fail_decode; |
789 | 0 | } |
790 | 0 | memset(tiff->palette, 0, 3 * 256); |
791 | 0 | if (guess_pal_depth(n, rmap, gmap, bmap) == 8) { |
792 | 0 | for (i=0; i < n; i++) { |
793 | 0 | tiff->palette[3*i+0] = rmap[i]; |
794 | 0 | tiff->palette[3*i+1] = gmap[i]; |
795 | 0 | tiff->palette[3*i+2] = bmap[i]; |
796 | 0 | } |
797 | 0 | } else { |
798 | 0 | for (i=0; i < n; i++) { |
799 | 0 | tiff->palette[3*i+0] = rmap[i]*255/65535; |
800 | 0 | tiff->palette[3*i+1] = gmap[i]*255/65535; |
801 | 0 | tiff->palette[3*i+2] = bmap[i]*255/65535; |
802 | 0 | } |
803 | 0 | } |
804 | 0 | tiff->pal_bpc = tiff->bpc; |
805 | 0 | tiff->bpc = 8; |
806 | 0 | tiff->num_comps = 3; |
807 | 0 | tiff->raw_num_comps = 1; |
808 | 0 | tiff->bpp = 24; |
809 | 0 | tiff->byte_width = tiff->tile_width * 3; |
810 | 0 | tiff->raw_byte_width = tiff->byte_width; |
811 | | /* Now we need to make a "proc_samples" area to store the |
812 | | * processed samples in. */ |
813 | 0 | if (tiff->is_rgba) { |
814 | 0 | emprintf(tiff->memory, "Unsupported: Paletted TIFF with RGBA\n"); |
815 | 0 | code = gs_error_unknownerror; |
816 | 0 | goto fail_decode; |
817 | 0 | } else if (tiff->tiled) { |
818 | 0 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 3, 0); |
819 | 0 | if (code < 0) { |
820 | 0 | emprintf(tiff->memory, "Unsupported: TIFF size overflow\n"); |
821 | 0 | goto fail_decode; |
822 | 0 | } |
823 | 0 | tiff->proc_samples = gs_alloc_bytes(tiff->memory, z, "tiff_tile"); |
824 | 0 | if (tiff->proc_samples == NULL) { |
825 | 0 | emprintf(tiff->memory, "Memory allocation failure\n"); |
826 | 0 | goto fail_decode; |
827 | 0 | } |
828 | 0 | } else { |
829 | 0 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, 1, 3, 0); |
830 | 0 | tiff->proc_samples = gs_alloc_bytes(tiff->memory, z, "tiff_scan"); |
831 | 0 | if (tiff->proc_samples == NULL) { |
832 | 0 | emprintf(tiff->memory, "Memory allocation failure\n"); |
833 | 0 | goto fail_decode; |
834 | 0 | } |
835 | 0 | } |
836 | 0 | break; |
837 | 0 | } |
838 | 0 | case PHOTOMETRIC_MASK: |
839 | 0 | if (tiff->num_comps != 1) { |
840 | 0 | emprintf1(tiff->memory, "Unsupported: Mask TIFF with nc=%d\n", tiff->num_comps); |
841 | 0 | code = gs_error_unknownerror; |
842 | 0 | goto fail_decode; |
843 | 0 | } |
844 | 0 | break; |
845 | 0 | case PHOTOMETRIC_SEPARATED: |
846 | 0 | if (tiff->num_comps == 3 || tiff->num_comps == 4) |
847 | 0 | { |
848 | 0 | emprintf1(tiff->memory, "Unsupported: Separated TIFF with nc=%d\n", tiff->num_comps); |
849 | 0 | break; |
850 | 0 | } |
851 | 0 | case PHOTOMETRIC_YCBCR: |
852 | 0 | case PHOTOMETRIC_CIELAB: |
853 | 0 | case PHOTOMETRIC_ICCLAB: |
854 | 0 | case PHOTOMETRIC_ITULAB: |
855 | 0 | if (tiff->num_comps != 3) { |
856 | 0 | emprintf1(tiff->memory, "Unsupported: YUV/LAB TIFF with nc=%d\n", tiff->num_comps); |
857 | 0 | code = gs_error_unknownerror; |
858 | 0 | goto fail_decode; |
859 | 0 | } |
860 | 0 | break; |
861 | 0 | case PHOTOMETRIC_CFA: |
862 | 0 | default: |
863 | 0 | emprintf(tiff->memory, "Unsupported TIFF\n"); |
864 | 0 | tiff->state = ii_state_flush; |
865 | 0 | break; |
866 | 0 | } |
867 | 0 | switch(tiff->num_comps) { |
868 | 0 | default: |
869 | 0 | case 1: |
870 | 0 | cs = tiff->gray; |
871 | 0 | break; |
872 | 0 | case 3: |
873 | 0 | cs = tiff->rgb; |
874 | 0 | break; |
875 | 0 | case 4: |
876 | 0 | cs = tiff->cmyk; |
877 | 0 | break; |
878 | 0 | } |
879 | | |
880 | 0 | switch (tiff->bpc) |
881 | 0 | { |
882 | 0 | case 1: |
883 | 0 | case 2: |
884 | 0 | case 4: |
885 | 0 | case 8: |
886 | 0 | case 16: |
887 | | /* We can cope with all these. */ |
888 | 0 | break; |
889 | 0 | default: |
890 | 0 | emprintf1(tiff->memory, "Unsupported: TIFF with bpc=%d\n", tiff->bpc); |
891 | 0 | code = gs_error_unknownerror; |
892 | 0 | goto fail_decode; |
893 | 0 | } |
894 | | |
895 | | /* Scale to fit, if too large. */ |
896 | 0 | scale = 1.0f; |
897 | 0 | if (tiff->width * tiff->dev->HWResolution[0] > tiff->dev->width * tiff->xresolution) |
898 | 0 | scale = ((float)tiff->dev->width * tiff->xresolution) / (tiff->width * tiff->dev->HWResolution[0]); |
899 | 0 | if (scale * tiff->height * tiff->dev->HWResolution[1] > tiff->dev->height * tiff->yresolution) |
900 | 0 | scale = ((float)tiff->dev->height * tiff->yresolution) / (tiff->height * tiff->dev->HWResolution[1]); |
901 | |
|
902 | 0 | code = gs_erasepage(tiff->pgs); |
903 | 0 | if (code < 0) |
904 | 0 | return code; |
905 | | |
906 | 0 | for (ty = 0; ty < tiff->height; ty += tiff->tile_height) { |
907 | 0 | for (tx = 0; tx < tiff->width; tx += tiff->tile_width) { |
908 | 0 | int y, s; |
909 | 0 | byte *row; |
910 | 0 | float xext, xoffset, yext, yoffset; |
911 | 0 | int tremx, tremy; |
912 | |
|
913 | 0 | tiff->penum = gs_image_enum_alloc(tiff->memory, "tiff_impl_process(penum)"); |
914 | 0 | if (tiff->penum == NULL) |
915 | 0 | return_error(gs_error_VMerror); |
916 | | |
917 | | /* Centre - Extents and offsets are all calculated in points (1/72 of an inch) */ |
918 | 0 | xext = (((float)tiff->width - tx * 2) * 72 * scale / tiff->xresolution); |
919 | 0 | xoffset = (tiff->dev->width * 72 / tiff->dev->HWResolution[0] - xext)/2; |
920 | 0 | yext = (((float)tiff->height - ty * 2) * 72 * scale / tiff->yresolution); |
921 | 0 | yoffset = (tiff->dev->height * 72 / tiff->dev->HWResolution[1] - yext)/2; |
922 | |
|
923 | 0 | gs_initmatrix(tiff->pgs); |
924 | | |
925 | | /* By default the ctm is set to: |
926 | | * xres/72 0 |
927 | | * 0 -yres/72 |
928 | | * 0 dev->height * yres/72 |
929 | | * i.e. it moves the origin from being top right to being bottom left. |
930 | | * We want to move it back, as without this, the image will be displayed |
931 | | * upside down. |
932 | | */ |
933 | 0 | code = gs_translate(tiff->pgs, 0.0, tiff->dev->height * 72 / tiff->dev->HWResolution[1]); |
934 | 0 | if (code >= 0) |
935 | 0 | code = gs_translate(tiff->pgs, xoffset, -yoffset); |
936 | 0 | if (code >= 0) |
937 | 0 | code = gs_scale(tiff->pgs, scale, -scale); |
938 | 0 | if (code < 0) |
939 | 0 | goto fail_decode; |
940 | | |
941 | 0 | memset(&tiff->image, 0, sizeof(tiff->image)); |
942 | 0 | gs_image_t_init(&tiff->image, cs); |
943 | 0 | tiff->image.BitsPerComponent = tiff->bpp/tiff->num_comps; |
944 | 0 | if (alpha) |
945 | 0 | tiff->image.BitsPerComponent = 8; |
946 | 0 | tiff->image.Width = tiff->tile_width; |
947 | 0 | tiff->image.Height = tiff->tile_height; |
948 | |
|
949 | 0 | tiff->image.ImageMatrix.xx = tiff->xresolution / 72.0f; |
950 | 0 | tiff->image.ImageMatrix.yy = tiff->yresolution / 72.0f; |
951 | 0 | if (invert) { |
952 | 0 | tiff->image.Decode[0] = 1; |
953 | 0 | tiff->image.Decode[1] = 0; |
954 | 0 | tiff->image.Decode[2] = 1; |
955 | 0 | tiff->image.Decode[3] = 0; |
956 | 0 | tiff->image.Decode[4] = 1; |
957 | 0 | tiff->image.Decode[5] = 0; |
958 | 0 | tiff->image.Decode[6] = 1; |
959 | 0 | tiff->image.Decode[7] = 0; |
960 | 0 | } |
961 | |
|
962 | 0 | if (tiff->is_rgba) { |
963 | 0 | size_t z = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 1, 0); |
964 | 0 | if (code < 0) |
965 | 0 | goto fail_decode; |
966 | 0 | if (TIFFReadRGBAImage(tiff->handle, tiff->width, tiff->height, |
967 | 0 | (uint32_t *)tiff->samples, 0) == 0) { |
968 | 0 | code = gs_error_unknownerror; |
969 | 0 | goto fail_decode; |
970 | 0 | } |
971 | 0 | blend_alpha(tiff, z, 4, planar); |
972 | 0 | } else if (tiff->tiled) { |
973 | 0 | if (TIFFReadTile(tiff->handle, tiff->samples, tx, ty, 0, 0) == 0) { |
974 | 0 | code = gs_error_unknownerror; |
975 | 0 | goto fail_decode; |
976 | 0 | } |
977 | 0 | } else if (planar != PLANARCONFIG_CONTIG) { |
978 | 0 | tiff->image.format = gs_image_format_component_planar; |
979 | 0 | } |
980 | | |
981 | 0 | if (!tiff->is_rgba && tiff->tiled) { |
982 | 0 | if (tiff->palette) { |
983 | 0 | size_t n = size_mla(tiff->memory, &code, tiff->tile_width, tiff->tile_height, 1, 0); |
984 | 0 | byte *q = tiff->samples; |
985 | 0 | byte *p = tiff->proc_samples; |
986 | 0 | if (code < 0) |
987 | 0 | goto fail_decode; |
988 | 0 | while (n--) { |
989 | 0 | byte *v = &tiff->palette[3 * *q++]; |
990 | 0 | p[0] = *v++; |
991 | 0 | p[1] = *v++; |
992 | 0 | p[2] = *v++; |
993 | 0 | p += 3; |
994 | 0 | } |
995 | 0 | } |
996 | 0 | if (alpha) { |
997 | 0 | blend_alpha(tiff, tiff->tile_width, tiff->num_comps, planar); |
998 | 0 | } |
999 | 0 | } |
1000 | | |
1001 | 0 | code = gs_image_init(tiff->penum, |
1002 | 0 | &tiff->image, |
1003 | 0 | false, |
1004 | 0 | false, |
1005 | 0 | tiff->pgs); |
1006 | 0 | if (code < 0) { |
1007 | 0 | goto fail_decode; |
1008 | 0 | } |
1009 | | |
1010 | 0 | tremx = tiff->width - tx; |
1011 | 0 | if (tremx > tiff->tile_width) |
1012 | 0 | tremx = tiff->tile_width; |
1013 | 0 | tremy = tiff->height - ty; |
1014 | 0 | if (tremy > tiff->tile_height) |
1015 | 0 | tremy = tiff->tile_height; |
1016 | 0 | { |
1017 | | /* Make sure we won't overflow in the loop. */ |
1018 | 0 | (void)size_mla(tiff->memory, &code, tiff->byte_width, tiff->tile_height, 1, 0); |
1019 | 0 | if (code < 0) |
1020 | 0 | goto fail_decode; |
1021 | 0 | } |
1022 | 0 | for (y = 0; y < tremy; y++) { |
1023 | 0 | if (tiff->is_rgba) { |
1024 | 0 | row = tiff->proc_samples + (size_t)tiff->byte_width * (tiff->tile_height-1-y); |
1025 | 0 | } else if (tiff->tiled) { |
1026 | 0 | row = tiff->proc_samples + (size_t)tiff->byte_width * y; |
1027 | 0 | } else if (planar == PLANARCONFIG_CONTIG) { |
1028 | 0 | row = tiff->proc_samples; |
1029 | 0 | if (TIFFReadScanline(tiff->handle, tiff->samples, ty+y, 0) == 0) { |
1030 | 0 | code = gs_error_unknownerror; |
1031 | 0 | goto fail_decode; |
1032 | 0 | } |
1033 | 0 | } else { |
1034 | 0 | int span = tiff->raw_byte_width; |
1035 | 0 | byte *in_row = tiff->samples; |
1036 | 0 | row = tiff->proc_samples; |
1037 | 0 | for (s = 0; s < tiff->raw_num_comps; s++) { |
1038 | 0 | plane_data[s].data = row; |
1039 | 0 | plane_data[s].size = span; |
1040 | 0 | if (TIFFReadScanline(tiff->handle, in_row, ty+y, s) == 0) { |
1041 | 0 | code = gs_error_unknownerror; |
1042 | 0 | goto fail_decode; |
1043 | 0 | } |
1044 | 0 | row += span; |
1045 | 0 | in_row += span; |
1046 | 0 | } |
1047 | 0 | row -= span * tiff->raw_num_comps; |
1048 | 0 | } |
1049 | | |
1050 | 0 | if (tiff->bpc == 16) |
1051 | 0 | { |
1052 | 0 | byte *p = row; |
1053 | 0 | int n = tiff->tile_width * tiff->raw_num_comps; |
1054 | 0 | while (n--) |
1055 | 0 | { |
1056 | 0 | byte b = p[0]; |
1057 | 0 | p[0] = p[1]; |
1058 | 0 | p[1] = b; |
1059 | 0 | p += 2; |
1060 | 0 | } |
1061 | 0 | } |
1062 | |
|
1063 | 0 | if (!tiff->tiled) { |
1064 | 0 | if (tiff->palette) { |
1065 | 0 | int n = tiff->tile_width; |
1066 | 0 | const byte *q = tiff->samples; |
1067 | 0 | byte *p = tiff->proc_samples; |
1068 | 0 | switch (tiff->pal_bpc) |
1069 | 0 | { |
1070 | 0 | case 8: |
1071 | 0 | while (n--) { |
1072 | 0 | byte *v = &tiff->palette[3 * *q++]; |
1073 | 0 | p[0] = *v++; |
1074 | 0 | p[1] = *v++; |
1075 | 0 | p[2] = *v++; |
1076 | 0 | p += 3; |
1077 | 0 | } |
1078 | 0 | break; |
1079 | 0 | case 1: |
1080 | 0 | { |
1081 | 0 | int sh = 7; |
1082 | 0 | while (n--) { |
1083 | 0 | byte *v = &tiff->palette[3 * (((*q)>>sh) & 1)]; |
1084 | 0 | sh--; |
1085 | 0 | if (sh < 0) |
1086 | 0 | sh = 7, q++; |
1087 | 0 | p[0] = *v++; |
1088 | 0 | p[1] = *v++; |
1089 | 0 | p[2] = *v++; |
1090 | 0 | p += 3; |
1091 | 0 | } |
1092 | 0 | break; |
1093 | 0 | } |
1094 | 0 | case 2: |
1095 | 0 | { |
1096 | 0 | int sh = 6; |
1097 | 0 | while (n--) { |
1098 | 0 | byte *v = &tiff->palette[3 * (((*q)>>sh) & 3)]; |
1099 | 0 | sh -= 2; |
1100 | 0 | if (sh < 0) |
1101 | 0 | sh = 6, q++; |
1102 | 0 | p[0] = *v++; |
1103 | 0 | p[1] = *v++; |
1104 | 0 | p[2] = *v++; |
1105 | 0 | p += 3; |
1106 | 0 | } |
1107 | 0 | break; |
1108 | 0 | } |
1109 | 0 | case 4: |
1110 | 0 | { |
1111 | 0 | int sh = 4; |
1112 | 0 | while (n--) { |
1113 | 0 | byte *v = &tiff->palette[3 * (((*q)>>sh) & 15)]; |
1114 | 0 | sh ^= 4; |
1115 | 0 | if (sh == 4) |
1116 | 0 | q++; |
1117 | 0 | p[0] = *v++; |
1118 | 0 | p[1] = *v++; |
1119 | 0 | p[2] = *v++; |
1120 | 0 | p += 3; |
1121 | 0 | } |
1122 | 0 | break; |
1123 | 0 | } |
1124 | 0 | } |
1125 | 0 | } |
1126 | 0 | if (alpha) { |
1127 | 0 | blend_alpha(tiff, tiff->tile_width, tiff->raw_num_comps, planar); |
1128 | 0 | } |
1129 | 0 | } |
1130 | | |
1131 | 0 | if (tiff->image.format == gs_image_format_component_planar) { |
1132 | 0 | code = gs_image_next_planes(tiff->penum, (gs_const_string *)&plane_data[0], used, false); |
1133 | 0 | } else { |
1134 | 0 | code = gs_image_next(tiff->penum, row, tiff->byte_width, used); |
1135 | 0 | } |
1136 | 0 | if (code < 0) { |
1137 | 0 | code = gs_error_unknownerror; |
1138 | 0 | goto fail_decode; |
1139 | 0 | } |
1140 | 0 | } |
1141 | 0 | code = gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1142 | 0 | tiff->penum = NULL; |
1143 | 0 | if (code < 0) |
1144 | 0 | return code; |
1145 | 0 | } |
1146 | 0 | } |
1147 | 0 | tiff->state = ii_state_flush; |
1148 | 0 | (void)pl_finish_page(tiff->memory->gs_lib_ctx->top_of_system, |
1149 | 0 | tiff->pgs, 1, true); |
1150 | 0 | return 0; |
1151 | | |
1152 | 0 | fail_decode: |
1153 | 0 | if (tiff->penum) |
1154 | 0 | { |
1155 | 0 | (void)gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1156 | 0 | tiff->penum = NULL; |
1157 | 0 | } |
1158 | 0 | tiff->state = ii_state_flush; |
1159 | |
|
1160 | 0 | return code; |
1161 | 0 | } |
1162 | | |
1163 | | static int |
1164 | | decode_all_tiffs(tiff_interp_instance_t *tiff) |
1165 | 0 | { |
1166 | 0 | int code; |
1167 | |
|
1168 | 0 | tiff->nulldev = gs_currentdevice(tiff->pgs); |
1169 | 0 | rc_increment(tiff->nulldev); |
1170 | 0 | code = gs_setdevice_no_erase(tiff->pgs, tiff->dev); |
1171 | 0 | if (code < 0) |
1172 | 0 | return code; |
1173 | | |
1174 | 0 | do |
1175 | 0 | { |
1176 | 0 | code = do_tiff_decode(tiff); |
1177 | 0 | if (code < 0) |
1178 | 0 | return code; |
1179 | 0 | } |
1180 | 0 | while (TIFFReadDirectory(tiff->handle)); |
1181 | | |
1182 | 0 | return 0; |
1183 | 0 | } |
1184 | | |
1185 | | |
1186 | | static int |
1187 | | do_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr, int eof) |
1188 | 97 | { |
1189 | 97 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
1190 | 97 | int code = 0; |
1191 | 97 | ii_state ostate = (ii_state)-1; |
1192 | 97 | int bytes_left = 0; |
1193 | | |
1194 | 308 | while (tiff->state != ostate || pr->limit - pr->ptr != bytes_left) |
1195 | 230 | { |
1196 | 230 | ostate = tiff->state; |
1197 | 230 | bytes_left = pr->limit - pr->ptr; |
1198 | 230 | switch(tiff->state) |
1199 | 230 | { |
1200 | 19 | case ii_state_identifying: |
1201 | 19 | { |
1202 | 19 | const byte *hdr; |
1203 | | /* Try and get us 4 bytes */ |
1204 | 19 | code = ensure_bytes(tiff, pr, 4); |
1205 | 19 | if (code < 0) |
1206 | 0 | return code; |
1207 | 19 | hdr = pr->ptr+1; |
1208 | 19 | if (hdr[0] == 'I' && hdr[1] == 'I' && (hdr[2] == 42 || hdr[2] == 43) && hdr[3] == 0) { |
1209 | 19 | tiff->state = ii_state_tiff; |
1210 | 19 | break; |
1211 | 19 | } |
1212 | 0 | if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && (hdr[3] == 42 || hdr[3] == 43)) { |
1213 | 0 | tiff->state = ii_state_tiff; |
1214 | 0 | break; |
1215 | 0 | } |
1216 | 0 | tiff->state = ii_state_flush; |
1217 | 0 | break; |
1218 | 0 | } |
1219 | 173 | case ii_state_tiff: |
1220 | 173 | { |
1221 | | /* Gather data into a buffer */ |
1222 | 173 | int bytes = bytes_until_uel(pr); |
1223 | | |
1224 | 173 | if (bytes == 0 && pr->limit - pr->ptr > 9) { |
1225 | | /* No bytes until UEL, and there is space for a UEL in the buffer */ |
1226 | 0 | tiff->state = ii_state_tiff_decode; |
1227 | 0 | tiff->file_pos = 0; |
1228 | 0 | break; |
1229 | 0 | } |
1230 | 173 | if (bytes == 0 && eof) { |
1231 | | /* No bytes until UEL, and we are at eof */ |
1232 | 19 | tiff->state = ii_state_tiff_decode; |
1233 | 19 | tiff->file_pos = 0; |
1234 | 19 | break; |
1235 | 19 | } |
1236 | | |
1237 | 154 | if (tiff->buffer_full + bytes > tiff->buffer_max) { |
1238 | | /* Need to expand our buffer */ |
1239 | 21 | size_t proposed = tiff->buffer_full*2; |
1240 | 21 | if (proposed == 0) |
1241 | 19 | proposed = 32768; |
1242 | 21 | while (proposed < tiff->buffer_full + bytes) |
1243 | 0 | proposed *= 2; |
1244 | | |
1245 | 21 | if (tiff->tiff_buffer == NULL) { |
1246 | 19 | tiff->tiff_buffer = gs_alloc_bytes(tiff->memory, proposed, "tiff_buffer"); |
1247 | 19 | if (tiff->tiff_buffer == NULL) { |
1248 | 0 | tiff->state = ii_state_flush; |
1249 | 0 | break; |
1250 | 0 | } |
1251 | 19 | } else { |
1252 | 2 | void *new_buf = gs_resize_object(tiff->memory, tiff->tiff_buffer, proposed, "tiff_buffer"); |
1253 | 2 | if (new_buf == NULL) { |
1254 | 0 | tiff->state = ii_state_flush; |
1255 | 0 | break; |
1256 | 0 | } |
1257 | 2 | tiff->tiff_buffer = new_buf; |
1258 | 2 | } |
1259 | 21 | tiff->buffer_max = proposed; |
1260 | 21 | } |
1261 | | |
1262 | 154 | memcpy(&tiff->tiff_buffer[tiff->buffer_full], pr->ptr+1, bytes); |
1263 | 154 | tiff->buffer_full += bytes; |
1264 | 154 | pr->ptr += bytes; |
1265 | 154 | break; |
1266 | 154 | } |
1267 | 19 | case ii_state_tiff_decode: |
1268 | 19 | { |
1269 | 19 | tiff->handle = TIFFClientOpen("dummy", "rm", |
1270 | 19 | (thandle_t)tiff, |
1271 | 19 | tifsReadProc, |
1272 | 19 | tifsWriteProc, |
1273 | 19 | tifsSeekProc, |
1274 | 19 | tifsCloseProc, |
1275 | 19 | tifsSizeProc, |
1276 | 19 | NULL, |
1277 | 19 | NULL); |
1278 | 19 | if (tiff->handle == NULL) { |
1279 | 19 | tiff->state = ii_state_flush; |
1280 | 19 | break; |
1281 | 19 | } |
1282 | | |
1283 | 0 | #if defined(SHARE_JPEG) && SHARE_JPEG==0 |
1284 | 0 | TIFFSetJpegMemFunction(tiff->handle, |
1285 | 0 | &tiff_jpeg_mem_callback); |
1286 | 0 | #endif |
1287 | |
|
1288 | 0 | code = decode_all_tiffs(tiff); |
1289 | 0 | if (code < 0) |
1290 | 0 | { |
1291 | 0 | tiff->state = ii_state_flush; |
1292 | 0 | break; |
1293 | 0 | } |
1294 | 0 | break; |
1295 | 0 | } |
1296 | 0 | default: |
1297 | 19 | case ii_state_flush: |
1298 | | |
1299 | 19 | if (tiff->handle) { |
1300 | 0 | TIFFClose(tiff->handle); |
1301 | 0 | tiff->handle = NULL; |
1302 | 0 | } |
1303 | | |
1304 | 19 | if (tiff->penum) { |
1305 | 0 | (void)gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs); |
1306 | 0 | tiff->penum = NULL; |
1307 | 0 | } |
1308 | | |
1309 | 19 | if (tiff->proc_samples && tiff->proc_samples != tiff->samples) { |
1310 | 0 | gs_free_object(tiff->memory, tiff->proc_samples, "tiff_impl_process(samples)"); |
1311 | 0 | tiff->proc_samples = NULL; |
1312 | 0 | } |
1313 | | |
1314 | 19 | if (tiff->samples) { |
1315 | 0 | gs_free_object(tiff->memory, tiff->samples, "tiff_impl_process(samples)"); |
1316 | 0 | tiff->samples = NULL; |
1317 | 0 | tiff->proc_samples = NULL; |
1318 | 0 | } |
1319 | | |
1320 | 19 | if (tiff->palette) { |
1321 | 0 | gs_free_object(tiff->memory, tiff->palette, "tiff_impl_process(samples)"); |
1322 | 0 | tiff->palette = NULL; |
1323 | 0 | } |
1324 | | |
1325 | 19 | if (tiff->tiff_buffer) { |
1326 | 19 | gs_free_object(tiff->memory, tiff->tiff_buffer, "tiff_impl_process(tiff_buffer)"); |
1327 | 19 | tiff->tiff_buffer = NULL; |
1328 | 19 | tiff->buffer_max = 0; |
1329 | 19 | tiff->buffer_full = 0; |
1330 | 19 | } |
1331 | | /* We want to bin any data we get up to, but not including |
1332 | | * a UEL. */ |
1333 | 19 | return flush_to_uel(pr); |
1334 | 230 | } |
1335 | 230 | } |
1336 | | |
1337 | 78 | return code; |
1338 | 97 | } |
1339 | | |
1340 | | static int |
1341 | 78 | tiff_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr) { |
1342 | 78 | return do_impl_process(impl, pr, 0); |
1343 | 78 | } |
1344 | | |
1345 | | static int |
1346 | | tiff_impl_process_end(pl_interp_implementation_t * impl) |
1347 | 19 | { |
1348 | 19 | return 0; |
1349 | 19 | } |
1350 | | |
1351 | | /* Not implemented */ |
1352 | | static int |
1353 | | tiff_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor) |
1354 | 0 | { |
1355 | 0 | const byte *p = cursor->ptr; |
1356 | 0 | const byte *rlimit = cursor->limit; |
1357 | | |
1358 | | /* Skip to, but leave UEL in buffer for PJL to find later */ |
1359 | 0 | for (; p < rlimit; ++p) |
1360 | 0 | if (p[1] == '\033') { |
1361 | 0 | uint avail = rlimit - p; |
1362 | |
|
1363 | 0 | if (memcmp(p + 1, "\033%-12345X", min(avail, 9))) |
1364 | 0 | continue; |
1365 | 0 | if (avail < 9) |
1366 | 0 | break; |
1367 | 0 | cursor->ptr = p; |
1368 | 0 | return 1; /* found eoj */ |
1369 | 0 | } |
1370 | 0 | cursor->ptr = p; |
1371 | 0 | return 0; /* need more */ |
1372 | 0 | } |
1373 | | |
1374 | | /* Parser action for end-of-file */ |
1375 | | static int |
1376 | | tiff_impl_process_eof(pl_interp_implementation_t *impl) |
1377 | 19 | { |
1378 | 19 | stream_cursor_read r; |
1379 | | |
1380 | 19 | r.ptr = NULL; |
1381 | 19 | r.limit = NULL; |
1382 | 19 | return do_impl_process(impl, &r, 1); |
1383 | 19 | } |
1384 | | |
1385 | | /* Report any errors after running a job */ |
1386 | | static int |
1387 | | tiff_impl_report_errors(pl_interp_implementation_t *impl, /* interp instance to wrap up job in */ |
1388 | | int code, /* prev termination status */ |
1389 | | long file_position, /* file position of error, -1 if unknown */ |
1390 | | bool force_to_cout /* force errors to cout */ |
1391 | | ) |
1392 | 0 | { |
1393 | 0 | return 0; |
1394 | 0 | } |
1395 | | |
1396 | | /* Wrap up interp instance after a "job" */ |
1397 | | static int |
1398 | | tiff_impl_dnit_job(pl_interp_implementation_t *impl) |
1399 | 19 | { |
1400 | 19 | tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data; |
1401 | | |
1402 | 19 | if (tiff->nulldev) { |
1403 | 0 | int code = gs_setdevice(tiff->pgs, tiff->nulldev); |
1404 | 0 | tiff->dev = NULL; |
1405 | 0 | rc_decrement(tiff->nulldev, "tiff_impl_dnit_job(nulldevice)"); |
1406 | 0 | tiff->nulldev = NULL; |
1407 | 0 | return code; |
1408 | 0 | } |
1409 | 19 | return 0; |
1410 | 19 | } |
1411 | | |
1412 | | /* Parser implementation descriptor */ |
1413 | | const pl_interp_implementation_t tiff_implementation = { |
1414 | | tiff_impl_characteristics, |
1415 | | tiff_impl_allocate_interp_instance, |
1416 | | tiff_impl_get_device_memory, |
1417 | | NULL, /* tiff_impl_set_param */ |
1418 | | NULL, /* tiff_impl_add_path */ |
1419 | | NULL, /* tiff_impl_post_args_init */ |
1420 | | tiff_impl_init_job, |
1421 | | NULL, /* tiff_impl_run_prefix_commands */ |
1422 | | NULL, /* tiff_impl_process_file */ |
1423 | | tiff_impl_process_begin, |
1424 | | tiff_impl_process, |
1425 | | tiff_impl_process_end, |
1426 | | tiff_impl_flush_to_eoj, |
1427 | | tiff_impl_process_eof, |
1428 | | tiff_impl_report_errors, |
1429 | | tiff_impl_dnit_job, |
1430 | | tiff_impl_deallocate_interp_instance, |
1431 | | NULL, /* tiff_impl_reset */ |
1432 | | NULL /* interp_client_data */ |
1433 | | }; |
1434 | | #endif /* TIFF_INCLUDED */ |