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