Line data Source code
1 : /*
2 : * Copyright (c) 1991-1997 Sam Leffler
3 : * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4 : *
5 : * Permission to use, copy, modify, distribute, and sell this software and
6 : * its documentation for any purpose is hereby granted without fee, provided
7 : * that (i) the above copyright notices and this permission notice appear in
8 : * all copies of the software and related documentation, and (ii) the names of
9 : * Sam Leffler and Silicon Graphics may not be used in any advertising or
10 : * publicity relating to the software without the specific, prior written
11 : * permission of Sam Leffler and Silicon Graphics.
12 : *
13 : * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 : * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 : * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 : *
17 : * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 : * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 : * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 : * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 : * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 : * OF THIS SOFTWARE.
23 : */
24 :
25 : /*
26 : * TIFF Library
27 : *
28 : * Read and return a packed RGBA image.
29 : */
30 : #include "tiffiop.h"
31 : #include <limits.h>
32 : #include <stdio.h>
33 :
34 : static int gtTileContig(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
35 : static int gtTileSeparate(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
36 : static int gtStripContig(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
37 : static int gtStripSeparate(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
38 : static int PickContigCase(TIFFRGBAImage *);
39 : static int PickSeparateCase(TIFFRGBAImage *);
40 :
41 : static int BuildMapUaToAa(TIFFRGBAImage *img);
42 : static int BuildMapBitdepth16To8(TIFFRGBAImage *img);
43 :
44 : static const char photoTag[] = "PhotometricInterpretation";
45 :
46 : /*
47 : * Helper constants used in Orientation tag handling
48 : */
49 : #define FLIP_VERTICALLY 0x01
50 : #define FLIP_HORIZONTALLY 0x02
51 :
52 : #define EMSG_BUF_SIZE 1024
53 :
54 : /*
55 : * Color conversion constants. We will define display types here.
56 : */
57 :
58 : static const TIFFDisplay display_sRGB = {
59 : {/* XYZ -> luminance matrix */
60 : {3.2410F, -1.5374F, -0.4986F},
61 : {-0.9692F, 1.8760F, 0.0416F},
62 : {0.0556F, -0.2040F, 1.0570F}},
63 : 100.0F,
64 : 100.0F,
65 : 100.0F, /* Light o/p for reference white */
66 : 255,
67 : 255,
68 : 255, /* Pixel values for ref. white */
69 : 1.0F,
70 : 1.0F,
71 : 1.0F, /* Residual light o/p for black pixel */
72 : 2.4F,
73 : 2.4F,
74 : 2.4F, /* Gamma values for the three guns */
75 : };
76 :
77 : /*
78 : * Check the image to see if TIFFReadRGBAImage can deal with it.
79 : * 1/0 is returned according to whether or not the image can
80 : * be handled. If 0 is returned, emsg contains the reason
81 : * why it is being rejected.
82 : */
83 98 : int TIFFRGBAImageOK(TIFF *tif, char emsg[EMSG_BUF_SIZE])
84 : {
85 98 : TIFFDirectory *td = &tif->tif_dir;
86 : uint16_t photometric;
87 : int colorchannels;
88 :
89 98 : if (!tif->tif_decodestatus)
90 : {
91 0 : snprintf(emsg, EMSG_BUF_SIZE,
92 : "Sorry, requested compression method is not configured");
93 0 : return (0);
94 : }
95 98 : switch (td->td_bitspersample)
96 : {
97 98 : case 1:
98 : case 2:
99 : case 4:
100 : case 8:
101 : case 16:
102 98 : break;
103 0 : default:
104 0 : snprintf(emsg, EMSG_BUF_SIZE,
105 : "Sorry, can not handle images with %" PRIu16
106 : "-bit samples",
107 0 : td->td_bitspersample);
108 0 : return (0);
109 : }
110 98 : if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
111 : {
112 0 : snprintf(
113 : emsg, EMSG_BUF_SIZE,
114 : "Sorry, can not handle images with IEEE floating-point samples");
115 0 : return (0);
116 : }
117 98 : colorchannels = td->td_samplesperpixel - td->td_extrasamples;
118 98 : if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
119 : {
120 0 : switch (colorchannels)
121 : {
122 0 : case 1:
123 0 : photometric = PHOTOMETRIC_MINISBLACK;
124 0 : break;
125 0 : case 3:
126 0 : photometric = PHOTOMETRIC_RGB;
127 0 : break;
128 0 : default:
129 0 : snprintf(emsg, EMSG_BUF_SIZE, "Missing needed %s tag",
130 : photoTag);
131 0 : return (0);
132 : }
133 98 : }
134 98 : switch (photometric)
135 : {
136 16 : case PHOTOMETRIC_MINISWHITE:
137 : case PHOTOMETRIC_MINISBLACK:
138 : case PHOTOMETRIC_PALETTE:
139 16 : if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
140 12 : td->td_samplesperpixel != 1 && td->td_bitspersample < 8)
141 : {
142 0 : snprintf(
143 : emsg, EMSG_BUF_SIZE,
144 : "Sorry, can not handle contiguous data with %s=%" PRIu16
145 : ", "
146 : "and %s=%" PRIu16 " and Bits/Sample=%" PRIu16 "",
147 : photoTag, photometric, "Samples/pixel",
148 0 : td->td_samplesperpixel, td->td_bitspersample);
149 0 : return (0);
150 : }
151 : /*
152 : * We should likely validate that any extra samples are either
153 : * to be ignored, or are alpha, and if alpha we should try to use
154 : * them. But for now we won't bother with this.
155 : */
156 16 : break;
157 30 : case PHOTOMETRIC_YCBCR:
158 : /*
159 : * TODO: if at all meaningful and useful, make more complete
160 : * support check here, or better still, refactor to let supporting
161 : * code decide whether there is support and what meaningful
162 : * error to return
163 : */
164 30 : break;
165 32 : case PHOTOMETRIC_RGB:
166 32 : if (colorchannels < 3)
167 : {
168 0 : snprintf(emsg, EMSG_BUF_SIZE,
169 : "Sorry, can not handle RGB image with %s=%d",
170 : "Color channels", colorchannels);
171 0 : return (0);
172 : }
173 32 : break;
174 16 : case PHOTOMETRIC_SEPARATED:
175 : {
176 : uint16_t inkset;
177 16 : TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
178 16 : if (inkset != INKSET_CMYK)
179 : {
180 0 : snprintf(emsg, EMSG_BUF_SIZE,
181 : "Sorry, can not handle separated image with %s=%d",
182 : "InkSet", inkset);
183 0 : return 0;
184 : }
185 16 : if (td->td_samplesperpixel < 4)
186 : {
187 0 : snprintf(
188 : emsg, EMSG_BUF_SIZE,
189 : "Sorry, can not handle separated image with %s=%" PRIu16,
190 0 : "Samples/pixel", td->td_samplesperpixel);
191 0 : return 0;
192 : }
193 16 : break;
194 : }
195 2 : case PHOTOMETRIC_LOGL:
196 2 : if (td->td_compression != COMPRESSION_SGILOG)
197 : {
198 0 : snprintf(emsg, EMSG_BUF_SIZE,
199 : "Sorry, LogL data must have %s=%d", "Compression",
200 : COMPRESSION_SGILOG);
201 0 : return (0);
202 : }
203 2 : break;
204 0 : case PHOTOMETRIC_LOGLUV:
205 0 : if (td->td_compression != COMPRESSION_SGILOG &&
206 0 : td->td_compression != COMPRESSION_SGILOG24)
207 : {
208 0 : snprintf(emsg, EMSG_BUF_SIZE,
209 : "Sorry, LogLuv data must have %s=%d or %d",
210 : "Compression", COMPRESSION_SGILOG,
211 : COMPRESSION_SGILOG24);
212 0 : return (0);
213 : }
214 0 : if (td->td_planarconfig != PLANARCONFIG_CONTIG)
215 : {
216 0 : snprintf(emsg, EMSG_BUF_SIZE,
217 : "Sorry, can not handle LogLuv images with %s=%" PRIu16,
218 0 : "Planarconfiguration", td->td_planarconfig);
219 0 : return (0);
220 : }
221 0 : if (td->td_samplesperpixel != 3 || colorchannels != 3)
222 : {
223 0 : snprintf(emsg, EMSG_BUF_SIZE,
224 : "Sorry, can not handle image with %s=%" PRIu16
225 : ", %s=%d",
226 0 : "Samples/pixel", td->td_samplesperpixel,
227 : "colorchannels", colorchannels);
228 0 : return 0;
229 : }
230 0 : break;
231 2 : case PHOTOMETRIC_CIELAB:
232 2 : if (td->td_samplesperpixel != 3 || colorchannels != 3 ||
233 2 : (td->td_bitspersample != 8 && td->td_bitspersample != 16))
234 : {
235 0 : snprintf(emsg, EMSG_BUF_SIZE,
236 : "Sorry, can not handle image with %s=%" PRIu16
237 : ", %s=%d and %s=%" PRIu16,
238 0 : "Samples/pixel", td->td_samplesperpixel,
239 : "colorchannels", colorchannels, "Bits/sample",
240 0 : td->td_bitspersample);
241 0 : return 0;
242 : }
243 2 : break;
244 0 : default:
245 0 : snprintf(emsg, EMSG_BUF_SIZE,
246 : "Sorry, can not handle image with %s=%" PRIu16, photoTag,
247 : photometric);
248 0 : return (0);
249 : }
250 98 : return (1);
251 : }
252 :
253 63 : void TIFFRGBAImageEnd(TIFFRGBAImage *img)
254 : {
255 63 : if (img->Map)
256 : {
257 0 : _TIFFfreeExt(img->tif, img->Map);
258 0 : img->Map = NULL;
259 : }
260 63 : if (img->BWmap)
261 : {
262 9 : _TIFFfreeExt(img->tif, img->BWmap);
263 9 : img->BWmap = NULL;
264 : }
265 63 : if (img->PALmap)
266 : {
267 1 : _TIFFfreeExt(img->tif, img->PALmap);
268 1 : img->PALmap = NULL;
269 : }
270 63 : if (img->ycbcr)
271 : {
272 17 : _TIFFfreeExt(img->tif, img->ycbcr);
273 17 : img->ycbcr = NULL;
274 : }
275 63 : if (img->cielab)
276 : {
277 1 : _TIFFfreeExt(img->tif, img->cielab);
278 1 : img->cielab = NULL;
279 : }
280 63 : if (img->UaToAa)
281 : {
282 13 : _TIFFfreeExt(img->tif, img->UaToAa);
283 13 : img->UaToAa = NULL;
284 : }
285 63 : if (img->Bitdepth16To8)
286 : {
287 0 : _TIFFfreeExt(img->tif, img->Bitdepth16To8);
288 0 : img->Bitdepth16To8 = NULL;
289 : }
290 :
291 63 : if (img->redcmap)
292 : {
293 1 : _TIFFfreeExt(img->tif, img->redcmap);
294 1 : _TIFFfreeExt(img->tif, img->greencmap);
295 1 : _TIFFfreeExt(img->tif, img->bluecmap);
296 1 : img->redcmap = img->greencmap = img->bluecmap = NULL;
297 : }
298 63 : }
299 :
300 0 : static int isCCITTCompression(TIFF *tif)
301 : {
302 : uint16_t compress;
303 0 : TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
304 0 : return (compress == COMPRESSION_CCITTFAX3 ||
305 0 : compress == COMPRESSION_CCITTFAX4 ||
306 0 : compress == COMPRESSION_CCITTRLE ||
307 0 : compress == COMPRESSION_CCITTRLEW);
308 : }
309 :
310 63 : int TIFFRGBAImageBegin(TIFFRGBAImage *img, TIFF *tif, int stop,
311 : char emsg[EMSG_BUF_SIZE])
312 : {
313 : uint16_t *sampleinfo;
314 : uint16_t extrasamples;
315 : uint16_t planarconfig;
316 : uint16_t compress;
317 : int colorchannels;
318 : uint16_t *red_orig, *green_orig, *blue_orig;
319 : int n_color;
320 :
321 63 : if (!TIFFRGBAImageOK(tif, emsg))
322 0 : return 0;
323 :
324 : /* Initialize to normal values */
325 63 : img->row_offset = 0;
326 63 : img->col_offset = 0;
327 63 : img->redcmap = NULL;
328 63 : img->greencmap = NULL;
329 63 : img->bluecmap = NULL;
330 63 : img->Map = NULL;
331 63 : img->BWmap = NULL;
332 63 : img->PALmap = NULL;
333 63 : img->ycbcr = NULL;
334 63 : img->cielab = NULL;
335 63 : img->UaToAa = NULL;
336 63 : img->Bitdepth16To8 = NULL;
337 63 : img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */
338 :
339 63 : img->tif = tif;
340 63 : img->stoponerr = stop;
341 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
342 63 : switch (img->bitspersample)
343 : {
344 63 : case 1:
345 : case 2:
346 : case 4:
347 : case 8:
348 : case 16:
349 63 : break;
350 0 : default:
351 0 : snprintf(emsg, EMSG_BUF_SIZE,
352 : "Sorry, can not handle images with %" PRIu16
353 : "-bit samples",
354 0 : img->bitspersample);
355 0 : goto fail_return;
356 : }
357 63 : img->alpha = 0;
358 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
359 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples,
360 : &sampleinfo);
361 63 : if (extrasamples >= 1)
362 : {
363 33 : switch (sampleinfo[0])
364 : {
365 14 : case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without
366 : */
367 14 : if (img->samplesperpixel >
368 : 3) /* correct info about alpha channel */
369 13 : img->alpha = EXTRASAMPLE_ASSOCALPHA;
370 14 : break;
371 19 : case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
372 : case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
373 19 : img->alpha = sampleinfo[0];
374 19 : break;
375 : }
376 30 : }
377 :
378 : #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
379 63 : if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
380 0 : img->photometric = PHOTOMETRIC_MINISWHITE;
381 :
382 63 : if (extrasamples == 0 && img->samplesperpixel == 4 &&
383 6 : img->photometric == PHOTOMETRIC_RGB)
384 : {
385 0 : img->alpha = EXTRASAMPLE_ASSOCALPHA;
386 0 : extrasamples = 1;
387 : }
388 : #endif
389 :
390 63 : colorchannels = img->samplesperpixel - extrasamples;
391 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
392 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
393 63 : if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
394 : {
395 0 : switch (colorchannels)
396 : {
397 0 : case 1:
398 0 : if (isCCITTCompression(tif))
399 0 : img->photometric = PHOTOMETRIC_MINISWHITE;
400 : else
401 0 : img->photometric = PHOTOMETRIC_MINISBLACK;
402 0 : break;
403 0 : case 3:
404 0 : img->photometric = PHOTOMETRIC_RGB;
405 0 : break;
406 0 : default:
407 0 : snprintf(emsg, EMSG_BUF_SIZE, "Missing needed %s tag",
408 : photoTag);
409 0 : goto fail_return;
410 : }
411 63 : }
412 63 : switch (img->photometric)
413 : {
414 1 : case PHOTOMETRIC_PALETTE:
415 1 : if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &red_orig, &green_orig,
416 : &blue_orig))
417 : {
418 0 : snprintf(emsg, EMSG_BUF_SIZE,
419 : "Missing required \"Colormap\" tag");
420 0 : goto fail_return;
421 : }
422 :
423 : /* copy the colormaps so we can modify them */
424 1 : n_color = (1U << img->bitspersample);
425 1 : img->redcmap =
426 1 : (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
427 1 : img->greencmap =
428 1 : (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
429 1 : img->bluecmap =
430 1 : (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
431 1 : if (!img->redcmap || !img->greencmap || !img->bluecmap)
432 : {
433 0 : snprintf(emsg, EMSG_BUF_SIZE,
434 : "Out of memory for colormap copy");
435 0 : goto fail_return;
436 : }
437 :
438 1 : _TIFFmemcpy(img->redcmap, red_orig, n_color * 2);
439 1 : _TIFFmemcpy(img->greencmap, green_orig, n_color * 2);
440 1 : _TIFFmemcpy(img->bluecmap, blue_orig, n_color * 2);
441 :
442 : /* fall through... */
443 10 : case PHOTOMETRIC_MINISWHITE:
444 : case PHOTOMETRIC_MINISBLACK:
445 10 : if (planarconfig == PLANARCONFIG_CONTIG &&
446 8 : img->samplesperpixel != 1 && img->bitspersample < 8)
447 : {
448 0 : snprintf(
449 : emsg, EMSG_BUF_SIZE,
450 : "Sorry, can not handle contiguous data with %s=%" PRIu16
451 : ", "
452 : "and %s=%" PRIu16 " and Bits/Sample=%" PRIu16,
453 0 : photoTag, img->photometric, "Samples/pixel",
454 0 : img->samplesperpixel, img->bitspersample);
455 0 : goto fail_return;
456 : }
457 10 : break;
458 17 : case PHOTOMETRIC_YCBCR:
459 : /* It would probably be nice to have a reality check here. */
460 17 : if (planarconfig == PLANARCONFIG_CONTIG)
461 : /* can rely on libjpeg to convert to RGB */
462 : /* XXX should restore current state on exit */
463 17 : switch (compress)
464 : {
465 0 : case COMPRESSION_JPEG:
466 : /*
467 : * TODO: when complete tests verify complete
468 : * desubsampling and YCbCr handling, remove use of
469 : * TIFFTAG_JPEGCOLORMODE in favor of tif_getimage.c
470 : * native handling
471 : */
472 0 : TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE,
473 : JPEGCOLORMODE_RGB);
474 0 : img->photometric = PHOTOMETRIC_RGB;
475 0 : break;
476 17 : default:
477 : /* do nothing */;
478 17 : break;
479 : }
480 : /*
481 : * TODO: if at all meaningful and useful, make more complete
482 : * support check here, or better still, refactor to let supporting
483 : * code decide whether there is support and what meaningful
484 : * error to return
485 : */
486 17 : break;
487 28 : case PHOTOMETRIC_RGB:
488 28 : if (colorchannels < 3)
489 : {
490 0 : snprintf(emsg, EMSG_BUF_SIZE,
491 : "Sorry, can not handle RGB image with %s=%d",
492 : "Color channels", colorchannels);
493 0 : goto fail_return;
494 : }
495 28 : break;
496 6 : case PHOTOMETRIC_SEPARATED:
497 : {
498 : uint16_t inkset;
499 6 : TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
500 6 : if (inkset != INKSET_CMYK)
501 : {
502 0 : snprintf(
503 : emsg, EMSG_BUF_SIZE,
504 : "Sorry, can not handle separated image with %s=%" PRIu16,
505 : "InkSet", inkset);
506 0 : goto fail_return;
507 : }
508 6 : if (img->samplesperpixel < 4)
509 : {
510 0 : snprintf(
511 : emsg, EMSG_BUF_SIZE,
512 : "Sorry, can not handle separated image with %s=%" PRIu16,
513 0 : "Samples/pixel", img->samplesperpixel);
514 0 : goto fail_return;
515 : }
516 : }
517 6 : break;
518 1 : case PHOTOMETRIC_LOGL:
519 1 : if (compress != COMPRESSION_SGILOG)
520 : {
521 0 : snprintf(emsg, EMSG_BUF_SIZE,
522 : "Sorry, LogL data must have %s=%d", "Compression",
523 : COMPRESSION_SGILOG);
524 0 : goto fail_return;
525 : }
526 1 : TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
527 1 : img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */
528 1 : img->bitspersample = 8;
529 1 : break;
530 0 : case PHOTOMETRIC_LOGLUV:
531 0 : if (compress != COMPRESSION_SGILOG &&
532 0 : compress != COMPRESSION_SGILOG24)
533 : {
534 0 : snprintf(emsg, EMSG_BUF_SIZE,
535 : "Sorry, LogLuv data must have %s=%d or %d",
536 : "Compression", COMPRESSION_SGILOG,
537 : COMPRESSION_SGILOG24);
538 0 : goto fail_return;
539 : }
540 0 : if (planarconfig != PLANARCONFIG_CONTIG)
541 : {
542 0 : snprintf(emsg, EMSG_BUF_SIZE,
543 : "Sorry, can not handle LogLuv images with %s=%" PRIu16,
544 : "Planarconfiguration", planarconfig);
545 0 : return (0);
546 : }
547 0 : TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
548 0 : img->photometric = PHOTOMETRIC_RGB; /* little white lie */
549 0 : img->bitspersample = 8;
550 0 : break;
551 1 : case PHOTOMETRIC_CIELAB:
552 1 : break;
553 0 : default:
554 0 : snprintf(emsg, EMSG_BUF_SIZE,
555 : "Sorry, can not handle image with %s=%" PRIu16, photoTag,
556 0 : img->photometric);
557 0 : goto fail_return;
558 : }
559 63 : TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
560 63 : TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
561 63 : TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
562 63 : img->isContig =
563 63 : !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1);
564 63 : if (img->isContig)
565 : {
566 60 : if (!PickContigCase(img))
567 : {
568 6 : snprintf(emsg, EMSG_BUF_SIZE, "Sorry, can not handle image");
569 6 : goto fail_return;
570 : }
571 : }
572 : else
573 : {
574 3 : if (!PickSeparateCase(img))
575 : {
576 0 : snprintf(emsg, EMSG_BUF_SIZE, "Sorry, can not handle image");
577 0 : goto fail_return;
578 : }
579 : }
580 57 : return 1;
581 :
582 6 : fail_return:
583 6 : TIFFRGBAImageEnd(img);
584 6 : return 0;
585 : }
586 :
587 57 : int TIFFRGBAImageGet(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
588 : uint32_t h)
589 : {
590 57 : if (img->get == NULL)
591 : {
592 0 : TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
593 : "No \"get\" routine setup");
594 0 : return (0);
595 : }
596 57 : if (img->put.any == NULL)
597 : {
598 0 : TIFFErrorExtR(
599 : img->tif, TIFFFileName(img->tif),
600 : "No \"put\" routine setupl; probably can not handle image format");
601 0 : return (0);
602 : }
603 57 : return (*img->get)(img, raster, w, h);
604 : }
605 :
606 : /*
607 : * Read the specified image into an ABGR-format rastertaking in account
608 : * specified orientation.
609 : */
610 0 : int TIFFReadRGBAImageOriented(TIFF *tif, uint32_t rwidth, uint32_t rheight,
611 : uint32_t *raster, int orientation, int stop)
612 : {
613 0 : char emsg[EMSG_BUF_SIZE] = "";
614 : TIFFRGBAImage img;
615 : int ok;
616 :
617 0 : if (TIFFRGBAImageBegin(&img, tif, stop, emsg))
618 : {
619 0 : img.req_orientation = (uint16_t)orientation;
620 : /* XXX verify rwidth and rheight against width and height */
621 0 : ok = TIFFRGBAImageGet(&img, raster + (rheight - img.height) * rwidth,
622 : rwidth, img.height);
623 0 : TIFFRGBAImageEnd(&img);
624 : }
625 : else
626 : {
627 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
628 0 : ok = 0;
629 : }
630 0 : return (ok);
631 : }
632 :
633 : /*
634 : * Read the specified image into an ABGR-format raster. Use bottom left
635 : * origin for raster by default.
636 : */
637 0 : int TIFFReadRGBAImage(TIFF *tif, uint32_t rwidth, uint32_t rheight,
638 : uint32_t *raster, int stop)
639 : {
640 0 : return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
641 : ORIENTATION_BOTLEFT, stop);
642 : }
643 :
644 57 : static int setorientation(TIFFRGBAImage *img)
645 : {
646 57 : switch (img->orientation)
647 : {
648 57 : case ORIENTATION_TOPLEFT:
649 : case ORIENTATION_LEFTTOP:
650 57 : if (img->req_orientation == ORIENTATION_TOPRIGHT ||
651 57 : img->req_orientation == ORIENTATION_RIGHTTOP)
652 0 : return FLIP_HORIZONTALLY;
653 57 : else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
654 57 : img->req_orientation == ORIENTATION_RIGHTBOT)
655 0 : return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
656 57 : else if (img->req_orientation == ORIENTATION_BOTLEFT ||
657 0 : img->req_orientation == ORIENTATION_LEFTBOT)
658 57 : return FLIP_VERTICALLY;
659 : else
660 0 : return 0;
661 0 : case ORIENTATION_TOPRIGHT:
662 : case ORIENTATION_RIGHTTOP:
663 0 : if (img->req_orientation == ORIENTATION_TOPLEFT ||
664 0 : img->req_orientation == ORIENTATION_LEFTTOP)
665 0 : return FLIP_HORIZONTALLY;
666 0 : else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
667 0 : img->req_orientation == ORIENTATION_RIGHTBOT)
668 0 : return FLIP_VERTICALLY;
669 0 : else if (img->req_orientation == ORIENTATION_BOTLEFT ||
670 0 : img->req_orientation == ORIENTATION_LEFTBOT)
671 0 : return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
672 : else
673 0 : return 0;
674 0 : case ORIENTATION_BOTRIGHT:
675 : case ORIENTATION_RIGHTBOT:
676 0 : if (img->req_orientation == ORIENTATION_TOPLEFT ||
677 0 : img->req_orientation == ORIENTATION_LEFTTOP)
678 0 : return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
679 0 : else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
680 0 : img->req_orientation == ORIENTATION_RIGHTTOP)
681 0 : return FLIP_VERTICALLY;
682 0 : else if (img->req_orientation == ORIENTATION_BOTLEFT ||
683 0 : img->req_orientation == ORIENTATION_LEFTBOT)
684 0 : return FLIP_HORIZONTALLY;
685 : else
686 0 : return 0;
687 0 : case ORIENTATION_BOTLEFT:
688 : case ORIENTATION_LEFTBOT:
689 0 : if (img->req_orientation == ORIENTATION_TOPLEFT ||
690 0 : img->req_orientation == ORIENTATION_LEFTTOP)
691 0 : return FLIP_VERTICALLY;
692 0 : else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
693 0 : img->req_orientation == ORIENTATION_RIGHTTOP)
694 0 : return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
695 0 : else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
696 0 : img->req_orientation == ORIENTATION_RIGHTBOT)
697 0 : return FLIP_HORIZONTALLY;
698 : else
699 0 : return 0;
700 0 : default: /* NOTREACHED */
701 0 : return 0;
702 : }
703 : }
704 :
705 : /*
706 : * Get an tile-organized image that has
707 : * PlanarConfiguration contiguous if SamplesPerPixel > 1
708 : * or
709 : * SamplesPerPixel == 1
710 : */
711 3 : static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
712 : uint32_t h)
713 : {
714 3 : TIFF *tif = img->tif;
715 3 : tileContigRoutine put = img->put.contig;
716 : uint32_t col, row, y, rowstoread;
717 : tmsize_t pos;
718 : uint32_t tw, th;
719 3 : unsigned char *buf = NULL;
720 : int32_t fromskew, toskew;
721 : uint32_t nrow;
722 3 : int ret = 1, flip;
723 : uint32_t this_tw, tocol;
724 : int32_t this_toskew, leftmost_toskew;
725 : int32_t leftmost_fromskew;
726 : uint32_t leftmost_tw;
727 : tmsize_t bufsize;
728 :
729 3 : bufsize = TIFFTileSize(tif);
730 3 : if (bufsize == 0)
731 : {
732 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s", "No space for tile buffer");
733 0 : return (0);
734 : }
735 :
736 3 : TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
737 3 : TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
738 :
739 3 : flip = setorientation(img);
740 3 : if (flip & FLIP_VERTICALLY)
741 : {
742 3 : if (((int64_t)tw + w) > INT_MAX)
743 : {
744 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
745 : "unsupported tile size (too wide)");
746 0 : return (0);
747 : }
748 3 : y = h - 1;
749 3 : toskew = -(int32_t)(tw + w);
750 : }
751 : else
752 : {
753 0 : if (tw > ((int64_t)INT_MAX + w))
754 : {
755 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
756 : "unsupported tile size (too wide)");
757 0 : return (0);
758 : }
759 0 : y = 0;
760 0 : toskew = -(int32_t)(tw - w);
761 : }
762 :
763 3 : if (tw == 0 || th == 0)
764 : {
765 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
766 0 : return (0);
767 : }
768 :
769 : /*
770 : * Leftmost tile is clipped on left side if col_offset > 0.
771 : */
772 3 : leftmost_fromskew = img->col_offset % tw;
773 3 : leftmost_tw = tw - leftmost_fromskew;
774 3 : int64_t skew_i64 = (int64_t)toskew + leftmost_fromskew;
775 3 : if (skew_i64 > INT_MAX || skew_i64 < INT_MIN)
776 : {
777 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s %" PRId64, "Invalid skew",
778 : skew_i64);
779 0 : return (0);
780 : }
781 3 : leftmost_toskew = (int32_t)skew_i64;
782 6 : for (row = 0; ret != 0 && row < h; row += nrow)
783 : {
784 3 : rowstoread = th - (row + img->row_offset) % th;
785 3 : nrow = (row + rowstoread > h ? h - row : rowstoread);
786 3 : fromskew = leftmost_fromskew;
787 3 : this_tw = leftmost_tw;
788 3 : this_toskew = leftmost_toskew;
789 3 : tocol = 0;
790 3 : col = img->col_offset;
791 5 : while (tocol < w)
792 : {
793 3 : if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize, col,
794 3 : row + img->row_offset, 0,
795 1 : 0) == (tmsize_t)(-1) &&
796 1 : (buf == NULL || img->stoponerr))
797 : {
798 1 : ret = 0;
799 1 : break;
800 : }
801 2 : pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
802 2 : ((tmsize_t)fromskew * img->samplesperpixel);
803 2 : if (tocol + this_tw > w)
804 : {
805 : /*
806 : * Rightmost tile is clipped on right side.
807 : */
808 2 : fromskew = tw - (w - tocol);
809 2 : this_tw = tw - fromskew;
810 2 : this_toskew = toskew + fromskew;
811 : }
812 2 : tmsize_t roffset = (tmsize_t)y * w + tocol;
813 2 : (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
814 : this_toskew, buf + pos);
815 2 : tocol += this_tw;
816 2 : col += this_tw;
817 : /*
818 : * After the leftmost tile, tiles are no longer clipped on left
819 : * side.
820 : */
821 2 : fromskew = 0;
822 2 : this_tw = tw;
823 2 : this_toskew = toskew;
824 : }
825 :
826 3 : y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
827 : }
828 3 : _TIFFfreeExt(img->tif, buf);
829 :
830 3 : if (flip & FLIP_HORIZONTALLY)
831 : {
832 : uint32_t line;
833 :
834 0 : for (line = 0; line < h; line++)
835 : {
836 0 : uint32_t *left = raster + (line * w);
837 0 : uint32_t *right = left + w - 1;
838 :
839 0 : while (left < right)
840 : {
841 0 : uint32_t temp = *left;
842 0 : *left = *right;
843 0 : *right = temp;
844 0 : left++;
845 0 : right--;
846 : }
847 : }
848 : }
849 :
850 3 : return (ret);
851 : }
852 :
853 : /*
854 : * Get an tile-organized image that has
855 : * SamplesPerPixel > 1
856 : * PlanarConfiguration separated
857 : * We assume that all such images are RGB.
858 : */
859 1 : static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
860 : uint32_t h)
861 : {
862 1 : TIFF *tif = img->tif;
863 1 : tileSeparateRoutine put = img->put.separate;
864 : uint32_t col, row, y, rowstoread;
865 : tmsize_t pos;
866 : uint32_t tw, th;
867 1 : unsigned char *buf = NULL;
868 1 : unsigned char *p0 = NULL;
869 1 : unsigned char *p1 = NULL;
870 1 : unsigned char *p2 = NULL;
871 1 : unsigned char *pa = NULL;
872 : tmsize_t tilesize;
873 : tmsize_t bufsize;
874 : int32_t fromskew, toskew;
875 1 : int alpha = img->alpha;
876 : uint32_t nrow;
877 1 : int ret = 1, flip;
878 : uint16_t colorchannels;
879 : uint32_t this_tw, tocol;
880 : int32_t this_toskew, leftmost_toskew;
881 : int32_t leftmost_fromskew;
882 : uint32_t leftmost_tw;
883 :
884 1 : tilesize = TIFFTileSize(tif);
885 : bufsize =
886 1 : _TIFFMultiplySSize(tif, alpha ? 4 : 3, tilesize, "gtTileSeparate");
887 1 : if (bufsize == 0)
888 : {
889 0 : return (0);
890 : }
891 :
892 1 : TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
893 1 : TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
894 :
895 1 : flip = setorientation(img);
896 1 : if (flip & FLIP_VERTICALLY)
897 : {
898 1 : if (((int64_t)tw + w) > INT_MAX)
899 : {
900 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
901 : "unsupported tile size (too wide)");
902 0 : return (0);
903 : }
904 1 : y = h - 1;
905 1 : toskew = -(int32_t)(tw + w);
906 : }
907 : else
908 : {
909 0 : if (tw > ((int64_t)INT_MAX + w))
910 : {
911 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
912 : "unsupported tile size (too wide)");
913 0 : return (0);
914 : }
915 0 : y = 0;
916 0 : toskew = -(int32_t)(tw - w);
917 : }
918 :
919 1 : switch (img->photometric)
920 : {
921 0 : case PHOTOMETRIC_MINISWHITE:
922 : case PHOTOMETRIC_MINISBLACK:
923 : case PHOTOMETRIC_PALETTE:
924 0 : colorchannels = 1;
925 0 : break;
926 :
927 1 : default:
928 1 : colorchannels = 3;
929 1 : break;
930 : }
931 :
932 1 : if (tw == 0 || th == 0)
933 : {
934 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
935 0 : return (0);
936 : }
937 :
938 : /*
939 : * Leftmost tile is clipped on left side if col_offset > 0.
940 : */
941 1 : leftmost_fromskew = img->col_offset % tw;
942 1 : leftmost_tw = tw - leftmost_fromskew;
943 1 : int64_t skew_i64 = (int64_t)toskew + leftmost_fromskew;
944 1 : if (skew_i64 > INT_MAX || skew_i64 < INT_MIN)
945 : {
946 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s %" PRId64, "Invalid skew",
947 : skew_i64);
948 0 : return (0);
949 : }
950 1 : leftmost_toskew = (int32_t)skew_i64;
951 2 : for (row = 0; ret != 0 && row < h; row += nrow)
952 : {
953 1 : rowstoread = th - (row + img->row_offset) % th;
954 1 : nrow = (row + rowstoread > h ? h - row : rowstoread);
955 1 : fromskew = leftmost_fromskew;
956 1 : this_tw = leftmost_tw;
957 1 : this_toskew = leftmost_toskew;
958 1 : tocol = 0;
959 1 : col = img->col_offset;
960 2 : while (tocol < w)
961 : {
962 1 : if (buf == NULL)
963 : {
964 1 : if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize,
965 1 : col, row + img->row_offset, 0,
966 0 : 0) == (tmsize_t)(-1) &&
967 0 : (buf == NULL || img->stoponerr))
968 : {
969 0 : ret = 0;
970 0 : break;
971 : }
972 1 : p0 = buf;
973 1 : if (colorchannels == 1)
974 : {
975 0 : p2 = p1 = p0;
976 0 : pa = (alpha ? (p0 + 3 * tilesize) : NULL);
977 : }
978 : else
979 : {
980 1 : p1 = p0 + tilesize;
981 1 : p2 = p1 + tilesize;
982 1 : pa = (alpha ? (p2 + tilesize) : NULL);
983 : }
984 : }
985 0 : else if (TIFFReadTile(tif, p0, col, row + img->row_offset, 0, 0) ==
986 0 : (tmsize_t)(-1) &&
987 0 : img->stoponerr)
988 : {
989 0 : ret = 0;
990 0 : break;
991 : }
992 2 : if (colorchannels > 1 &&
993 1 : TIFFReadTile(tif, p1, col, row + img->row_offset, 0, 1) ==
994 0 : (tmsize_t)(-1) &&
995 0 : img->stoponerr)
996 : {
997 0 : ret = 0;
998 0 : break;
999 : }
1000 2 : if (colorchannels > 1 &&
1001 1 : TIFFReadTile(tif, p2, col, row + img->row_offset, 0, 2) ==
1002 0 : (tmsize_t)(-1) &&
1003 0 : img->stoponerr)
1004 : {
1005 0 : ret = 0;
1006 0 : break;
1007 : }
1008 1 : if (alpha &&
1009 0 : TIFFReadTile(tif, pa, col, row + img->row_offset, 0,
1010 0 : colorchannels) == (tmsize_t)(-1) &&
1011 0 : img->stoponerr)
1012 : {
1013 0 : ret = 0;
1014 0 : break;
1015 : }
1016 :
1017 1 : pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
1018 1 : ((tmsize_t)fromskew * img->samplesperpixel);
1019 1 : if (tocol + this_tw > w)
1020 : {
1021 : /*
1022 : * Rightmost tile is clipped on right side.
1023 : */
1024 1 : fromskew = tw - (w - tocol);
1025 1 : this_tw = tw - fromskew;
1026 1 : this_toskew = toskew + fromskew;
1027 : }
1028 1 : tmsize_t roffset = (tmsize_t)y * w + tocol;
1029 1 : (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
1030 : this_toskew, p0 + pos, p1 + pos, p2 + pos,
1031 0 : (alpha ? (pa + pos) : NULL));
1032 1 : tocol += this_tw;
1033 1 : col += this_tw;
1034 : /*
1035 : * After the leftmost tile, tiles are no longer clipped on left
1036 : * side.
1037 : */
1038 1 : fromskew = 0;
1039 1 : this_tw = tw;
1040 1 : this_toskew = toskew;
1041 : }
1042 :
1043 1 : y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
1044 : }
1045 :
1046 1 : if (flip & FLIP_HORIZONTALLY)
1047 : {
1048 : uint32_t line;
1049 :
1050 0 : for (line = 0; line < h; line++)
1051 : {
1052 0 : uint32_t *left = raster + (line * w);
1053 0 : uint32_t *right = left + w - 1;
1054 :
1055 0 : while (left < right)
1056 : {
1057 0 : uint32_t temp = *left;
1058 0 : *left = *right;
1059 0 : *right = temp;
1060 0 : left++;
1061 0 : right--;
1062 : }
1063 : }
1064 : }
1065 :
1066 1 : _TIFFfreeExt(img->tif, buf);
1067 1 : return (ret);
1068 : }
1069 :
1070 : /*
1071 : * Get a strip-organized image that has
1072 : * PlanarConfiguration contiguous if SamplesPerPixel > 1
1073 : * or
1074 : * SamplesPerPixel == 1
1075 : */
1076 51 : static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
1077 : uint32_t h)
1078 : {
1079 51 : TIFF *tif = img->tif;
1080 51 : tileContigRoutine put = img->put.contig;
1081 : uint32_t row, y, nrow, nrowsub, rowstoread;
1082 : tmsize_t pos;
1083 51 : unsigned char *buf = NULL;
1084 : uint32_t rowsperstrip;
1085 : uint16_t subsamplinghor, subsamplingver;
1086 51 : uint32_t imagewidth = img->width;
1087 : tmsize_t scanline;
1088 : int32_t fromskew, toskew;
1089 51 : int ret = 1, flip;
1090 : tmsize_t maxstripsize;
1091 :
1092 51 : TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor,
1093 : &subsamplingver);
1094 51 : if (subsamplingver == 0)
1095 : {
1096 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
1097 : "Invalid vertical YCbCr subsampling");
1098 0 : return (0);
1099 : }
1100 :
1101 51 : maxstripsize = TIFFStripSize(tif);
1102 :
1103 51 : flip = setorientation(img);
1104 51 : if (flip & FLIP_VERTICALLY)
1105 : {
1106 51 : if (w > INT_MAX / 2)
1107 : {
1108 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
1109 0 : return (0);
1110 : }
1111 51 : y = h - 1;
1112 51 : toskew = -(int32_t)(w + w);
1113 : }
1114 : else
1115 : {
1116 0 : y = 0;
1117 0 : toskew = 0;
1118 : }
1119 :
1120 51 : TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1121 51 : if (rowsperstrip == 0)
1122 : {
1123 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
1124 0 : return (0);
1125 : }
1126 :
1127 51 : scanline = TIFFScanlineSize(tif);
1128 51 : fromskew = (w < imagewidth ? imagewidth - w : 0);
1129 102 : for (row = 0; row < h; row += nrow)
1130 : {
1131 : uint32_t temp;
1132 51 : rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
1133 51 : nrow = (row + rowstoread > h ? h - row : rowstoread);
1134 51 : nrowsub = nrow;
1135 51 : if ((nrowsub % subsamplingver) != 0)
1136 11 : nrowsub += subsamplingver - nrowsub % subsamplingver;
1137 51 : temp = (row + img->row_offset) % rowsperstrip + nrowsub;
1138 51 : if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
1139 : {
1140 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
1141 : "Integer overflow in gtStripContig");
1142 0 : return 0;
1143 : }
1144 51 : if (_TIFFReadEncodedStripAndAllocBuffer(
1145 51 : tif, TIFFComputeStrip(tif, row + img->row_offset, 0),
1146 : (void **)(&buf), maxstripsize,
1147 0 : temp * scanline) == (tmsize_t)(-1) &&
1148 0 : (buf == NULL || img->stoponerr))
1149 : {
1150 0 : ret = 0;
1151 0 : break;
1152 : }
1153 :
1154 51 : pos = ((row + img->row_offset) % rowsperstrip) * scanline +
1155 51 : ((tmsize_t)img->col_offset * img->samplesperpixel);
1156 51 : tmsize_t roffset = (tmsize_t)y * w;
1157 51 : (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew,
1158 : buf + pos);
1159 51 : y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
1160 : }
1161 :
1162 51 : if (flip & FLIP_HORIZONTALLY)
1163 : {
1164 : uint32_t line;
1165 :
1166 0 : for (line = 0; line < h; line++)
1167 : {
1168 0 : uint32_t *left = raster + (line * w);
1169 0 : uint32_t *right = left + w - 1;
1170 :
1171 0 : while (left < right)
1172 : {
1173 0 : uint32_t temp = *left;
1174 0 : *left = *right;
1175 0 : *right = temp;
1176 0 : left++;
1177 0 : right--;
1178 : }
1179 : }
1180 : }
1181 :
1182 51 : _TIFFfreeExt(img->tif, buf);
1183 51 : return (ret);
1184 : }
1185 :
1186 : /*
1187 : * Get a strip-organized image with
1188 : * SamplesPerPixel > 1
1189 : * PlanarConfiguration separated
1190 : * We assume that all such images are RGB.
1191 : */
1192 2 : static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
1193 : uint32_t h)
1194 : {
1195 2 : TIFF *tif = img->tif;
1196 2 : tileSeparateRoutine put = img->put.separate;
1197 2 : unsigned char *buf = NULL;
1198 2 : unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL;
1199 : uint32_t row, y, nrow, rowstoread;
1200 : tmsize_t pos;
1201 : tmsize_t scanline;
1202 : uint32_t rowsperstrip, offset_row;
1203 2 : uint32_t imagewidth = img->width;
1204 : tmsize_t stripsize;
1205 : tmsize_t bufsize;
1206 : int32_t fromskew, toskew;
1207 2 : int alpha = img->alpha;
1208 2 : int ret = 1, flip;
1209 : uint16_t colorchannels;
1210 :
1211 2 : stripsize = TIFFStripSize(tif);
1212 : bufsize =
1213 2 : _TIFFMultiplySSize(tif, alpha ? 4 : 3, stripsize, "gtStripSeparate");
1214 2 : if (bufsize == 0)
1215 : {
1216 0 : return (0);
1217 : }
1218 :
1219 2 : flip = setorientation(img);
1220 2 : if (flip & FLIP_VERTICALLY)
1221 : {
1222 2 : if (w > INT_MAX / 2)
1223 : {
1224 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
1225 0 : return (0);
1226 : }
1227 2 : y = h - 1;
1228 2 : toskew = -(int32_t)(w + w);
1229 : }
1230 : else
1231 : {
1232 0 : y = 0;
1233 0 : toskew = 0;
1234 : }
1235 :
1236 2 : switch (img->photometric)
1237 : {
1238 1 : case PHOTOMETRIC_MINISWHITE:
1239 : case PHOTOMETRIC_MINISBLACK:
1240 : case PHOTOMETRIC_PALETTE:
1241 1 : colorchannels = 1;
1242 1 : break;
1243 :
1244 1 : default:
1245 1 : colorchannels = 3;
1246 1 : break;
1247 : }
1248 :
1249 2 : TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1250 2 : if (rowsperstrip == 0)
1251 : {
1252 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
1253 0 : return (0);
1254 : }
1255 :
1256 2 : scanline = TIFFScanlineSize(tif);
1257 2 : fromskew = (w < imagewidth ? imagewidth - w : 0);
1258 4 : for (row = 0; row < h; row += nrow)
1259 : {
1260 : uint32_t temp;
1261 2 : rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
1262 2 : nrow = (row + rowstoread > h ? h - row : rowstoread);
1263 2 : offset_row = row + img->row_offset;
1264 2 : temp = (row + img->row_offset) % rowsperstrip + nrow;
1265 2 : if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
1266 : {
1267 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
1268 : "Integer overflow in gtStripSeparate");
1269 0 : return 0;
1270 : }
1271 2 : if (buf == NULL)
1272 : {
1273 2 : if (_TIFFReadEncodedStripAndAllocBuffer(
1274 : tif, TIFFComputeStrip(tif, offset_row, 0), (void **)&buf,
1275 0 : bufsize, temp * scanline) == (tmsize_t)(-1) &&
1276 0 : (buf == NULL || img->stoponerr))
1277 : {
1278 0 : ret = 0;
1279 0 : break;
1280 : }
1281 2 : p0 = buf;
1282 2 : if (colorchannels == 1)
1283 : {
1284 1 : p2 = p1 = p0;
1285 1 : pa = (alpha ? (p0 + 3 * stripsize) : NULL);
1286 : }
1287 : else
1288 : {
1289 1 : p1 = p0 + stripsize;
1290 1 : p2 = p1 + stripsize;
1291 1 : pa = (alpha ? (p2 + stripsize) : NULL);
1292 : }
1293 : }
1294 0 : else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
1295 0 : p0, temp * scanline) == (tmsize_t)(-1) &&
1296 0 : img->stoponerr)
1297 : {
1298 0 : ret = 0;
1299 0 : break;
1300 : }
1301 3 : if (colorchannels > 1 &&
1302 1 : TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), p1,
1303 0 : temp * scanline) == (tmsize_t)(-1) &&
1304 0 : img->stoponerr)
1305 : {
1306 0 : ret = 0;
1307 0 : break;
1308 : }
1309 3 : if (colorchannels > 1 &&
1310 1 : TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), p2,
1311 0 : temp * scanline) == (tmsize_t)(-1) &&
1312 0 : img->stoponerr)
1313 : {
1314 0 : ret = 0;
1315 0 : break;
1316 : }
1317 2 : if (alpha)
1318 : {
1319 0 : if (TIFFReadEncodedStrip(
1320 : tif, TIFFComputeStrip(tif, offset_row, colorchannels), pa,
1321 0 : temp * scanline) == (tmsize_t)(-1) &&
1322 0 : img->stoponerr)
1323 : {
1324 0 : ret = 0;
1325 0 : break;
1326 : }
1327 : }
1328 :
1329 2 : pos = ((row + img->row_offset) % rowsperstrip) * scanline +
1330 2 : ((tmsize_t)img->col_offset * img->samplesperpixel);
1331 2 : tmsize_t roffset = (tmsize_t)y * w;
1332 2 : (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew, p0 + pos,
1333 0 : p1 + pos, p2 + pos, (alpha ? (pa + pos) : NULL));
1334 2 : y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
1335 : }
1336 :
1337 2 : if (flip & FLIP_HORIZONTALLY)
1338 : {
1339 : uint32_t line;
1340 :
1341 0 : for (line = 0; line < h; line++)
1342 : {
1343 0 : uint32_t *left = raster + (line * w);
1344 0 : uint32_t *right = left + w - 1;
1345 :
1346 0 : while (left < right)
1347 : {
1348 0 : uint32_t temp = *left;
1349 0 : *left = *right;
1350 0 : *right = temp;
1351 0 : left++;
1352 0 : right--;
1353 : }
1354 : }
1355 : }
1356 :
1357 2 : _TIFFfreeExt(img->tif, buf);
1358 2 : return (ret);
1359 : }
1360 :
1361 : /*
1362 : * The following routines move decoded data returned
1363 : * from the TIFF library into rasters filled with packed
1364 : * ABGR pixels (i.e. suitable for passing to lrecwrite.)
1365 : *
1366 : * The routines have been created according to the most
1367 : * important cases and optimized. PickContigCase and
1368 : * PickSeparateCase analyze the parameters and select
1369 : * the appropriate "get" and "put" routine to use.
1370 : */
1371 : #define REPEAT8(op) \
1372 : REPEAT4(op); \
1373 : REPEAT4(op)
1374 : #define REPEAT4(op) \
1375 : REPEAT2(op); \
1376 : REPEAT2(op)
1377 : #define REPEAT2(op) \
1378 : op; \
1379 : op
1380 : #define CASE8(x, op) \
1381 : switch (x) \
1382 : { \
1383 : case 7: \
1384 : op; /*-fallthrough*/ \
1385 : case 6: \
1386 : op; /*-fallthrough*/ \
1387 : case 5: \
1388 : op; /*-fallthrough*/ \
1389 : case 4: \
1390 : op; /*-fallthrough*/ \
1391 : case 3: \
1392 : op; /*-fallthrough*/ \
1393 : case 2: \
1394 : op; /*-fallthrough*/ \
1395 : case 1: \
1396 : op; \
1397 : }
1398 : #define CASE4(x, op) \
1399 : switch (x) \
1400 : { \
1401 : case 3: \
1402 : op; /*-fallthrough*/ \
1403 : case 2: \
1404 : op; /*-fallthrough*/ \
1405 : case 1: \
1406 : op; \
1407 : }
1408 : #define NOP
1409 :
1410 : #define UNROLL8(w, op1, op2) \
1411 : { \
1412 : uint32_t _x; \
1413 : for (_x = w; _x >= 8; _x -= 8) \
1414 : { \
1415 : op1; \
1416 : REPEAT8(op2); \
1417 : } \
1418 : if (_x > 0) \
1419 : { \
1420 : op1; \
1421 : CASE8(_x, op2); \
1422 : } \
1423 : }
1424 : #define UNROLL4(w, op1, op2) \
1425 : { \
1426 : uint32_t _x; \
1427 : for (_x = w; _x >= 4; _x -= 4) \
1428 : { \
1429 : op1; \
1430 : REPEAT4(op2); \
1431 : } \
1432 : if (_x > 0) \
1433 : { \
1434 : op1; \
1435 : CASE4(_x, op2); \
1436 : } \
1437 : }
1438 : #define UNROLL2(w, op1, op2) \
1439 : { \
1440 : uint32_t _x; \
1441 : for (_x = w; _x >= 2; _x -= 2) \
1442 : { \
1443 : op1; \
1444 : REPEAT2(op2); \
1445 : } \
1446 : if (_x) \
1447 : { \
1448 : op1; \
1449 : op2; \
1450 : } \
1451 : }
1452 :
1453 : #define SKEW(r, g, b, skew) \
1454 : { \
1455 : r += skew; \
1456 : g += skew; \
1457 : b += skew; \
1458 : }
1459 : #define SKEW4(r, g, b, a, skew) \
1460 : { \
1461 : r += skew; \
1462 : g += skew; \
1463 : b += skew; \
1464 : a += skew; \
1465 : }
1466 :
1467 : #define A1 (((uint32_t)0xffL) << 24)
1468 : #define PACK(r, g, b) \
1469 : ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) | A1)
1470 : #define PACK4(r, g, b, a) \
1471 : ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) | \
1472 : ((uint32_t)(a) << 24))
1473 : #define W2B(v) (((v) >> 8) & 0xff)
1474 : /* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */
1475 : #define PACKW(r, g, b) \
1476 : ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) | A1)
1477 : #define PACKW4(r, g, b, a) \
1478 : ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) | \
1479 : ((uint32_t)W2B(a) << 24))
1480 :
1481 : #define DECLAREContigPutFunc(name) \
1482 : static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
1483 : uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
1484 : unsigned char *pp)
1485 :
1486 : /*
1487 : * 8-bit palette => colormap/RGB
1488 : */
1489 1 : DECLAREContigPutFunc(put8bitcmaptile)
1490 : {
1491 1 : uint32_t **PALmap = img->PALmap;
1492 1 : int samplesperpixel = img->samplesperpixel;
1493 :
1494 : (void)y;
1495 21 : for (; h > 0; --h)
1496 : {
1497 420 : for (x = w; x > 0; --x)
1498 : {
1499 400 : *cp++ = PALmap[*pp][0];
1500 400 : pp += samplesperpixel;
1501 : }
1502 20 : cp += toskew;
1503 20 : pp += fromskew;
1504 : }
1505 1 : }
1506 :
1507 : /*
1508 : * 4-bit palette => colormap/RGB
1509 : */
1510 0 : DECLAREContigPutFunc(put4bitcmaptile)
1511 : {
1512 0 : uint32_t **PALmap = img->PALmap;
1513 :
1514 : (void)x;
1515 : (void)y;
1516 0 : fromskew /= 2;
1517 0 : for (; h > 0; --h)
1518 : {
1519 : uint32_t *bw;
1520 0 : UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
1521 0 : cp += toskew;
1522 0 : pp += fromskew;
1523 : }
1524 0 : }
1525 :
1526 : /*
1527 : * 2-bit palette => colormap/RGB
1528 : */
1529 0 : DECLAREContigPutFunc(put2bitcmaptile)
1530 : {
1531 0 : uint32_t **PALmap = img->PALmap;
1532 :
1533 : (void)x;
1534 : (void)y;
1535 0 : fromskew /= 4;
1536 0 : for (; h > 0; --h)
1537 : {
1538 : uint32_t *bw;
1539 0 : UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
1540 0 : cp += toskew;
1541 0 : pp += fromskew;
1542 : }
1543 0 : }
1544 :
1545 : /*
1546 : * 1-bit palette => colormap/RGB
1547 : */
1548 0 : DECLAREContigPutFunc(put1bitcmaptile)
1549 : {
1550 0 : uint32_t **PALmap = img->PALmap;
1551 :
1552 : (void)x;
1553 : (void)y;
1554 0 : fromskew /= 8;
1555 0 : for (; h > 0; --h)
1556 : {
1557 : uint32_t *bw;
1558 0 : UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
1559 0 : cp += toskew;
1560 0 : pp += fromskew;
1561 : }
1562 0 : }
1563 :
1564 : /*
1565 : * 8-bit greyscale => colormap/RGB
1566 : */
1567 3 : DECLAREContigPutFunc(putgreytile)
1568 : {
1569 3 : int samplesperpixel = img->samplesperpixel;
1570 3 : uint32_t **BWmap = img->BWmap;
1571 :
1572 : (void)y;
1573 63 : for (; h > 0; --h)
1574 : {
1575 1260 : for (x = w; x > 0; --x)
1576 : {
1577 1200 : *cp++ = BWmap[*pp][0];
1578 1200 : pp += samplesperpixel;
1579 : }
1580 60 : cp += toskew;
1581 60 : pp += fromskew;
1582 : }
1583 3 : }
1584 :
1585 : /*
1586 : * 8-bit greyscale with associated alpha => colormap/RGBA
1587 : */
1588 6 : DECLAREContigPutFunc(putagreytile)
1589 : {
1590 6 : int samplesperpixel = img->samplesperpixel;
1591 6 : uint32_t **BWmap = img->BWmap;
1592 :
1593 : (void)y;
1594 156 : for (; h > 0; --h)
1595 : {
1596 24450 : for (x = w; x > 0; --x)
1597 : {
1598 24300 : *cp++ = BWmap[*pp][0] & ((uint32_t) * (pp + 1) << 24 | ~A1);
1599 24300 : pp += samplesperpixel;
1600 : }
1601 150 : cp += toskew;
1602 150 : pp += fromskew;
1603 : }
1604 6 : }
1605 :
1606 : /*
1607 : * 16-bit greyscale => colormap/RGB
1608 : */
1609 0 : DECLAREContigPutFunc(put16bitbwtile)
1610 : {
1611 0 : int samplesperpixel = img->samplesperpixel;
1612 0 : uint32_t **BWmap = img->BWmap;
1613 :
1614 : (void)y;
1615 0 : for (; h > 0; --h)
1616 : {
1617 0 : uint16_t *wp = (uint16_t *)pp;
1618 :
1619 0 : for (x = w; x > 0; --x)
1620 : {
1621 : /* use high order byte of 16bit value */
1622 :
1623 0 : *cp++ = BWmap[*wp >> 8][0];
1624 0 : pp += 2 * samplesperpixel;
1625 0 : wp += samplesperpixel;
1626 : }
1627 0 : cp += toskew;
1628 0 : pp += fromskew;
1629 : }
1630 0 : }
1631 :
1632 : /*
1633 : * 1-bit bilevel => colormap/RGB
1634 : */
1635 0 : DECLAREContigPutFunc(put1bitbwtile)
1636 : {
1637 0 : uint32_t **BWmap = img->BWmap;
1638 :
1639 : (void)x;
1640 : (void)y;
1641 0 : fromskew /= 8;
1642 0 : for (; h > 0; --h)
1643 : {
1644 : uint32_t *bw;
1645 0 : UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
1646 0 : cp += toskew;
1647 0 : pp += fromskew;
1648 : }
1649 0 : }
1650 :
1651 : /*
1652 : * 2-bit greyscale => colormap/RGB
1653 : */
1654 0 : DECLAREContigPutFunc(put2bitbwtile)
1655 : {
1656 0 : uint32_t **BWmap = img->BWmap;
1657 :
1658 : (void)x;
1659 : (void)y;
1660 0 : fromskew /= 4;
1661 0 : for (; h > 0; --h)
1662 : {
1663 : uint32_t *bw;
1664 0 : UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
1665 0 : cp += toskew;
1666 0 : pp += fromskew;
1667 : }
1668 0 : }
1669 :
1670 : /*
1671 : * 4-bit greyscale => colormap/RGB
1672 : */
1673 0 : DECLAREContigPutFunc(put4bitbwtile)
1674 : {
1675 0 : uint32_t **BWmap = img->BWmap;
1676 :
1677 : (void)x;
1678 : (void)y;
1679 0 : fromskew /= 2;
1680 0 : for (; h > 0; --h)
1681 : {
1682 : uint32_t *bw;
1683 0 : UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
1684 0 : cp += toskew;
1685 0 : pp += fromskew;
1686 : }
1687 0 : }
1688 :
1689 : /*
1690 : * 8-bit packed samples, no Map => RGB
1691 : */
1692 0 : DECLAREContigPutFunc(putRGBcontig8bittile)
1693 : {
1694 0 : int samplesperpixel = img->samplesperpixel;
1695 :
1696 : (void)x;
1697 : (void)y;
1698 0 : fromskew *= samplesperpixel;
1699 0 : for (; h > 0; --h)
1700 : {
1701 0 : UNROLL8(w, NOP, *cp++ = PACK(pp[0], pp[1], pp[2]);
1702 : pp += samplesperpixel);
1703 0 : cp += toskew;
1704 0 : pp += fromskew;
1705 : }
1706 0 : }
1707 :
1708 : /*
1709 : * 8-bit packed samples => RGBA w/ associated alpha
1710 : * (known to have Map == NULL)
1711 : */
1712 13 : DECLAREContigPutFunc(putRGBAAcontig8bittile)
1713 : {
1714 13 : int samplesperpixel = img->samplesperpixel;
1715 :
1716 : (void)x;
1717 : (void)y;
1718 13 : fromskew *= samplesperpixel;
1719 163 : for (; h > 0; --h)
1720 : {
1721 3150 : UNROLL8(w, NOP, *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
1722 : pp += samplesperpixel);
1723 150 : cp += toskew;
1724 150 : pp += fromskew;
1725 : }
1726 13 : }
1727 :
1728 : /*
1729 : * 8-bit packed samples => RGBA w/ unassociated alpha
1730 : * (known to have Map == NULL)
1731 : */
1732 13 : DECLAREContigPutFunc(putRGBUAcontig8bittile)
1733 : {
1734 13 : int samplesperpixel = img->samplesperpixel;
1735 : (void)y;
1736 13 : fromskew *= samplesperpixel;
1737 163 : for (; h > 0; --h)
1738 : {
1739 : uint32_t r, g, b, a;
1740 : uint8_t *m;
1741 24450 : for (x = w; x > 0; --x)
1742 : {
1743 24300 : a = pp[3];
1744 24300 : m = img->UaToAa + ((size_t)a << 8);
1745 24300 : r = m[pp[0]];
1746 24300 : g = m[pp[1]];
1747 24300 : b = m[pp[2]];
1748 24300 : *cp++ = PACK4(r, g, b, a);
1749 24300 : pp += samplesperpixel;
1750 : }
1751 150 : cp += toskew;
1752 150 : pp += fromskew;
1753 : }
1754 13 : }
1755 :
1756 : /*
1757 : * 16-bit packed samples => RGB
1758 : */
1759 0 : DECLAREContigPutFunc(putRGBcontig16bittile)
1760 : {
1761 0 : int samplesperpixel = img->samplesperpixel;
1762 0 : uint16_t *wp = (uint16_t *)pp;
1763 : (void)y;
1764 0 : fromskew *= samplesperpixel;
1765 0 : for (; h > 0; --h)
1766 : {
1767 0 : for (x = w; x > 0; --x)
1768 : {
1769 0 : *cp++ = PACK(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
1770 : img->Bitdepth16To8[wp[2]]);
1771 0 : wp += samplesperpixel;
1772 : }
1773 0 : cp += toskew;
1774 0 : wp += fromskew;
1775 : }
1776 0 : }
1777 :
1778 : /*
1779 : * 16-bit packed samples => RGBA w/ associated alpha
1780 : * (known to have Map == NULL)
1781 : */
1782 0 : DECLAREContigPutFunc(putRGBAAcontig16bittile)
1783 : {
1784 0 : int samplesperpixel = img->samplesperpixel;
1785 0 : uint16_t *wp = (uint16_t *)pp;
1786 : (void)y;
1787 0 : fromskew *= samplesperpixel;
1788 0 : for (; h > 0; --h)
1789 : {
1790 0 : for (x = w; x > 0; --x)
1791 : {
1792 0 : *cp++ = PACK4(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
1793 : img->Bitdepth16To8[wp[2]], img->Bitdepth16To8[wp[3]]);
1794 0 : wp += samplesperpixel;
1795 : }
1796 0 : cp += toskew;
1797 0 : wp += fromskew;
1798 : }
1799 0 : }
1800 :
1801 : /*
1802 : * 16-bit packed samples => RGBA w/ unassociated alpha
1803 : * (known to have Map == NULL)
1804 : */
1805 0 : DECLAREContigPutFunc(putRGBUAcontig16bittile)
1806 : {
1807 0 : int samplesperpixel = img->samplesperpixel;
1808 0 : uint16_t *wp = (uint16_t *)pp;
1809 : (void)y;
1810 0 : fromskew *= samplesperpixel;
1811 0 : for (; h > 0; --h)
1812 : {
1813 : uint32_t r, g, b, a;
1814 : uint8_t *m;
1815 0 : for (x = w; x > 0; --x)
1816 : {
1817 0 : a = img->Bitdepth16To8[wp[3]];
1818 0 : m = img->UaToAa + ((size_t)a << 8);
1819 0 : r = m[img->Bitdepth16To8[wp[0]]];
1820 0 : g = m[img->Bitdepth16To8[wp[1]]];
1821 0 : b = m[img->Bitdepth16To8[wp[2]]];
1822 0 : *cp++ = PACK4(r, g, b, a);
1823 0 : wp += samplesperpixel;
1824 : }
1825 0 : cp += toskew;
1826 0 : wp += fromskew;
1827 : }
1828 0 : }
1829 :
1830 : /*
1831 : * 8-bit packed CMYK samples w/o Map => RGB
1832 : *
1833 : * NB: The conversion of CMYK->RGB is *very* crude.
1834 : */
1835 6 : DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
1836 : {
1837 6 : int samplesperpixel = img->samplesperpixel;
1838 : uint16_t r, g, b, k;
1839 :
1840 : (void)x;
1841 : (void)y;
1842 6 : fromskew *= samplesperpixel;
1843 156 : for (; h > 0; --h)
1844 : {
1845 1050 : UNROLL8(w, NOP, k = 255 - pp[3]; r = (k * (255 - pp[0])) / 255;
1846 : g = (k * (255 - pp[1])) / 255; b = (k * (255 - pp[2])) / 255;
1847 : *cp++ = PACK(r, g, b); pp += samplesperpixel);
1848 150 : cp += toskew;
1849 150 : pp += fromskew;
1850 : }
1851 6 : }
1852 :
1853 : /*
1854 : * 8-bit packed CMYK samples w/Map => RGB
1855 : *
1856 : * NB: The conversion of CMYK->RGB is *very* crude.
1857 : */
1858 0 : DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
1859 : {
1860 0 : int samplesperpixel = img->samplesperpixel;
1861 0 : TIFFRGBValue *Map = img->Map;
1862 : uint16_t r, g, b, k;
1863 :
1864 : (void)y;
1865 0 : fromskew *= samplesperpixel;
1866 0 : for (; h > 0; --h)
1867 : {
1868 0 : for (x = w; x > 0; --x)
1869 : {
1870 0 : k = 255 - pp[3];
1871 0 : r = (k * (255 - pp[0])) / 255;
1872 0 : g = (k * (255 - pp[1])) / 255;
1873 0 : b = (k * (255 - pp[2])) / 255;
1874 0 : *cp++ = PACK(Map[r], Map[g], Map[b]);
1875 0 : pp += samplesperpixel;
1876 : }
1877 0 : pp += fromskew;
1878 0 : cp += toskew;
1879 : }
1880 0 : }
1881 :
1882 : #define DECLARESepPutFunc(name) \
1883 : static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
1884 : uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
1885 : unsigned char *r, unsigned char *g, unsigned char *b, \
1886 : unsigned char *a)
1887 :
1888 : /*
1889 : * 8-bit unpacked samples => RGB
1890 : */
1891 3 : DECLARESepPutFunc(putRGBseparate8bittile)
1892 : {
1893 : (void)img;
1894 : (void)x;
1895 : (void)y;
1896 : (void)a;
1897 153 : for (; h > 0; --h)
1898 : {
1899 1050 : UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
1900 150 : SKEW(r, g, b, fromskew);
1901 150 : cp += toskew;
1902 : }
1903 3 : }
1904 :
1905 : /*
1906 : * 8-bit unpacked samples => RGBA w/ associated alpha
1907 : */
1908 0 : DECLARESepPutFunc(putRGBAAseparate8bittile)
1909 : {
1910 : (void)img;
1911 : (void)x;
1912 : (void)y;
1913 0 : for (; h > 0; --h)
1914 : {
1915 0 : UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
1916 0 : SKEW4(r, g, b, a, fromskew);
1917 0 : cp += toskew;
1918 : }
1919 0 : }
1920 :
1921 : /*
1922 : * 8-bit unpacked CMYK samples => RGBA
1923 : */
1924 0 : DECLARESepPutFunc(putCMYKseparate8bittile)
1925 : {
1926 : (void)img;
1927 : (void)y;
1928 0 : for (; h > 0; --h)
1929 : {
1930 : uint32_t rv, gv, bv, kv;
1931 0 : for (x = w; x > 0; --x)
1932 : {
1933 0 : kv = 255 - *a++;
1934 0 : rv = (kv * (255 - *r++)) / 255;
1935 0 : gv = (kv * (255 - *g++)) / 255;
1936 0 : bv = (kv * (255 - *b++)) / 255;
1937 0 : *cp++ = PACK4(rv, gv, bv, 255);
1938 : }
1939 0 : SKEW4(r, g, b, a, fromskew);
1940 0 : cp += toskew;
1941 : }
1942 0 : }
1943 :
1944 : /*
1945 : * 8-bit unpacked samples => RGBA w/ unassociated alpha
1946 : */
1947 0 : DECLARESepPutFunc(putRGBUAseparate8bittile)
1948 : {
1949 : (void)img;
1950 : (void)y;
1951 0 : for (; h > 0; --h)
1952 : {
1953 : uint32_t rv, gv, bv, av;
1954 : uint8_t *m;
1955 0 : for (x = w; x > 0; --x)
1956 : {
1957 0 : av = *a++;
1958 0 : m = img->UaToAa + ((size_t)av << 8);
1959 0 : rv = m[*r++];
1960 0 : gv = m[*g++];
1961 0 : bv = m[*b++];
1962 0 : *cp++ = PACK4(rv, gv, bv, av);
1963 : }
1964 0 : SKEW4(r, g, b, a, fromskew);
1965 0 : cp += toskew;
1966 : }
1967 0 : }
1968 :
1969 : /*
1970 : * 16-bit unpacked samples => RGB
1971 : */
1972 0 : DECLARESepPutFunc(putRGBseparate16bittile)
1973 : {
1974 0 : uint16_t *wr = (uint16_t *)r;
1975 0 : uint16_t *wg = (uint16_t *)g;
1976 0 : uint16_t *wb = (uint16_t *)b;
1977 : (void)img;
1978 : (void)y;
1979 : (void)a;
1980 0 : for (; h > 0; --h)
1981 : {
1982 0 : for (x = 0; x < w; x++)
1983 0 : *cp++ = PACK(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
1984 : img->Bitdepth16To8[*wb++]);
1985 0 : SKEW(wr, wg, wb, fromskew);
1986 0 : cp += toskew;
1987 : }
1988 0 : }
1989 :
1990 : /*
1991 : * 16-bit unpacked samples => RGBA w/ associated alpha
1992 : */
1993 0 : DECLARESepPutFunc(putRGBAAseparate16bittile)
1994 : {
1995 0 : uint16_t *wr = (uint16_t *)r;
1996 0 : uint16_t *wg = (uint16_t *)g;
1997 0 : uint16_t *wb = (uint16_t *)b;
1998 0 : uint16_t *wa = (uint16_t *)a;
1999 : (void)img;
2000 : (void)y;
2001 0 : for (; h > 0; --h)
2002 : {
2003 0 : for (x = 0; x < w; x++)
2004 0 : *cp++ = PACK4(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
2005 : img->Bitdepth16To8[*wb++], img->Bitdepth16To8[*wa++]);
2006 0 : SKEW4(wr, wg, wb, wa, fromskew);
2007 0 : cp += toskew;
2008 : }
2009 0 : }
2010 :
2011 : /*
2012 : * 16-bit unpacked samples => RGBA w/ unassociated alpha
2013 : */
2014 0 : DECLARESepPutFunc(putRGBUAseparate16bittile)
2015 : {
2016 0 : uint16_t *wr = (uint16_t *)r;
2017 0 : uint16_t *wg = (uint16_t *)g;
2018 0 : uint16_t *wb = (uint16_t *)b;
2019 0 : uint16_t *wa = (uint16_t *)a;
2020 : (void)img;
2021 : (void)y;
2022 0 : for (; h > 0; --h)
2023 : {
2024 : uint32_t r2, g2, b2, a2;
2025 : uint8_t *m;
2026 0 : for (x = w; x > 0; --x)
2027 : {
2028 0 : a2 = img->Bitdepth16To8[*wa++];
2029 0 : m = img->UaToAa + ((size_t)a2 << 8);
2030 0 : r2 = m[img->Bitdepth16To8[*wr++]];
2031 0 : g2 = m[img->Bitdepth16To8[*wg++]];
2032 0 : b2 = m[img->Bitdepth16To8[*wb++]];
2033 0 : *cp++ = PACK4(r2, g2, b2, a2);
2034 : }
2035 0 : SKEW4(wr, wg, wb, wa, fromskew);
2036 0 : cp += toskew;
2037 : }
2038 0 : }
2039 :
2040 : /*
2041 : * 8-bit packed CIE L*a*b 1976 samples => RGB
2042 : */
2043 1 : DECLAREContigPutFunc(putcontig8bitCIELab8)
2044 : {
2045 : float X, Y, Z;
2046 : uint32_t r, g, b;
2047 : (void)y;
2048 1 : fromskew *= 3;
2049 2 : for (; h > 0; --h)
2050 : {
2051 2 : for (x = w; x > 0; --x)
2052 : {
2053 1 : TIFFCIELabToXYZ(img->cielab, (unsigned char)pp[0],
2054 1 : (signed char)pp[1], (signed char)pp[2], &X, &Y, &Z);
2055 1 : TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
2056 1 : *cp++ = PACK(r, g, b);
2057 1 : pp += 3;
2058 : }
2059 1 : cp += toskew;
2060 1 : pp += fromskew;
2061 : }
2062 1 : }
2063 :
2064 : /*
2065 : * 16-bit packed CIE L*a*b 1976 samples => RGB
2066 : */
2067 0 : DECLAREContigPutFunc(putcontig8bitCIELab16)
2068 : {
2069 : float X, Y, Z;
2070 : uint32_t r, g, b;
2071 0 : uint16_t *wp = (uint16_t *)pp;
2072 : (void)y;
2073 0 : fromskew *= 3;
2074 0 : for (; h > 0; --h)
2075 : {
2076 0 : for (x = w; x > 0; --x)
2077 : {
2078 0 : TIFFCIELab16ToXYZ(img->cielab, (uint16_t)wp[0], (int16_t)wp[1],
2079 0 : (int16_t)wp[2], &X, &Y, &Z);
2080 0 : TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
2081 0 : *cp++ = PACK(r, g, b);
2082 0 : wp += 3;
2083 : }
2084 0 : cp += toskew;
2085 0 : wp += fromskew;
2086 : }
2087 0 : }
2088 :
2089 : /*
2090 : * YCbCr -> RGB conversion and packing routines.
2091 : */
2092 :
2093 : #define YCbCrtoRGB(dst, Y) \
2094 : { \
2095 : uint32_t r, g, b; \
2096 : TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \
2097 : dst = PACK(r, g, b); \
2098 : }
2099 :
2100 : /*
2101 : * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
2102 : */
2103 2 : DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
2104 : {
2105 2 : uint32_t *cp1 = cp + w + toskew;
2106 2 : uint32_t *cp2 = cp1 + w + toskew;
2107 2 : uint32_t *cp3 = cp2 + w + toskew;
2108 2 : int32_t incr = 3 * w + 4 * toskew;
2109 :
2110 : (void)y;
2111 : /* adjust fromskew */
2112 2 : fromskew = (fromskew / 4) * (4 * 2 + 2);
2113 2 : if ((h & 3) == 0 && (w & 3) == 0)
2114 : {
2115 13 : for (; h >= 4; h -= 4)
2116 : {
2117 12 : x = w >> 2;
2118 : do
2119 : {
2120 144 : int32_t Cb = pp[16];
2121 144 : int32_t Cr = pp[17];
2122 :
2123 144 : YCbCrtoRGB(cp[0], pp[0]);
2124 144 : YCbCrtoRGB(cp[1], pp[1]);
2125 144 : YCbCrtoRGB(cp[2], pp[2]);
2126 144 : YCbCrtoRGB(cp[3], pp[3]);
2127 144 : YCbCrtoRGB(cp1[0], pp[4]);
2128 144 : YCbCrtoRGB(cp1[1], pp[5]);
2129 144 : YCbCrtoRGB(cp1[2], pp[6]);
2130 144 : YCbCrtoRGB(cp1[3], pp[7]);
2131 144 : YCbCrtoRGB(cp2[0], pp[8]);
2132 144 : YCbCrtoRGB(cp2[1], pp[9]);
2133 144 : YCbCrtoRGB(cp2[2], pp[10]);
2134 144 : YCbCrtoRGB(cp2[3], pp[11]);
2135 144 : YCbCrtoRGB(cp3[0], pp[12]);
2136 144 : YCbCrtoRGB(cp3[1], pp[13]);
2137 144 : YCbCrtoRGB(cp3[2], pp[14]);
2138 144 : YCbCrtoRGB(cp3[3], pp[15]);
2139 :
2140 144 : cp += 4;
2141 144 : cp1 += 4;
2142 144 : cp2 += 4;
2143 144 : cp3 += 4;
2144 144 : pp += 18;
2145 144 : } while (--x);
2146 12 : cp += incr;
2147 12 : cp1 += incr;
2148 12 : cp2 += incr;
2149 12 : cp3 += incr;
2150 12 : pp += fromskew;
2151 : }
2152 : }
2153 : else
2154 : {
2155 10 : while (h > 0)
2156 : {
2157 110 : for (x = w; x > 0;)
2158 : {
2159 100 : int32_t Cb = pp[16];
2160 100 : int32_t Cr = pp[17];
2161 100 : switch (x)
2162 : {
2163 90 : default:
2164 90 : switch (h)
2165 : {
2166 81 : default:
2167 81 : YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
2168 90 : case 3:
2169 90 : YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
2170 90 : case 2:
2171 90 : YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
2172 90 : case 1:
2173 90 : YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
2174 : } /* FALLTHROUGH */
2175 100 : case 3:
2176 100 : switch (h)
2177 : {
2178 90 : default:
2179 90 : YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
2180 100 : case 3:
2181 100 : YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
2182 100 : case 2:
2183 100 : YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
2184 100 : case 1:
2185 100 : YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
2186 : } /* FALLTHROUGH */
2187 100 : case 2:
2188 100 : switch (h)
2189 : {
2190 90 : default:
2191 90 : YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
2192 100 : case 3:
2193 100 : YCbCrtoRGB(cp2[1], pp[9]); /* FALLTHROUGH */
2194 100 : case 2:
2195 100 : YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
2196 100 : case 1:
2197 100 : YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
2198 : } /* FALLTHROUGH */
2199 100 : case 1:
2200 100 : switch (h)
2201 : {
2202 90 : default:
2203 90 : YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
2204 100 : case 3:
2205 100 : YCbCrtoRGB(cp2[0], pp[8]); /* FALLTHROUGH */
2206 100 : case 2:
2207 100 : YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
2208 100 : case 1:
2209 100 : YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
2210 : } /* FALLTHROUGH */
2211 : }
2212 100 : if (x < 4)
2213 : {
2214 10 : cp += x;
2215 10 : cp1 += x;
2216 10 : cp2 += x;
2217 10 : cp3 += x;
2218 10 : x = 0;
2219 : }
2220 : else
2221 : {
2222 90 : cp += 4;
2223 90 : cp1 += 4;
2224 90 : cp2 += 4;
2225 90 : cp3 += 4;
2226 90 : x -= 4;
2227 : }
2228 100 : pp += 18;
2229 : }
2230 10 : if (h <= 4)
2231 1 : break;
2232 9 : h -= 4;
2233 9 : cp += incr;
2234 9 : cp1 += incr;
2235 9 : cp2 += incr;
2236 9 : cp3 += incr;
2237 9 : pp += fromskew;
2238 : }
2239 : }
2240 2 : }
2241 :
2242 : /*
2243 : * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
2244 : */
2245 2 : DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
2246 : {
2247 2 : uint32_t *cp1 = cp + w + toskew;
2248 2 : int32_t incr = 2 * toskew + w;
2249 :
2250 : (void)y;
2251 2 : fromskew = (fromskew / 4) * (4 * 2 + 2);
2252 2 : if ((w & 3) == 0 && (h & 1) == 0)
2253 : {
2254 25 : for (; h >= 2; h -= 2)
2255 : {
2256 24 : x = w >> 2;
2257 : do
2258 : {
2259 288 : int32_t Cb = pp[8];
2260 288 : int32_t Cr = pp[9];
2261 :
2262 288 : YCbCrtoRGB(cp[0], pp[0]);
2263 288 : YCbCrtoRGB(cp[1], pp[1]);
2264 288 : YCbCrtoRGB(cp[2], pp[2]);
2265 288 : YCbCrtoRGB(cp[3], pp[3]);
2266 288 : YCbCrtoRGB(cp1[0], pp[4]);
2267 288 : YCbCrtoRGB(cp1[1], pp[5]);
2268 288 : YCbCrtoRGB(cp1[2], pp[6]);
2269 288 : YCbCrtoRGB(cp1[3], pp[7]);
2270 :
2271 288 : cp += 4;
2272 288 : cp1 += 4;
2273 288 : pp += 10;
2274 288 : } while (--x);
2275 24 : cp += incr;
2276 24 : cp1 += incr;
2277 24 : pp += fromskew;
2278 : }
2279 : }
2280 : else
2281 : {
2282 20 : while (h > 0)
2283 : {
2284 220 : for (x = w; x > 0;)
2285 : {
2286 200 : int32_t Cb = pp[8];
2287 200 : int32_t Cr = pp[9];
2288 200 : switch (x)
2289 : {
2290 180 : default:
2291 180 : switch (h)
2292 : {
2293 171 : default:
2294 171 : YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
2295 180 : case 1:
2296 180 : YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
2297 : } /* FALLTHROUGH */
2298 200 : case 3:
2299 200 : switch (h)
2300 : {
2301 190 : default:
2302 190 : YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
2303 200 : case 1:
2304 200 : YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
2305 : } /* FALLTHROUGH */
2306 200 : case 2:
2307 200 : switch (h)
2308 : {
2309 190 : default:
2310 190 : YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
2311 200 : case 1:
2312 200 : YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
2313 : } /* FALLTHROUGH */
2314 200 : case 1:
2315 200 : switch (h)
2316 : {
2317 190 : default:
2318 190 : YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
2319 200 : case 1:
2320 200 : YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
2321 : } /* FALLTHROUGH */
2322 : }
2323 200 : if (x < 4)
2324 : {
2325 20 : cp += x;
2326 20 : cp1 += x;
2327 20 : x = 0;
2328 : }
2329 : else
2330 : {
2331 180 : cp += 4;
2332 180 : cp1 += 4;
2333 180 : x -= 4;
2334 : }
2335 200 : pp += 10;
2336 : }
2337 20 : if (h <= 2)
2338 1 : break;
2339 19 : h -= 2;
2340 19 : cp += incr;
2341 19 : cp1 += incr;
2342 19 : pp += fromskew;
2343 : }
2344 : }
2345 2 : }
2346 :
2347 : /*
2348 : * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
2349 : */
2350 1 : DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
2351 : {
2352 : (void)y;
2353 1 : fromskew = (fromskew / 4) * (4 * 1 + 2);
2354 : do
2355 : {
2356 39 : x = w >> 2;
2357 390 : while (x > 0)
2358 : {
2359 351 : int32_t Cb = pp[4];
2360 351 : int32_t Cr = pp[5];
2361 :
2362 351 : YCbCrtoRGB(cp[0], pp[0]);
2363 351 : YCbCrtoRGB(cp[1], pp[1]);
2364 351 : YCbCrtoRGB(cp[2], pp[2]);
2365 351 : YCbCrtoRGB(cp[3], pp[3]);
2366 :
2367 351 : cp += 4;
2368 351 : pp += 6;
2369 351 : x--;
2370 : }
2371 :
2372 39 : if ((w & 3) != 0)
2373 : {
2374 39 : int32_t Cb = pp[4];
2375 39 : int32_t Cr = pp[5];
2376 :
2377 39 : switch ((w & 3))
2378 : {
2379 39 : case 3:
2380 39 : YCbCrtoRGB(cp[2], pp[2]); /*-fallthrough*/
2381 39 : case 2:
2382 39 : YCbCrtoRGB(cp[1], pp[1]); /*-fallthrough*/
2383 39 : case 1:
2384 39 : YCbCrtoRGB(cp[0], pp[0]); /*-fallthrough*/
2385 39 : case 0:
2386 39 : break;
2387 : }
2388 :
2389 39 : cp += (w & 3);
2390 39 : pp += 6;
2391 : }
2392 :
2393 39 : cp += toskew;
2394 39 : pp += fromskew;
2395 39 : } while (--h);
2396 1 : }
2397 :
2398 : /*
2399 : * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
2400 : */
2401 2 : DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
2402 : {
2403 : uint32_t *cp2;
2404 2 : int32_t incr = 2 * toskew + w;
2405 : (void)y;
2406 2 : fromskew = (fromskew / 2) * (2 * 2 + 2);
2407 2 : cp2 = cp + w + toskew;
2408 127 : while (h >= 2)
2409 : {
2410 125 : x = w;
2411 12888 : while (x >= 2)
2412 : {
2413 12763 : uint32_t Cb = pp[4];
2414 12763 : uint32_t Cr = pp[5];
2415 12763 : YCbCrtoRGB(cp[0], pp[0]);
2416 12763 : YCbCrtoRGB(cp[1], pp[1]);
2417 12763 : YCbCrtoRGB(cp2[0], pp[2]);
2418 12763 : YCbCrtoRGB(cp2[1], pp[3]);
2419 12763 : cp += 2;
2420 12763 : cp2 += 2;
2421 12763 : pp += 6;
2422 12763 : x -= 2;
2423 : }
2424 125 : if (x == 1)
2425 : {
2426 19 : uint32_t Cb = pp[4];
2427 19 : uint32_t Cr = pp[5];
2428 19 : YCbCrtoRGB(cp[0], pp[0]);
2429 19 : YCbCrtoRGB(cp2[0], pp[2]);
2430 19 : cp++;
2431 19 : cp2++;
2432 19 : pp += 6;
2433 : }
2434 125 : cp += incr;
2435 125 : cp2 += incr;
2436 125 : pp += fromskew;
2437 125 : h -= 2;
2438 : }
2439 2 : if (h == 1)
2440 : {
2441 2 : x = w;
2442 138 : while (x >= 2)
2443 : {
2444 136 : uint32_t Cb = pp[4];
2445 136 : uint32_t Cr = pp[5];
2446 136 : YCbCrtoRGB(cp[0], pp[0]);
2447 136 : YCbCrtoRGB(cp[1], pp[1]);
2448 136 : cp += 2;
2449 136 : cp2 += 2;
2450 136 : pp += 6;
2451 136 : x -= 2;
2452 : }
2453 2 : if (x == 1)
2454 : {
2455 1 : uint32_t Cb = pp[4];
2456 1 : uint32_t Cr = pp[5];
2457 1 : YCbCrtoRGB(cp[0], pp[0]);
2458 : }
2459 : }
2460 2 : }
2461 :
2462 : /*
2463 : * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
2464 : */
2465 1 : DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
2466 : {
2467 : (void)y;
2468 1 : fromskew = (fromskew / 2) * (2 * 1 + 2);
2469 : do
2470 : {
2471 39 : x = w >> 1;
2472 780 : while (x > 0)
2473 : {
2474 741 : int32_t Cb = pp[2];
2475 741 : int32_t Cr = pp[3];
2476 :
2477 741 : YCbCrtoRGB(cp[0], pp[0]);
2478 741 : YCbCrtoRGB(cp[1], pp[1]);
2479 :
2480 741 : cp += 2;
2481 741 : pp += 4;
2482 741 : x--;
2483 : }
2484 :
2485 39 : if ((w & 1) != 0)
2486 : {
2487 39 : int32_t Cb = pp[2];
2488 39 : int32_t Cr = pp[3];
2489 :
2490 39 : YCbCrtoRGB(cp[0], pp[0]);
2491 :
2492 39 : cp += 1;
2493 39 : pp += 4;
2494 : }
2495 :
2496 39 : cp += toskew;
2497 39 : pp += fromskew;
2498 39 : } while (--h);
2499 1 : }
2500 :
2501 : /*
2502 : * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
2503 : */
2504 1 : DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
2505 : {
2506 : uint32_t *cp2;
2507 1 : int32_t incr = 2 * toskew + w;
2508 : (void)y;
2509 1 : fromskew = (fromskew / 1) * (1 * 2 + 2);
2510 1 : cp2 = cp + w + toskew;
2511 20 : while (h >= 2)
2512 : {
2513 19 : x = w;
2514 : do
2515 : {
2516 741 : uint32_t Cb = pp[2];
2517 741 : uint32_t Cr = pp[3];
2518 741 : YCbCrtoRGB(cp[0], pp[0]);
2519 741 : YCbCrtoRGB(cp2[0], pp[1]);
2520 741 : cp++;
2521 741 : cp2++;
2522 741 : pp += 4;
2523 741 : } while (--x);
2524 19 : cp += incr;
2525 19 : cp2 += incr;
2526 19 : pp += fromskew;
2527 19 : h -= 2;
2528 : }
2529 1 : if (h == 1)
2530 : {
2531 1 : x = w;
2532 : do
2533 : {
2534 39 : uint32_t Cb = pp[2];
2535 39 : uint32_t Cr = pp[3];
2536 39 : YCbCrtoRGB(cp[0], pp[0]);
2537 39 : cp++;
2538 39 : pp += 4;
2539 39 : } while (--x);
2540 : }
2541 1 : }
2542 :
2543 : /*
2544 : * 8-bit packed YCbCr samples w/ no subsampling => RGB
2545 : */
2546 1 : DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
2547 : {
2548 : (void)y;
2549 1 : fromskew = (fromskew / 1) * (1 * 1 + 2);
2550 : do
2551 : {
2552 39 : x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
2553 : do
2554 : {
2555 1521 : int32_t Cb = pp[1];
2556 1521 : int32_t Cr = pp[2];
2557 :
2558 1521 : YCbCrtoRGB(*cp++, pp[0]);
2559 :
2560 1521 : pp += 3;
2561 1521 : } while (--x);
2562 39 : cp += toskew;
2563 39 : pp += fromskew;
2564 39 : } while (--h);
2565 1 : }
2566 :
2567 : /*
2568 : * 8-bit packed YCbCr samples w/ no subsampling => RGB
2569 : */
2570 0 : DECLARESepPutFunc(putseparate8bitYCbCr11tile)
2571 : {
2572 : (void)y;
2573 : (void)a;
2574 : /* TODO: naming of input vars is still off, change obfuscating declaration
2575 : * inside define, or resolve obfuscation */
2576 0 : for (; h > 0; --h)
2577 : {
2578 0 : x = w;
2579 : do
2580 : {
2581 : uint32_t dr, dg, db;
2582 0 : TIFFYCbCrtoRGB(img->ycbcr, *r++, *g++, *b++, &dr, &dg, &db);
2583 0 : *cp++ = PACK(dr, dg, db);
2584 0 : } while (--x);
2585 0 : SKEW(r, g, b, fromskew);
2586 0 : cp += toskew;
2587 : }
2588 0 : }
2589 : #undef YCbCrtoRGB
2590 :
2591 102 : static int isInRefBlackWhiteRange(float f)
2592 : {
2593 102 : return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF;
2594 : }
2595 :
2596 17 : static int initYCbCrConversion(TIFFRGBAImage *img)
2597 : {
2598 : static const char module[] = "initYCbCrConversion";
2599 :
2600 : float *luma, *refBlackWhite;
2601 :
2602 17 : if (img->ycbcr == NULL)
2603 : {
2604 17 : img->ycbcr = (TIFFYCbCrToRGB *)_TIFFmallocExt(
2605 : img->tif, TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)) +
2606 : 4 * 256 * sizeof(TIFFRGBValue) +
2607 : 2 * 256 * sizeof(int) + 3 * 256 * sizeof(int32_t));
2608 17 : if (img->ycbcr == NULL)
2609 : {
2610 0 : TIFFErrorExtR(img->tif, module,
2611 : "No space for YCbCr->RGB conversion state");
2612 0 : return (0);
2613 : }
2614 : }
2615 :
2616 17 : TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
2617 17 : TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
2618 : &refBlackWhite);
2619 :
2620 : /* Do some validation to avoid later issues. Detect NaN for now */
2621 : /* and also if lumaGreen is zero since we divide by it later */
2622 17 : if (luma[0] != luma[0] || luma[1] != luma[1] || luma[1] == 0.0 ||
2623 17 : luma[2] != luma[2])
2624 : {
2625 0 : TIFFErrorExtR(img->tif, module,
2626 : "Invalid values for YCbCrCoefficients tag");
2627 0 : return (0);
2628 : }
2629 :
2630 34 : if (!isInRefBlackWhiteRange(refBlackWhite[0]) ||
2631 34 : !isInRefBlackWhiteRange(refBlackWhite[1]) ||
2632 34 : !isInRefBlackWhiteRange(refBlackWhite[2]) ||
2633 34 : !isInRefBlackWhiteRange(refBlackWhite[3]) ||
2634 34 : !isInRefBlackWhiteRange(refBlackWhite[4]) ||
2635 17 : !isInRefBlackWhiteRange(refBlackWhite[5]))
2636 : {
2637 0 : TIFFErrorExtR(img->tif, module,
2638 : "Invalid values for ReferenceBlackWhite tag");
2639 0 : return (0);
2640 : }
2641 :
2642 17 : if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
2643 0 : return (0);
2644 17 : return (1);
2645 : }
2646 :
2647 1 : static tileContigRoutine initCIELabConversion(TIFFRGBAImage *img)
2648 : {
2649 : static const char module[] = "initCIELabConversion";
2650 :
2651 : float *whitePoint;
2652 : float refWhite[3];
2653 :
2654 1 : TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
2655 1 : if (whitePoint[1] == 0.0f)
2656 : {
2657 0 : TIFFErrorExtR(img->tif, module, "Invalid value for WhitePoint tag.");
2658 0 : return NULL;
2659 : }
2660 :
2661 1 : if (!img->cielab)
2662 : {
2663 1 : img->cielab = (TIFFCIELabToRGB *)_TIFFmallocExt(
2664 : img->tif, sizeof(TIFFCIELabToRGB));
2665 1 : if (!img->cielab)
2666 : {
2667 0 : TIFFErrorExtR(img->tif, module,
2668 : "No space for CIE L*a*b*->RGB conversion state.");
2669 0 : return NULL;
2670 : }
2671 : }
2672 :
2673 1 : refWhite[1] = 100.0F;
2674 1 : refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
2675 1 : refWhite[2] =
2676 1 : (1.0F - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
2677 1 : if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0)
2678 : {
2679 0 : TIFFErrorExtR(img->tif, module,
2680 : "Failed to initialize CIE L*a*b*->RGB conversion state.");
2681 0 : _TIFFfreeExt(img->tif, img->cielab);
2682 0 : return NULL;
2683 : }
2684 :
2685 1 : if (img->bitspersample == 8)
2686 1 : return putcontig8bitCIELab8;
2687 0 : else if (img->bitspersample == 16)
2688 0 : return putcontig8bitCIELab16;
2689 0 : return NULL;
2690 : }
2691 :
2692 : /*
2693 : * Greyscale images with less than 8 bits/sample are handled
2694 : * with a table to avoid lots of shifts and masks. The table
2695 : * is setup so that put*bwtile (below) can retrieve 8/bitspersample
2696 : * pixel values simply by indexing into the table with one
2697 : * number.
2698 : */
2699 9 : static int makebwmap(TIFFRGBAImage *img)
2700 : {
2701 9 : TIFFRGBValue *Map = img->Map;
2702 9 : int bitspersample = img->bitspersample;
2703 9 : int nsamples = 8 / bitspersample;
2704 : int i;
2705 : uint32_t *p;
2706 :
2707 9 : if (nsamples == 0)
2708 0 : nsamples = 1;
2709 :
2710 18 : img->BWmap = (uint32_t **)_TIFFmallocExt(
2711 : img->tif,
2712 9 : 256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
2713 9 : if (img->BWmap == NULL)
2714 : {
2715 0 : TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
2716 : "No space for B&W mapping table");
2717 0 : return (0);
2718 : }
2719 9 : p = (uint32_t *)(img->BWmap + 256);
2720 2313 : for (i = 0; i < 256; i++)
2721 : {
2722 : TIFFRGBValue c;
2723 2304 : img->BWmap[i] = p;
2724 2304 : switch (bitspersample)
2725 : {
2726 : #define GREY(x) \
2727 : c = Map[x]; \
2728 : *p++ = PACK(c, c, c);
2729 0 : case 1:
2730 0 : GREY(i >> 7);
2731 0 : GREY((i >> 6) & 1);
2732 0 : GREY((i >> 5) & 1);
2733 0 : GREY((i >> 4) & 1);
2734 0 : GREY((i >> 3) & 1);
2735 0 : GREY((i >> 2) & 1);
2736 0 : GREY((i >> 1) & 1);
2737 0 : GREY(i & 1);
2738 0 : break;
2739 0 : case 2:
2740 0 : GREY(i >> 6);
2741 0 : GREY((i >> 4) & 3);
2742 0 : GREY((i >> 2) & 3);
2743 0 : GREY(i & 3);
2744 0 : break;
2745 0 : case 4:
2746 0 : GREY(i >> 4);
2747 0 : GREY(i & 0xf);
2748 0 : break;
2749 2304 : case 8:
2750 : case 16:
2751 2304 : GREY(i);
2752 2304 : break;
2753 : }
2754 : #undef GREY
2755 2304 : }
2756 9 : return (1);
2757 : }
2758 :
2759 : /*
2760 : * Construct a mapping table to convert from the range
2761 : * of the data samples to [0,255] --for display. This
2762 : * process also handles inverting B&W images when needed.
2763 : */
2764 9 : static int setupMap(TIFFRGBAImage *img)
2765 : {
2766 : int32_t x, range;
2767 :
2768 9 : range = (int32_t)((1L << img->bitspersample) - 1);
2769 :
2770 : /* treat 16 bit the same as eight bit */
2771 9 : if (img->bitspersample == 16)
2772 0 : range = (int32_t)255;
2773 :
2774 18 : img->Map = (TIFFRGBValue *)_TIFFmallocExt(
2775 9 : img->tif, (range + 1) * sizeof(TIFFRGBValue));
2776 9 : if (img->Map == NULL)
2777 : {
2778 0 : TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
2779 : "No space for photometric conversion table");
2780 0 : return (0);
2781 : }
2782 9 : if (img->photometric == PHOTOMETRIC_MINISWHITE)
2783 : {
2784 0 : for (x = 0; x <= range; x++)
2785 0 : img->Map[x] = (TIFFRGBValue)(((range - x) * 255) / range);
2786 : }
2787 : else
2788 : {
2789 2313 : for (x = 0; x <= range; x++)
2790 2304 : img->Map[x] = (TIFFRGBValue)((x * 255) / range);
2791 : }
2792 9 : if (img->bitspersample <= 16 &&
2793 9 : (img->photometric == PHOTOMETRIC_MINISBLACK ||
2794 0 : img->photometric == PHOTOMETRIC_MINISWHITE))
2795 : {
2796 : /*
2797 : * Use photometric mapping table to construct
2798 : * unpacking tables for samples <= 8 bits.
2799 : */
2800 9 : if (!makebwmap(img))
2801 0 : return (0);
2802 : /* no longer need Map, free it */
2803 9 : _TIFFfreeExt(img->tif, img->Map);
2804 9 : img->Map = NULL;
2805 : }
2806 9 : return (1);
2807 : }
2808 :
2809 1 : static int checkcmap(TIFFRGBAImage *img)
2810 : {
2811 1 : uint16_t *r = img->redcmap;
2812 1 : uint16_t *g = img->greencmap;
2813 1 : uint16_t *b = img->bluecmap;
2814 1 : long n = 1L << img->bitspersample;
2815 :
2816 2 : while (n-- > 0)
2817 2 : if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
2818 1 : return (16);
2819 0 : return (8);
2820 : }
2821 :
2822 1 : static void cvtcmap(TIFFRGBAImage *img)
2823 : {
2824 1 : uint16_t *r = img->redcmap;
2825 1 : uint16_t *g = img->greencmap;
2826 1 : uint16_t *b = img->bluecmap;
2827 : long i;
2828 :
2829 257 : for (i = (1L << img->bitspersample) - 1; i >= 0; i--)
2830 : {
2831 : #define CVT(x) ((uint16_t)((x) >> 8))
2832 256 : r[i] = CVT(r[i]);
2833 256 : g[i] = CVT(g[i]);
2834 256 : b[i] = CVT(b[i]);
2835 : #undef CVT
2836 : }
2837 1 : }
2838 :
2839 : /*
2840 : * Palette images with <= 8 bits/sample are handled
2841 : * with a table to avoid lots of shifts and masks. The table
2842 : * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
2843 : * pixel values simply by indexing into the table with one
2844 : * number.
2845 : */
2846 1 : static int makecmap(TIFFRGBAImage *img)
2847 : {
2848 1 : int bitspersample = img->bitspersample;
2849 1 : int nsamples = 8 / bitspersample;
2850 1 : uint16_t *r = img->redcmap;
2851 1 : uint16_t *g = img->greencmap;
2852 1 : uint16_t *b = img->bluecmap;
2853 : uint32_t *p;
2854 : int i;
2855 :
2856 2 : img->PALmap = (uint32_t **)_TIFFmallocExt(
2857 : img->tif,
2858 1 : 256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
2859 1 : if (img->PALmap == NULL)
2860 : {
2861 0 : TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
2862 : "No space for Palette mapping table");
2863 0 : return (0);
2864 : }
2865 1 : p = (uint32_t *)(img->PALmap + 256);
2866 257 : for (i = 0; i < 256; i++)
2867 : {
2868 : TIFFRGBValue c;
2869 256 : img->PALmap[i] = p;
2870 : #define CMAP(x) \
2871 : c = (TIFFRGBValue)x; \
2872 : *p++ = PACK(r[c] & 0xff, g[c] & 0xff, b[c] & 0xff);
2873 256 : switch (bitspersample)
2874 : {
2875 0 : case 1:
2876 0 : CMAP(i >> 7);
2877 0 : CMAP((i >> 6) & 1);
2878 0 : CMAP((i >> 5) & 1);
2879 0 : CMAP((i >> 4) & 1);
2880 0 : CMAP((i >> 3) & 1);
2881 0 : CMAP((i >> 2) & 1);
2882 0 : CMAP((i >> 1) & 1);
2883 0 : CMAP(i & 1);
2884 0 : break;
2885 0 : case 2:
2886 0 : CMAP(i >> 6);
2887 0 : CMAP((i >> 4) & 3);
2888 0 : CMAP((i >> 2) & 3);
2889 0 : CMAP(i & 3);
2890 0 : break;
2891 0 : case 4:
2892 0 : CMAP(i >> 4);
2893 0 : CMAP(i & 0xf);
2894 0 : break;
2895 256 : case 8:
2896 256 : CMAP(i);
2897 256 : break;
2898 : }
2899 : #undef CMAP
2900 256 : }
2901 1 : return (1);
2902 : }
2903 :
2904 : /*
2905 : * Construct any mapping table used
2906 : * by the associated put routine.
2907 : */
2908 17 : static int buildMap(TIFFRGBAImage *img)
2909 : {
2910 17 : switch (img->photometric)
2911 : {
2912 6 : case PHOTOMETRIC_RGB:
2913 : case PHOTOMETRIC_YCBCR:
2914 : case PHOTOMETRIC_SEPARATED:
2915 6 : if (img->bitspersample == 8)
2916 6 : break;
2917 : /* fall through... */
2918 : case PHOTOMETRIC_MINISBLACK:
2919 : case PHOTOMETRIC_MINISWHITE:
2920 9 : if (!setupMap(img))
2921 0 : return (0);
2922 9 : break;
2923 1 : case PHOTOMETRIC_PALETTE:
2924 : /*
2925 : * Convert 16-bit colormap to 8-bit (unless it looks
2926 : * like an old-style 8-bit colormap).
2927 : */
2928 1 : if (checkcmap(img) == 16)
2929 1 : cvtcmap(img);
2930 : else
2931 0 : TIFFWarningExtR(img->tif, TIFFFileName(img->tif),
2932 : "Assuming 8-bit colormap");
2933 : /*
2934 : * Use mapping table and colormap to construct
2935 : * unpacking tables for samples < 8 bits.
2936 : */
2937 1 : if (img->bitspersample <= 8 && !makecmap(img))
2938 0 : return (0);
2939 1 : break;
2940 : }
2941 17 : return (1);
2942 : }
2943 :
2944 : /*
2945 : * Select the appropriate conversion routine for packed data.
2946 : */
2947 60 : static int PickContigCase(TIFFRGBAImage *img)
2948 : {
2949 60 : img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
2950 60 : img->put.contig = NULL;
2951 60 : switch (img->photometric)
2952 : {
2953 26 : case PHOTOMETRIC_RGB:
2954 26 : switch (img->bitspersample)
2955 : {
2956 26 : case 8:
2957 26 : if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
2958 13 : img->samplesperpixel >= 4)
2959 13 : img->put.contig = putRGBAAcontig8bittile;
2960 13 : else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
2961 13 : img->samplesperpixel >= 4)
2962 : {
2963 13 : if (BuildMapUaToAa(img))
2964 13 : img->put.contig = putRGBUAcontig8bittile;
2965 : }
2966 0 : else if (img->samplesperpixel >= 3)
2967 0 : img->put.contig = putRGBcontig8bittile;
2968 26 : break;
2969 0 : case 16:
2970 0 : if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
2971 0 : img->samplesperpixel >= 4)
2972 : {
2973 0 : if (BuildMapBitdepth16To8(img))
2974 0 : img->put.contig = putRGBAAcontig16bittile;
2975 : }
2976 0 : else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
2977 0 : img->samplesperpixel >= 4)
2978 : {
2979 0 : if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
2980 0 : img->put.contig = putRGBUAcontig16bittile;
2981 : }
2982 0 : else if (img->samplesperpixel >= 3)
2983 : {
2984 0 : if (BuildMapBitdepth16To8(img))
2985 0 : img->put.contig = putRGBcontig16bittile;
2986 : }
2987 0 : break;
2988 : }
2989 26 : break;
2990 6 : case PHOTOMETRIC_SEPARATED:
2991 6 : if (img->samplesperpixel >= 4 && buildMap(img))
2992 : {
2993 6 : if (img->bitspersample == 8)
2994 : {
2995 6 : if (!img->Map)
2996 6 : img->put.contig = putRGBcontig8bitCMYKtile;
2997 : else
2998 0 : img->put.contig = putRGBcontig8bitCMYKMaptile;
2999 : }
3000 : }
3001 6 : break;
3002 1 : case PHOTOMETRIC_PALETTE:
3003 1 : if (buildMap(img))
3004 : {
3005 1 : switch (img->bitspersample)
3006 : {
3007 1 : case 8:
3008 1 : img->put.contig = put8bitcmaptile;
3009 1 : break;
3010 0 : case 4:
3011 0 : img->put.contig = put4bitcmaptile;
3012 0 : break;
3013 0 : case 2:
3014 0 : img->put.contig = put2bitcmaptile;
3015 0 : break;
3016 0 : case 1:
3017 0 : img->put.contig = put1bitcmaptile;
3018 0 : break;
3019 : }
3020 0 : }
3021 1 : break;
3022 9 : case PHOTOMETRIC_MINISWHITE:
3023 : case PHOTOMETRIC_MINISBLACK:
3024 9 : if (buildMap(img))
3025 : {
3026 9 : switch (img->bitspersample)
3027 : {
3028 0 : case 16:
3029 0 : img->put.contig = put16bitbwtile;
3030 0 : break;
3031 9 : case 8:
3032 9 : if (img->alpha && img->samplesperpixel == 2)
3033 6 : img->put.contig = putagreytile;
3034 : else
3035 3 : img->put.contig = putgreytile;
3036 9 : break;
3037 0 : case 4:
3038 0 : img->put.contig = put4bitbwtile;
3039 0 : break;
3040 0 : case 2:
3041 0 : img->put.contig = put2bitbwtile;
3042 0 : break;
3043 0 : case 1:
3044 0 : img->put.contig = put1bitbwtile;
3045 0 : break;
3046 : }
3047 0 : }
3048 9 : break;
3049 17 : case PHOTOMETRIC_YCBCR:
3050 17 : if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
3051 : {
3052 17 : if (initYCbCrConversion(img) != 0)
3053 : {
3054 : /*
3055 : * The 6.0 spec says that subsampling must be
3056 : * one of 1, 2, or 4, and that vertical subsampling
3057 : * must always be <= horizontal subsampling; so
3058 : * there are only a few possibilities and we just
3059 : * enumerate the cases.
3060 : * Joris: added support for the [1,2] case, nonetheless, to
3061 : * accommodate some OJPEG files
3062 : */
3063 : uint16_t SubsamplingHor;
3064 : uint16_t SubsamplingVer;
3065 17 : TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
3066 : &SubsamplingHor, &SubsamplingVer);
3067 17 : switch ((SubsamplingHor << 4) | SubsamplingVer)
3068 : {
3069 2 : case 0x44:
3070 2 : img->put.contig = putcontig8bitYCbCr44tile;
3071 2 : break;
3072 2 : case 0x42:
3073 2 : img->put.contig = putcontig8bitYCbCr42tile;
3074 2 : break;
3075 1 : case 0x41:
3076 1 : img->put.contig = putcontig8bitYCbCr41tile;
3077 1 : break;
3078 3 : case 0x22:
3079 3 : img->put.contig = putcontig8bitYCbCr22tile;
3080 3 : break;
3081 1 : case 0x21:
3082 1 : img->put.contig = putcontig8bitYCbCr21tile;
3083 1 : break;
3084 1 : case 0x12:
3085 1 : img->put.contig = putcontig8bitYCbCr12tile;
3086 1 : break;
3087 1 : case 0x11:
3088 1 : img->put.contig = putcontig8bitYCbCr11tile;
3089 1 : break;
3090 : }
3091 17 : }
3092 : }
3093 17 : break;
3094 1 : case PHOTOMETRIC_CIELAB:
3095 1 : if (img->samplesperpixel == 3 && buildMap(img))
3096 : {
3097 1 : if (img->bitspersample == 8 || img->bitspersample == 16)
3098 1 : img->put.contig = initCIELabConversion(img);
3099 1 : break;
3100 : }
3101 : }
3102 60 : return ((img->get != NULL) && (img->put.contig != NULL));
3103 : }
3104 :
3105 : /*
3106 : * Select the appropriate conversion routine for unpacked data.
3107 : *
3108 : * NB: we assume that unpacked single channel data is directed
3109 : * to the "packed routines.
3110 : */
3111 3 : static int PickSeparateCase(TIFFRGBAImage *img)
3112 : {
3113 3 : img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
3114 3 : img->put.separate = NULL;
3115 3 : switch (img->photometric)
3116 : {
3117 3 : case PHOTOMETRIC_MINISWHITE:
3118 : case PHOTOMETRIC_MINISBLACK:
3119 : /* greyscale images processed pretty much as RGB by gtTileSeparate
3120 : */
3121 : case PHOTOMETRIC_RGB:
3122 3 : switch (img->bitspersample)
3123 : {
3124 3 : case 8:
3125 3 : if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
3126 0 : img->put.separate = putRGBAAseparate8bittile;
3127 3 : else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
3128 : {
3129 0 : if (BuildMapUaToAa(img))
3130 0 : img->put.separate = putRGBUAseparate8bittile;
3131 : }
3132 : else
3133 3 : img->put.separate = putRGBseparate8bittile;
3134 3 : break;
3135 0 : case 16:
3136 0 : if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
3137 : {
3138 0 : if (BuildMapBitdepth16To8(img))
3139 0 : img->put.separate = putRGBAAseparate16bittile;
3140 : }
3141 0 : else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
3142 : {
3143 0 : if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
3144 0 : img->put.separate = putRGBUAseparate16bittile;
3145 : }
3146 : else
3147 : {
3148 0 : if (BuildMapBitdepth16To8(img))
3149 0 : img->put.separate = putRGBseparate16bittile;
3150 : }
3151 0 : break;
3152 : }
3153 3 : break;
3154 0 : case PHOTOMETRIC_SEPARATED:
3155 0 : if (img->bitspersample == 8 && img->samplesperpixel == 4)
3156 : {
3157 0 : img->alpha =
3158 : 1; // Not alpha, but seems like the only way to get 4th band
3159 0 : img->put.separate = putCMYKseparate8bittile;
3160 : }
3161 0 : break;
3162 0 : case PHOTOMETRIC_YCBCR:
3163 0 : if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
3164 : {
3165 0 : if (initYCbCrConversion(img) != 0)
3166 : {
3167 : uint16_t hs, vs;
3168 0 : TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
3169 : &hs, &vs);
3170 0 : switch ((hs << 4) | vs)
3171 : {
3172 0 : case 0x11:
3173 0 : img->put.separate = putseparate8bitYCbCr11tile;
3174 0 : break;
3175 : /* TODO: add other cases here */
3176 : }
3177 0 : }
3178 : }
3179 0 : break;
3180 : }
3181 3 : return ((img->get != NULL) && (img->put.separate != NULL));
3182 : }
3183 :
3184 13 : static int BuildMapUaToAa(TIFFRGBAImage *img)
3185 : {
3186 : static const char module[] = "BuildMapUaToAa";
3187 : uint8_t *m;
3188 : uint16_t na, nv;
3189 13 : assert(img->UaToAa == NULL);
3190 13 : img->UaToAa = _TIFFmallocExt(img->tif, 65536);
3191 13 : if (img->UaToAa == NULL)
3192 : {
3193 0 : TIFFErrorExtR(img->tif, module, "Out of memory");
3194 0 : return (0);
3195 : }
3196 13 : m = img->UaToAa;
3197 3341 : for (na = 0; na < 256; na++)
3198 : {
3199 855296 : for (nv = 0; nv < 256; nv++)
3200 851968 : *m++ = (uint8_t)((nv * na + 127) / 255);
3201 : }
3202 13 : return (1);
3203 : }
3204 :
3205 0 : static int BuildMapBitdepth16To8(TIFFRGBAImage *img)
3206 : {
3207 : static const char module[] = "BuildMapBitdepth16To8";
3208 : uint8_t *m;
3209 : uint32_t n;
3210 0 : assert(img->Bitdepth16To8 == NULL);
3211 0 : img->Bitdepth16To8 = _TIFFmallocExt(img->tif, 65536);
3212 0 : if (img->Bitdepth16To8 == NULL)
3213 : {
3214 0 : TIFFErrorExtR(img->tif, module, "Out of memory");
3215 0 : return (0);
3216 : }
3217 0 : m = img->Bitdepth16To8;
3218 0 : for (n = 0; n < 65536; n++)
3219 0 : *m++ = (uint8_t)((n + 128) / 257);
3220 0 : return (1);
3221 : }
3222 :
3223 : /*
3224 : * Read a whole strip off data from the file, and convert to RGBA form.
3225 : * If this is the last strip, then it will only contain the portion of
3226 : * the strip that is actually within the image space. The result is
3227 : * organized in bottom to top form.
3228 : */
3229 :
3230 0 : int TIFFReadRGBAStrip(TIFF *tif, uint32_t row, uint32_t *raster)
3231 :
3232 : {
3233 0 : return TIFFReadRGBAStripExt(tif, row, raster, 0);
3234 : }
3235 :
3236 59 : int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
3237 : int stop_on_error)
3238 :
3239 : {
3240 59 : char emsg[EMSG_BUF_SIZE] = "";
3241 : TIFFRGBAImage img;
3242 : int ok;
3243 : uint32_t rowsperstrip, rows_to_read;
3244 :
3245 59 : if (TIFFIsTiled(tif))
3246 : {
3247 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3248 : "Can't use TIFFReadRGBAStrip() with tiled file.");
3249 0 : return (0);
3250 : }
3251 :
3252 59 : TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
3253 :
3254 59 : if (rowsperstrip == 0)
3255 : {
3256 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
3257 0 : return (0);
3258 : }
3259 :
3260 59 : if ((row % rowsperstrip) != 0)
3261 : {
3262 0 : TIFFErrorExtR(
3263 : tif, TIFFFileName(tif),
3264 : "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
3265 0 : return (0);
3266 : }
3267 :
3268 59 : if (TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
3269 : {
3270 53 : if (row >= img.height)
3271 : {
3272 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3273 : "Invalid row passed to TIFFReadRGBAStrip().");
3274 0 : TIFFRGBAImageEnd(&img);
3275 0 : return (0);
3276 : }
3277 :
3278 53 : img.row_offset = row;
3279 53 : img.col_offset = 0;
3280 :
3281 53 : if (row + rowsperstrip > img.height)
3282 14 : rows_to_read = img.height - row;
3283 : else
3284 39 : rows_to_read = rowsperstrip;
3285 :
3286 53 : ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read);
3287 :
3288 53 : TIFFRGBAImageEnd(&img);
3289 : }
3290 : else
3291 : {
3292 6 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
3293 6 : ok = 0;
3294 : }
3295 :
3296 59 : return (ok);
3297 : }
3298 :
3299 : /*
3300 : * Read a whole tile off data from the file, and convert to RGBA form.
3301 : * The returned RGBA data is organized from bottom to top of tile,
3302 : * and may include zeroed areas if the tile extends off the image.
3303 : */
3304 :
3305 0 : int TIFFReadRGBATile(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster)
3306 :
3307 : {
3308 0 : return TIFFReadRGBATileExt(tif, col, row, raster, 0);
3309 : }
3310 :
3311 4 : int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
3312 : int stop_on_error)
3313 : {
3314 4 : char emsg[EMSG_BUF_SIZE] = "";
3315 : TIFFRGBAImage img;
3316 : int ok;
3317 : uint32_t tile_xsize, tile_ysize;
3318 : uint32_t read_xsize, read_ysize;
3319 : uint32_t i_row;
3320 :
3321 : /*
3322 : * Verify that our request is legal - on a tile file, and on a
3323 : * tile boundary.
3324 : */
3325 :
3326 4 : if (!TIFFIsTiled(tif))
3327 : {
3328 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3329 : "Can't use TIFFReadRGBATile() with striped file.");
3330 0 : return (0);
3331 : }
3332 :
3333 4 : TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
3334 4 : TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
3335 4 : if (tile_xsize == 0 || tile_ysize == 0)
3336 : {
3337 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3338 : "tile_xsize or tile_ysize is zero");
3339 0 : return (0);
3340 : }
3341 :
3342 4 : if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
3343 : {
3344 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3345 : "Row/col passed to TIFFReadRGBATile() must be top"
3346 : "left corner of a tile.");
3347 0 : return (0);
3348 : }
3349 :
3350 : /*
3351 : * Setup the RGBA reader.
3352 : */
3353 :
3354 4 : if (!TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
3355 : {
3356 0 : TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
3357 0 : return (0);
3358 : }
3359 :
3360 4 : if (col >= img.width || row >= img.height)
3361 : {
3362 0 : TIFFErrorExtR(tif, TIFFFileName(tif),
3363 : "Invalid row/col passed to TIFFReadRGBATile().");
3364 0 : TIFFRGBAImageEnd(&img);
3365 0 : return (0);
3366 : }
3367 :
3368 : /*
3369 : * The TIFFRGBAImageGet() function doesn't allow us to get off the
3370 : * edge of the image, even to fill an otherwise valid tile. So we
3371 : * figure out how much we can read, and fix up the tile buffer to
3372 : * a full tile configuration afterwards.
3373 : */
3374 :
3375 4 : if (row + tile_ysize > img.height)
3376 4 : read_ysize = img.height - row;
3377 : else
3378 0 : read_ysize = tile_ysize;
3379 :
3380 4 : if (col + tile_xsize > img.width)
3381 4 : read_xsize = img.width - col;
3382 : else
3383 0 : read_xsize = tile_xsize;
3384 :
3385 : /*
3386 : * Read the chunk of imagery.
3387 : */
3388 :
3389 4 : img.row_offset = row;
3390 4 : img.col_offset = col;
3391 :
3392 4 : ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize);
3393 :
3394 4 : TIFFRGBAImageEnd(&img);
3395 :
3396 : /*
3397 : * If our read was incomplete we will need to fix up the tile by
3398 : * shifting the data around as if a full tile of data is being returned.
3399 : *
3400 : * This is all the more complicated because the image is organized in
3401 : * bottom to top format.
3402 : */
3403 :
3404 4 : if (read_xsize == tile_xsize && read_ysize == tile_ysize)
3405 0 : return (ok);
3406 :
3407 500 : for (i_row = 0; i_row < read_ysize; i_row++)
3408 : {
3409 496 : memmove(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize,
3410 496 : raster + (size_t)(read_ysize - i_row - 1) * read_xsize,
3411 : read_xsize * sizeof(uint32_t));
3412 496 : _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize +
3413 : read_xsize,
3414 496 : 0, sizeof(uint32_t) * (tile_xsize - read_xsize));
3415 : }
3416 :
3417 468 : for (i_row = read_ysize; i_row < tile_ysize; i_row++)
3418 : {
3419 464 : _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize, 0,
3420 464 : sizeof(uint32_t) * tile_xsize);
3421 : }
3422 :
3423 4 : return (ok);
3424 : }
|