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