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