ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_getimage.c
Go to the documentation of this file.
00001 /* $Id: tif_getimage.c,v 1.63.2.4 2010-06-08 18:50:42 bfriesen Exp $ */
00002 
00003 /*
00004  * Copyright (c) 1991-1997 Sam Leffler
00005  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
00006  *
00007  * Permission to use, copy, modify, distribute, and sell this software and 
00008  * its documentation for any purpose is hereby granted without fee, provided
00009  * that (i) the above copyright notices and this permission notice appear in
00010  * all copies of the software and related documentation, and (ii) the names of
00011  * Sam Leffler and Silicon Graphics may not be used in any advertising or
00012  * publicity relating to the software without the specific, prior written
00013  * permission of Sam Leffler and Silicon Graphics.
00014  * 
00015  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
00016  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
00017  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
00018  * 
00019  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
00020  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
00021  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00022  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
00023  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
00024  * OF THIS SOFTWARE.
00025  */
00026 
00027 /*
00028  * TIFF Library
00029  *
00030  * Read and return a packed RGBA image.
00031  */
00032 #include "tiffiop.h"
00033 #include <stdio.h>
00034 
00035 static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32);
00036 static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
00037 static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
00038 static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
00039 static int PickContigCase(TIFFRGBAImage*);
00040 static int PickSeparateCase(TIFFRGBAImage*);
00041 static const char photoTag[] = "PhotometricInterpretation";
00042 
00043 /* 
00044  * Helper constants used in Orientation tag handling
00045  */
00046 #define FLIP_VERTICALLY 0x01
00047 #define FLIP_HORIZONTALLY 0x02
00048 
00049 /*
00050  * Color conversion constants. We will define display types here.
00051  */
00052 
00053 TIFFDisplay display_sRGB = {
00054     {           /* XYZ -> luminance matrix */
00055         {  3.2410F, -1.5374F, -0.4986F },
00056         {  -0.9692F, 1.8760F, 0.0416F },
00057         {  0.0556F, -0.2040F, 1.0570F }
00058     },  
00059     100.0F, 100.0F, 100.0F, /* Light o/p for reference white */
00060     255, 255, 255,      /* Pixel values for ref. white */
00061     1.0F, 1.0F, 1.0F,   /* Residual light o/p for black pixel */
00062     2.4F, 2.4F, 2.4F,   /* Gamma values for the three guns */
00063 };
00064 
00065 /*
00066  * Check the image to see if TIFFReadRGBAImage can deal with it.
00067  * 1/0 is returned according to whether or not the image can
00068  * be handled.  If 0 is returned, emsg contains the reason
00069  * why it is being rejected.
00070  */
00071 int
00072 TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
00073 {
00074     TIFFDirectory* td = &tif->tif_dir;
00075     uint16 photometric;
00076     int colorchannels;
00077 
00078     if (!tif->tif_decodestatus) {
00079         sprintf(emsg, "Sorry, requested compression method is not configured");
00080         return (0);
00081     }
00082     switch (td->td_bitspersample) {
00083         case 1:
00084         case 2:
00085         case 4:
00086         case 8:
00087         case 16:
00088             break;
00089         default:
00090             sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
00091                 td->td_bitspersample);
00092             return (0);
00093     }
00094     colorchannels = td->td_samplesperpixel - td->td_extrasamples;
00095     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
00096         switch (colorchannels) {
00097             case 1:
00098                 photometric = PHOTOMETRIC_MINISBLACK;
00099                 break;
00100             case 3:
00101                 photometric = PHOTOMETRIC_RGB;
00102                 break;
00103             default:
00104                 sprintf(emsg, "Missing needed %s tag", photoTag);
00105                 return (0);
00106         }
00107     }
00108     switch (photometric) {
00109         case PHOTOMETRIC_MINISWHITE:
00110         case PHOTOMETRIC_MINISBLACK:
00111         case PHOTOMETRIC_PALETTE:
00112             if (td->td_planarconfig == PLANARCONFIG_CONTIG
00113                 && td->td_samplesperpixel != 1
00114                 && td->td_bitspersample < 8 ) {
00115                 sprintf(emsg,
00116                     "Sorry, can not handle contiguous data with %s=%d, "
00117                     "and %s=%d and Bits/Sample=%d",
00118                     photoTag, photometric,
00119                     "Samples/pixel", td->td_samplesperpixel,
00120                     td->td_bitspersample);
00121                 return (0);
00122             }
00123             /*
00124              * We should likely validate that any extra samples are either
00125              * to be ignored, or are alpha, and if alpha we should try to use
00126              * them.  But for now we won't bother with this.
00127             */
00128             break;
00129         case PHOTOMETRIC_YCBCR:
00130             /*
00131              * TODO: if at all meaningful and useful, make more complete
00132              * support check here, or better still, refactor to let supporting
00133              * code decide whether there is support and what meaningfull
00134              * error to return
00135              */
00136             break;
00137         case PHOTOMETRIC_RGB:
00138             if (colorchannels < 3) {
00139                 sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
00140                     "Color channels", colorchannels);
00141                 return (0);
00142             }
00143             break;
00144         case PHOTOMETRIC_SEPARATED:
00145             {
00146                 uint16 inkset;
00147                 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
00148                 if (inkset != INKSET_CMYK) {
00149                     sprintf(emsg,
00150                         "Sorry, can not handle separated image with %s=%d",
00151                         "InkSet", inkset);
00152                     return 0;
00153                 }
00154                 if (td->td_samplesperpixel < 4) {
00155                     sprintf(emsg,
00156                         "Sorry, can not handle separated image with %s=%d",
00157                         "Samples/pixel", td->td_samplesperpixel);
00158                     return 0;
00159                 }
00160                 break;
00161             }
00162         case PHOTOMETRIC_LOGL:
00163             if (td->td_compression != COMPRESSION_SGILOG) {
00164                 sprintf(emsg, "Sorry, LogL data must have %s=%d",
00165                     "Compression", COMPRESSION_SGILOG);
00166                 return (0);
00167             }
00168             break;
00169         case PHOTOMETRIC_LOGLUV:
00170             if (td->td_compression != COMPRESSION_SGILOG &&
00171                 td->td_compression != COMPRESSION_SGILOG24) {
00172                 sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
00173                     "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
00174                 return (0);
00175             }
00176             if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
00177                 sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
00178                     "Planarconfiguration", td->td_planarconfig);
00179                 return (0);
00180             }
00181             break;
00182         case PHOTOMETRIC_CIELAB:
00183             break;
00184         default:
00185             sprintf(emsg, "Sorry, can not handle image with %s=%d",
00186                 photoTag, photometric);
00187             return (0);
00188     }
00189     return (1);
00190 }
00191 
00192 void
00193 TIFFRGBAImageEnd(TIFFRGBAImage* img)
00194 {
00195     if (img->Map)
00196         _TIFFfree(img->Map), img->Map = NULL;
00197     if (img->BWmap)
00198         _TIFFfree(img->BWmap), img->BWmap = NULL;
00199     if (img->PALmap)
00200         _TIFFfree(img->PALmap), img->PALmap = NULL;
00201     if (img->ycbcr)
00202         _TIFFfree(img->ycbcr), img->ycbcr = NULL;
00203     if (img->cielab)
00204         _TIFFfree(img->cielab), img->cielab = NULL;
00205     if( img->redcmap ) {
00206         _TIFFfree( img->redcmap );
00207         _TIFFfree( img->greencmap );
00208         _TIFFfree( img->bluecmap );
00209     }
00210 }
00211 
00212 static int
00213 isCCITTCompression(TIFF* tif)
00214 {
00215     uint16 compress;
00216     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
00217     return (compress == COMPRESSION_CCITTFAX3 ||
00218         compress == COMPRESSION_CCITTFAX4 ||
00219         compress == COMPRESSION_CCITTRLE ||
00220         compress == COMPRESSION_CCITTRLEW);
00221 }
00222 
00223 int
00224 TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
00225 {
00226     uint16* sampleinfo;
00227     uint16 extrasamples;
00228     uint16 planarconfig;
00229     uint16 compress;
00230     int colorchannels;
00231     uint16 *red_orig, *green_orig, *blue_orig;
00232     int n_color;
00233 
00234     /* Initialize to normal values */
00235     img->row_offset = 0;
00236     img->col_offset = 0;
00237     img->redcmap = NULL;
00238     img->greencmap = NULL;
00239     img->bluecmap = NULL;
00240     img->req_orientation = ORIENTATION_BOTLEFT;     /* It is the default */
00241 
00242     img->tif = tif;
00243     img->stoponerr = stop;
00244     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
00245     switch (img->bitspersample) {
00246         case 1:
00247         case 2:
00248         case 4:
00249         case 8:
00250         case 16:
00251             break;
00252         default:
00253             sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
00254                 img->bitspersample);
00255             return (0);
00256     }
00257     img->alpha = 0;
00258     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
00259     TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
00260         &extrasamples, &sampleinfo);
00261     if (extrasamples >= 1)
00262     {
00263         switch (sampleinfo[0]) {
00264             case EXTRASAMPLE_UNSPECIFIED:          /* Workaround for some images without */
00265                 if (img->samplesperpixel > 3)  /* correct info about alpha channel */
00266                     img->alpha = EXTRASAMPLE_ASSOCALPHA;
00267                 break;
00268             case EXTRASAMPLE_ASSOCALPHA:           /* data is pre-multiplied */
00269             case EXTRASAMPLE_UNASSALPHA:           /* data is not pre-multiplied */
00270                 img->alpha = sampleinfo[0];
00271                 break;
00272         }
00273     }
00274 
00275 #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
00276     if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
00277         img->photometric = PHOTOMETRIC_MINISWHITE;
00278 
00279     if( extrasamples == 0
00280         && img->samplesperpixel == 4
00281         && img->photometric == PHOTOMETRIC_RGB )
00282     {
00283         img->alpha = EXTRASAMPLE_ASSOCALPHA;
00284         extrasamples = 1;
00285     }
00286 #endif
00287 
00288     colorchannels = img->samplesperpixel - extrasamples;
00289     TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
00290     TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
00291     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
00292         switch (colorchannels) {
00293             case 1:
00294                 if (isCCITTCompression(tif))
00295                     img->photometric = PHOTOMETRIC_MINISWHITE;
00296                 else
00297                     img->photometric = PHOTOMETRIC_MINISBLACK;
00298                 break;
00299             case 3:
00300                 img->photometric = PHOTOMETRIC_RGB;
00301                 break;
00302             default:
00303                 sprintf(emsg, "Missing needed %s tag", photoTag);
00304                 return (0);
00305         }
00306     }
00307     switch (img->photometric) {
00308         case PHOTOMETRIC_PALETTE:
00309             if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
00310                 &red_orig, &green_orig, &blue_orig)) {
00311                 sprintf(emsg, "Missing required \"Colormap\" tag");
00312                 return (0);
00313             }
00314 
00315             /* copy the colormaps so we can modify them */
00316             n_color = (1L << img->bitspersample);
00317             img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
00318             img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
00319             img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
00320             if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
00321                 sprintf(emsg, "Out of memory for colormap copy");
00322                 return (0);
00323             }
00324 
00325             _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
00326             _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 );
00327             _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 );
00328 
00329             /* fall thru... */
00330         case PHOTOMETRIC_MINISWHITE:
00331         case PHOTOMETRIC_MINISBLACK:
00332             if (planarconfig == PLANARCONFIG_CONTIG
00333                 && img->samplesperpixel != 1
00334                 && img->bitspersample < 8 ) {
00335                 sprintf(emsg,
00336                     "Sorry, can not handle contiguous data with %s=%d, "
00337                     "and %s=%d and Bits/Sample=%d",
00338                     photoTag, img->photometric,
00339                     "Samples/pixel", img->samplesperpixel,
00340                     img->bitspersample);
00341                 return (0);
00342             }
00343             break;
00344         case PHOTOMETRIC_YCBCR:
00345             /* It would probably be nice to have a reality check here. */
00346             if (planarconfig == PLANARCONFIG_CONTIG)
00347                 /* can rely on libjpeg to convert to RGB */
00348                 /* XXX should restore current state on exit */
00349                 switch (compress) {
00350                     case COMPRESSION_JPEG:
00351                         /*
00352                          * TODO: when complete tests verify complete desubsampling
00353                          * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in
00354                          * favor of tif_getimage.c native handling
00355                          */
00356                         TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
00357                         img->photometric = PHOTOMETRIC_RGB;
00358                         break;
00359                     default:
00360                         /* do nothing */;
00361                         break;
00362                 }
00363             /*
00364              * TODO: if at all meaningful and useful, make more complete
00365              * support check here, or better still, refactor to let supporting
00366              * code decide whether there is support and what meaningfull
00367              * error to return
00368              */
00369             break;
00370         case PHOTOMETRIC_RGB:
00371             if (colorchannels < 3) {
00372                 sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
00373                     "Color channels", colorchannels);
00374                 return (0);
00375             }
00376             break;
00377         case PHOTOMETRIC_SEPARATED:
00378             {
00379                 uint16 inkset;
00380                 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
00381                 if (inkset != INKSET_CMYK) {
00382                     sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
00383                         "InkSet", inkset);
00384                     return (0);
00385                 }
00386                 if (img->samplesperpixel < 4) {
00387                     sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
00388                         "Samples/pixel", img->samplesperpixel);
00389                     return (0);
00390                 }
00391             }
00392             break;
00393         case PHOTOMETRIC_LOGL:
00394             if (compress != COMPRESSION_SGILOG) {
00395                 sprintf(emsg, "Sorry, LogL data must have %s=%d",
00396                     "Compression", COMPRESSION_SGILOG);
00397                 return (0);
00398             }
00399             TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
00400             img->photometric = PHOTOMETRIC_MINISBLACK;  /* little white lie */
00401             img->bitspersample = 8;
00402             break;
00403         case PHOTOMETRIC_LOGLUV:
00404             if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
00405                 sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
00406                     "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
00407                 return (0);
00408             }
00409             if (planarconfig != PLANARCONFIG_CONTIG) {
00410                 sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
00411                     "Planarconfiguration", planarconfig);
00412                 return (0);
00413             }
00414             TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
00415             img->photometric = PHOTOMETRIC_RGB;     /* little white lie */
00416             img->bitspersample = 8;
00417             break;
00418         case PHOTOMETRIC_CIELAB:
00419             break;
00420         default:
00421             sprintf(emsg, "Sorry, can not handle image with %s=%d",
00422                 photoTag, img->photometric);
00423             return (0);
00424     }
00425     img->Map = NULL;
00426     img->BWmap = NULL;
00427     img->PALmap = NULL;
00428     img->ycbcr = NULL;
00429     img->cielab = NULL;
00430     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
00431     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
00432     TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
00433     img->isContig =
00434         !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
00435     if (img->isContig) {
00436         if (!PickContigCase(img)) {
00437             sprintf(emsg, "Sorry, can not handle image");
00438             return 0;
00439         }
00440     } else {
00441         if (!PickSeparateCase(img)) {
00442             sprintf(emsg, "Sorry, can not handle image");
00443             return 0;
00444         }
00445     }
00446     return 1;
00447 }
00448 
00449 int
00450 TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
00451 {
00452     if (img->get == NULL) {
00453         TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup");
00454         return (0);
00455     }
00456     if (img->put.any == NULL) {
00457         TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
00458         "No \"put\" routine setupl; probably can not handle image format");
00459         return (0);
00460     }
00461     return (*img->get)(img, raster, w, h);
00462 }
00463 
00464 /*
00465  * Read the specified image into an ABGR-format rastertaking in account
00466  * specified orientation.
00467  */
00468 int
00469 TIFFReadRGBAImageOriented(TIFF* tif,
00470               uint32 rwidth, uint32 rheight, uint32* raster,
00471               int orientation, int stop)
00472 {
00473     char emsg[1024] = "";
00474     TIFFRGBAImage img;
00475     int ok;
00476 
00477     if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
00478         img.req_orientation = orientation;
00479         /* XXX verify rwidth and rheight against width and height */
00480         ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
00481             rwidth, img.height);
00482         TIFFRGBAImageEnd(&img);
00483     } else {
00484         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
00485         ok = 0;
00486     }
00487     return (ok);
00488 }
00489 
00490 /*
00491  * Read the specified image into an ABGR-format raster. Use bottom left
00492  * origin for raster by default.
00493  */
00494 int
00495 TIFFReadRGBAImage(TIFF* tif,
00496           uint32 rwidth, uint32 rheight, uint32* raster, int stop)
00497 {
00498     return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
00499                      ORIENTATION_BOTLEFT, stop);
00500 }
00501 
00502 static int 
00503 setorientation(TIFFRGBAImage* img)
00504 {
00505     switch (img->orientation) {
00506         case ORIENTATION_TOPLEFT:
00507         case ORIENTATION_LEFTTOP:
00508             if (img->req_orientation == ORIENTATION_TOPRIGHT ||
00509                 img->req_orientation == ORIENTATION_RIGHTTOP)
00510                 return FLIP_HORIZONTALLY;
00511             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
00512                 img->req_orientation == ORIENTATION_RIGHTBOT)
00513                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
00514             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
00515                 img->req_orientation == ORIENTATION_LEFTBOT)
00516                 return FLIP_VERTICALLY;
00517             else
00518                 return 0;
00519         case ORIENTATION_TOPRIGHT:
00520         case ORIENTATION_RIGHTTOP:
00521             if (img->req_orientation == ORIENTATION_TOPLEFT ||
00522                 img->req_orientation == ORIENTATION_LEFTTOP)
00523                 return FLIP_HORIZONTALLY;
00524             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
00525                 img->req_orientation == ORIENTATION_RIGHTBOT)
00526                 return FLIP_VERTICALLY;
00527             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
00528                 img->req_orientation == ORIENTATION_LEFTBOT)
00529                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
00530             else
00531                 return 0;
00532         case ORIENTATION_BOTRIGHT:
00533         case ORIENTATION_RIGHTBOT:
00534             if (img->req_orientation == ORIENTATION_TOPLEFT ||
00535                 img->req_orientation == ORIENTATION_LEFTTOP)
00536                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
00537             else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
00538                 img->req_orientation == ORIENTATION_RIGHTTOP)
00539                 return FLIP_VERTICALLY;
00540             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
00541                 img->req_orientation == ORIENTATION_LEFTBOT)
00542                 return FLIP_HORIZONTALLY;
00543             else
00544                 return 0;
00545         case ORIENTATION_BOTLEFT:
00546         case ORIENTATION_LEFTBOT:
00547             if (img->req_orientation == ORIENTATION_TOPLEFT ||
00548                 img->req_orientation == ORIENTATION_LEFTTOP)
00549                 return FLIP_VERTICALLY;
00550             else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
00551                 img->req_orientation == ORIENTATION_RIGHTTOP)
00552                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
00553             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
00554                 img->req_orientation == ORIENTATION_RIGHTBOT)
00555                 return FLIP_HORIZONTALLY;
00556             else
00557                 return 0;
00558         default:    /* NOTREACHED */
00559             return 0;
00560     }
00561 }
00562 
00563 /*
00564  * Get an tile-organized image that has
00565  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
00566  * or
00567  *  SamplesPerPixel == 1
00568  */ 
00569 static int
00570 gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
00571 {
00572     TIFF* tif = img->tif;
00573     tileContigRoutine put = img->put.contig;
00574     uint32 col, row, y, rowstoread;
00575     uint32 pos;
00576     uint32 tw, th;
00577     unsigned char* buf;
00578     int32 fromskew, toskew;
00579     uint32 nrow;
00580     int ret = 1, flip;
00581 
00582     buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
00583     if (buf == 0) {
00584         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
00585         return (0);
00586     }
00587     _TIFFmemset(buf, 0, TIFFTileSize(tif));
00588     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
00589     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
00590 
00591     flip = setorientation(img);
00592     if (flip & FLIP_VERTICALLY) {
00593         y = h - 1;
00594         toskew = -(int32)(tw + w);
00595     }
00596     else {
00597         y = 0;
00598         toskew = -(int32)(tw - w);
00599     }
00600      
00601     for (row = 0; row < h; row += nrow)
00602     {
00603         rowstoread = th - (row + img->row_offset) % th;
00604         nrow = (row + rowstoread > h ? h - row : rowstoread);
00605     for (col = 0; col < w; col += tw) 
00606         {
00607             if (TIFFReadTile(tif, buf, col+img->col_offset,
00608                              row+img->row_offset, 0, 0) < 0 && img->stoponerr)
00609             {
00610                 ret = 0;
00611                 break;
00612             }
00613         
00614             pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
00615 
00616             if (col + tw > w) 
00617             {
00618                 /*
00619                  * Tile is clipped horizontally.  Calculate
00620                  * visible portion and skewing factors.
00621                  */
00622                 uint32 npix = w - col;
00623                 fromskew = tw - npix;
00624                 (*put)(img, raster+y*w+col, col, y,
00625                        npix, nrow, fromskew, toskew + fromskew, buf + pos);
00626             }
00627             else 
00628             {
00629                 (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos);
00630             }
00631         }
00632 
00633         y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
00634     }
00635     _TIFFfree(buf);
00636 
00637     if (flip & FLIP_HORIZONTALLY) {
00638         uint32 line;
00639 
00640         for (line = 0; line < h; line++) {
00641             uint32 *left = raster + (line * w);
00642             uint32 *right = left + w - 1;
00643             
00644             while ( left < right ) {
00645                 uint32 temp = *left;
00646                 *left = *right;
00647                 *right = temp;
00648                 left++, right--;
00649             }
00650         }
00651     }
00652 
00653     return (ret);
00654 }
00655 
00656 /*
00657  * Get an tile-organized image that has
00658  *   SamplesPerPixel > 1
00659  *   PlanarConfiguration separated
00660  * We assume that all such images are RGB.
00661  */ 
00662 static int
00663 gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
00664 {
00665     TIFF* tif = img->tif;
00666     tileSeparateRoutine put = img->put.separate;
00667     uint32 col, row, y, rowstoread;
00668     uint32 pos;
00669     uint32 tw, th;
00670     unsigned char* buf;
00671     unsigned char* p0;
00672     unsigned char* p1;
00673     unsigned char* p2;
00674     unsigned char* pa;
00675     tsize_t tilesize;
00676     int32 fromskew, toskew;
00677     int alpha = img->alpha;
00678     uint32 nrow;
00679     int ret = 1, flip;
00680 
00681     tilesize = TIFFTileSize(tif);
00682     buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize);
00683     if (buf == 0) {
00684         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
00685         return (0);
00686     }
00687     _TIFFmemset(buf, 0, (alpha?4:3)*tilesize);
00688     p0 = buf;
00689     p1 = p0 + tilesize;
00690     p2 = p1 + tilesize;
00691     pa = (alpha?(p2+tilesize):NULL);
00692     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
00693     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
00694 
00695     flip = setorientation(img);
00696     if (flip & FLIP_VERTICALLY) {
00697         y = h - 1;
00698         toskew = -(int32)(tw + w);
00699     }
00700     else {
00701         y = 0;
00702         toskew = -(int32)(tw - w);
00703     }
00704 
00705     for (row = 0; row < h; row += nrow)
00706     {
00707         rowstoread = th - (row + img->row_offset) % th;
00708         nrow = (row + rowstoread > h ? h - row : rowstoread);
00709         for (col = 0; col < w; col += tw)
00710         {
00711             if (TIFFReadTile(tif, p0, col+img->col_offset,
00712                 row+img->row_offset,0,0) < 0 && img->stoponerr)
00713             {
00714                 ret = 0;
00715                 break;
00716             }
00717             if (TIFFReadTile(tif, p1, col+img->col_offset,
00718                 row+img->row_offset,0,1) < 0 && img->stoponerr)
00719             {
00720                 ret = 0;
00721                 break;
00722             }
00723             if (TIFFReadTile(tif, p2, col+img->col_offset,
00724                 row+img->row_offset,0,2) < 0 && img->stoponerr)
00725             {
00726                 ret = 0;
00727                 break;
00728             }
00729             if (alpha)
00730             {
00731                 if (TIFFReadTile(tif,pa,col+img->col_offset,
00732                     row+img->row_offset,0,3) < 0 && img->stoponerr)
00733                 {
00734                     ret = 0;
00735                     break;
00736                 }
00737             }
00738 
00739             pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
00740 
00741             if (col + tw > w)
00742             {
00743                 /*
00744                  * Tile is clipped horizontally.  Calculate
00745                  * visible portion and skewing factors.
00746                  */
00747                 uint32 npix = w - col;
00748                 fromskew = tw - npix;
00749                 (*put)(img, raster+y*w+col, col, y,
00750                     npix, nrow, fromskew, toskew + fromskew,
00751                     p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
00752             } else {
00753                 (*put)(img, raster+y*w+col, col, y,
00754                     tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
00755             }
00756         }
00757 
00758         y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
00759     }
00760 
00761     if (flip & FLIP_HORIZONTALLY) {
00762         uint32 line;
00763 
00764         for (line = 0; line < h; line++) {
00765             uint32 *left = raster + (line * w);
00766             uint32 *right = left + w - 1;
00767 
00768             while ( left < right ) {
00769                 uint32 temp = *left;
00770                 *left = *right;
00771                 *right = temp;
00772                 left++, right--;
00773             }
00774         }
00775     }
00776 
00777     _TIFFfree(buf);
00778     return (ret);
00779 }
00780 
00781 /*
00782  * Get a strip-organized image that has
00783  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
00784  * or
00785  *  SamplesPerPixel == 1
00786  */ 
00787 static int
00788 gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
00789 {
00790     TIFF* tif = img->tif;
00791     tileContigRoutine put = img->put.contig;
00792     uint32 row, y, nrow, nrowsub, rowstoread;
00793     uint32 pos;
00794     unsigned char* buf;
00795     uint32 rowsperstrip;
00796     uint16 subsamplinghor,subsamplingver;
00797     uint32 imagewidth = img->width;
00798     tsize_t scanline;
00799     int32 fromskew, toskew;
00800     int ret = 1, flip;
00801 
00802     buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif));
00803     if (buf == 0) {
00804         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
00805         return (0);
00806     }
00807     _TIFFmemset(buf, 0, TIFFStripSize(tif));
00808 
00809     flip = setorientation(img);
00810     if (flip & FLIP_VERTICALLY) {
00811         y = h - 1;
00812         toskew = -(int32)(w + w);
00813     } else {
00814         y = 0;
00815         toskew = -(int32)(w - w);
00816     }
00817 
00818     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
00819     TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
00820     scanline = TIFFNewScanlineSize(tif);
00821     fromskew = (w < imagewidth ? imagewidth - w : 0);
00822     for (row = 0; row < h; row += nrow)
00823     {
00824         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
00825         nrow = (row + rowstoread > h ? h - row : rowstoread);
00826         nrowsub = nrow;
00827         if ((nrowsub%subsamplingver)!=0)
00828             nrowsub+=subsamplingver-nrowsub%subsamplingver;
00829         if (TIFFReadEncodedStrip(tif,
00830             TIFFComputeStrip(tif,row+img->row_offset, 0),
00831             buf,
00832             ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0
00833             && img->stoponerr)
00834         {
00835             ret = 0;
00836             break;
00837         }
00838 
00839         pos = ((row + img->row_offset) % rowsperstrip) * scanline;
00840         (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
00841         y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
00842     }
00843 
00844     if (flip & FLIP_HORIZONTALLY) {
00845         uint32 line;
00846 
00847         for (line = 0; line < h; line++) {
00848             uint32 *left = raster + (line * w);
00849             uint32 *right = left + w - 1;
00850 
00851             while ( left < right ) {
00852                 uint32 temp = *left;
00853                 *left = *right;
00854                 *right = temp;
00855                 left++, right--;
00856             }
00857         }
00858     }
00859 
00860     _TIFFfree(buf);
00861     return (ret);
00862 }
00863 
00864 /*
00865  * Get a strip-organized image with
00866  *   SamplesPerPixel > 1
00867  *   PlanarConfiguration separated
00868  * We assume that all such images are RGB.
00869  */
00870 static int
00871 gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
00872 {
00873     TIFF* tif = img->tif;
00874     tileSeparateRoutine put = img->put.separate;
00875     unsigned char *buf;
00876     unsigned char *p0, *p1, *p2, *pa;
00877     uint32 row, y, nrow, rowstoread;
00878     uint32 pos;
00879     tsize_t scanline;
00880     uint32 rowsperstrip, offset_row;
00881     uint32 imagewidth = img->width;
00882     tsize_t stripsize;
00883     int32 fromskew, toskew;
00884     int alpha = img->alpha;
00885     int ret = 1, flip;
00886 
00887     stripsize = TIFFStripSize(tif);
00888     p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize);
00889     if (buf == 0) {
00890         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
00891         return (0);
00892     }
00893     _TIFFmemset(buf, 0, (alpha?4:3)*stripsize);
00894     p1 = p0 + stripsize;
00895     p2 = p1 + stripsize;
00896     pa = (alpha?(p2+stripsize):NULL);
00897 
00898     flip = setorientation(img);
00899     if (flip & FLIP_VERTICALLY) {
00900         y = h - 1;
00901         toskew = -(int32)(w + w);
00902     }
00903     else {
00904         y = 0;
00905         toskew = -(int32)(w - w);
00906     }
00907 
00908     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
00909     scanline = TIFFScanlineSize(tif);
00910     fromskew = (w < imagewidth ? imagewidth - w : 0);
00911     for (row = 0; row < h; row += nrow)
00912     {
00913         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
00914         nrow = (row + rowstoread > h ? h - row : rowstoread);
00915         offset_row = row + img->row_offset;
00916         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
00917             p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
00918             && img->stoponerr)
00919         {
00920             ret = 0;
00921             break;
00922         }
00923         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
00924             p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
00925             && img->stoponerr)
00926         {
00927             ret = 0;
00928             break;
00929         }
00930         if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
00931             p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
00932             && img->stoponerr)
00933         {
00934             ret = 0;
00935             break;
00936         }
00937         if (alpha)
00938         {
00939             if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3),
00940                 pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
00941                 && img->stoponerr)
00942             {
00943                 ret = 0;
00944                 break;
00945             }
00946         }
00947 
00948         pos = ((row + img->row_offset) % rowsperstrip) * scanline;
00949         (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
00950             p2 + pos, (alpha?(pa+pos):NULL));
00951         y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
00952     }
00953 
00954     if (flip & FLIP_HORIZONTALLY) {
00955         uint32 line;
00956 
00957         for (line = 0; line < h; line++) {
00958             uint32 *left = raster + (line * w);
00959             uint32 *right = left + w - 1;
00960 
00961             while ( left < right ) {
00962                 uint32 temp = *left;
00963                 *left = *right;
00964                 *right = temp;
00965                 left++, right--;
00966             }
00967         }
00968     }
00969 
00970     _TIFFfree(buf);
00971     return (ret);
00972 }
00973 
00974 /*
00975  * The following routines move decoded data returned
00976  * from the TIFF library into rasters filled with packed
00977  * ABGR pixels (i.e. suitable for passing to lrecwrite.)
00978  *
00979  * The routines have been created according to the most
00980  * important cases and optimized.  PickContigCase and
00981  * PickSeparateCase analyze the parameters and select
00982  * the appropriate "get" and "put" routine to use.
00983  */
00984 #define REPEAT8(op) REPEAT4(op); REPEAT4(op)
00985 #define REPEAT4(op) REPEAT2(op); REPEAT2(op)
00986 #define REPEAT2(op) op; op
00987 #define CASE8(x,op)         \
00988     switch (x) {            \
00989     case 7: op; case 6: op; case 5: op; \
00990     case 4: op; case 3: op; case 2: op; \
00991     case 1: op;             \
00992     }
00993 #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; }
00994 #define NOP
00995 
00996 #define UNROLL8(w, op1, op2) {      \
00997     uint32 _x;              \
00998     for (_x = w; _x >= 8; _x -= 8) {    \
00999     op1;                \
01000     REPEAT8(op2);           \
01001     }                   \
01002     if (_x > 0) {           \
01003     op1;                \
01004     CASE8(_x,op2);          \
01005     }                   \
01006 }
01007 #define UNROLL4(w, op1, op2) {      \
01008     uint32 _x;              \
01009     for (_x = w; _x >= 4; _x -= 4) {    \
01010     op1;                \
01011     REPEAT4(op2);           \
01012     }                   \
01013     if (_x > 0) {           \
01014     op1;                \
01015     CASE4(_x,op2);          \
01016     }                   \
01017 }
01018 #define UNROLL2(w, op1, op2) {      \
01019     uint32 _x;              \
01020     for (_x = w; _x >= 2; _x -= 2) {    \
01021     op1;                \
01022     REPEAT2(op2);           \
01023     }                   \
01024     if (_x) {               \
01025     op1;                \
01026     op2;                \
01027     }                   \
01028 }
01029     
01030 #define SKEW(r,g,b,skew)    { r += skew; g += skew; b += skew; }
01031 #define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; }
01032 
01033 #define A1 (((uint32)0xffL)<<24)
01034 #define PACK(r,g,b) \
01035     ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1)
01036 #define PACK4(r,g,b,a)  \
01037     ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24))
01038 #define W2B(v) (((v)>>8)&0xff)
01039 #define PACKW(r,g,b)    \
01040     ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1)
01041 #define PACKW4(r,g,b,a) \
01042     ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24))
01043 
01044 #define DECLAREContigPutFunc(name) \
01045 static void name(\
01046     TIFFRGBAImage* img, \
01047     uint32* cp, \
01048     uint32 x, uint32 y, \
01049     uint32 w, uint32 h, \
01050     int32 fromskew, int32 toskew, \
01051     unsigned char* pp \
01052 )
01053 
01054 /*
01055  * 8-bit palette => colormap/RGB
01056  */
01057 DECLAREContigPutFunc(put8bitcmaptile)
01058 {
01059     uint32** PALmap = img->PALmap;
01060     int samplesperpixel = img->samplesperpixel;
01061 
01062     (void) y;
01063     while (h-- > 0) {
01064     for (x = w; x-- > 0;)
01065         {
01066         *cp++ = PALmap[*pp][0];
01067             pp += samplesperpixel;
01068         }
01069     cp += toskew;
01070     pp += fromskew;
01071     }
01072 }
01073 
01074 /*
01075  * 4-bit palette => colormap/RGB
01076  */
01077 DECLAREContigPutFunc(put4bitcmaptile)
01078 {
01079     uint32** PALmap = img->PALmap;
01080 
01081     (void) x; (void) y;
01082     fromskew /= 2;
01083     while (h-- > 0) {
01084     uint32* bw;
01085     UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
01086     cp += toskew;
01087     pp += fromskew;
01088     }
01089 }
01090 
01091 /*
01092  * 2-bit palette => colormap/RGB
01093  */
01094 DECLAREContigPutFunc(put2bitcmaptile)
01095 {
01096     uint32** PALmap = img->PALmap;
01097 
01098     (void) x; (void) y;
01099     fromskew /= 4;
01100     while (h-- > 0) {
01101     uint32* bw;
01102     UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
01103     cp += toskew;
01104     pp += fromskew;
01105     }
01106 }
01107 
01108 /*
01109  * 1-bit palette => colormap/RGB
01110  */
01111 DECLAREContigPutFunc(put1bitcmaptile)
01112 {
01113     uint32** PALmap = img->PALmap;
01114 
01115     (void) x; (void) y;
01116     fromskew /= 8;
01117     while (h-- > 0) {
01118     uint32* bw;
01119     UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
01120     cp += toskew;
01121     pp += fromskew;
01122     }
01123 }
01124 
01125 /*
01126  * 8-bit greyscale => colormap/RGB
01127  */
01128 DECLAREContigPutFunc(putgreytile)
01129 {
01130     int samplesperpixel = img->samplesperpixel;
01131     uint32** BWmap = img->BWmap;
01132 
01133     (void) y;
01134     while (h-- > 0) {
01135     for (x = w; x-- > 0;)
01136         {
01137         *cp++ = BWmap[*pp][0];
01138             pp += samplesperpixel;
01139         }
01140     cp += toskew;
01141     pp += fromskew;
01142     }
01143 }
01144 
01145 /*
01146  * 16-bit greyscale => colormap/RGB
01147  */
01148 DECLAREContigPutFunc(put16bitbwtile)
01149 {
01150     int samplesperpixel = img->samplesperpixel;
01151     uint32** BWmap = img->BWmap;
01152 
01153     (void) y;
01154     while (h-- > 0) {
01155         uint16 *wp = (uint16 *) pp;
01156 
01157     for (x = w; x-- > 0;)
01158         {
01159             /* use high order byte of 16bit value */
01160 
01161         *cp++ = BWmap[*wp >> 8][0];
01162             pp += 2 * samplesperpixel;
01163             wp += samplesperpixel;
01164         }
01165     cp += toskew;
01166     pp += fromskew;
01167     }
01168 }
01169 
01170 /*
01171  * 1-bit bilevel => colormap/RGB
01172  */
01173 DECLAREContigPutFunc(put1bitbwtile)
01174 {
01175     uint32** BWmap = img->BWmap;
01176 
01177     (void) x; (void) y;
01178     fromskew /= 8;
01179     while (h-- > 0) {
01180     uint32* bw;
01181     UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
01182     cp += toskew;
01183     pp += fromskew;
01184     }
01185 }
01186 
01187 /*
01188  * 2-bit greyscale => colormap/RGB
01189  */
01190 DECLAREContigPutFunc(put2bitbwtile)
01191 {
01192     uint32** BWmap = img->BWmap;
01193 
01194     (void) x; (void) y;
01195     fromskew /= 4;
01196     while (h-- > 0) {
01197     uint32* bw;
01198     UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
01199     cp += toskew;
01200     pp += fromskew;
01201     }
01202 }
01203 
01204 /*
01205  * 4-bit greyscale => colormap/RGB
01206  */
01207 DECLAREContigPutFunc(put4bitbwtile)
01208 {
01209     uint32** BWmap = img->BWmap;
01210 
01211     (void) x; (void) y;
01212     fromskew /= 2;
01213     while (h-- > 0) {
01214     uint32* bw;
01215     UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
01216     cp += toskew;
01217     pp += fromskew;
01218     }
01219 }
01220 
01221 /*
01222  * 8-bit packed samples, no Map => RGB
01223  */
01224 DECLAREContigPutFunc(putRGBcontig8bittile)
01225 {
01226     int samplesperpixel = img->samplesperpixel;
01227 
01228     (void) x; (void) y;
01229     fromskew *= samplesperpixel;
01230     while (h-- > 0) {
01231     UNROLL8(w, NOP,
01232         *cp++ = PACK(pp[0], pp[1], pp[2]);
01233         pp += samplesperpixel);
01234     cp += toskew;
01235     pp += fromskew;
01236     }
01237 }
01238 
01239 /*
01240  * 8-bit packed samples => RGBA w/ associated alpha
01241  * (known to have Map == NULL)
01242  */
01243 DECLAREContigPutFunc(putRGBAAcontig8bittile)
01244 {
01245     int samplesperpixel = img->samplesperpixel;
01246 
01247     (void) x; (void) y;
01248     fromskew *= samplesperpixel;
01249     while (h-- > 0) {
01250     UNROLL8(w, NOP,
01251         *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
01252         pp += samplesperpixel);
01253     cp += toskew;
01254     pp += fromskew;
01255     }
01256 }
01257 
01258 /*
01259  * 8-bit packed samples => RGBA w/ unassociated alpha
01260  * (known to have Map == NULL)
01261  */
01262 DECLAREContigPutFunc(putRGBUAcontig8bittile)
01263 {
01264     int samplesperpixel = img->samplesperpixel;
01265     (void) y;
01266     fromskew *= samplesperpixel;
01267     while (h-- > 0) {
01268         uint32 r, g, b, a;
01269         for (x = w; x-- > 0;) {
01270             a = pp[3];
01271                         r = (a*pp[0] + 127) / 255;
01272                         g = (a*pp[1] + 127) / 255;
01273                         b = (a*pp[2] + 127) / 255;
01274             *cp++ = PACK4(r,g,b,a);
01275             pp += samplesperpixel;
01276         }
01277         cp += toskew;
01278         pp += fromskew;
01279     }
01280 }
01281 
01282 /*
01283  * 16-bit packed samples => RGB
01284  */
01285 DECLAREContigPutFunc(putRGBcontig16bittile)
01286 {
01287     int samplesperpixel = img->samplesperpixel;
01288     uint16 *wp = (uint16 *)pp;
01289     (void) y;
01290     fromskew *= samplesperpixel;
01291     while (h-- > 0) {
01292         for (x = w; x-- > 0;) {
01293                     *cp++ = PACKW(wp[0],wp[1],wp[2]);
01294                     wp += samplesperpixel;
01295         }
01296         cp += toskew;
01297         wp += fromskew;
01298     }
01299 }
01300 
01301 /*
01302  * 16-bit packed samples => RGBA w/ associated alpha
01303  * (known to have Map == NULL)
01304  */
01305 DECLAREContigPutFunc(putRGBAAcontig16bittile)
01306 {
01307     int samplesperpixel = img->samplesperpixel;
01308     uint16 *wp = (uint16 *)pp;
01309     (void) y;
01310     fromskew *= samplesperpixel;
01311     while (h-- > 0) {
01312         for (x = w; x-- > 0;) {
01313                     *cp++ = PACKW4(wp[0],wp[1],wp[2],wp[3]);
01314                     wp += samplesperpixel;
01315         }
01316         cp += toskew;
01317         wp += fromskew;
01318     }
01319 }
01320 
01321 /*
01322  * 16-bit packed samples => RGBA w/ unassociated alpha
01323  * (known to have Map == NULL)
01324  */
01325 DECLAREContigPutFunc(putRGBUAcontig16bittile)
01326 {
01327     int samplesperpixel = img->samplesperpixel;
01328     uint16 *wp = (uint16 *)pp;
01329     (void) y;
01330     fromskew *= samplesperpixel;
01331     while (h-- > 0) {
01332         uint32 r,g,b,a;
01333         for (x = w; x-- > 0;) {
01334                     a = W2B(wp[3]);
01335                     r = (a*W2B(wp[0]) + 127) / 255;
01336                     g = (a*W2B(wp[1]) + 127) / 255;
01337                     b = (a*W2B(wp[2]) + 127) / 255;
01338                     *cp++ = PACK4(r,g,b,a);
01339                     wp += samplesperpixel;
01340         }
01341         cp += toskew;
01342         wp += fromskew;
01343     }
01344 }
01345 
01346 /*
01347  * 8-bit packed CMYK samples w/o Map => RGB
01348  *
01349  * NB: The conversion of CMYK->RGB is *very* crude.
01350  */
01351 DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
01352 {
01353     int samplesperpixel = img->samplesperpixel;
01354     uint16 r, g, b, k;
01355 
01356     (void) x; (void) y;
01357     fromskew *= samplesperpixel;
01358     while (h-- > 0) {
01359     UNROLL8(w, NOP,
01360         k = 255 - pp[3];
01361         r = (k*(255-pp[0]))/255;
01362         g = (k*(255-pp[1]))/255;
01363         b = (k*(255-pp[2]))/255;
01364         *cp++ = PACK(r, g, b);
01365         pp += samplesperpixel);
01366     cp += toskew;
01367     pp += fromskew;
01368     }
01369 }
01370 
01371 /*
01372  * 8-bit packed CMYK samples w/Map => RGB
01373  *
01374  * NB: The conversion of CMYK->RGB is *very* crude.
01375  */
01376 DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
01377 {
01378     int samplesperpixel = img->samplesperpixel;
01379     TIFFRGBValue* Map = img->Map;
01380     uint16 r, g, b, k;
01381 
01382     (void) y;
01383     fromskew *= samplesperpixel;
01384     while (h-- > 0) {
01385     for (x = w; x-- > 0;) {
01386         k = 255 - pp[3];
01387         r = (k*(255-pp[0]))/255;
01388         g = (k*(255-pp[1]))/255;
01389         b = (k*(255-pp[2]))/255;
01390         *cp++ = PACK(Map[r], Map[g], Map[b]);
01391         pp += samplesperpixel;
01392     }
01393     pp += fromskew;
01394     cp += toskew;
01395     }
01396 }
01397 
01398 #define DECLARESepPutFunc(name) \
01399 static void name(\
01400     TIFFRGBAImage* img,\
01401     uint32* cp,\
01402     uint32 x, uint32 y, \
01403     uint32 w, uint32 h,\
01404     int32 fromskew, int32 toskew,\
01405     unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\
01406 )
01407 
01408 /*
01409  * 8-bit unpacked samples => RGB
01410  */
01411 DECLARESepPutFunc(putRGBseparate8bittile)
01412 {
01413     (void) img; (void) x; (void) y; (void) a;
01414     while (h-- > 0) {
01415     UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
01416     SKEW(r, g, b, fromskew);
01417     cp += toskew;
01418     }
01419 }
01420 
01421 /*
01422  * 8-bit unpacked samples => RGBA w/ associated alpha
01423  */
01424 DECLARESepPutFunc(putRGBAAseparate8bittile)
01425 {
01426     (void) img; (void) x; (void) y;
01427     while (h-- > 0) {
01428         UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
01429         SKEW4(r, g, b, a, fromskew);
01430         cp += toskew;
01431     }
01432 }
01433 
01434 /*
01435  * 8-bit unpacked samples => RGBA w/ unassociated alpha
01436  */
01437 DECLARESepPutFunc(putRGBUAseparate8bittile)
01438 {
01439     (void) img; (void) y;
01440     while (h-- > 0) {
01441         uint32 rv, gv, bv, av;
01442         for (x = w; x-- > 0;) {
01443             av = *a++;
01444                         rv = (av* *r++ + 127) / 255;
01445                         gv = (av* *g++ + 127) / 255;
01446                         bv = (av* *b++ + 127) / 255;
01447             *cp++ = PACK4(rv,gv,bv,av);
01448         }
01449         SKEW4(r, g, b, a, fromskew);
01450         cp += toskew;
01451     }
01452 }
01453 
01454 /*
01455  * 16-bit unpacked samples => RGB
01456  */
01457 DECLARESepPutFunc(putRGBseparate16bittile)
01458 {
01459     uint16 *wr = (uint16*) r;
01460     uint16 *wg = (uint16*) g;
01461     uint16 *wb = (uint16*) b;
01462     (void) img; (void) y; (void) a;
01463     while (h-- > 0) {
01464         for (x = 0; x < w; x++)
01465                     *cp++ = PACKW(*wr++,*wg++,*wb++);
01466         SKEW(wr, wg, wb, fromskew);
01467         cp += toskew;
01468     }
01469 }
01470 
01471 /*
01472  * 16-bit unpacked samples => RGBA w/ associated alpha
01473  */
01474 DECLARESepPutFunc(putRGBAAseparate16bittile)
01475 {
01476     uint16 *wr = (uint16*) r;
01477     uint16 *wg = (uint16*) g;
01478     uint16 *wb = (uint16*) b;
01479     uint16 *wa = (uint16*) a;
01480     (void) img; (void) y;
01481     while (h-- > 0) {
01482         for (x = 0; x < w; x++)
01483                     *cp++ = PACKW4(*wr++,*wg++,*wb++,*wa++);
01484         SKEW4(wr, wg, wb, wa, fromskew);
01485         cp += toskew;
01486     }
01487 }
01488 
01489 /*
01490  * 16-bit unpacked samples => RGBA w/ unassociated alpha
01491  */
01492 DECLARESepPutFunc(putRGBUAseparate16bittile)
01493 {
01494     uint16 *wr = (uint16*) r;
01495     uint16 *wg = (uint16*) g;
01496     uint16 *wb = (uint16*) b;
01497     uint16 *wa = (uint16*) a;
01498     (void) img; (void) y;
01499     while (h-- > 0) {
01500         uint32 r,g,b,a;
01501         for (x = w; x-- > 0;) {
01502                     a = W2B(*wa++);
01503                     r = (a*W2B(*wr++) + 127) / 255;
01504                     g = (a*W2B(*wg++) + 127) / 255;
01505                     b = (a*W2B(*wb++) + 127) / 255;
01506                     *cp++ = PACK4(r,g,b,a);
01507         }
01508         SKEW4(wr, wg, wb, wa, fromskew);
01509         cp += toskew;
01510     }
01511 }
01512 
01513 /*
01514  * 8-bit packed CIE L*a*b 1976 samples => RGB
01515  */
01516 DECLAREContigPutFunc(putcontig8bitCIELab)
01517 {
01518     float X, Y, Z;
01519     uint32 r, g, b;
01520     (void) y;
01521     fromskew *= 3;
01522     while (h-- > 0) {
01523         for (x = w; x-- > 0;) {
01524             TIFFCIELabToXYZ(img->cielab,
01525                     (unsigned char)pp[0],
01526                     (signed char)pp[1],
01527                     (signed char)pp[2],
01528                     &X, &Y, &Z);
01529             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
01530             *cp++ = PACK(r, g, b);
01531             pp += 3;
01532         }
01533         cp += toskew;
01534         pp += fromskew;
01535     }
01536 }
01537 
01538 /*
01539  * YCbCr -> RGB conversion and packing routines.
01540  */
01541 
01542 #define YCbCrtoRGB(dst, Y) {                        \
01543     uint32 r, g, b;                         \
01544     TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);        \
01545     dst = PACK(r, g, b);                        \
01546 }
01547 
01548 /*
01549  * 8-bit packed YCbCr samples => RGB 
01550  * This function is generic for different sampling sizes, 
01551  * and can handle blocks sizes that aren't multiples of the
01552  * sampling size.  However, it is substantially less optimized
01553  * than the specific sampling cases.  It is used as a fallback
01554  * for difficult blocks.
01555  */
01556 #ifdef notdef
01557 static void putcontig8bitYCbCrGenericTile( 
01558     TIFFRGBAImage* img, 
01559     uint32* cp, 
01560     uint32 x, uint32 y, 
01561     uint32 w, uint32 h, 
01562     int32 fromskew, int32 toskew, 
01563     unsigned char* pp,
01564     int h_group, 
01565     int v_group )
01566 
01567 {
01568     uint32* cp1 = cp+w+toskew;
01569     uint32* cp2 = cp1+w+toskew;
01570     uint32* cp3 = cp2+w+toskew;
01571     int32 incr = 3*w+4*toskew;
01572     int32   Cb, Cr;
01573     int     group_size = v_group * h_group + 2;
01574 
01575     (void) y;
01576     fromskew = (fromskew * group_size) / h_group;
01577 
01578     for( yy = 0; yy < h; yy++ )
01579     {
01580         unsigned char *pp_line;
01581         int     y_line_group = yy / v_group;
01582         int     y_remainder = yy - y_line_group * v_group;
01583 
01584         pp_line = pp + v_line_group * 
01585 
01586         
01587         for( xx = 0; xx < w; xx++ )
01588         {
01589             Cb = pp
01590         }
01591     }
01592     for (; h >= 4; h -= 4) {
01593     x = w>>2;
01594     do {
01595         Cb = pp[16];
01596         Cr = pp[17];
01597 
01598         YCbCrtoRGB(cp [0], pp[ 0]);
01599         YCbCrtoRGB(cp [1], pp[ 1]);
01600         YCbCrtoRGB(cp [2], pp[ 2]);
01601         YCbCrtoRGB(cp [3], pp[ 3]);
01602         YCbCrtoRGB(cp1[0], pp[ 4]);
01603         YCbCrtoRGB(cp1[1], pp[ 5]);
01604         YCbCrtoRGB(cp1[2], pp[ 6]);
01605         YCbCrtoRGB(cp1[3], pp[ 7]);
01606         YCbCrtoRGB(cp2[0], pp[ 8]);
01607         YCbCrtoRGB(cp2[1], pp[ 9]);
01608         YCbCrtoRGB(cp2[2], pp[10]);
01609         YCbCrtoRGB(cp2[3], pp[11]);
01610         YCbCrtoRGB(cp3[0], pp[12]);
01611         YCbCrtoRGB(cp3[1], pp[13]);
01612         YCbCrtoRGB(cp3[2], pp[14]);
01613         YCbCrtoRGB(cp3[3], pp[15]);
01614 
01615         cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
01616         pp += 18;
01617     } while (--x);
01618     cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
01619     pp += fromskew;
01620     }
01621 }
01622 #endif
01623 
01624 /*
01625  * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
01626  */
01627 DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
01628 {
01629     uint32* cp1 = cp+w+toskew;
01630     uint32* cp2 = cp1+w+toskew;
01631     uint32* cp3 = cp2+w+toskew;
01632     int32 incr = 3*w+4*toskew;
01633 
01634     (void) y;
01635     /* adjust fromskew */
01636     fromskew = (fromskew * 18) / 4;
01637     if ((h & 3) == 0 && (w & 3) == 0) {                     
01638         for (; h >= 4; h -= 4) {
01639             x = w>>2;
01640             do {
01641                 int32 Cb = pp[16];
01642                 int32 Cr = pp[17];
01643 
01644                 YCbCrtoRGB(cp [0], pp[ 0]);
01645                 YCbCrtoRGB(cp [1], pp[ 1]);
01646                 YCbCrtoRGB(cp [2], pp[ 2]);
01647                 YCbCrtoRGB(cp [3], pp[ 3]);
01648                 YCbCrtoRGB(cp1[0], pp[ 4]);
01649                 YCbCrtoRGB(cp1[1], pp[ 5]);
01650                 YCbCrtoRGB(cp1[2], pp[ 6]);
01651                 YCbCrtoRGB(cp1[3], pp[ 7]);
01652                 YCbCrtoRGB(cp2[0], pp[ 8]);
01653                 YCbCrtoRGB(cp2[1], pp[ 9]);
01654                 YCbCrtoRGB(cp2[2], pp[10]);
01655                 YCbCrtoRGB(cp2[3], pp[11]);
01656                 YCbCrtoRGB(cp3[0], pp[12]);
01657                 YCbCrtoRGB(cp3[1], pp[13]);
01658                 YCbCrtoRGB(cp3[2], pp[14]);
01659                 YCbCrtoRGB(cp3[3], pp[15]);
01660 
01661                 cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
01662                 pp += 18;
01663             } while (--x);
01664             cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
01665             pp += fromskew;
01666         }
01667     } else {
01668         while (h > 0) {
01669             for (x = w; x > 0;) {
01670                 int32 Cb = pp[16];
01671                 int32 Cr = pp[17];
01672                 switch (x) {
01673                 default:
01674                     switch (h) {
01675                     default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
01676                     case 3:  YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
01677                     case 2:  YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
01678                     case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
01679                     }                                    /* FALLTHROUGH */
01680                 case 3:
01681                     switch (h) {
01682                     default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
01683                     case 3:  YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
01684                     case 2:  YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
01685                     case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
01686                     }                                    /* FALLTHROUGH */
01687                 case 2:
01688                     switch (h) {
01689                     default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
01690                     case 3:  YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */
01691                     case 2:  YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
01692                     case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
01693                     }                                    /* FALLTHROUGH */
01694                 case 1:
01695                     switch (h) {
01696                     default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
01697                     case 3:  YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */
01698                     case 2:  YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
01699                     case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
01700                     }                                    /* FALLTHROUGH */
01701                 }
01702                 if (x < 4) {
01703                     cp += x; cp1 += x; cp2 += x; cp3 += x;
01704                     x = 0;
01705                 }
01706                 else {
01707                     cp += 4; cp1 += 4; cp2 += 4; cp3 += 4;
01708                     x -= 4;
01709                 }
01710                 pp += 18;
01711             }
01712             if (h <= 4)
01713                 break;
01714             h -= 4;
01715             cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
01716             pp += fromskew;
01717         }
01718     }
01719 }
01720 
01721 /*
01722  * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
01723  */
01724 DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
01725 {
01726     uint32* cp1 = cp+w+toskew;
01727     int32 incr = 2*toskew+w;
01728 
01729     (void) y;
01730     fromskew = (fromskew * 10) / 4;
01731     if ((h & 3) == 0 && (w & 1) == 0) {
01732         for (; h >= 2; h -= 2) {
01733             x = w>>2;
01734             do {
01735                 int32 Cb = pp[8];
01736                 int32 Cr = pp[9];
01737                 
01738                 YCbCrtoRGB(cp [0], pp[0]);
01739                 YCbCrtoRGB(cp [1], pp[1]);
01740                 YCbCrtoRGB(cp [2], pp[2]);
01741                 YCbCrtoRGB(cp [3], pp[3]);
01742                 YCbCrtoRGB(cp1[0], pp[4]);
01743                 YCbCrtoRGB(cp1[1], pp[5]);
01744                 YCbCrtoRGB(cp1[2], pp[6]);
01745                 YCbCrtoRGB(cp1[3], pp[7]);
01746                 
01747                 cp += 4, cp1 += 4;
01748                 pp += 10;
01749             } while (--x);
01750             cp += incr, cp1 += incr;
01751             pp += fromskew;
01752         }
01753     } else {
01754         while (h > 0) {
01755             for (x = w; x > 0;) {
01756                 int32 Cb = pp[8];
01757                 int32 Cr = pp[9];
01758                 switch (x) {
01759                 default:
01760                     switch (h) {
01761                     default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
01762                     case 1:  YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
01763                     }                                    /* FALLTHROUGH */
01764                 case 3:
01765                     switch (h) {
01766                     default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
01767                     case 1:  YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
01768                     }                                    /* FALLTHROUGH */
01769                 case 2:
01770                     switch (h) {
01771                     default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
01772                     case 1:  YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
01773                     }                                    /* FALLTHROUGH */
01774                 case 1:
01775                     switch (h) {
01776                     default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
01777                     case 1:  YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
01778                     }                                    /* FALLTHROUGH */
01779                 }
01780                 if (x < 4) {
01781                     cp += x; cp1 += x;
01782                     x = 0;
01783                 }
01784                 else {
01785                     cp += 4; cp1 += 4;
01786                     x -= 4;
01787                 }
01788                 pp += 10;
01789             }
01790             if (h <= 2)
01791                 break;
01792             h -= 2;
01793             cp += incr, cp1 += incr;
01794             pp += fromskew;
01795         }
01796     }
01797 }
01798 
01799 /*
01800  * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
01801  */
01802 DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
01803 {
01804     (void) y;
01805     /* XXX adjust fromskew */
01806     do {
01807     x = w>>2;
01808     do {
01809         int32 Cb = pp[4];
01810         int32 Cr = pp[5];
01811 
01812         YCbCrtoRGB(cp [0], pp[0]);
01813         YCbCrtoRGB(cp [1], pp[1]);
01814         YCbCrtoRGB(cp [2], pp[2]);
01815         YCbCrtoRGB(cp [3], pp[3]);
01816 
01817         cp += 4;
01818         pp += 6;
01819     } while (--x);
01820 
01821         if( (w&3) != 0 )
01822         {
01823         int32 Cb = pp[4];
01824         int32 Cr = pp[5];
01825 
01826             switch( (w&3) ) {
01827               case 3: YCbCrtoRGB(cp [2], pp[2]);
01828               case 2: YCbCrtoRGB(cp [1], pp[1]);
01829               case 1: YCbCrtoRGB(cp [0], pp[0]);
01830               case 0: break;
01831             }
01832 
01833             cp += (w&3);
01834             pp += 6;
01835         }
01836 
01837     cp += toskew;
01838     pp += fromskew;
01839     } while (--h);
01840 
01841 }
01842 
01843 /*
01844  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
01845  */
01846 DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
01847 {
01848     uint32* cp2;
01849     (void) y;
01850     fromskew = (fromskew / 2) * 6;
01851     cp2 = cp+w+toskew;
01852     while (h>=2) {
01853         x = w;
01854         while (x>=2) {
01855             uint32 Cb = pp[4];
01856             uint32 Cr = pp[5];
01857             YCbCrtoRGB(cp[0], pp[0]);
01858             YCbCrtoRGB(cp[1], pp[1]);
01859             YCbCrtoRGB(cp2[0], pp[2]);
01860             YCbCrtoRGB(cp2[1], pp[3]);
01861             cp += 2;
01862             cp2 += 2;
01863             pp += 6;
01864             x -= 2;
01865         }
01866         if (x==1) {
01867             uint32 Cb = pp[4];
01868             uint32 Cr = pp[5];
01869             YCbCrtoRGB(cp[0], pp[0]);
01870             YCbCrtoRGB(cp2[0], pp[2]);
01871             cp ++ ;
01872             cp2 ++ ;
01873             pp += 6;
01874         }
01875         cp += toskew*2+w;
01876         cp2 += toskew*2+w;
01877         pp += fromskew;
01878         h-=2;
01879     }
01880     if (h==1) {
01881         x = w;
01882         while (x>=2) {
01883             uint32 Cb = pp[4];
01884             uint32 Cr = pp[5];
01885             YCbCrtoRGB(cp[0], pp[0]);
01886             YCbCrtoRGB(cp[1], pp[1]);
01887             cp += 2;
01888             cp2 += 2;
01889             pp += 6;
01890             x -= 2;
01891         }
01892         if (x==1) {
01893             uint32 Cb = pp[4];
01894             uint32 Cr = pp[5];
01895             YCbCrtoRGB(cp[0], pp[0]);
01896         }
01897     }
01898 }
01899 
01900 /*
01901  * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
01902  */
01903 DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
01904 {
01905     (void) y;
01906     fromskew = (fromskew * 4) / 2;
01907     do {
01908         x = w>>1;
01909         do {
01910             int32 Cb = pp[2];
01911             int32 Cr = pp[3];
01912 
01913             YCbCrtoRGB(cp[0], pp[0]);
01914             YCbCrtoRGB(cp[1], pp[1]);
01915 
01916             cp += 2;
01917             pp += 4;
01918         } while (--x);
01919 
01920         if( (w&1) != 0 )
01921         {
01922             int32 Cb = pp[2];
01923             int32 Cr = pp[3];
01924 
01925             YCbCrtoRGB(cp[0], pp[0]);
01926 
01927             cp += 1;
01928             pp += 4;
01929         }
01930 
01931         cp += toskew;
01932         pp += fromskew;
01933     } while (--h);
01934 }
01935 
01936 /*
01937  * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
01938  */
01939 DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
01940 {
01941     uint32* cp2;
01942     (void) y;
01943     fromskew = (fromskew / 2) * 4;
01944     cp2 = cp+w+toskew;
01945     while (h>=2) {
01946         x = w;
01947         do {
01948             uint32 Cb = pp[2];
01949             uint32 Cr = pp[3];
01950             YCbCrtoRGB(cp[0], pp[0]);
01951             YCbCrtoRGB(cp2[0], pp[1]);
01952             cp ++;
01953             cp2 ++;
01954             pp += 4;
01955         } while (--x);
01956         cp += toskew*2+w;
01957         cp2 += toskew*2+w;
01958         pp += fromskew;
01959         h-=2;
01960     }
01961     if (h==1) {
01962         x = w;
01963         do {
01964             uint32 Cb = pp[2];
01965             uint32 Cr = pp[3];
01966             YCbCrtoRGB(cp[0], pp[0]);
01967             cp ++;
01968             pp += 4;
01969         } while (--x);
01970     }
01971 }
01972 
01973 /*
01974  * 8-bit packed YCbCr samples w/ no subsampling => RGB
01975  */
01976 DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
01977 {
01978     (void) y;
01979     fromskew *= 3;
01980     do {
01981         x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
01982         do {
01983             int32 Cb = pp[1];
01984             int32 Cr = pp[2];
01985 
01986             YCbCrtoRGB(*cp++, pp[0]);
01987 
01988             pp += 3;
01989         } while (--x);
01990         cp += toskew;
01991         pp += fromskew;
01992     } while (--h);
01993 }
01994 
01995 /*
01996  * 8-bit packed YCbCr samples w/ no subsampling => RGB
01997  */
01998 DECLARESepPutFunc(putseparate8bitYCbCr11tile)
01999 {
02000     (void) y;
02001     (void) a;
02002     /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */
02003     while (h-- > 0) {
02004         x = w;
02005         do {
02006             uint32 dr, dg, db;
02007             TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db);
02008             *cp++ = PACK(dr,dg,db);
02009         } while (--x);
02010         SKEW(r, g, b, fromskew);
02011         cp += toskew;
02012     }
02013 }
02014 #undef YCbCrtoRGB
02015 
02016 static int
02017 initYCbCrConversion(TIFFRGBAImage* img)
02018 {
02019     static char module[] = "initYCbCrConversion";
02020 
02021     float *luma, *refBlackWhite;
02022 
02023     if (img->ycbcr == NULL) {
02024         img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
02025             TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
02026             + 4*256*sizeof (TIFFRGBValue)
02027             + 2*256*sizeof (int)
02028             + 3*256*sizeof (int32)
02029             );
02030         if (img->ycbcr == NULL) {
02031             TIFFErrorExt(img->tif->tif_clientdata, module,
02032                 "No space for YCbCr->RGB conversion state");
02033             return (0);
02034         }
02035     }
02036 
02037     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
02038     TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
02039         &refBlackWhite);
02040     if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
02041         return(0);
02042     return (1);
02043 }
02044 
02045 static tileContigRoutine
02046 initCIELabConversion(TIFFRGBAImage* img)
02047 {
02048     static char module[] = "initCIELabConversion";
02049 
02050     float   *whitePoint;
02051     float   refWhite[3];
02052 
02053     if (!img->cielab) {
02054         img->cielab = (TIFFCIELabToRGB *)
02055             _TIFFmalloc(sizeof(TIFFCIELabToRGB));
02056         if (!img->cielab) {
02057             TIFFErrorExt(img->tif->tif_clientdata, module,
02058                 "No space for CIE L*a*b*->RGB conversion state.");
02059             return NULL;
02060         }
02061     }
02062 
02063     TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
02064     refWhite[1] = 100.0F;
02065     refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
02066     refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1])
02067               / whitePoint[1] * refWhite[1];
02068     if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) {
02069         TIFFErrorExt(img->tif->tif_clientdata, module,
02070             "Failed to initialize CIE L*a*b*->RGB conversion state.");
02071         _TIFFfree(img->cielab);
02072         return NULL;
02073     }
02074 
02075     return putcontig8bitCIELab;
02076 }
02077 
02078 /*
02079  * Greyscale images with less than 8 bits/sample are handled
02080  * with a table to avoid lots of shifts and masks.  The table
02081  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
02082  * pixel values simply by indexing into the table with one
02083  * number.
02084  */
02085 static int
02086 makebwmap(TIFFRGBAImage* img)
02087 {
02088     TIFFRGBValue* Map = img->Map;
02089     int bitspersample = img->bitspersample;
02090     int nsamples = 8 / bitspersample;
02091     int i;
02092     uint32* p;
02093 
02094     if( nsamples == 0 )
02095         nsamples = 1;
02096 
02097     img->BWmap = (uint32**) _TIFFmalloc(
02098     256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
02099     if (img->BWmap == NULL) {
02100         TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table");
02101         return (0);
02102     }
02103     p = (uint32*)(img->BWmap + 256);
02104     for (i = 0; i < 256; i++) {
02105     TIFFRGBValue c;
02106     img->BWmap[i] = p;
02107     switch (bitspersample) {
02108 #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c);
02109     case 1:
02110         GREY(i>>7);
02111         GREY((i>>6)&1);
02112         GREY((i>>5)&1);
02113         GREY((i>>4)&1);
02114         GREY((i>>3)&1);
02115         GREY((i>>2)&1);
02116         GREY((i>>1)&1);
02117         GREY(i&1);
02118         break;
02119     case 2:
02120         GREY(i>>6);
02121         GREY((i>>4)&3);
02122         GREY((i>>2)&3);
02123         GREY(i&3);
02124         break;
02125     case 4:
02126         GREY(i>>4);
02127         GREY(i&0xf);
02128         break;
02129     case 8:
02130         case 16:
02131         GREY(i);
02132         break;
02133     }
02134 #undef  GREY
02135     }
02136     return (1);
02137 }
02138 
02139 /*
02140  * Construct a mapping table to convert from the range
02141  * of the data samples to [0,255] --for display.  This
02142  * process also handles inverting B&W images when needed.
02143  */ 
02144 static int
02145 setupMap(TIFFRGBAImage* img)
02146 {
02147     int32 x, range;
02148 
02149     range = (int32)((1L<<img->bitspersample)-1);
02150     
02151     /* treat 16 bit the same as eight bit */
02152     if( img->bitspersample == 16 )
02153         range = (int32) 255;
02154 
02155     img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue));
02156     if (img->Map == NULL) {
02157         TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
02158             "No space for photometric conversion table");
02159         return (0);
02160     }
02161     if (img->photometric == PHOTOMETRIC_MINISWHITE) {
02162     for (x = 0; x <= range; x++)
02163         img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range);
02164     } else {
02165     for (x = 0; x <= range; x++)
02166         img->Map[x] = (TIFFRGBValue) ((x * 255) / range);
02167     }
02168     if (img->bitspersample <= 16 &&
02169     (img->photometric == PHOTOMETRIC_MINISBLACK ||
02170      img->photometric == PHOTOMETRIC_MINISWHITE)) {
02171     /*
02172      * Use photometric mapping table to construct
02173      * unpacking tables for samples <= 8 bits.
02174      */
02175     if (!makebwmap(img))
02176         return (0);
02177     /* no longer need Map, free it */
02178     _TIFFfree(img->Map), img->Map = NULL;
02179     }
02180     return (1);
02181 }
02182 
02183 static int
02184 checkcmap(TIFFRGBAImage* img)
02185 {
02186     uint16* r = img->redcmap;
02187     uint16* g = img->greencmap;
02188     uint16* b = img->bluecmap;
02189     long n = 1L<<img->bitspersample;
02190 
02191     while (n-- > 0)
02192     if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
02193         return (16);
02194     return (8);
02195 }
02196 
02197 static void
02198 cvtcmap(TIFFRGBAImage* img)
02199 {
02200     uint16* r = img->redcmap;
02201     uint16* g = img->greencmap;
02202     uint16* b = img->bluecmap;
02203     long i;
02204 
02205     for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {
02206 #define CVT(x)      ((uint16)((x)>>8))
02207     r[i] = CVT(r[i]);
02208     g[i] = CVT(g[i]);
02209     b[i] = CVT(b[i]);
02210 #undef  CVT
02211     }
02212 }
02213 
02214 /*
02215  * Palette images with <= 8 bits/sample are handled
02216  * with a table to avoid lots of shifts and masks.  The table
02217  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
02218  * pixel values simply by indexing into the table with one
02219  * number.
02220  */
02221 static int
02222 makecmap(TIFFRGBAImage* img)
02223 {
02224     int bitspersample = img->bitspersample;
02225     int nsamples = 8 / bitspersample;
02226     uint16* r = img->redcmap;
02227     uint16* g = img->greencmap;
02228     uint16* b = img->bluecmap;
02229     uint32 *p;
02230     int i;
02231 
02232     img->PALmap = (uint32**) _TIFFmalloc(
02233     256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
02234     if (img->PALmap == NULL) {
02235         TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table");
02236         return (0);
02237     }
02238     p = (uint32*)(img->PALmap + 256);
02239     for (i = 0; i < 256; i++) {
02240     TIFFRGBValue c;
02241     img->PALmap[i] = p;
02242 #define CMAP(x) c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff);
02243     switch (bitspersample) {
02244     case 1:
02245         CMAP(i>>7);
02246         CMAP((i>>6)&1);
02247         CMAP((i>>5)&1);
02248         CMAP((i>>4)&1);
02249         CMAP((i>>3)&1);
02250         CMAP((i>>2)&1);
02251         CMAP((i>>1)&1);
02252         CMAP(i&1);
02253         break;
02254     case 2:
02255         CMAP(i>>6);
02256         CMAP((i>>4)&3);
02257         CMAP((i>>2)&3);
02258         CMAP(i&3);
02259         break;
02260     case 4:
02261         CMAP(i>>4);
02262         CMAP(i&0xf);
02263         break;
02264     case 8:
02265         CMAP(i);
02266         break;
02267     }
02268 #undef CMAP
02269     }
02270     return (1);
02271 }
02272 
02273 /* 
02274  * Construct any mapping table used
02275  * by the associated put routine.
02276  */
02277 static int
02278 buildMap(TIFFRGBAImage* img)
02279 {
02280     switch (img->photometric) {
02281     case PHOTOMETRIC_RGB:
02282     case PHOTOMETRIC_YCBCR:
02283     case PHOTOMETRIC_SEPARATED:
02284     if (img->bitspersample == 8)
02285         break;
02286     /* fall thru... */
02287     case PHOTOMETRIC_MINISBLACK:
02288     case PHOTOMETRIC_MINISWHITE:
02289     if (!setupMap(img))
02290         return (0);
02291     break;
02292     case PHOTOMETRIC_PALETTE:
02293     /*
02294      * Convert 16-bit colormap to 8-bit (unless it looks
02295      * like an old-style 8-bit colormap).
02296      */
02297     if (checkcmap(img) == 16)
02298         cvtcmap(img);
02299     else
02300         TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap");
02301     /*
02302      * Use mapping table and colormap to construct
02303      * unpacking tables for samples < 8 bits.
02304      */
02305     if (img->bitspersample <= 8 && !makecmap(img))
02306         return (0);
02307     break;
02308     }
02309     return (1);
02310 }
02311 
02312 /*
02313  * Select the appropriate conversion routine for packed data.
02314  */
02315 static int
02316 PickContigCase(TIFFRGBAImage* img)
02317 {
02318     img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
02319     img->put.contig = NULL;
02320     switch (img->photometric) {
02321         case PHOTOMETRIC_RGB:
02322             switch (img->bitspersample) {
02323                 case 8:
02324                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
02325                         img->put.contig = putRGBAAcontig8bittile;
02326                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
02327                     {
02328                                             img->put.contig = putRGBUAcontig8bittile;
02329                     }
02330                     else
02331                                             img->put.contig = putRGBcontig8bittile;
02332                     break;
02333                 case 16:
02334                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
02335                     {
02336                                             img->put.contig = putRGBAAcontig16bittile;
02337                     }
02338                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
02339                     {
02340                                             img->put.contig = putRGBUAcontig16bittile;
02341                     }
02342                     else
02343                     {
02344                                             img->put.contig = putRGBcontig16bittile;
02345                     }
02346                     break;
02347             }
02348             break;
02349         case PHOTOMETRIC_SEPARATED:
02350             if (buildMap(img)) {
02351                 if (img->bitspersample == 8) {
02352                     if (!img->Map)
02353                         img->put.contig = putRGBcontig8bitCMYKtile;
02354                     else
02355                         img->put.contig = putRGBcontig8bitCMYKMaptile;
02356                 }
02357             }
02358             break;
02359         case PHOTOMETRIC_PALETTE:
02360             if (buildMap(img)) {
02361                 switch (img->bitspersample) {
02362                     case 8:
02363                         img->put.contig = put8bitcmaptile;
02364                         break;
02365                     case 4:
02366                         img->put.contig = put4bitcmaptile;
02367                         break;
02368                     case 2:
02369                         img->put.contig = put2bitcmaptile;
02370                         break;
02371                     case 1:
02372                         img->put.contig = put1bitcmaptile;
02373                         break;
02374                 }
02375             }
02376             break;
02377         case PHOTOMETRIC_MINISWHITE:
02378         case PHOTOMETRIC_MINISBLACK:
02379             if (buildMap(img)) {
02380                 switch (img->bitspersample) {
02381                     case 16:
02382                         img->put.contig = put16bitbwtile;
02383                         break;
02384                     case 8:
02385                         img->put.contig = putgreytile;
02386                         break;
02387                     case 4:
02388                         img->put.contig = put4bitbwtile;
02389                         break;
02390                     case 2:
02391                         img->put.contig = put2bitbwtile;
02392                         break;
02393                     case 1:
02394                         img->put.contig = put1bitbwtile;
02395                         break;
02396                 }
02397             }
02398             break;
02399         case PHOTOMETRIC_YCBCR:
02400             if (img->bitspersample == 8)
02401             {
02402                 if (initYCbCrConversion(img)!=0)
02403                 {
02404                     /*
02405                      * The 6.0 spec says that subsampling must be
02406                      * one of 1, 2, or 4, and that vertical subsampling
02407                      * must always be <= horizontal subsampling; so
02408                      * there are only a few possibilities and we just
02409                      * enumerate the cases.
02410                      * Joris: added support for the [1,2] case, nonetheless, to accomodate
02411                      * some OJPEG files
02412                      */
02413                     uint16 SubsamplingHor;
02414                     uint16 SubsamplingVer;
02415                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer);
02416                     switch ((SubsamplingHor<<4)|SubsamplingVer) {
02417                         case 0x44:
02418                             img->put.contig = putcontig8bitYCbCr44tile;
02419                             break;
02420                         case 0x42:
02421                             img->put.contig = putcontig8bitYCbCr42tile;
02422                             break;
02423                         case 0x41:
02424                             img->put.contig = putcontig8bitYCbCr41tile;
02425                             break;
02426                         case 0x22:
02427                             img->put.contig = putcontig8bitYCbCr22tile;
02428                             break;
02429                         case 0x21:
02430                             img->put.contig = putcontig8bitYCbCr21tile;
02431                             break;
02432                         case 0x12:
02433                             img->put.contig = putcontig8bitYCbCr12tile;
02434                             break;
02435                         case 0x11:
02436                             img->put.contig = putcontig8bitYCbCr11tile;
02437                             break;
02438                     }
02439                 }
02440             }
02441             break;
02442         case PHOTOMETRIC_CIELAB:
02443             if (buildMap(img)) {
02444                 if (img->bitspersample == 8)
02445                     img->put.contig = initCIELabConversion(img);
02446                 break;
02447             }
02448     }
02449     return ((img->get!=NULL) && (img->put.contig!=NULL));
02450 }
02451 
02452 /*
02453  * Select the appropriate conversion routine for unpacked data.
02454  *
02455  * NB: we assume that unpacked single channel data is directed
02456  *   to the "packed routines.
02457  */
02458 static int
02459 PickSeparateCase(TIFFRGBAImage* img)
02460 {
02461     img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
02462     img->put.separate = NULL;
02463     switch (img->photometric) {
02464         case PHOTOMETRIC_RGB:
02465             switch (img->bitspersample) {
02466                 case 8:
02467                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
02468                         img->put.separate = putRGBAAseparate8bittile;
02469                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
02470                     {
02471                                             img->put.separate = putRGBUAseparate8bittile;
02472                     }
02473                     else
02474                         img->put.separate = putRGBseparate8bittile;
02475                     break;
02476                 case 16:
02477                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
02478                     {
02479                                             img->put.separate = putRGBAAseparate16bittile;
02480                     }
02481                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
02482                     {
02483                                             img->put.separate = putRGBUAseparate16bittile;
02484                     }
02485                     else
02486                     {
02487                                             img->put.separate = putRGBseparate16bittile;
02488                     }
02489                     break;
02490             }
02491             break;
02492         case PHOTOMETRIC_YCBCR:
02493             if ((img->bitspersample==8) && (img->samplesperpixel==3))
02494             {
02495                 if (initYCbCrConversion(img)!=0)
02496                 {
02497                     uint16 hs, vs;
02498                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
02499                     switch ((hs<<4)|vs) {
02500                         case 0x11:
02501                             img->put.separate = putseparate8bitYCbCr11tile;
02502                             break;
02503                         /* TODO: add other cases here */
02504                     }
02505                 }
02506             }
02507             break;
02508     }
02509     return ((img->get!=NULL) && (img->put.separate!=NULL));
02510 }
02511 
02512 /*
02513  * Read a whole strip off data from the file, and convert to RGBA form.
02514  * If this is the last strip, then it will only contain the portion of
02515  * the strip that is actually within the image space.  The result is
02516  * organized in bottom to top form.
02517  */
02518 
02519 
02520 int
02521 TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
02522 
02523 {
02524     char    emsg[1024] = "";
02525     TIFFRGBAImage img;
02526     int     ok;
02527     uint32  rowsperstrip, rows_to_read;
02528 
02529     if( TIFFIsTiled( tif ) )
02530     {
02531         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
02532                   "Can't use TIFFReadRGBAStrip() with tiled file.");
02533     return (0);
02534     }
02535     
02536     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
02537     if( (row % rowsperstrip) != 0 )
02538     {
02539         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
02540                 "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
02541         return (0);
02542     }
02543 
02544     if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
02545 
02546         img.row_offset = row;
02547         img.col_offset = 0;
02548 
02549         if( row + rowsperstrip > img.height )
02550             rows_to_read = img.height - row;
02551         else
02552             rows_to_read = rowsperstrip;
02553         
02554     ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read );
02555         
02556     TIFFRGBAImageEnd(&img);
02557     } else {
02558         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
02559         ok = 0;
02560     }
02561     
02562     return (ok);
02563 }
02564 
02565 /*
02566  * Read a whole tile off data from the file, and convert to RGBA form.
02567  * The returned RGBA data is organized from bottom to top of tile,
02568  * and may include zeroed areas if the tile extends off the image.
02569  */
02570 
02571 int
02572 TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
02573 
02574 {
02575     char    emsg[1024] = "";
02576     TIFFRGBAImage img;
02577     int     ok;
02578     uint32  tile_xsize, tile_ysize;
02579     uint32  read_xsize, read_ysize;
02580     uint32  i_row;
02581 
02582     /*
02583      * Verify that our request is legal - on a tile file, and on a
02584      * tile boundary.
02585      */
02586     
02587     if( !TIFFIsTiled( tif ) )
02588     {
02589         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
02590                   "Can't use TIFFReadRGBATile() with stripped file.");
02591         return (0);
02592     }
02593     
02594     TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
02595     TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
02596     if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
02597     {
02598         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
02599                   "Row/col passed to TIFFReadRGBATile() must be top"
02600                   "left corner of a tile.");
02601     return (0);
02602     }
02603 
02604     /*
02605      * Setup the RGBA reader.
02606      */
02607     
02608     if (!TIFFRGBAImageOK(tif, emsg) 
02609     || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
02610         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
02611         return( 0 );
02612     }
02613 
02614     /*
02615      * The TIFFRGBAImageGet() function doesn't allow us to get off the
02616      * edge of the image, even to fill an otherwise valid tile.  So we
02617      * figure out how much we can read, and fix up the tile buffer to
02618      * a full tile configuration afterwards.
02619      */
02620 
02621     if( row + tile_ysize > img.height )
02622         read_ysize = img.height - row;
02623     else
02624         read_ysize = tile_ysize;
02625     
02626     if( col + tile_xsize > img.width )
02627         read_xsize = img.width - col;
02628     else
02629         read_xsize = tile_xsize;
02630 
02631     /*
02632      * Read the chunk of imagery.
02633      */
02634     
02635     img.row_offset = row;
02636     img.col_offset = col;
02637 
02638     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize );
02639         
02640     TIFFRGBAImageEnd(&img);
02641 
02642     /*
02643      * If our read was incomplete we will need to fix up the tile by
02644      * shifting the data around as if a full tile of data is being returned.
02645      *
02646      * This is all the more complicated because the image is organized in
02647      * bottom to top format. 
02648      */
02649 
02650     if( read_xsize == tile_xsize && read_ysize == tile_ysize )
02651         return( ok );
02652 
02653     for( i_row = 0; i_row < read_ysize; i_row++ ) {
02654         memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
02655                  raster + (read_ysize - i_row - 1) * read_xsize,
02656                  read_xsize * sizeof(uint32) );
02657         _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
02658                      0, sizeof(uint32) * (tile_xsize - read_xsize) );
02659     }
02660 
02661     for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
02662         _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
02663                      0, sizeof(uint32) * tile_xsize );
02664     }
02665 
02666     return (ok);
02667 }
02668 
02669 /* vim: set ts=8 sts=8 sw=8 noet: */
02670 /*
02671  * Local Variables:
02672  * mode: c
02673  * c-basic-offset: 8
02674  * fill-column: 78
02675  * End:
02676  */

Generated on Sun May 27 2012 04:19:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.