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