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