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