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