LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_getimage.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 1013 1706 59.4 %
Date: 2024-11-21 22:18:42 Functions: 38 64 59.4 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1991-1997 Sam Leffler
       3             :  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
       4             :  *
       5             :  * Permission to use, copy, modify, distribute, and sell this software and
       6             :  * its documentation for any purpose is hereby granted without fee, provided
       7             :  * that (i) the above copyright notices and this permission notice appear in
       8             :  * all copies of the software and related documentation, and (ii) the names of
       9             :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      10             :  * publicity relating to the software without the specific, prior written
      11             :  * permission of Sam Leffler and Silicon Graphics.
      12             :  *
      13             :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
      14             :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
      15             :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
      16             :  *
      17             :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      18             :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      19             :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      20             :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
      21             :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      22             :  * OF THIS SOFTWARE.
      23             :  */
      24             : 
      25             : /*
      26             :  * TIFF Library
      27             :  *
      28             :  * Read and return a packed RGBA image.
      29             :  */
      30             : #include "tiffiop.h"
      31             : #include <limits.h>
      32             : #include <stdio.h>
      33             : 
      34             : static int gtTileContig(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
      35             : static int gtTileSeparate(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
      36             : static int gtStripContig(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
      37             : static int gtStripSeparate(TIFFRGBAImage *, uint32_t *, uint32_t, uint32_t);
      38             : static int PickContigCase(TIFFRGBAImage *);
      39             : static int PickSeparateCase(TIFFRGBAImage *);
      40             : 
      41             : static int BuildMapUaToAa(TIFFRGBAImage *img);
      42             : static int BuildMapBitdepth16To8(TIFFRGBAImage *img);
      43             : 
      44             : static const char photoTag[] = "PhotometricInterpretation";
      45             : 
      46             : /*
      47             :  * Helper constants used in Orientation tag handling
      48             :  */
      49             : #define FLIP_VERTICALLY 0x01
      50             : #define FLIP_HORIZONTALLY 0x02
      51             : 
      52             : #define EMSG_BUF_SIZE 1024
      53             : 
      54             : /*
      55             :  * Color conversion constants. We will define display types here.
      56             :  */
      57             : 
      58             : static const TIFFDisplay display_sRGB = {
      59             :     {/* XYZ -> luminance matrix */
      60             :      {3.2410F, -1.5374F, -0.4986F},
      61             :      {-0.9692F, 1.8760F, 0.0416F},
      62             :      {0.0556F, -0.2040F, 1.0570F}},
      63             :     100.0F,
      64             :     100.0F,
      65             :     100.0F, /* Light o/p for reference white */
      66             :     255,
      67             :     255,
      68             :     255, /* Pixel values for ref. white */
      69             :     1.0F,
      70             :     1.0F,
      71             :     1.0F, /* Residual light o/p for black pixel */
      72             :     2.4F,
      73             :     2.4F,
      74             :     2.4F, /* Gamma values for the three guns */
      75             : };
      76             : 
      77             : /*
      78             :  * Check the image to see if TIFFReadRGBAImage can deal with it.
      79             :  * 1/0 is returned according to whether or not the image can
      80             :  * be handled.  If 0 is returned, emsg contains the reason
      81             :  * why it is being rejected.
      82             :  */
      83         161 : int TIFFRGBAImageOK(TIFF *tif, char emsg[EMSG_BUF_SIZE])
      84             : {
      85         161 :     TIFFDirectory *td = &tif->tif_dir;
      86             :     uint16_t photometric;
      87             :     int colorchannels;
      88             : 
      89         161 :     if (!tif->tif_decodestatus)
      90             :     {
      91           0 :         snprintf(emsg, EMSG_BUF_SIZE,
      92             :                  "Sorry, requested compression method is not configured");
      93           0 :         return (0);
      94             :     }
      95         161 :     switch (td->td_bitspersample)
      96             :     {
      97         161 :         case 1:
      98             :         case 2:
      99             :         case 4:
     100             :         case 8:
     101             :         case 16:
     102         161 :             break;
     103           0 :         default:
     104           0 :             snprintf(emsg, EMSG_BUF_SIZE,
     105             :                      "Sorry, can not handle images with %" PRIu16
     106             :                      "-bit samples",
     107           0 :                      td->td_bitspersample);
     108           0 :             return (0);
     109             :     }
     110         161 :     if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP)
     111             :     {
     112           0 :         snprintf(
     113             :             emsg, EMSG_BUF_SIZE,
     114             :             "Sorry, can not handle images with IEEE floating-point samples");
     115           0 :         return (0);
     116             :     }
     117         161 :     colorchannels = td->td_samplesperpixel - td->td_extrasamples;
     118         161 :     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric))
     119             :     {
     120           0 :         switch (colorchannels)
     121             :         {
     122           0 :             case 1:
     123           0 :                 photometric = PHOTOMETRIC_MINISBLACK;
     124           0 :                 break;
     125           0 :             case 3:
     126           0 :                 photometric = PHOTOMETRIC_RGB;
     127           0 :                 break;
     128           0 :             default:
     129           0 :                 snprintf(emsg, EMSG_BUF_SIZE, "Missing needed %s tag",
     130             :                          photoTag);
     131           0 :                 return (0);
     132             :         }
     133         161 :     }
     134         161 :     switch (photometric)
     135             :     {
     136          26 :         case PHOTOMETRIC_MINISWHITE:
     137             :         case PHOTOMETRIC_MINISBLACK:
     138             :         case PHOTOMETRIC_PALETTE:
     139          26 :             if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
     140          20 :                 td->td_samplesperpixel != 1 && td->td_bitspersample < 8)
     141             :             {
     142           0 :                 snprintf(
     143             :                     emsg, EMSG_BUF_SIZE,
     144             :                     "Sorry, can not handle contiguous data with %s=%" PRIu16
     145             :                     ", "
     146             :                     "and %s=%" PRIu16 " and Bits/Sample=%" PRIu16 "",
     147             :                     photoTag, photometric, "Samples/pixel",
     148           0 :                     td->td_samplesperpixel, td->td_bitspersample);
     149           0 :                 return (0);
     150             :             }
     151             :             /*
     152             :              * We should likely validate that any extra samples are either
     153             :              * to be ignored, or are alpha, and if alpha we should try to use
     154             :              * them.  But for now we won't bother with this.
     155             :              */
     156          26 :             break;
     157          47 :         case PHOTOMETRIC_YCBCR:
     158             :             /*
     159             :              * TODO: if at all meaningful and useful, make more complete
     160             :              * support check here, or better still, refactor to let supporting
     161             :              * code decide whether there is support and what meaningful
     162             :              * error to return
     163             :              */
     164          47 :             break;
     165          60 :         case PHOTOMETRIC_RGB:
     166          60 :             if (colorchannels < 3)
     167             :             {
     168           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     169             :                          "Sorry, can not handle RGB image with %s=%d",
     170             :                          "Color channels", colorchannels);
     171           0 :                 return (0);
     172             :             }
     173          60 :             break;
     174          22 :         case PHOTOMETRIC_SEPARATED:
     175             :         {
     176             :             uint16_t inkset;
     177          22 :             TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
     178          22 :             if (inkset != INKSET_CMYK)
     179             :             {
     180           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     181             :                          "Sorry, can not handle separated image with %s=%d",
     182             :                          "InkSet", inkset);
     183           0 :                 return 0;
     184             :             }
     185          22 :             if (td->td_samplesperpixel < 4)
     186             :             {
     187           0 :                 snprintf(
     188             :                     emsg, EMSG_BUF_SIZE,
     189             :                     "Sorry, can not handle separated image with %s=%" PRIu16,
     190           0 :                     "Samples/pixel", td->td_samplesperpixel);
     191           0 :                 return 0;
     192             :             }
     193          22 :             break;
     194             :         }
     195           3 :         case PHOTOMETRIC_LOGL:
     196           3 :             if (td->td_compression != COMPRESSION_SGILOG)
     197             :             {
     198           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     199             :                          "Sorry, LogL data must have %s=%d", "Compression",
     200             :                          COMPRESSION_SGILOG);
     201           0 :                 return (0);
     202             :             }
     203           3 :             break;
     204           0 :         case PHOTOMETRIC_LOGLUV:
     205           0 :             if (td->td_compression != COMPRESSION_SGILOG &&
     206           0 :                 td->td_compression != COMPRESSION_SGILOG24)
     207             :             {
     208           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     209             :                          "Sorry, LogLuv data must have %s=%d or %d",
     210             :                          "Compression", COMPRESSION_SGILOG,
     211             :                          COMPRESSION_SGILOG24);
     212           0 :                 return (0);
     213             :             }
     214           0 :             if (td->td_planarconfig != PLANARCONFIG_CONTIG)
     215             :             {
     216           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     217             :                          "Sorry, can not handle LogLuv images with %s=%" PRIu16,
     218           0 :                          "Planarconfiguration", td->td_planarconfig);
     219           0 :                 return (0);
     220             :             }
     221           0 :             if (td->td_samplesperpixel != 3 || colorchannels != 3)
     222             :             {
     223           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     224             :                          "Sorry, can not handle image with %s=%" PRIu16
     225             :                          ", %s=%d",
     226           0 :                          "Samples/pixel", td->td_samplesperpixel,
     227             :                          "colorchannels", colorchannels);
     228           0 :                 return 0;
     229             :             }
     230           0 :             break;
     231           3 :         case PHOTOMETRIC_CIELAB:
     232           3 :             if (td->td_samplesperpixel != 3 || colorchannels != 3 ||
     233           3 :                 (td->td_bitspersample != 8 && td->td_bitspersample != 16))
     234             :             {
     235           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     236             :                          "Sorry, can not handle image with %s=%" PRIu16
     237             :                          ", %s=%d and %s=%" PRIu16,
     238           0 :                          "Samples/pixel", td->td_samplesperpixel,
     239             :                          "colorchannels", colorchannels, "Bits/sample",
     240           0 :                          td->td_bitspersample);
     241           0 :                 return 0;
     242             :             }
     243           3 :             break;
     244           0 :         default:
     245           0 :             snprintf(emsg, EMSG_BUF_SIZE,
     246             :                      "Sorry, can not handle image with %s=%" PRIu16, photoTag,
     247             :                      photometric);
     248           0 :             return (0);
     249             :     }
     250         161 :     return (1);
     251             : }
     252             : 
     253          63 : void TIFFRGBAImageEnd(TIFFRGBAImage *img)
     254             : {
     255          63 :     if (img->Map)
     256             :     {
     257           0 :         _TIFFfreeExt(img->tif, img->Map);
     258           0 :         img->Map = NULL;
     259             :     }
     260          63 :     if (img->BWmap)
     261             :     {
     262           9 :         _TIFFfreeExt(img->tif, img->BWmap);
     263           9 :         img->BWmap = NULL;
     264             :     }
     265          63 :     if (img->PALmap)
     266             :     {
     267           1 :         _TIFFfreeExt(img->tif, img->PALmap);
     268           1 :         img->PALmap = NULL;
     269             :     }
     270          63 :     if (img->ycbcr)
     271             :     {
     272          17 :         _TIFFfreeExt(img->tif, img->ycbcr);
     273          17 :         img->ycbcr = NULL;
     274             :     }
     275          63 :     if (img->cielab)
     276             :     {
     277           1 :         _TIFFfreeExt(img->tif, img->cielab);
     278           1 :         img->cielab = NULL;
     279             :     }
     280          63 :     if (img->UaToAa)
     281             :     {
     282          13 :         _TIFFfreeExt(img->tif, img->UaToAa);
     283          13 :         img->UaToAa = NULL;
     284             :     }
     285          63 :     if (img->Bitdepth16To8)
     286             :     {
     287           0 :         _TIFFfreeExt(img->tif, img->Bitdepth16To8);
     288           0 :         img->Bitdepth16To8 = NULL;
     289             :     }
     290             : 
     291          63 :     if (img->redcmap)
     292             :     {
     293           1 :         _TIFFfreeExt(img->tif, img->redcmap);
     294           1 :         _TIFFfreeExt(img->tif, img->greencmap);
     295           1 :         _TIFFfreeExt(img->tif, img->bluecmap);
     296           1 :         img->redcmap = img->greencmap = img->bluecmap = NULL;
     297             :     }
     298          63 : }
     299             : 
     300           0 : static int isCCITTCompression(TIFF *tif)
     301             : {
     302             :     uint16_t compress;
     303           0 :     TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
     304           0 :     return (compress == COMPRESSION_CCITTFAX3 ||
     305           0 :             compress == COMPRESSION_CCITTFAX4 ||
     306           0 :             compress == COMPRESSION_CCITTRLE ||
     307           0 :             compress == COMPRESSION_CCITTRLEW);
     308             : }
     309             : 
     310          63 : int TIFFRGBAImageBegin(TIFFRGBAImage *img, TIFF *tif, int stop,
     311             :                        char emsg[EMSG_BUF_SIZE])
     312             : {
     313             :     uint16_t *sampleinfo;
     314             :     uint16_t extrasamples;
     315             :     uint16_t planarconfig;
     316             :     uint16_t compress;
     317             :     int colorchannels;
     318             :     uint16_t *red_orig, *green_orig, *blue_orig;
     319             :     int n_color;
     320             : 
     321          63 :     if (!TIFFRGBAImageOK(tif, emsg))
     322           0 :         return 0;
     323             : 
     324             :     /* Initialize to normal values */
     325          63 :     img->row_offset = 0;
     326          63 :     img->col_offset = 0;
     327          63 :     img->redcmap = NULL;
     328          63 :     img->greencmap = NULL;
     329          63 :     img->bluecmap = NULL;
     330          63 :     img->Map = NULL;
     331          63 :     img->BWmap = NULL;
     332          63 :     img->PALmap = NULL;
     333          63 :     img->ycbcr = NULL;
     334          63 :     img->cielab = NULL;
     335          63 :     img->UaToAa = NULL;
     336          63 :     img->Bitdepth16To8 = NULL;
     337          63 :     img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */
     338             : 
     339          63 :     img->tif = tif;
     340          63 :     img->stoponerr = stop;
     341          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
     342          63 :     switch (img->bitspersample)
     343             :     {
     344          63 :         case 1:
     345             :         case 2:
     346             :         case 4:
     347             :         case 8:
     348             :         case 16:
     349          63 :             break;
     350           0 :         default:
     351           0 :             snprintf(emsg, EMSG_BUF_SIZE,
     352             :                      "Sorry, can not handle images with %" PRIu16
     353             :                      "-bit samples",
     354           0 :                      img->bitspersample);
     355           0 :             goto fail_return;
     356             :     }
     357          63 :     img->alpha = 0;
     358          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
     359          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples,
     360             :                           &sampleinfo);
     361          63 :     if (extrasamples >= 1)
     362             :     {
     363          33 :         switch (sampleinfo[0])
     364             :         {
     365          14 :             case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without
     366             :                                            */
     367          14 :                 if (img->samplesperpixel >
     368             :                     3) /* correct info about alpha channel */
     369          13 :                     img->alpha = EXTRASAMPLE_ASSOCALPHA;
     370          14 :                 break;
     371          19 :             case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
     372             :             case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
     373          19 :                 img->alpha = sampleinfo[0];
     374          19 :                 break;
     375             :         }
     376          30 :     }
     377             : 
     378             : #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
     379          63 :     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
     380           0 :         img->photometric = PHOTOMETRIC_MINISWHITE;
     381             : 
     382          63 :     if (extrasamples == 0 && img->samplesperpixel == 4 &&
     383           6 :         img->photometric == PHOTOMETRIC_RGB)
     384             :     {
     385           0 :         img->alpha = EXTRASAMPLE_ASSOCALPHA;
     386           0 :         extrasamples = 1;
     387             :     }
     388             : #endif
     389             : 
     390          63 :     colorchannels = img->samplesperpixel - extrasamples;
     391          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
     392          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
     393          63 :     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
     394             :     {
     395           0 :         switch (colorchannels)
     396             :         {
     397           0 :             case 1:
     398           0 :                 if (isCCITTCompression(tif))
     399           0 :                     img->photometric = PHOTOMETRIC_MINISWHITE;
     400             :                 else
     401           0 :                     img->photometric = PHOTOMETRIC_MINISBLACK;
     402           0 :                 break;
     403           0 :             case 3:
     404           0 :                 img->photometric = PHOTOMETRIC_RGB;
     405           0 :                 break;
     406           0 :             default:
     407           0 :                 snprintf(emsg, EMSG_BUF_SIZE, "Missing needed %s tag",
     408             :                          photoTag);
     409           0 :                 goto fail_return;
     410             :         }
     411          63 :     }
     412          63 :     switch (img->photometric)
     413             :     {
     414           1 :         case PHOTOMETRIC_PALETTE:
     415           1 :             if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &red_orig, &green_orig,
     416             :                               &blue_orig))
     417             :             {
     418           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     419             :                          "Missing required \"Colormap\" tag");
     420           0 :                 goto fail_return;
     421             :             }
     422             : 
     423             :             /* copy the colormaps so we can modify them */
     424           1 :             n_color = (1U << img->bitspersample);
     425           1 :             img->redcmap =
     426           1 :                 (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
     427           1 :             img->greencmap =
     428           1 :                 (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
     429           1 :             img->bluecmap =
     430           1 :                 (uint16_t *)_TIFFmallocExt(tif, sizeof(uint16_t) * n_color);
     431           1 :             if (!img->redcmap || !img->greencmap || !img->bluecmap)
     432             :             {
     433           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     434             :                          "Out of memory for colormap copy");
     435           0 :                 goto fail_return;
     436             :             }
     437             : 
     438           1 :             _TIFFmemcpy(img->redcmap, red_orig, n_color * 2);
     439           1 :             _TIFFmemcpy(img->greencmap, green_orig, n_color * 2);
     440           1 :             _TIFFmemcpy(img->bluecmap, blue_orig, n_color * 2);
     441             : 
     442             :             /* fall through... */
     443          10 :         case PHOTOMETRIC_MINISWHITE:
     444             :         case PHOTOMETRIC_MINISBLACK:
     445          10 :             if (planarconfig == PLANARCONFIG_CONTIG &&
     446           8 :                 img->samplesperpixel != 1 && img->bitspersample < 8)
     447             :             {
     448           0 :                 snprintf(
     449             :                     emsg, EMSG_BUF_SIZE,
     450             :                     "Sorry, can not handle contiguous data with %s=%" PRIu16
     451             :                     ", "
     452             :                     "and %s=%" PRIu16 " and Bits/Sample=%" PRIu16,
     453           0 :                     photoTag, img->photometric, "Samples/pixel",
     454           0 :                     img->samplesperpixel, img->bitspersample);
     455           0 :                 goto fail_return;
     456             :             }
     457          10 :             break;
     458          17 :         case PHOTOMETRIC_YCBCR:
     459             :             /* It would probably be nice to have a reality check here. */
     460          17 :             if (planarconfig == PLANARCONFIG_CONTIG)
     461             :                 /* can rely on libjpeg to convert to RGB */
     462             :                 /* XXX should restore current state on exit */
     463          17 :                 switch (compress)
     464             :                 {
     465           0 :                     case COMPRESSION_JPEG:
     466             :                         /*
     467             :                          * TODO: when complete tests verify complete
     468             :                          * desubsampling and YCbCr handling, remove use of
     469             :                          * TIFFTAG_JPEGCOLORMODE in favor of tif_getimage.c
     470             :                          * native handling
     471             :                          */
     472           0 :                         TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE,
     473             :                                      JPEGCOLORMODE_RGB);
     474           0 :                         img->photometric = PHOTOMETRIC_RGB;
     475           0 :                         break;
     476          17 :                     default:
     477             :                         /* do nothing */;
     478          17 :                         break;
     479             :                 }
     480             :             /*
     481             :              * TODO: if at all meaningful and useful, make more complete
     482             :              * support check here, or better still, refactor to let supporting
     483             :              * code decide whether there is support and what meaningful
     484             :              * error to return
     485             :              */
     486          17 :             break;
     487          28 :         case PHOTOMETRIC_RGB:
     488          28 :             if (colorchannels < 3)
     489             :             {
     490           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     491             :                          "Sorry, can not handle RGB image with %s=%d",
     492             :                          "Color channels", colorchannels);
     493           0 :                 goto fail_return;
     494             :             }
     495          28 :             break;
     496           6 :         case PHOTOMETRIC_SEPARATED:
     497             :         {
     498             :             uint16_t inkset;
     499           6 :             TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
     500           6 :             if (inkset != INKSET_CMYK)
     501             :             {
     502           0 :                 snprintf(
     503             :                     emsg, EMSG_BUF_SIZE,
     504             :                     "Sorry, can not handle separated image with %s=%" PRIu16,
     505             :                     "InkSet", inkset);
     506           0 :                 goto fail_return;
     507             :             }
     508           6 :             if (img->samplesperpixel < 4)
     509             :             {
     510           0 :                 snprintf(
     511             :                     emsg, EMSG_BUF_SIZE,
     512             :                     "Sorry, can not handle separated image with %s=%" PRIu16,
     513           0 :                     "Samples/pixel", img->samplesperpixel);
     514           0 :                 goto fail_return;
     515             :             }
     516             :         }
     517           6 :         break;
     518           1 :         case PHOTOMETRIC_LOGL:
     519           1 :             if (compress != COMPRESSION_SGILOG)
     520             :             {
     521           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     522             :                          "Sorry, LogL data must have %s=%d", "Compression",
     523             :                          COMPRESSION_SGILOG);
     524           0 :                 goto fail_return;
     525             :             }
     526           1 :             TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
     527           1 :             img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */
     528           1 :             img->bitspersample = 8;
     529           1 :             break;
     530           0 :         case PHOTOMETRIC_LOGLUV:
     531           0 :             if (compress != COMPRESSION_SGILOG &&
     532           0 :                 compress != COMPRESSION_SGILOG24)
     533             :             {
     534           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     535             :                          "Sorry, LogLuv data must have %s=%d or %d",
     536             :                          "Compression", COMPRESSION_SGILOG,
     537             :                          COMPRESSION_SGILOG24);
     538           0 :                 goto fail_return;
     539             :             }
     540           0 :             if (planarconfig != PLANARCONFIG_CONTIG)
     541             :             {
     542           0 :                 snprintf(emsg, EMSG_BUF_SIZE,
     543             :                          "Sorry, can not handle LogLuv images with %s=%" PRIu16,
     544             :                          "Planarconfiguration", planarconfig);
     545           0 :                 return (0);
     546             :             }
     547           0 :             TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
     548           0 :             img->photometric = PHOTOMETRIC_RGB; /* little white lie */
     549           0 :             img->bitspersample = 8;
     550           0 :             break;
     551           1 :         case PHOTOMETRIC_CIELAB:
     552           1 :             break;
     553           0 :         default:
     554           0 :             snprintf(emsg, EMSG_BUF_SIZE,
     555             :                      "Sorry, can not handle image with %s=%" PRIu16, photoTag,
     556           0 :                      img->photometric);
     557           0 :             goto fail_return;
     558             :     }
     559          63 :     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
     560          63 :     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
     561          63 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
     562          63 :     img->isContig =
     563          63 :         !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1);
     564          63 :     if (img->isContig)
     565             :     {
     566          60 :         if (!PickContigCase(img))
     567             :         {
     568           6 :             snprintf(emsg, EMSG_BUF_SIZE, "Sorry, can not handle image");
     569           6 :             goto fail_return;
     570             :         }
     571             :     }
     572             :     else
     573             :     {
     574           3 :         if (!PickSeparateCase(img))
     575             :         {
     576           0 :             snprintf(emsg, EMSG_BUF_SIZE, "Sorry, can not handle image");
     577           0 :             goto fail_return;
     578             :         }
     579             :     }
     580          57 :     return 1;
     581             : 
     582           6 : fail_return:
     583           6 :     TIFFRGBAImageEnd(img);
     584           6 :     return 0;
     585             : }
     586             : 
     587          57 : int TIFFRGBAImageGet(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
     588             :                      uint32_t h)
     589             : {
     590          57 :     if (img->get == NULL)
     591             :     {
     592           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
     593             :                       "No \"get\" routine setup");
     594           0 :         return (0);
     595             :     }
     596          57 :     if (img->put.any == NULL)
     597             :     {
     598           0 :         TIFFErrorExtR(
     599             :             img->tif, TIFFFileName(img->tif),
     600             :             "No \"put\" routine setupl; probably can not handle image format");
     601           0 :         return (0);
     602             :     }
     603          57 :     return (*img->get)(img, raster, w, h);
     604             : }
     605             : 
     606             : /*
     607             :  * Read the specified image into an ABGR-format rastertaking in account
     608             :  * specified orientation.
     609             :  */
     610           0 : int TIFFReadRGBAImageOriented(TIFF *tif, uint32_t rwidth, uint32_t rheight,
     611             :                               uint32_t *raster, int orientation, int stop)
     612             : {
     613           0 :     char emsg[EMSG_BUF_SIZE] = "";
     614             :     TIFFRGBAImage img;
     615             :     int ok;
     616             : 
     617           0 :     if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg))
     618             :     {
     619           0 :         img.req_orientation = (uint16_t)orientation;
     620             :         /* XXX verify rwidth and rheight against width and height */
     621           0 :         ok = TIFFRGBAImageGet(&img, raster + (rheight - img.height) * rwidth,
     622             :                               rwidth, img.height);
     623           0 :         TIFFRGBAImageEnd(&img);
     624             :     }
     625             :     else
     626             :     {
     627           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
     628           0 :         ok = 0;
     629             :     }
     630           0 :     return (ok);
     631             : }
     632             : 
     633             : /*
     634             :  * Read the specified image into an ABGR-format raster. Use bottom left
     635             :  * origin for raster by default.
     636             :  */
     637           0 : int TIFFReadRGBAImage(TIFF *tif, uint32_t rwidth, uint32_t rheight,
     638             :                       uint32_t *raster, int stop)
     639             : {
     640           0 :     return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
     641             :                                      ORIENTATION_BOTLEFT, stop);
     642             : }
     643             : 
     644          57 : static int setorientation(TIFFRGBAImage *img)
     645             : {
     646          57 :     switch (img->orientation)
     647             :     {
     648          57 :         case ORIENTATION_TOPLEFT:
     649             :         case ORIENTATION_LEFTTOP:
     650          57 :             if (img->req_orientation == ORIENTATION_TOPRIGHT ||
     651          57 :                 img->req_orientation == ORIENTATION_RIGHTTOP)
     652           0 :                 return FLIP_HORIZONTALLY;
     653          57 :             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
     654          57 :                      img->req_orientation == ORIENTATION_RIGHTBOT)
     655           0 :                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
     656          57 :             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
     657           0 :                      img->req_orientation == ORIENTATION_LEFTBOT)
     658          57 :                 return FLIP_VERTICALLY;
     659             :             else
     660           0 :                 return 0;
     661           0 :         case ORIENTATION_TOPRIGHT:
     662             :         case ORIENTATION_RIGHTTOP:
     663           0 :             if (img->req_orientation == ORIENTATION_TOPLEFT ||
     664           0 :                 img->req_orientation == ORIENTATION_LEFTTOP)
     665           0 :                 return FLIP_HORIZONTALLY;
     666           0 :             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
     667           0 :                      img->req_orientation == ORIENTATION_RIGHTBOT)
     668           0 :                 return FLIP_VERTICALLY;
     669           0 :             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
     670           0 :                      img->req_orientation == ORIENTATION_LEFTBOT)
     671           0 :                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
     672             :             else
     673           0 :                 return 0;
     674           0 :         case ORIENTATION_BOTRIGHT:
     675             :         case ORIENTATION_RIGHTBOT:
     676           0 :             if (img->req_orientation == ORIENTATION_TOPLEFT ||
     677           0 :                 img->req_orientation == ORIENTATION_LEFTTOP)
     678           0 :                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
     679           0 :             else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
     680           0 :                      img->req_orientation == ORIENTATION_RIGHTTOP)
     681           0 :                 return FLIP_VERTICALLY;
     682           0 :             else if (img->req_orientation == ORIENTATION_BOTLEFT ||
     683           0 :                      img->req_orientation == ORIENTATION_LEFTBOT)
     684           0 :                 return FLIP_HORIZONTALLY;
     685             :             else
     686           0 :                 return 0;
     687           0 :         case ORIENTATION_BOTLEFT:
     688             :         case ORIENTATION_LEFTBOT:
     689           0 :             if (img->req_orientation == ORIENTATION_TOPLEFT ||
     690           0 :                 img->req_orientation == ORIENTATION_LEFTTOP)
     691           0 :                 return FLIP_VERTICALLY;
     692           0 :             else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
     693           0 :                      img->req_orientation == ORIENTATION_RIGHTTOP)
     694           0 :                 return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
     695           0 :             else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
     696           0 :                      img->req_orientation == ORIENTATION_RIGHTBOT)
     697           0 :                 return FLIP_HORIZONTALLY;
     698             :             else
     699           0 :                 return 0;
     700           0 :         default: /* NOTREACHED */
     701           0 :             return 0;
     702             :     }
     703             : }
     704             : 
     705             : /*
     706             :  * Get an tile-organized image that has
     707             :  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
     708             :  * or
     709             :  *  SamplesPerPixel == 1
     710             :  */
     711           3 : static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
     712             :                         uint32_t h)
     713             : {
     714           3 :     TIFF *tif = img->tif;
     715           3 :     tileContigRoutine put = img->put.contig;
     716             :     uint32_t col, row, y, rowstoread;
     717             :     tmsize_t pos;
     718             :     uint32_t tw, th;
     719           3 :     unsigned char *buf = NULL;
     720             :     int32_t fromskew, toskew;
     721             :     uint32_t nrow;
     722           3 :     int ret = 1, flip;
     723             :     uint32_t this_tw, tocol;
     724             :     int32_t this_toskew, leftmost_toskew;
     725             :     int32_t leftmost_fromskew;
     726             :     uint32_t leftmost_tw;
     727             :     tmsize_t bufsize;
     728             : 
     729           3 :     bufsize = TIFFTileSize(tif);
     730           3 :     if (bufsize == 0)
     731             :     {
     732           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", "No space for tile buffer");
     733           0 :         return (0);
     734             :     }
     735             : 
     736           3 :     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
     737           3 :     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
     738             : 
     739           3 :     flip = setorientation(img);
     740           3 :     if (flip & FLIP_VERTICALLY)
     741             :     {
     742           3 :         if ((tw + w) > INT_MAX)
     743             :         {
     744           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     745             :                           "unsupported tile size (too wide)");
     746           0 :             return (0);
     747             :         }
     748           3 :         y = h - 1;
     749           3 :         toskew = -(int32_t)(tw + w);
     750             :     }
     751             :     else
     752             :     {
     753           0 :         if (tw > (INT_MAX + w))
     754             :         {
     755           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     756             :                           "unsupported tile size (too wide)");
     757           0 :             return (0);
     758             :         }
     759           0 :         y = 0;
     760           0 :         toskew = -(int32_t)(tw - w);
     761             :     }
     762             : 
     763           3 :     if (tw == 0 || th == 0)
     764             :     {
     765           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
     766           0 :         return (0);
     767             :     }
     768             : 
     769             :     /*
     770             :      *  Leftmost tile is clipped on left side if col_offset > 0.
     771             :      */
     772           3 :     leftmost_fromskew = img->col_offset % tw;
     773           3 :     leftmost_tw = tw - leftmost_fromskew;
     774           3 :     leftmost_toskew = toskew + leftmost_fromskew;
     775           6 :     for (row = 0; ret != 0 && row < h; row += nrow)
     776             :     {
     777           3 :         rowstoread = th - (row + img->row_offset) % th;
     778           3 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
     779           3 :         fromskew = leftmost_fromskew;
     780           3 :         this_tw = leftmost_tw;
     781           3 :         this_toskew = leftmost_toskew;
     782           3 :         tocol = 0;
     783           3 :         col = img->col_offset;
     784           5 :         while (tocol < w)
     785             :         {
     786           3 :             if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize, col,
     787           3 :                                             row + img->row_offset, 0,
     788           1 :                                             0) == (tmsize_t)(-1) &&
     789           1 :                 (buf == NULL || img->stoponerr))
     790             :             {
     791           1 :                 ret = 0;
     792           1 :                 break;
     793             :             }
     794           2 :             pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
     795           2 :                   ((tmsize_t)fromskew * img->samplesperpixel);
     796           2 :             if (tocol + this_tw > w)
     797             :             {
     798             :                 /*
     799             :                  * Rightmost tile is clipped on right side.
     800             :                  */
     801           2 :                 fromskew = tw - (w - tocol);
     802           2 :                 this_tw = tw - fromskew;
     803           2 :                 this_toskew = toskew + fromskew;
     804             :             }
     805           2 :             tmsize_t roffset = (tmsize_t)y * w + tocol;
     806           2 :             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
     807             :                    this_toskew, buf + pos);
     808           2 :             tocol += this_tw;
     809           2 :             col += this_tw;
     810             :             /*
     811             :              * After the leftmost tile, tiles are no longer clipped on left
     812             :              * side.
     813             :              */
     814           2 :             fromskew = 0;
     815           2 :             this_tw = tw;
     816           2 :             this_toskew = toskew;
     817             :         }
     818             : 
     819           3 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
     820             :     }
     821           3 :     _TIFFfreeExt(img->tif, buf);
     822             : 
     823           3 :     if (flip & FLIP_HORIZONTALLY)
     824             :     {
     825             :         uint32_t line;
     826             : 
     827           0 :         for (line = 0; line < h; line++)
     828             :         {
     829           0 :             uint32_t *left = raster + (line * w);
     830           0 :             uint32_t *right = left + w - 1;
     831             : 
     832           0 :             while (left < right)
     833             :             {
     834           0 :                 uint32_t temp = *left;
     835           0 :                 *left = *right;
     836           0 :                 *right = temp;
     837           0 :                 left++;
     838           0 :                 right--;
     839             :             }
     840             :         }
     841             :     }
     842             : 
     843           3 :     return (ret);
     844             : }
     845             : 
     846             : /*
     847             :  * Get an tile-organized image that has
     848             :  *   SamplesPerPixel > 1
     849             :  *   PlanarConfiguration separated
     850             :  * We assume that all such images are RGB.
     851             :  */
     852           1 : static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
     853             :                           uint32_t h)
     854             : {
     855           1 :     TIFF *tif = img->tif;
     856           1 :     tileSeparateRoutine put = img->put.separate;
     857             :     uint32_t col, row, y, rowstoread;
     858             :     tmsize_t pos;
     859             :     uint32_t tw, th;
     860           1 :     unsigned char *buf = NULL;
     861           1 :     unsigned char *p0 = NULL;
     862           1 :     unsigned char *p1 = NULL;
     863           1 :     unsigned char *p2 = NULL;
     864           1 :     unsigned char *pa = NULL;
     865             :     tmsize_t tilesize;
     866             :     tmsize_t bufsize;
     867             :     int32_t fromskew, toskew;
     868           1 :     int alpha = img->alpha;
     869             :     uint32_t nrow;
     870           1 :     int ret = 1, flip;
     871             :     uint16_t colorchannels;
     872             :     uint32_t this_tw, tocol;
     873             :     int32_t this_toskew, leftmost_toskew;
     874             :     int32_t leftmost_fromskew;
     875             :     uint32_t leftmost_tw;
     876             : 
     877           1 :     tilesize = TIFFTileSize(tif);
     878             :     bufsize =
     879           1 :         _TIFFMultiplySSize(tif, alpha ? 4 : 3, tilesize, "gtTileSeparate");
     880           1 :     if (bufsize == 0)
     881             :     {
     882           0 :         return (0);
     883             :     }
     884             : 
     885           1 :     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
     886           1 :     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
     887             : 
     888           1 :     flip = setorientation(img);
     889           1 :     if (flip & FLIP_VERTICALLY)
     890             :     {
     891           1 :         if ((tw + w) > INT_MAX)
     892             :         {
     893           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     894             :                           "unsupported tile size (too wide)");
     895           0 :             return (0);
     896             :         }
     897           1 :         y = h - 1;
     898           1 :         toskew = -(int32_t)(tw + w);
     899             :     }
     900             :     else
     901             :     {
     902           0 :         if (tw > (INT_MAX + w))
     903             :         {
     904           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     905             :                           "unsupported tile size (too wide)");
     906           0 :             return (0);
     907             :         }
     908           0 :         y = 0;
     909           0 :         toskew = -(int32_t)(tw - w);
     910             :     }
     911             : 
     912           1 :     switch (img->photometric)
     913             :     {
     914           0 :         case PHOTOMETRIC_MINISWHITE:
     915             :         case PHOTOMETRIC_MINISBLACK:
     916             :         case PHOTOMETRIC_PALETTE:
     917           0 :             colorchannels = 1;
     918           0 :             break;
     919             : 
     920           1 :         default:
     921           1 :             colorchannels = 3;
     922           1 :             break;
     923             :     }
     924             : 
     925           1 :     if (tw == 0 || th == 0)
     926             :     {
     927           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
     928           0 :         return (0);
     929             :     }
     930             : 
     931             :     /*
     932             :      *  Leftmost tile is clipped on left side if col_offset > 0.
     933             :      */
     934           1 :     leftmost_fromskew = img->col_offset % tw;
     935           1 :     leftmost_tw = tw - leftmost_fromskew;
     936           1 :     leftmost_toskew = toskew + leftmost_fromskew;
     937           2 :     for (row = 0; ret != 0 && row < h; row += nrow)
     938             :     {
     939           1 :         rowstoread = th - (row + img->row_offset) % th;
     940           1 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
     941           1 :         fromskew = leftmost_fromskew;
     942           1 :         this_tw = leftmost_tw;
     943           1 :         this_toskew = leftmost_toskew;
     944           1 :         tocol = 0;
     945           1 :         col = img->col_offset;
     946           2 :         while (tocol < w)
     947             :         {
     948           1 :             if (buf == NULL)
     949             :             {
     950           1 :                 if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize,
     951           1 :                                                 col, row + img->row_offset, 0,
     952           0 :                                                 0) == (tmsize_t)(-1) &&
     953           0 :                     (buf == NULL || img->stoponerr))
     954             :                 {
     955           0 :                     ret = 0;
     956           0 :                     break;
     957             :                 }
     958           1 :                 p0 = buf;
     959           1 :                 if (colorchannels == 1)
     960             :                 {
     961           0 :                     p2 = p1 = p0;
     962           0 :                     pa = (alpha ? (p0 + 3 * tilesize) : NULL);
     963             :                 }
     964             :                 else
     965             :                 {
     966           1 :                     p1 = p0 + tilesize;
     967           1 :                     p2 = p1 + tilesize;
     968           1 :                     pa = (alpha ? (p2 + tilesize) : NULL);
     969             :                 }
     970             :             }
     971           0 :             else if (TIFFReadTile(tif, p0, col, row + img->row_offset, 0, 0) ==
     972           0 :                          (tmsize_t)(-1) &&
     973           0 :                      img->stoponerr)
     974             :             {
     975           0 :                 ret = 0;
     976           0 :                 break;
     977             :             }
     978           2 :             if (colorchannels > 1 &&
     979           1 :                 TIFFReadTile(tif, p1, col, row + img->row_offset, 0, 1) ==
     980           0 :                     (tmsize_t)(-1) &&
     981           0 :                 img->stoponerr)
     982             :             {
     983           0 :                 ret = 0;
     984           0 :                 break;
     985             :             }
     986           2 :             if (colorchannels > 1 &&
     987           1 :                 TIFFReadTile(tif, p2, col, row + img->row_offset, 0, 2) ==
     988           0 :                     (tmsize_t)(-1) &&
     989           0 :                 img->stoponerr)
     990             :             {
     991           0 :                 ret = 0;
     992           0 :                 break;
     993             :             }
     994           1 :             if (alpha &&
     995           0 :                 TIFFReadTile(tif, pa, col, row + img->row_offset, 0,
     996           0 :                              colorchannels) == (tmsize_t)(-1) &&
     997           0 :                 img->stoponerr)
     998             :             {
     999           0 :                 ret = 0;
    1000           0 :                 break;
    1001             :             }
    1002             : 
    1003           1 :             pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
    1004           1 :                   ((tmsize_t)fromskew * img->samplesperpixel);
    1005           1 :             if (tocol + this_tw > w)
    1006             :             {
    1007             :                 /*
    1008             :                  * Rightmost tile is clipped on right side.
    1009             :                  */
    1010           1 :                 fromskew = tw - (w - tocol);
    1011           1 :                 this_tw = tw - fromskew;
    1012           1 :                 this_toskew = toskew + fromskew;
    1013             :             }
    1014           1 :             tmsize_t roffset = (tmsize_t)y * w + tocol;
    1015           1 :             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
    1016             :                    this_toskew, p0 + pos, p1 + pos, p2 + pos,
    1017           0 :                    (alpha ? (pa + pos) : NULL));
    1018           1 :             tocol += this_tw;
    1019           1 :             col += this_tw;
    1020             :             /*
    1021             :              * After the leftmost tile, tiles are no longer clipped on left
    1022             :              * side.
    1023             :              */
    1024           1 :             fromskew = 0;
    1025           1 :             this_tw = tw;
    1026           1 :             this_toskew = toskew;
    1027             :         }
    1028             : 
    1029           1 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1030             :     }
    1031             : 
    1032           1 :     if (flip & FLIP_HORIZONTALLY)
    1033             :     {
    1034             :         uint32_t line;
    1035             : 
    1036           0 :         for (line = 0; line < h; line++)
    1037             :         {
    1038           0 :             uint32_t *left = raster + (line * w);
    1039           0 :             uint32_t *right = left + w - 1;
    1040             : 
    1041           0 :             while (left < right)
    1042             :             {
    1043           0 :                 uint32_t temp = *left;
    1044           0 :                 *left = *right;
    1045           0 :                 *right = temp;
    1046           0 :                 left++;
    1047           0 :                 right--;
    1048             :             }
    1049             :         }
    1050             :     }
    1051             : 
    1052           1 :     _TIFFfreeExt(img->tif, buf);
    1053           1 :     return (ret);
    1054             : }
    1055             : 
    1056             : /*
    1057             :  * Get a strip-organized image that has
    1058             :  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
    1059             :  * or
    1060             :  *  SamplesPerPixel == 1
    1061             :  */
    1062          51 : static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
    1063             :                          uint32_t h)
    1064             : {
    1065          51 :     TIFF *tif = img->tif;
    1066          51 :     tileContigRoutine put = img->put.contig;
    1067             :     uint32_t row, y, nrow, nrowsub, rowstoread;
    1068             :     tmsize_t pos;
    1069          51 :     unsigned char *buf = NULL;
    1070             :     uint32_t rowsperstrip;
    1071             :     uint16_t subsamplinghor, subsamplingver;
    1072          51 :     uint32_t imagewidth = img->width;
    1073             :     tmsize_t scanline;
    1074             :     int32_t fromskew, toskew;
    1075          51 :     int ret = 1, flip;
    1076             :     tmsize_t maxstripsize;
    1077             : 
    1078          51 :     TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor,
    1079             :                           &subsamplingver);
    1080          51 :     if (subsamplingver == 0)
    1081             :     {
    1082           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    1083             :                       "Invalid vertical YCbCr subsampling");
    1084           0 :         return (0);
    1085             :     }
    1086             : 
    1087          51 :     maxstripsize = TIFFStripSize(tif);
    1088             : 
    1089          51 :     flip = setorientation(img);
    1090          51 :     if (flip & FLIP_VERTICALLY)
    1091             :     {
    1092          51 :         if (w > INT_MAX)
    1093             :         {
    1094           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
    1095           0 :             return (0);
    1096             :         }
    1097          51 :         y = h - 1;
    1098          51 :         toskew = -(int32_t)(w + w);
    1099             :     }
    1100             :     else
    1101             :     {
    1102           0 :         y = 0;
    1103           0 :         toskew = -(int32_t)(w - w);
    1104             :     }
    1105             : 
    1106          51 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    1107          51 :     if (rowsperstrip == 0)
    1108             :     {
    1109           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    1110           0 :         return (0);
    1111             :     }
    1112             : 
    1113          51 :     scanline = TIFFScanlineSize(tif);
    1114          51 :     fromskew = (w < imagewidth ? imagewidth - w : 0);
    1115         102 :     for (row = 0; row < h; row += nrow)
    1116             :     {
    1117             :         uint32_t temp;
    1118          51 :         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
    1119          51 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
    1120          51 :         nrowsub = nrow;
    1121          51 :         if ((nrowsub % subsamplingver) != 0)
    1122          11 :             nrowsub += subsamplingver - nrowsub % subsamplingver;
    1123          51 :         temp = (row + img->row_offset) % rowsperstrip + nrowsub;
    1124          51 :         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
    1125             :         {
    1126           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    1127             :                           "Integer overflow in gtStripContig");
    1128           0 :             return 0;
    1129             :         }
    1130          51 :         if (_TIFFReadEncodedStripAndAllocBuffer(
    1131          51 :                 tif, TIFFComputeStrip(tif, row + img->row_offset, 0),
    1132             :                 (void **)(&buf), maxstripsize,
    1133           0 :                 temp * scanline) == (tmsize_t)(-1) &&
    1134           0 :             (buf == NULL || img->stoponerr))
    1135             :         {
    1136           0 :             ret = 0;
    1137           0 :             break;
    1138             :         }
    1139             : 
    1140          51 :         pos = ((row + img->row_offset) % rowsperstrip) * scanline +
    1141          51 :               ((tmsize_t)img->col_offset * img->samplesperpixel);
    1142          51 :         tmsize_t roffset = (tmsize_t)y * w;
    1143          51 :         (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew,
    1144             :                buf + pos);
    1145          51 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1146             :     }
    1147             : 
    1148          51 :     if (flip & FLIP_HORIZONTALLY)
    1149             :     {
    1150             :         uint32_t line;
    1151             : 
    1152           0 :         for (line = 0; line < h; line++)
    1153             :         {
    1154           0 :             uint32_t *left = raster + (line * w);
    1155           0 :             uint32_t *right = left + w - 1;
    1156             : 
    1157           0 :             while (left < right)
    1158             :             {
    1159           0 :                 uint32_t temp = *left;
    1160           0 :                 *left = *right;
    1161           0 :                 *right = temp;
    1162           0 :                 left++;
    1163           0 :                 right--;
    1164             :             }
    1165             :         }
    1166             :     }
    1167             : 
    1168          51 :     _TIFFfreeExt(img->tif, buf);
    1169          51 :     return (ret);
    1170             : }
    1171             : 
    1172             : /*
    1173             :  * Get a strip-organized image with
    1174             :  *   SamplesPerPixel > 1
    1175             :  *   PlanarConfiguration separated
    1176             :  * We assume that all such images are RGB.
    1177             :  */
    1178           2 : static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
    1179             :                            uint32_t h)
    1180             : {
    1181           2 :     TIFF *tif = img->tif;
    1182           2 :     tileSeparateRoutine put = img->put.separate;
    1183           2 :     unsigned char *buf = NULL;
    1184           2 :     unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL;
    1185             :     uint32_t row, y, nrow, rowstoread;
    1186             :     tmsize_t pos;
    1187             :     tmsize_t scanline;
    1188             :     uint32_t rowsperstrip, offset_row;
    1189           2 :     uint32_t imagewidth = img->width;
    1190             :     tmsize_t stripsize;
    1191             :     tmsize_t bufsize;
    1192             :     int32_t fromskew, toskew;
    1193           2 :     int alpha = img->alpha;
    1194           2 :     int ret = 1, flip;
    1195             :     uint16_t colorchannels;
    1196             : 
    1197           2 :     stripsize = TIFFStripSize(tif);
    1198             :     bufsize =
    1199           2 :         _TIFFMultiplySSize(tif, alpha ? 4 : 3, stripsize, "gtStripSeparate");
    1200           2 :     if (bufsize == 0)
    1201             :     {
    1202           0 :         return (0);
    1203             :     }
    1204             : 
    1205           2 :     flip = setorientation(img);
    1206           2 :     if (flip & FLIP_VERTICALLY)
    1207             :     {
    1208           2 :         if (w > INT_MAX)
    1209             :         {
    1210           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
    1211           0 :             return (0);
    1212             :         }
    1213           2 :         y = h - 1;
    1214           2 :         toskew = -(int32_t)(w + w);
    1215             :     }
    1216             :     else
    1217             :     {
    1218           0 :         y = 0;
    1219           0 :         toskew = -(int32_t)(w - w);
    1220             :     }
    1221             : 
    1222           2 :     switch (img->photometric)
    1223             :     {
    1224           1 :         case PHOTOMETRIC_MINISWHITE:
    1225             :         case PHOTOMETRIC_MINISBLACK:
    1226             :         case PHOTOMETRIC_PALETTE:
    1227           1 :             colorchannels = 1;
    1228           1 :             break;
    1229             : 
    1230           1 :         default:
    1231           1 :             colorchannels = 3;
    1232           1 :             break;
    1233             :     }
    1234             : 
    1235           2 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    1236           2 :     if (rowsperstrip == 0)
    1237             :     {
    1238           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    1239           0 :         return (0);
    1240             :     }
    1241             : 
    1242           2 :     scanline = TIFFScanlineSize(tif);
    1243           2 :     fromskew = (w < imagewidth ? imagewidth - w : 0);
    1244           4 :     for (row = 0; row < h; row += nrow)
    1245             :     {
    1246             :         uint32_t temp;
    1247           2 :         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
    1248           2 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
    1249           2 :         offset_row = row + img->row_offset;
    1250           2 :         temp = (row + img->row_offset) % rowsperstrip + nrow;
    1251           2 :         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
    1252             :         {
    1253           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    1254             :                           "Integer overflow in gtStripSeparate");
    1255           0 :             return 0;
    1256             :         }
    1257           2 :         if (buf == NULL)
    1258             :         {
    1259           2 :             if (_TIFFReadEncodedStripAndAllocBuffer(
    1260             :                     tif, TIFFComputeStrip(tif, offset_row, 0), (void **)&buf,
    1261           0 :                     bufsize, temp * scanline) == (tmsize_t)(-1) &&
    1262           0 :                 (buf == NULL || img->stoponerr))
    1263             :             {
    1264           0 :                 ret = 0;
    1265           0 :                 break;
    1266             :             }
    1267           2 :             p0 = buf;
    1268           2 :             if (colorchannels == 1)
    1269             :             {
    1270           1 :                 p2 = p1 = p0;
    1271           1 :                 pa = (alpha ? (p0 + 3 * stripsize) : NULL);
    1272             :             }
    1273             :             else
    1274             :             {
    1275           1 :                 p1 = p0 + stripsize;
    1276           1 :                 p2 = p1 + stripsize;
    1277           1 :                 pa = (alpha ? (p2 + stripsize) : NULL);
    1278             :             }
    1279             :         }
    1280           0 :         else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
    1281           0 :                                       p0, temp * scanline) == (tmsize_t)(-1) &&
    1282           0 :                  img->stoponerr)
    1283             :         {
    1284           0 :             ret = 0;
    1285           0 :             break;
    1286             :         }
    1287           3 :         if (colorchannels > 1 &&
    1288           1 :             TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), p1,
    1289           0 :                                  temp * scanline) == (tmsize_t)(-1) &&
    1290           0 :             img->stoponerr)
    1291             :         {
    1292           0 :             ret = 0;
    1293           0 :             break;
    1294             :         }
    1295           3 :         if (colorchannels > 1 &&
    1296           1 :             TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), p2,
    1297           0 :                                  temp * scanline) == (tmsize_t)(-1) &&
    1298           0 :             img->stoponerr)
    1299             :         {
    1300           0 :             ret = 0;
    1301           0 :             break;
    1302             :         }
    1303           2 :         if (alpha)
    1304             :         {
    1305           0 :             if (TIFFReadEncodedStrip(
    1306             :                     tif, TIFFComputeStrip(tif, offset_row, colorchannels), pa,
    1307           0 :                     temp * scanline) == (tmsize_t)(-1) &&
    1308           0 :                 img->stoponerr)
    1309             :             {
    1310           0 :                 ret = 0;
    1311           0 :                 break;
    1312             :             }
    1313             :         }
    1314             : 
    1315           2 :         pos = ((row + img->row_offset) % rowsperstrip) * scanline +
    1316           2 :               ((tmsize_t)img->col_offset * img->samplesperpixel);
    1317           2 :         tmsize_t roffset = (tmsize_t)y * w;
    1318           2 :         (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew, p0 + pos,
    1319           0 :                p1 + pos, p2 + pos, (alpha ? (pa + pos) : NULL));
    1320           2 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1321             :     }
    1322             : 
    1323           2 :     if (flip & FLIP_HORIZONTALLY)
    1324             :     {
    1325             :         uint32_t line;
    1326             : 
    1327           0 :         for (line = 0; line < h; line++)
    1328             :         {
    1329           0 :             uint32_t *left = raster + (line * w);
    1330           0 :             uint32_t *right = left + w - 1;
    1331             : 
    1332           0 :             while (left < right)
    1333             :             {
    1334           0 :                 uint32_t temp = *left;
    1335           0 :                 *left = *right;
    1336           0 :                 *right = temp;
    1337           0 :                 left++;
    1338           0 :                 right--;
    1339             :             }
    1340             :         }
    1341             :     }
    1342             : 
    1343           2 :     _TIFFfreeExt(img->tif, buf);
    1344           2 :     return (ret);
    1345             : }
    1346             : 
    1347             : /*
    1348             :  * The following routines move decoded data returned
    1349             :  * from the TIFF library into rasters filled with packed
    1350             :  * ABGR pixels (i.e. suitable for passing to lrecwrite.)
    1351             :  *
    1352             :  * The routines have been created according to the most
    1353             :  * important cases and optimized.  PickContigCase and
    1354             :  * PickSeparateCase analyze the parameters and select
    1355             :  * the appropriate "get" and "put" routine to use.
    1356             :  */
    1357             : #define REPEAT8(op)                                                            \
    1358             :     REPEAT4(op);                                                               \
    1359             :     REPEAT4(op)
    1360             : #define REPEAT4(op)                                                            \
    1361             :     REPEAT2(op);                                                               \
    1362             :     REPEAT2(op)
    1363             : #define REPEAT2(op)                                                            \
    1364             :     op;                                                                        \
    1365             :     op
    1366             : #define CASE8(x, op)                                                           \
    1367             :     switch (x)                                                                 \
    1368             :     {                                                                          \
    1369             :         case 7:                                                                \
    1370             :             op; /*-fallthrough*/                                               \
    1371             :         case 6:                                                                \
    1372             :             op; /*-fallthrough*/                                               \
    1373             :         case 5:                                                                \
    1374             :             op; /*-fallthrough*/                                               \
    1375             :         case 4:                                                                \
    1376             :             op; /*-fallthrough*/                                               \
    1377             :         case 3:                                                                \
    1378             :             op; /*-fallthrough*/                                               \
    1379             :         case 2:                                                                \
    1380             :             op; /*-fallthrough*/                                               \
    1381             :         case 1:                                                                \
    1382             :             op;                                                                \
    1383             :     }
    1384             : #define CASE4(x, op)                                                           \
    1385             :     switch (x)                                                                 \
    1386             :     {                                                                          \
    1387             :         case 3:                                                                \
    1388             :             op; /*-fallthrough*/                                               \
    1389             :         case 2:                                                                \
    1390             :             op; /*-fallthrough*/                                               \
    1391             :         case 1:                                                                \
    1392             :             op;                                                                \
    1393             :     }
    1394             : #define NOP
    1395             : 
    1396             : #define UNROLL8(w, op1, op2)                                                   \
    1397             :     {                                                                          \
    1398             :         uint32_t _x;                                                           \
    1399             :         for (_x = w; _x >= 8; _x -= 8)                                         \
    1400             :         {                                                                      \
    1401             :             op1;                                                               \
    1402             :             REPEAT8(op2);                                                      \
    1403             :         }                                                                      \
    1404             :         if (_x > 0)                                                            \
    1405             :         {                                                                      \
    1406             :             op1;                                                               \
    1407             :             CASE8(_x, op2);                                                    \
    1408             :         }                                                                      \
    1409             :     }
    1410             : #define UNROLL4(w, op1, op2)                                                   \
    1411             :     {                                                                          \
    1412             :         uint32_t _x;                                                           \
    1413             :         for (_x = w; _x >= 4; _x -= 4)                                         \
    1414             :         {                                                                      \
    1415             :             op1;                                                               \
    1416             :             REPEAT4(op2);                                                      \
    1417             :         }                                                                      \
    1418             :         if (_x > 0)                                                            \
    1419             :         {                                                                      \
    1420             :             op1;                                                               \
    1421             :             CASE4(_x, op2);                                                    \
    1422             :         }                                                                      \
    1423             :     }
    1424             : #define UNROLL2(w, op1, op2)                                                   \
    1425             :     {                                                                          \
    1426             :         uint32_t _x;                                                           \
    1427             :         for (_x = w; _x >= 2; _x -= 2)                                         \
    1428             :         {                                                                      \
    1429             :             op1;                                                               \
    1430             :             REPEAT2(op2);                                                      \
    1431             :         }                                                                      \
    1432             :         if (_x)                                                                \
    1433             :         {                                                                      \
    1434             :             op1;                                                               \
    1435             :             op2;                                                               \
    1436             :         }                                                                      \
    1437             :     }
    1438             : 
    1439             : #define SKEW(r, g, b, skew)                                                    \
    1440             :     {                                                                          \
    1441             :         r += skew;                                                             \
    1442             :         g += skew;                                                             \
    1443             :         b += skew;                                                             \
    1444             :     }
    1445             : #define SKEW4(r, g, b, a, skew)                                                \
    1446             :     {                                                                          \
    1447             :         r += skew;                                                             \
    1448             :         g += skew;                                                             \
    1449             :         b += skew;                                                             \
    1450             :         a += skew;                                                             \
    1451             :     }
    1452             : 
    1453             : #define A1 (((uint32_t)0xffL) << 24)
    1454             : #define PACK(r, g, b)                                                          \
    1455             :     ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) | A1)
    1456             : #define PACK4(r, g, b, a)                                                      \
    1457             :     ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) |            \
    1458             :      ((uint32_t)(a) << 24))
    1459             : #define W2B(v) (((v) >> 8) & 0xff)
    1460             : /* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */
    1461             : #define PACKW(r, g, b)                                                         \
    1462             :     ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) | A1)
    1463             : #define PACKW4(r, g, b, a)                                                     \
    1464             :     ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) |   \
    1465             :      ((uint32_t)W2B(a) << 24))
    1466             : 
    1467             : #define DECLAREContigPutFunc(name)                                             \
    1468             :     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
    1469             :                      uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
    1470             :                      unsigned char *pp)
    1471             : 
    1472             : /*
    1473             :  * 8-bit palette => colormap/RGB
    1474             :  */
    1475           1 : DECLAREContigPutFunc(put8bitcmaptile)
    1476             : {
    1477           1 :     uint32_t **PALmap = img->PALmap;
    1478           1 :     int samplesperpixel = img->samplesperpixel;
    1479             : 
    1480             :     (void)y;
    1481          21 :     for (; h > 0; --h)
    1482             :     {
    1483         420 :         for (x = w; x > 0; --x)
    1484             :         {
    1485         400 :             *cp++ = PALmap[*pp][0];
    1486         400 :             pp += samplesperpixel;
    1487             :         }
    1488          20 :         cp += toskew;
    1489          20 :         pp += fromskew;
    1490             :     }
    1491           1 : }
    1492             : 
    1493             : /*
    1494             :  * 4-bit palette => colormap/RGB
    1495             :  */
    1496           0 : DECLAREContigPutFunc(put4bitcmaptile)
    1497             : {
    1498           0 :     uint32_t **PALmap = img->PALmap;
    1499             : 
    1500             :     (void)x;
    1501             :     (void)y;
    1502           0 :     fromskew /= 2;
    1503           0 :     for (; h > 0; --h)
    1504             :     {
    1505             :         uint32_t *bw;
    1506           0 :         UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1507           0 :         cp += toskew;
    1508           0 :         pp += fromskew;
    1509             :     }
    1510           0 : }
    1511             : 
    1512             : /*
    1513             :  * 2-bit palette => colormap/RGB
    1514             :  */
    1515           0 : DECLAREContigPutFunc(put2bitcmaptile)
    1516             : {
    1517           0 :     uint32_t **PALmap = img->PALmap;
    1518             : 
    1519             :     (void)x;
    1520             :     (void)y;
    1521           0 :     fromskew /= 4;
    1522           0 :     for (; h > 0; --h)
    1523             :     {
    1524             :         uint32_t *bw;
    1525           0 :         UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1526           0 :         cp += toskew;
    1527           0 :         pp += fromskew;
    1528             :     }
    1529           0 : }
    1530             : 
    1531             : /*
    1532             :  * 1-bit palette => colormap/RGB
    1533             :  */
    1534           0 : DECLAREContigPutFunc(put1bitcmaptile)
    1535             : {
    1536           0 :     uint32_t **PALmap = img->PALmap;
    1537             : 
    1538             :     (void)x;
    1539             :     (void)y;
    1540           0 :     fromskew /= 8;
    1541           0 :     for (; h > 0; --h)
    1542             :     {
    1543             :         uint32_t *bw;
    1544           0 :         UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1545           0 :         cp += toskew;
    1546           0 :         pp += fromskew;
    1547             :     }
    1548           0 : }
    1549             : 
    1550             : /*
    1551             :  * 8-bit greyscale => colormap/RGB
    1552             :  */
    1553           3 : DECLAREContigPutFunc(putgreytile)
    1554             : {
    1555           3 :     int samplesperpixel = img->samplesperpixel;
    1556           3 :     uint32_t **BWmap = img->BWmap;
    1557             : 
    1558             :     (void)y;
    1559          63 :     for (; h > 0; --h)
    1560             :     {
    1561        1260 :         for (x = w; x > 0; --x)
    1562             :         {
    1563        1200 :             *cp++ = BWmap[*pp][0];
    1564        1200 :             pp += samplesperpixel;
    1565             :         }
    1566          60 :         cp += toskew;
    1567          60 :         pp += fromskew;
    1568             :     }
    1569           3 : }
    1570             : 
    1571             : /*
    1572             :  * 8-bit greyscale with associated alpha => colormap/RGBA
    1573             :  */
    1574           6 : DECLAREContigPutFunc(putagreytile)
    1575             : {
    1576           6 :     int samplesperpixel = img->samplesperpixel;
    1577           6 :     uint32_t **BWmap = img->BWmap;
    1578             : 
    1579             :     (void)y;
    1580         156 :     for (; h > 0; --h)
    1581             :     {
    1582       24450 :         for (x = w; x > 0; --x)
    1583             :         {
    1584       24300 :             *cp++ = BWmap[*pp][0] & ((uint32_t) * (pp + 1) << 24 | ~A1);
    1585       24300 :             pp += samplesperpixel;
    1586             :         }
    1587         150 :         cp += toskew;
    1588         150 :         pp += fromskew;
    1589             :     }
    1590           6 : }
    1591             : 
    1592             : /*
    1593             :  * 16-bit greyscale => colormap/RGB
    1594             :  */
    1595           0 : DECLAREContigPutFunc(put16bitbwtile)
    1596             : {
    1597           0 :     int samplesperpixel = img->samplesperpixel;
    1598           0 :     uint32_t **BWmap = img->BWmap;
    1599             : 
    1600             :     (void)y;
    1601           0 :     for (; h > 0; --h)
    1602             :     {
    1603           0 :         uint16_t *wp = (uint16_t *)pp;
    1604             : 
    1605           0 :         for (x = w; x > 0; --x)
    1606             :         {
    1607             :             /* use high order byte of 16bit value */
    1608             : 
    1609           0 :             *cp++ = BWmap[*wp >> 8][0];
    1610           0 :             pp += 2 * samplesperpixel;
    1611           0 :             wp += samplesperpixel;
    1612             :         }
    1613           0 :         cp += toskew;
    1614           0 :         pp += fromskew;
    1615             :     }
    1616           0 : }
    1617             : 
    1618             : /*
    1619             :  * 1-bit bilevel => colormap/RGB
    1620             :  */
    1621           0 : DECLAREContigPutFunc(put1bitbwtile)
    1622             : {
    1623           0 :     uint32_t **BWmap = img->BWmap;
    1624             : 
    1625             :     (void)x;
    1626             :     (void)y;
    1627           0 :     fromskew /= 8;
    1628           0 :     for (; h > 0; --h)
    1629             :     {
    1630             :         uint32_t *bw;
    1631           0 :         UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1632           0 :         cp += toskew;
    1633           0 :         pp += fromskew;
    1634             :     }
    1635           0 : }
    1636             : 
    1637             : /*
    1638             :  * 2-bit greyscale => colormap/RGB
    1639             :  */
    1640           0 : DECLAREContigPutFunc(put2bitbwtile)
    1641             : {
    1642           0 :     uint32_t **BWmap = img->BWmap;
    1643             : 
    1644             :     (void)x;
    1645             :     (void)y;
    1646           0 :     fromskew /= 4;
    1647           0 :     for (; h > 0; --h)
    1648             :     {
    1649             :         uint32_t *bw;
    1650           0 :         UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1651           0 :         cp += toskew;
    1652           0 :         pp += fromskew;
    1653             :     }
    1654           0 : }
    1655             : 
    1656             : /*
    1657             :  * 4-bit greyscale => colormap/RGB
    1658             :  */
    1659           0 : DECLAREContigPutFunc(put4bitbwtile)
    1660             : {
    1661           0 :     uint32_t **BWmap = img->BWmap;
    1662             : 
    1663             :     (void)x;
    1664             :     (void)y;
    1665           0 :     fromskew /= 2;
    1666           0 :     for (; h > 0; --h)
    1667             :     {
    1668             :         uint32_t *bw;
    1669           0 :         UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1670           0 :         cp += toskew;
    1671           0 :         pp += fromskew;
    1672             :     }
    1673           0 : }
    1674             : 
    1675             : /*
    1676             :  * 8-bit packed samples, no Map => RGB
    1677             :  */
    1678           0 : DECLAREContigPutFunc(putRGBcontig8bittile)
    1679             : {
    1680           0 :     int samplesperpixel = img->samplesperpixel;
    1681             : 
    1682             :     (void)x;
    1683             :     (void)y;
    1684           0 :     fromskew *= samplesperpixel;
    1685           0 :     for (; h > 0; --h)
    1686             :     {
    1687           0 :         UNROLL8(w, NOP, *cp++ = PACK(pp[0], pp[1], pp[2]);
    1688             :                 pp += samplesperpixel);
    1689           0 :         cp += toskew;
    1690           0 :         pp += fromskew;
    1691             :     }
    1692           0 : }
    1693             : 
    1694             : /*
    1695             :  * 8-bit packed samples => RGBA w/ associated alpha
    1696             :  * (known to have Map == NULL)
    1697             :  */
    1698          13 : DECLAREContigPutFunc(putRGBAAcontig8bittile)
    1699             : {
    1700          13 :     int samplesperpixel = img->samplesperpixel;
    1701             : 
    1702             :     (void)x;
    1703             :     (void)y;
    1704          13 :     fromskew *= samplesperpixel;
    1705         163 :     for (; h > 0; --h)
    1706             :     {
    1707        3150 :         UNROLL8(w, NOP, *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
    1708             :                 pp += samplesperpixel);
    1709         150 :         cp += toskew;
    1710         150 :         pp += fromskew;
    1711             :     }
    1712          13 : }
    1713             : 
    1714             : /*
    1715             :  * 8-bit packed samples => RGBA w/ unassociated alpha
    1716             :  * (known to have Map == NULL)
    1717             :  */
    1718          13 : DECLAREContigPutFunc(putRGBUAcontig8bittile)
    1719             : {
    1720          13 :     int samplesperpixel = img->samplesperpixel;
    1721             :     (void)y;
    1722          13 :     fromskew *= samplesperpixel;
    1723         163 :     for (; h > 0; --h)
    1724             :     {
    1725             :         uint32_t r, g, b, a;
    1726             :         uint8_t *m;
    1727       24450 :         for (x = w; x > 0; --x)
    1728             :         {
    1729       24300 :             a = pp[3];
    1730       24300 :             m = img->UaToAa + ((size_t)a << 8);
    1731       24300 :             r = m[pp[0]];
    1732       24300 :             g = m[pp[1]];
    1733       24300 :             b = m[pp[2]];
    1734       24300 :             *cp++ = PACK4(r, g, b, a);
    1735       24300 :             pp += samplesperpixel;
    1736             :         }
    1737         150 :         cp += toskew;
    1738         150 :         pp += fromskew;
    1739             :     }
    1740          13 : }
    1741             : 
    1742             : /*
    1743             :  * 16-bit packed samples => RGB
    1744             :  */
    1745           0 : DECLAREContigPutFunc(putRGBcontig16bittile)
    1746             : {
    1747           0 :     int samplesperpixel = img->samplesperpixel;
    1748           0 :     uint16_t *wp = (uint16_t *)pp;
    1749             :     (void)y;
    1750           0 :     fromskew *= samplesperpixel;
    1751           0 :     for (; h > 0; --h)
    1752             :     {
    1753           0 :         for (x = w; x > 0; --x)
    1754             :         {
    1755           0 :             *cp++ = PACK(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1756             :                          img->Bitdepth16To8[wp[2]]);
    1757           0 :             wp += samplesperpixel;
    1758             :         }
    1759           0 :         cp += toskew;
    1760           0 :         wp += fromskew;
    1761             :     }
    1762           0 : }
    1763             : 
    1764             : /*
    1765             :  * 16-bit packed samples => RGBA w/ associated alpha
    1766             :  * (known to have Map == NULL)
    1767             :  */
    1768           0 : DECLAREContigPutFunc(putRGBAAcontig16bittile)
    1769             : {
    1770           0 :     int samplesperpixel = img->samplesperpixel;
    1771           0 :     uint16_t *wp = (uint16_t *)pp;
    1772             :     (void)y;
    1773           0 :     fromskew *= samplesperpixel;
    1774           0 :     for (; h > 0; --h)
    1775             :     {
    1776           0 :         for (x = w; x > 0; --x)
    1777             :         {
    1778           0 :             *cp++ = PACK4(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1779             :                           img->Bitdepth16To8[wp[2]], img->Bitdepth16To8[wp[3]]);
    1780           0 :             wp += samplesperpixel;
    1781             :         }
    1782           0 :         cp += toskew;
    1783           0 :         wp += fromskew;
    1784             :     }
    1785           0 : }
    1786             : 
    1787             : /*
    1788             :  * 16-bit packed samples => RGBA w/ unassociated alpha
    1789             :  * (known to have Map == NULL)
    1790             :  */
    1791           0 : DECLAREContigPutFunc(putRGBUAcontig16bittile)
    1792             : {
    1793           0 :     int samplesperpixel = img->samplesperpixel;
    1794           0 :     uint16_t *wp = (uint16_t *)pp;
    1795             :     (void)y;
    1796           0 :     fromskew *= samplesperpixel;
    1797           0 :     for (; h > 0; --h)
    1798             :     {
    1799             :         uint32_t r, g, b, a;
    1800             :         uint8_t *m;
    1801           0 :         for (x = w; x > 0; --x)
    1802             :         {
    1803           0 :             a = img->Bitdepth16To8[wp[3]];
    1804           0 :             m = img->UaToAa + ((size_t)a << 8);
    1805           0 :             r = m[img->Bitdepth16To8[wp[0]]];
    1806           0 :             g = m[img->Bitdepth16To8[wp[1]]];
    1807           0 :             b = m[img->Bitdepth16To8[wp[2]]];
    1808           0 :             *cp++ = PACK4(r, g, b, a);
    1809           0 :             wp += samplesperpixel;
    1810             :         }
    1811           0 :         cp += toskew;
    1812           0 :         wp += fromskew;
    1813             :     }
    1814           0 : }
    1815             : 
    1816             : /*
    1817             :  * 8-bit packed CMYK samples w/o Map => RGB
    1818             :  *
    1819             :  * NB: The conversion of CMYK->RGB is *very* crude.
    1820             :  */
    1821           6 : DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
    1822             : {
    1823           6 :     int samplesperpixel = img->samplesperpixel;
    1824             :     uint16_t r, g, b, k;
    1825             : 
    1826             :     (void)x;
    1827             :     (void)y;
    1828           6 :     fromskew *= samplesperpixel;
    1829         156 :     for (; h > 0; --h)
    1830             :     {
    1831        1050 :         UNROLL8(w, NOP, k = 255 - pp[3]; r = (k * (255 - pp[0])) / 255;
    1832             :                 g = (k * (255 - pp[1])) / 255; b = (k * (255 - pp[2])) / 255;
    1833             :                 *cp++ = PACK(r, g, b); pp += samplesperpixel);
    1834         150 :         cp += toskew;
    1835         150 :         pp += fromskew;
    1836             :     }
    1837           6 : }
    1838             : 
    1839             : /*
    1840             :  * 8-bit packed CMYK samples w/Map => RGB
    1841             :  *
    1842             :  * NB: The conversion of CMYK->RGB is *very* crude.
    1843             :  */
    1844           0 : DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
    1845             : {
    1846           0 :     int samplesperpixel = img->samplesperpixel;
    1847           0 :     TIFFRGBValue *Map = img->Map;
    1848             :     uint16_t r, g, b, k;
    1849             : 
    1850             :     (void)y;
    1851           0 :     fromskew *= samplesperpixel;
    1852           0 :     for (; h > 0; --h)
    1853             :     {
    1854           0 :         for (x = w; x > 0; --x)
    1855             :         {
    1856           0 :             k = 255 - pp[3];
    1857           0 :             r = (k * (255 - pp[0])) / 255;
    1858           0 :             g = (k * (255 - pp[1])) / 255;
    1859           0 :             b = (k * (255 - pp[2])) / 255;
    1860           0 :             *cp++ = PACK(Map[r], Map[g], Map[b]);
    1861           0 :             pp += samplesperpixel;
    1862             :         }
    1863           0 :         pp += fromskew;
    1864           0 :         cp += toskew;
    1865             :     }
    1866           0 : }
    1867             : 
    1868             : #define DECLARESepPutFunc(name)                                                \
    1869             :     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
    1870             :                      uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
    1871             :                      unsigned char *r, unsigned char *g, unsigned char *b,     \
    1872             :                      unsigned char *a)
    1873             : 
    1874             : /*
    1875             :  * 8-bit unpacked samples => RGB
    1876             :  */
    1877           3 : DECLARESepPutFunc(putRGBseparate8bittile)
    1878             : {
    1879             :     (void)img;
    1880             :     (void)x;
    1881             :     (void)y;
    1882             :     (void)a;
    1883         153 :     for (; h > 0; --h)
    1884             :     {
    1885        1050 :         UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
    1886         150 :         SKEW(r, g, b, fromskew);
    1887         150 :         cp += toskew;
    1888             :     }
    1889           3 : }
    1890             : 
    1891             : /*
    1892             :  * 8-bit unpacked samples => RGBA w/ associated alpha
    1893             :  */
    1894           0 : DECLARESepPutFunc(putRGBAAseparate8bittile)
    1895             : {
    1896             :     (void)img;
    1897             :     (void)x;
    1898             :     (void)y;
    1899           0 :     for (; h > 0; --h)
    1900             :     {
    1901           0 :         UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
    1902           0 :         SKEW4(r, g, b, a, fromskew);
    1903           0 :         cp += toskew;
    1904             :     }
    1905           0 : }
    1906             : 
    1907             : /*
    1908             :  * 8-bit unpacked CMYK samples => RGBA
    1909             :  */
    1910           0 : DECLARESepPutFunc(putCMYKseparate8bittile)
    1911             : {
    1912             :     (void)img;
    1913             :     (void)y;
    1914           0 :     for (; h > 0; --h)
    1915             :     {
    1916             :         uint32_t rv, gv, bv, kv;
    1917           0 :         for (x = w; x > 0; --x)
    1918             :         {
    1919           0 :             kv = 255 - *a++;
    1920           0 :             rv = (kv * (255 - *r++)) / 255;
    1921           0 :             gv = (kv * (255 - *g++)) / 255;
    1922           0 :             bv = (kv * (255 - *b++)) / 255;
    1923           0 :             *cp++ = PACK4(rv, gv, bv, 255);
    1924             :         }
    1925           0 :         SKEW4(r, g, b, a, fromskew);
    1926           0 :         cp += toskew;
    1927             :     }
    1928           0 : }
    1929             : 
    1930             : /*
    1931             :  * 8-bit unpacked samples => RGBA w/ unassociated alpha
    1932             :  */
    1933           0 : DECLARESepPutFunc(putRGBUAseparate8bittile)
    1934             : {
    1935             :     (void)img;
    1936             :     (void)y;
    1937           0 :     for (; h > 0; --h)
    1938             :     {
    1939             :         uint32_t rv, gv, bv, av;
    1940             :         uint8_t *m;
    1941           0 :         for (x = w; x > 0; --x)
    1942             :         {
    1943           0 :             av = *a++;
    1944           0 :             m = img->UaToAa + ((size_t)av << 8);
    1945           0 :             rv = m[*r++];
    1946           0 :             gv = m[*g++];
    1947           0 :             bv = m[*b++];
    1948           0 :             *cp++ = PACK4(rv, gv, bv, av);
    1949             :         }
    1950           0 :         SKEW4(r, g, b, a, fromskew);
    1951           0 :         cp += toskew;
    1952             :     }
    1953           0 : }
    1954             : 
    1955             : /*
    1956             :  * 16-bit unpacked samples => RGB
    1957             :  */
    1958           0 : DECLARESepPutFunc(putRGBseparate16bittile)
    1959             : {
    1960           0 :     uint16_t *wr = (uint16_t *)r;
    1961           0 :     uint16_t *wg = (uint16_t *)g;
    1962           0 :     uint16_t *wb = (uint16_t *)b;
    1963             :     (void)img;
    1964             :     (void)y;
    1965             :     (void)a;
    1966           0 :     for (; h > 0; --h)
    1967             :     {
    1968           0 :         for (x = 0; x < w; x++)
    1969           0 :             *cp++ = PACK(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    1970             :                          img->Bitdepth16To8[*wb++]);
    1971           0 :         SKEW(wr, wg, wb, fromskew);
    1972           0 :         cp += toskew;
    1973             :     }
    1974           0 : }
    1975             : 
    1976             : /*
    1977             :  * 16-bit unpacked samples => RGBA w/ associated alpha
    1978             :  */
    1979           0 : DECLARESepPutFunc(putRGBAAseparate16bittile)
    1980             : {
    1981           0 :     uint16_t *wr = (uint16_t *)r;
    1982           0 :     uint16_t *wg = (uint16_t *)g;
    1983           0 :     uint16_t *wb = (uint16_t *)b;
    1984           0 :     uint16_t *wa = (uint16_t *)a;
    1985             :     (void)img;
    1986             :     (void)y;
    1987           0 :     for (; h > 0; --h)
    1988             :     {
    1989           0 :         for (x = 0; x < w; x++)
    1990           0 :             *cp++ = PACK4(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    1991             :                           img->Bitdepth16To8[*wb++], img->Bitdepth16To8[*wa++]);
    1992           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    1993           0 :         cp += toskew;
    1994             :     }
    1995           0 : }
    1996             : 
    1997             : /*
    1998             :  * 16-bit unpacked samples => RGBA w/ unassociated alpha
    1999             :  */
    2000           0 : DECLARESepPutFunc(putRGBUAseparate16bittile)
    2001             : {
    2002           0 :     uint16_t *wr = (uint16_t *)r;
    2003           0 :     uint16_t *wg = (uint16_t *)g;
    2004           0 :     uint16_t *wb = (uint16_t *)b;
    2005           0 :     uint16_t *wa = (uint16_t *)a;
    2006             :     (void)img;
    2007             :     (void)y;
    2008           0 :     for (; h > 0; --h)
    2009             :     {
    2010             :         uint32_t r2, g2, b2, a2;
    2011             :         uint8_t *m;
    2012           0 :         for (x = w; x > 0; --x)
    2013             :         {
    2014           0 :             a2 = img->Bitdepth16To8[*wa++];
    2015           0 :             m = img->UaToAa + ((size_t)a2 << 8);
    2016           0 :             r2 = m[img->Bitdepth16To8[*wr++]];
    2017           0 :             g2 = m[img->Bitdepth16To8[*wg++]];
    2018           0 :             b2 = m[img->Bitdepth16To8[*wb++]];
    2019           0 :             *cp++ = PACK4(r2, g2, b2, a2);
    2020             :         }
    2021           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    2022           0 :         cp += toskew;
    2023             :     }
    2024           0 : }
    2025             : 
    2026             : /*
    2027             :  * 8-bit packed CIE L*a*b 1976 samples => RGB
    2028             :  */
    2029           1 : DECLAREContigPutFunc(putcontig8bitCIELab8)
    2030             : {
    2031             :     float X, Y, Z;
    2032             :     uint32_t r, g, b;
    2033             :     (void)y;
    2034           1 :     fromskew *= 3;
    2035           2 :     for (; h > 0; --h)
    2036             :     {
    2037           2 :         for (x = w; x > 0; --x)
    2038             :         {
    2039           1 :             TIFFCIELabToXYZ(img->cielab, (unsigned char)pp[0],
    2040           1 :                             (signed char)pp[1], (signed char)pp[2], &X, &Y, &Z);
    2041           1 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2042           1 :             *cp++ = PACK(r, g, b);
    2043           1 :             pp += 3;
    2044             :         }
    2045           1 :         cp += toskew;
    2046           1 :         pp += fromskew;
    2047             :     }
    2048           1 : }
    2049             : 
    2050             : /*
    2051             :  * 16-bit packed CIE L*a*b 1976 samples => RGB
    2052             :  */
    2053           0 : DECLAREContigPutFunc(putcontig8bitCIELab16)
    2054             : {
    2055             :     float X, Y, Z;
    2056             :     uint32_t r, g, b;
    2057           0 :     uint16_t *wp = (uint16_t *)pp;
    2058             :     (void)y;
    2059           0 :     fromskew *= 3;
    2060           0 :     for (; h > 0; --h)
    2061             :     {
    2062           0 :         for (x = w; x > 0; --x)
    2063             :         {
    2064           0 :             TIFFCIELab16ToXYZ(img->cielab, (uint16_t)wp[0], (int16_t)wp[1],
    2065           0 :                               (int16_t)wp[2], &X, &Y, &Z);
    2066           0 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2067           0 :             *cp++ = PACK(r, g, b);
    2068           0 :             wp += 3;
    2069             :         }
    2070           0 :         cp += toskew;
    2071           0 :         wp += fromskew;
    2072             :     }
    2073           0 : }
    2074             : 
    2075             : /*
    2076             :  * YCbCr -> RGB conversion and packing routines.
    2077             :  */
    2078             : 
    2079             : #define YCbCrtoRGB(dst, Y)                                                     \
    2080             :     {                                                                          \
    2081             :         uint32_t r, g, b;                                                      \
    2082             :         TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);                   \
    2083             :         dst = PACK(r, g, b);                                                   \
    2084             :     }
    2085             : 
    2086             : /*
    2087             :  * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
    2088             :  */
    2089           2 : DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
    2090             : {
    2091           2 :     uint32_t *cp1 = cp + w + toskew;
    2092           2 :     uint32_t *cp2 = cp1 + w + toskew;
    2093           2 :     uint32_t *cp3 = cp2 + w + toskew;
    2094           2 :     int32_t incr = 3 * w + 4 * toskew;
    2095             : 
    2096             :     (void)y;
    2097             :     /* adjust fromskew */
    2098           2 :     fromskew = (fromskew / 4) * (4 * 2 + 2);
    2099           2 :     if ((h & 3) == 0 && (w & 3) == 0)
    2100             :     {
    2101          13 :         for (; h >= 4; h -= 4)
    2102             :         {
    2103          12 :             x = w >> 2;
    2104             :             do
    2105             :             {
    2106         144 :                 int32_t Cb = pp[16];
    2107         144 :                 int32_t Cr = pp[17];
    2108             : 
    2109         144 :                 YCbCrtoRGB(cp[0], pp[0]);
    2110         144 :                 YCbCrtoRGB(cp[1], pp[1]);
    2111         144 :                 YCbCrtoRGB(cp[2], pp[2]);
    2112         144 :                 YCbCrtoRGB(cp[3], pp[3]);
    2113         144 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2114         144 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2115         144 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2116         144 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2117         144 :                 YCbCrtoRGB(cp2[0], pp[8]);
    2118         144 :                 YCbCrtoRGB(cp2[1], pp[9]);
    2119         144 :                 YCbCrtoRGB(cp2[2], pp[10]);
    2120         144 :                 YCbCrtoRGB(cp2[3], pp[11]);
    2121         144 :                 YCbCrtoRGB(cp3[0], pp[12]);
    2122         144 :                 YCbCrtoRGB(cp3[1], pp[13]);
    2123         144 :                 YCbCrtoRGB(cp3[2], pp[14]);
    2124         144 :                 YCbCrtoRGB(cp3[3], pp[15]);
    2125             : 
    2126         144 :                 cp += 4;
    2127         144 :                 cp1 += 4;
    2128         144 :                 cp2 += 4;
    2129         144 :                 cp3 += 4;
    2130         144 :                 pp += 18;
    2131         144 :             } while (--x);
    2132          12 :             cp += incr;
    2133          12 :             cp1 += incr;
    2134          12 :             cp2 += incr;
    2135          12 :             cp3 += incr;
    2136          12 :             pp += fromskew;
    2137             :         }
    2138             :     }
    2139             :     else
    2140             :     {
    2141          10 :         while (h > 0)
    2142             :         {
    2143         110 :             for (x = w; x > 0;)
    2144             :             {
    2145         100 :                 int32_t Cb = pp[16];
    2146         100 :                 int32_t Cr = pp[17];
    2147         100 :                 switch (x)
    2148             :                 {
    2149          90 :                     default:
    2150          90 :                         switch (h)
    2151             :                         {
    2152          81 :                             default:
    2153          81 :                                 YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
    2154          90 :                             case 3:
    2155          90 :                                 YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
    2156          90 :                             case 2:
    2157          90 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2158          90 :                             case 1:
    2159          90 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2160             :                         }                                 /* FALLTHROUGH */
    2161         100 :                     case 3:
    2162         100 :                         switch (h)
    2163             :                         {
    2164          90 :                             default:
    2165          90 :                                 YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
    2166         100 :                             case 3:
    2167         100 :                                 YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
    2168         100 :                             case 2:
    2169         100 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2170         100 :                             case 1:
    2171         100 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2172             :                         }                                 /* FALLTHROUGH */
    2173         100 :                     case 2:
    2174         100 :                         switch (h)
    2175             :                         {
    2176          90 :                             default:
    2177          90 :                                 YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
    2178         100 :                             case 3:
    2179         100 :                                 YCbCrtoRGB(cp2[1], pp[9]); /* FALLTHROUGH */
    2180         100 :                             case 2:
    2181         100 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2182         100 :                             case 1:
    2183         100 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2184             :                         }                                 /* FALLTHROUGH */
    2185         100 :                     case 1:
    2186         100 :                         switch (h)
    2187             :                         {
    2188          90 :                             default:
    2189          90 :                                 YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
    2190         100 :                             case 3:
    2191         100 :                                 YCbCrtoRGB(cp2[0], pp[8]); /* FALLTHROUGH */
    2192         100 :                             case 2:
    2193         100 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2194         100 :                             case 1:
    2195         100 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2196             :                         }                                 /* FALLTHROUGH */
    2197             :                 }
    2198         100 :                 if (x < 4)
    2199             :                 {
    2200          10 :                     cp += x;
    2201          10 :                     cp1 += x;
    2202          10 :                     cp2 += x;
    2203          10 :                     cp3 += x;
    2204          10 :                     x = 0;
    2205             :                 }
    2206             :                 else
    2207             :                 {
    2208          90 :                     cp += 4;
    2209          90 :                     cp1 += 4;
    2210          90 :                     cp2 += 4;
    2211          90 :                     cp3 += 4;
    2212          90 :                     x -= 4;
    2213             :                 }
    2214         100 :                 pp += 18;
    2215             :             }
    2216          10 :             if (h <= 4)
    2217           1 :                 break;
    2218           9 :             h -= 4;
    2219           9 :             cp += incr;
    2220           9 :             cp1 += incr;
    2221           9 :             cp2 += incr;
    2222           9 :             cp3 += incr;
    2223           9 :             pp += fromskew;
    2224             :         }
    2225             :     }
    2226           2 : }
    2227             : 
    2228             : /*
    2229             :  * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
    2230             :  */
    2231           2 : DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
    2232             : {
    2233           2 :     uint32_t *cp1 = cp + w + toskew;
    2234           2 :     int32_t incr = 2 * toskew + w;
    2235             : 
    2236             :     (void)y;
    2237           2 :     fromskew = (fromskew / 4) * (4 * 2 + 2);
    2238           2 :     if ((w & 3) == 0 && (h & 1) == 0)
    2239             :     {
    2240          25 :         for (; h >= 2; h -= 2)
    2241             :         {
    2242          24 :             x = w >> 2;
    2243             :             do
    2244             :             {
    2245         288 :                 int32_t Cb = pp[8];
    2246         288 :                 int32_t Cr = pp[9];
    2247             : 
    2248         288 :                 YCbCrtoRGB(cp[0], pp[0]);
    2249         288 :                 YCbCrtoRGB(cp[1], pp[1]);
    2250         288 :                 YCbCrtoRGB(cp[2], pp[2]);
    2251         288 :                 YCbCrtoRGB(cp[3], pp[3]);
    2252         288 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2253         288 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2254         288 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2255         288 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2256             : 
    2257         288 :                 cp += 4;
    2258         288 :                 cp1 += 4;
    2259         288 :                 pp += 10;
    2260         288 :             } while (--x);
    2261          24 :             cp += incr;
    2262          24 :             cp1 += incr;
    2263          24 :             pp += fromskew;
    2264             :         }
    2265             :     }
    2266             :     else
    2267             :     {
    2268          20 :         while (h > 0)
    2269             :         {
    2270         220 :             for (x = w; x > 0;)
    2271             :             {
    2272         200 :                 int32_t Cb = pp[8];
    2273         200 :                 int32_t Cr = pp[9];
    2274         200 :                 switch (x)
    2275             :                 {
    2276         180 :                     default:
    2277         180 :                         switch (h)
    2278             :                         {
    2279         171 :                             default:
    2280         171 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2281         180 :                             case 1:
    2282         180 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2283             :                         }                                 /* FALLTHROUGH */
    2284         200 :                     case 3:
    2285         200 :                         switch (h)
    2286             :                         {
    2287         190 :                             default:
    2288         190 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2289         200 :                             case 1:
    2290         200 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2291             :                         }                                 /* FALLTHROUGH */
    2292         200 :                     case 2:
    2293         200 :                         switch (h)
    2294             :                         {
    2295         190 :                             default:
    2296         190 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2297         200 :                             case 1:
    2298         200 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2299             :                         }                                 /* FALLTHROUGH */
    2300         200 :                     case 1:
    2301         200 :                         switch (h)
    2302             :                         {
    2303         190 :                             default:
    2304         190 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2305         200 :                             case 1:
    2306         200 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2307             :                         }                                 /* FALLTHROUGH */
    2308             :                 }
    2309         200 :                 if (x < 4)
    2310             :                 {
    2311          20 :                     cp += x;
    2312          20 :                     cp1 += x;
    2313          20 :                     x = 0;
    2314             :                 }
    2315             :                 else
    2316             :                 {
    2317         180 :                     cp += 4;
    2318         180 :                     cp1 += 4;
    2319         180 :                     x -= 4;
    2320             :                 }
    2321         200 :                 pp += 10;
    2322             :             }
    2323          20 :             if (h <= 2)
    2324           1 :                 break;
    2325          19 :             h -= 2;
    2326          19 :             cp += incr;
    2327          19 :             cp1 += incr;
    2328          19 :             pp += fromskew;
    2329             :         }
    2330             :     }
    2331           2 : }
    2332             : 
    2333             : /*
    2334             :  * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
    2335             :  */
    2336           1 : DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
    2337             : {
    2338             :     (void)y;
    2339           1 :     fromskew = (fromskew / 4) * (4 * 1 + 2);
    2340             :     do
    2341             :     {
    2342          39 :         x = w >> 2;
    2343         390 :         while (x > 0)
    2344             :         {
    2345         351 :             int32_t Cb = pp[4];
    2346         351 :             int32_t Cr = pp[5];
    2347             : 
    2348         351 :             YCbCrtoRGB(cp[0], pp[0]);
    2349         351 :             YCbCrtoRGB(cp[1], pp[1]);
    2350         351 :             YCbCrtoRGB(cp[2], pp[2]);
    2351         351 :             YCbCrtoRGB(cp[3], pp[3]);
    2352             : 
    2353         351 :             cp += 4;
    2354         351 :             pp += 6;
    2355         351 :             x--;
    2356             :         }
    2357             : 
    2358          39 :         if ((w & 3) != 0)
    2359             :         {
    2360          39 :             int32_t Cb = pp[4];
    2361          39 :             int32_t Cr = pp[5];
    2362             : 
    2363          39 :             switch ((w & 3))
    2364             :             {
    2365          39 :                 case 3:
    2366          39 :                     YCbCrtoRGB(cp[2], pp[2]); /*-fallthrough*/
    2367          39 :                 case 2:
    2368          39 :                     YCbCrtoRGB(cp[1], pp[1]); /*-fallthrough*/
    2369          39 :                 case 1:
    2370          39 :                     YCbCrtoRGB(cp[0], pp[0]); /*-fallthrough*/
    2371          39 :                 case 0:
    2372          39 :                     break;
    2373             :             }
    2374             : 
    2375          39 :             cp += (w & 3);
    2376          39 :             pp += 6;
    2377             :         }
    2378             : 
    2379          39 :         cp += toskew;
    2380          39 :         pp += fromskew;
    2381          39 :     } while (--h);
    2382           1 : }
    2383             : 
    2384             : /*
    2385             :  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
    2386             :  */
    2387           2 : DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
    2388             : {
    2389             :     uint32_t *cp2;
    2390           2 :     int32_t incr = 2 * toskew + w;
    2391             :     (void)y;
    2392           2 :     fromskew = (fromskew / 2) * (2 * 2 + 2);
    2393           2 :     cp2 = cp + w + toskew;
    2394         127 :     while (h >= 2)
    2395             :     {
    2396         125 :         x = w;
    2397       12888 :         while (x >= 2)
    2398             :         {
    2399       12763 :             uint32_t Cb = pp[4];
    2400       12763 :             uint32_t Cr = pp[5];
    2401       12763 :             YCbCrtoRGB(cp[0], pp[0]);
    2402       12763 :             YCbCrtoRGB(cp[1], pp[1]);
    2403       12763 :             YCbCrtoRGB(cp2[0], pp[2]);
    2404       12763 :             YCbCrtoRGB(cp2[1], pp[3]);
    2405       12763 :             cp += 2;
    2406       12763 :             cp2 += 2;
    2407       12763 :             pp += 6;
    2408       12763 :             x -= 2;
    2409             :         }
    2410         125 :         if (x == 1)
    2411             :         {
    2412          19 :             uint32_t Cb = pp[4];
    2413          19 :             uint32_t Cr = pp[5];
    2414          19 :             YCbCrtoRGB(cp[0], pp[0]);
    2415          19 :             YCbCrtoRGB(cp2[0], pp[2]);
    2416          19 :             cp++;
    2417          19 :             cp2++;
    2418          19 :             pp += 6;
    2419             :         }
    2420         125 :         cp += incr;
    2421         125 :         cp2 += incr;
    2422         125 :         pp += fromskew;
    2423         125 :         h -= 2;
    2424             :     }
    2425           2 :     if (h == 1)
    2426             :     {
    2427           2 :         x = w;
    2428         138 :         while (x >= 2)
    2429             :         {
    2430         136 :             uint32_t Cb = pp[4];
    2431         136 :             uint32_t Cr = pp[5];
    2432         136 :             YCbCrtoRGB(cp[0], pp[0]);
    2433         136 :             YCbCrtoRGB(cp[1], pp[1]);
    2434         136 :             cp += 2;
    2435         136 :             cp2 += 2;
    2436         136 :             pp += 6;
    2437         136 :             x -= 2;
    2438             :         }
    2439           2 :         if (x == 1)
    2440             :         {
    2441           1 :             uint32_t Cb = pp[4];
    2442           1 :             uint32_t Cr = pp[5];
    2443           1 :             YCbCrtoRGB(cp[0], pp[0]);
    2444             :         }
    2445             :     }
    2446           2 : }
    2447             : 
    2448             : /*
    2449             :  * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
    2450             :  */
    2451           1 : DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
    2452             : {
    2453             :     (void)y;
    2454           1 :     fromskew = (fromskew / 2) * (2 * 1 + 2);
    2455             :     do
    2456             :     {
    2457          39 :         x = w >> 1;
    2458         780 :         while (x > 0)
    2459             :         {
    2460         741 :             int32_t Cb = pp[2];
    2461         741 :             int32_t Cr = pp[3];
    2462             : 
    2463         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2464         741 :             YCbCrtoRGB(cp[1], pp[1]);
    2465             : 
    2466         741 :             cp += 2;
    2467         741 :             pp += 4;
    2468         741 :             x--;
    2469             :         }
    2470             : 
    2471          39 :         if ((w & 1) != 0)
    2472             :         {
    2473          39 :             int32_t Cb = pp[2];
    2474          39 :             int32_t Cr = pp[3];
    2475             : 
    2476          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2477             : 
    2478          39 :             cp += 1;
    2479          39 :             pp += 4;
    2480             :         }
    2481             : 
    2482          39 :         cp += toskew;
    2483          39 :         pp += fromskew;
    2484          39 :     } while (--h);
    2485           1 : }
    2486             : 
    2487             : /*
    2488             :  * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
    2489             :  */
    2490           1 : DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
    2491             : {
    2492             :     uint32_t *cp2;
    2493           1 :     int32_t incr = 2 * toskew + w;
    2494             :     (void)y;
    2495           1 :     fromskew = (fromskew / 1) * (1 * 2 + 2);
    2496           1 :     cp2 = cp + w + toskew;
    2497          20 :     while (h >= 2)
    2498             :     {
    2499          19 :         x = w;
    2500             :         do
    2501             :         {
    2502         741 :             uint32_t Cb = pp[2];
    2503         741 :             uint32_t Cr = pp[3];
    2504         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2505         741 :             YCbCrtoRGB(cp2[0], pp[1]);
    2506         741 :             cp++;
    2507         741 :             cp2++;
    2508         741 :             pp += 4;
    2509         741 :         } while (--x);
    2510          19 :         cp += incr;
    2511          19 :         cp2 += incr;
    2512          19 :         pp += fromskew;
    2513          19 :         h -= 2;
    2514             :     }
    2515           1 :     if (h == 1)
    2516             :     {
    2517           1 :         x = w;
    2518             :         do
    2519             :         {
    2520          39 :             uint32_t Cb = pp[2];
    2521          39 :             uint32_t Cr = pp[3];
    2522          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2523          39 :             cp++;
    2524          39 :             pp += 4;
    2525          39 :         } while (--x);
    2526             :     }
    2527           1 : }
    2528             : 
    2529             : /*
    2530             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2531             :  */
    2532           1 : DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
    2533             : {
    2534             :     (void)y;
    2535           1 :     fromskew = (fromskew / 1) * (1 * 1 + 2);
    2536             :     do
    2537             :     {
    2538          39 :         x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
    2539             :         do
    2540             :         {
    2541        1521 :             int32_t Cb = pp[1];
    2542        1521 :             int32_t Cr = pp[2];
    2543             : 
    2544        1521 :             YCbCrtoRGB(*cp++, pp[0]);
    2545             : 
    2546        1521 :             pp += 3;
    2547        1521 :         } while (--x);
    2548          39 :         cp += toskew;
    2549          39 :         pp += fromskew;
    2550          39 :     } while (--h);
    2551           1 : }
    2552             : 
    2553             : /*
    2554             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2555             :  */
    2556           0 : DECLARESepPutFunc(putseparate8bitYCbCr11tile)
    2557             : {
    2558             :     (void)y;
    2559             :     (void)a;
    2560             :     /* TODO: naming of input vars is still off, change obfuscating declaration
    2561             :      * inside define, or resolve obfuscation */
    2562           0 :     for (; h > 0; --h)
    2563             :     {
    2564           0 :         x = w;
    2565             :         do
    2566             :         {
    2567             :             uint32_t dr, dg, db;
    2568           0 :             TIFFYCbCrtoRGB(img->ycbcr, *r++, *g++, *b++, &dr, &dg, &db);
    2569           0 :             *cp++ = PACK(dr, dg, db);
    2570           0 :         } while (--x);
    2571           0 :         SKEW(r, g, b, fromskew);
    2572           0 :         cp += toskew;
    2573             :     }
    2574           0 : }
    2575             : #undef YCbCrtoRGB
    2576             : 
    2577         102 : static int isInRefBlackWhiteRange(float f)
    2578             : {
    2579         102 :     return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF;
    2580             : }
    2581             : 
    2582          17 : static int initYCbCrConversion(TIFFRGBAImage *img)
    2583             : {
    2584             :     static const char module[] = "initYCbCrConversion";
    2585             : 
    2586             :     float *luma, *refBlackWhite;
    2587             : 
    2588          17 :     if (img->ycbcr == NULL)
    2589             :     {
    2590          17 :         img->ycbcr = (TIFFYCbCrToRGB *)_TIFFmallocExt(
    2591             :             img->tif, TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)) +
    2592             :                           4 * 256 * sizeof(TIFFRGBValue) +
    2593             :                           2 * 256 * sizeof(int) + 3 * 256 * sizeof(int32_t));
    2594          17 :         if (img->ycbcr == NULL)
    2595             :         {
    2596           0 :             TIFFErrorExtR(img->tif, module,
    2597             :                           "No space for YCbCr->RGB conversion state");
    2598           0 :             return (0);
    2599             :         }
    2600             :     }
    2601             : 
    2602          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
    2603          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
    2604             :                           &refBlackWhite);
    2605             : 
    2606             :     /* Do some validation to avoid later issues. Detect NaN for now */
    2607             :     /* and also if lumaGreen is zero since we divide by it later */
    2608          17 :     if (luma[0] != luma[0] || luma[1] != luma[1] || luma[1] == 0.0 ||
    2609          17 :         luma[2] != luma[2])
    2610             :     {
    2611           0 :         TIFFErrorExtR(img->tif, module,
    2612             :                       "Invalid values for YCbCrCoefficients tag");
    2613           0 :         return (0);
    2614             :     }
    2615             : 
    2616          34 :     if (!isInRefBlackWhiteRange(refBlackWhite[0]) ||
    2617          34 :         !isInRefBlackWhiteRange(refBlackWhite[1]) ||
    2618          34 :         !isInRefBlackWhiteRange(refBlackWhite[2]) ||
    2619          34 :         !isInRefBlackWhiteRange(refBlackWhite[3]) ||
    2620          34 :         !isInRefBlackWhiteRange(refBlackWhite[4]) ||
    2621          17 :         !isInRefBlackWhiteRange(refBlackWhite[5]))
    2622             :     {
    2623           0 :         TIFFErrorExtR(img->tif, module,
    2624             :                       "Invalid values for ReferenceBlackWhite tag");
    2625           0 :         return (0);
    2626             :     }
    2627             : 
    2628          17 :     if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
    2629           0 :         return (0);
    2630          17 :     return (1);
    2631             : }
    2632             : 
    2633           1 : static tileContigRoutine initCIELabConversion(TIFFRGBAImage *img)
    2634             : {
    2635             :     static const char module[] = "initCIELabConversion";
    2636             : 
    2637             :     float *whitePoint;
    2638             :     float refWhite[3];
    2639             : 
    2640           1 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
    2641           1 :     if (whitePoint[1] == 0.0f)
    2642             :     {
    2643           0 :         TIFFErrorExtR(img->tif, module, "Invalid value for WhitePoint tag.");
    2644           0 :         return NULL;
    2645             :     }
    2646             : 
    2647           1 :     if (!img->cielab)
    2648             :     {
    2649           1 :         img->cielab = (TIFFCIELabToRGB *)_TIFFmallocExt(
    2650             :             img->tif, sizeof(TIFFCIELabToRGB));
    2651           1 :         if (!img->cielab)
    2652             :         {
    2653           0 :             TIFFErrorExtR(img->tif, module,
    2654             :                           "No space for CIE L*a*b*->RGB conversion state.");
    2655           0 :             return NULL;
    2656             :         }
    2657             :     }
    2658             : 
    2659           1 :     refWhite[1] = 100.0F;
    2660           1 :     refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
    2661           1 :     refWhite[2] =
    2662           1 :         (1.0F - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
    2663           1 :     if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0)
    2664             :     {
    2665           0 :         TIFFErrorExtR(img->tif, module,
    2666             :                       "Failed to initialize CIE L*a*b*->RGB conversion state.");
    2667           0 :         _TIFFfreeExt(img->tif, img->cielab);
    2668           0 :         return NULL;
    2669             :     }
    2670             : 
    2671           1 :     if (img->bitspersample == 8)
    2672           1 :         return putcontig8bitCIELab8;
    2673           0 :     else if (img->bitspersample == 16)
    2674           0 :         return putcontig8bitCIELab16;
    2675           0 :     return NULL;
    2676             : }
    2677             : 
    2678             : /*
    2679             :  * Greyscale images with less than 8 bits/sample are handled
    2680             :  * with a table to avoid lots of shifts and masks.  The table
    2681             :  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
    2682             :  * pixel values simply by indexing into the table with one
    2683             :  * number.
    2684             :  */
    2685           9 : static int makebwmap(TIFFRGBAImage *img)
    2686             : {
    2687           9 :     TIFFRGBValue *Map = img->Map;
    2688           9 :     int bitspersample = img->bitspersample;
    2689           9 :     int nsamples = 8 / bitspersample;
    2690             :     int i;
    2691             :     uint32_t *p;
    2692             : 
    2693           9 :     if (nsamples == 0)
    2694           0 :         nsamples = 1;
    2695             : 
    2696          18 :     img->BWmap = (uint32_t **)_TIFFmallocExt(
    2697             :         img->tif,
    2698           9 :         256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
    2699           9 :     if (img->BWmap == NULL)
    2700             :     {
    2701           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2702             :                       "No space for B&W mapping table");
    2703           0 :         return (0);
    2704             :     }
    2705           9 :     p = (uint32_t *)(img->BWmap + 256);
    2706        2313 :     for (i = 0; i < 256; i++)
    2707             :     {
    2708             :         TIFFRGBValue c;
    2709        2304 :         img->BWmap[i] = p;
    2710        2304 :         switch (bitspersample)
    2711             :         {
    2712             : #define GREY(x)                                                                \
    2713             :     c = Map[x];                                                                \
    2714             :     *p++ = PACK(c, c, c);
    2715           0 :             case 1:
    2716           0 :                 GREY(i >> 7);
    2717           0 :                 GREY((i >> 6) & 1);
    2718           0 :                 GREY((i >> 5) & 1);
    2719           0 :                 GREY((i >> 4) & 1);
    2720           0 :                 GREY((i >> 3) & 1);
    2721           0 :                 GREY((i >> 2) & 1);
    2722           0 :                 GREY((i >> 1) & 1);
    2723           0 :                 GREY(i & 1);
    2724           0 :                 break;
    2725           0 :             case 2:
    2726           0 :                 GREY(i >> 6);
    2727           0 :                 GREY((i >> 4) & 3);
    2728           0 :                 GREY((i >> 2) & 3);
    2729           0 :                 GREY(i & 3);
    2730           0 :                 break;
    2731           0 :             case 4:
    2732           0 :                 GREY(i >> 4);
    2733           0 :                 GREY(i & 0xf);
    2734           0 :                 break;
    2735        2304 :             case 8:
    2736             :             case 16:
    2737        2304 :                 GREY(i);
    2738        2304 :                 break;
    2739             :         }
    2740             : #undef GREY
    2741        2304 :     }
    2742           9 :     return (1);
    2743             : }
    2744             : 
    2745             : /*
    2746             :  * Construct a mapping table to convert from the range
    2747             :  * of the data samples to [0,255] --for display.  This
    2748             :  * process also handles inverting B&W images when needed.
    2749             :  */
    2750           9 : static int setupMap(TIFFRGBAImage *img)
    2751             : {
    2752             :     int32_t x, range;
    2753             : 
    2754           9 :     range = (int32_t)((1L << img->bitspersample) - 1);
    2755             : 
    2756             :     /* treat 16 bit the same as eight bit */
    2757           9 :     if (img->bitspersample == 16)
    2758           0 :         range = (int32_t)255;
    2759             : 
    2760          18 :     img->Map = (TIFFRGBValue *)_TIFFmallocExt(
    2761           9 :         img->tif, (range + 1) * sizeof(TIFFRGBValue));
    2762           9 :     if (img->Map == NULL)
    2763             :     {
    2764           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2765             :                       "No space for photometric conversion table");
    2766           0 :         return (0);
    2767             :     }
    2768           9 :     if (img->photometric == PHOTOMETRIC_MINISWHITE)
    2769             :     {
    2770           0 :         for (x = 0; x <= range; x++)
    2771           0 :             img->Map[x] = (TIFFRGBValue)(((range - x) * 255) / range);
    2772             :     }
    2773             :     else
    2774             :     {
    2775        2313 :         for (x = 0; x <= range; x++)
    2776        2304 :             img->Map[x] = (TIFFRGBValue)((x * 255) / range);
    2777             :     }
    2778           9 :     if (img->bitspersample <= 16 &&
    2779           9 :         (img->photometric == PHOTOMETRIC_MINISBLACK ||
    2780           0 :          img->photometric == PHOTOMETRIC_MINISWHITE))
    2781             :     {
    2782             :         /*
    2783             :          * Use photometric mapping table to construct
    2784             :          * unpacking tables for samples <= 8 bits.
    2785             :          */
    2786           9 :         if (!makebwmap(img))
    2787           0 :             return (0);
    2788             :         /* no longer need Map, free it */
    2789           9 :         _TIFFfreeExt(img->tif, img->Map);
    2790           9 :         img->Map = NULL;
    2791             :     }
    2792           9 :     return (1);
    2793             : }
    2794             : 
    2795           1 : static int checkcmap(TIFFRGBAImage *img)
    2796             : {
    2797           1 :     uint16_t *r = img->redcmap;
    2798           1 :     uint16_t *g = img->greencmap;
    2799           1 :     uint16_t *b = img->bluecmap;
    2800           1 :     long n = 1L << img->bitspersample;
    2801             : 
    2802           2 :     while (n-- > 0)
    2803           2 :         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
    2804           1 :             return (16);
    2805           0 :     return (8);
    2806             : }
    2807             : 
    2808           1 : static void cvtcmap(TIFFRGBAImage *img)
    2809             : {
    2810           1 :     uint16_t *r = img->redcmap;
    2811           1 :     uint16_t *g = img->greencmap;
    2812           1 :     uint16_t *b = img->bluecmap;
    2813             :     long i;
    2814             : 
    2815         257 :     for (i = (1L << img->bitspersample) - 1; i >= 0; i--)
    2816             :     {
    2817             : #define CVT(x) ((uint16_t)((x) >> 8))
    2818         256 :         r[i] = CVT(r[i]);
    2819         256 :         g[i] = CVT(g[i]);
    2820         256 :         b[i] = CVT(b[i]);
    2821             : #undef CVT
    2822             :     }
    2823           1 : }
    2824             : 
    2825             : /*
    2826             :  * Palette images with <= 8 bits/sample are handled
    2827             :  * with a table to avoid lots of shifts and masks.  The table
    2828             :  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
    2829             :  * pixel values simply by indexing into the table with one
    2830             :  * number.
    2831             :  */
    2832           1 : static int makecmap(TIFFRGBAImage *img)
    2833             : {
    2834           1 :     int bitspersample = img->bitspersample;
    2835           1 :     int nsamples = 8 / bitspersample;
    2836           1 :     uint16_t *r = img->redcmap;
    2837           1 :     uint16_t *g = img->greencmap;
    2838           1 :     uint16_t *b = img->bluecmap;
    2839             :     uint32_t *p;
    2840             :     int i;
    2841             : 
    2842           2 :     img->PALmap = (uint32_t **)_TIFFmallocExt(
    2843             :         img->tif,
    2844           1 :         256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
    2845           1 :     if (img->PALmap == NULL)
    2846             :     {
    2847           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2848             :                       "No space for Palette mapping table");
    2849           0 :         return (0);
    2850             :     }
    2851           1 :     p = (uint32_t *)(img->PALmap + 256);
    2852         257 :     for (i = 0; i < 256; i++)
    2853             :     {
    2854             :         TIFFRGBValue c;
    2855         256 :         img->PALmap[i] = p;
    2856             : #define CMAP(x)                                                                \
    2857             :     c = (TIFFRGBValue)x;                                                       \
    2858             :     *p++ = PACK(r[c] & 0xff, g[c] & 0xff, b[c] & 0xff);
    2859         256 :         switch (bitspersample)
    2860             :         {
    2861           0 :             case 1:
    2862           0 :                 CMAP(i >> 7);
    2863           0 :                 CMAP((i >> 6) & 1);
    2864           0 :                 CMAP((i >> 5) & 1);
    2865           0 :                 CMAP((i >> 4) & 1);
    2866           0 :                 CMAP((i >> 3) & 1);
    2867           0 :                 CMAP((i >> 2) & 1);
    2868           0 :                 CMAP((i >> 1) & 1);
    2869           0 :                 CMAP(i & 1);
    2870           0 :                 break;
    2871           0 :             case 2:
    2872           0 :                 CMAP(i >> 6);
    2873           0 :                 CMAP((i >> 4) & 3);
    2874           0 :                 CMAP((i >> 2) & 3);
    2875           0 :                 CMAP(i & 3);
    2876           0 :                 break;
    2877           0 :             case 4:
    2878           0 :                 CMAP(i >> 4);
    2879           0 :                 CMAP(i & 0xf);
    2880           0 :                 break;
    2881         256 :             case 8:
    2882         256 :                 CMAP(i);
    2883         256 :                 break;
    2884             :         }
    2885             : #undef CMAP
    2886         256 :     }
    2887           1 :     return (1);
    2888             : }
    2889             : 
    2890             : /*
    2891             :  * Construct any mapping table used
    2892             :  * by the associated put routine.
    2893             :  */
    2894          17 : static int buildMap(TIFFRGBAImage *img)
    2895             : {
    2896          17 :     switch (img->photometric)
    2897             :     {
    2898           6 :         case PHOTOMETRIC_RGB:
    2899             :         case PHOTOMETRIC_YCBCR:
    2900             :         case PHOTOMETRIC_SEPARATED:
    2901           6 :             if (img->bitspersample == 8)
    2902           6 :                 break;
    2903             :             /* fall through... */
    2904             :         case PHOTOMETRIC_MINISBLACK:
    2905             :         case PHOTOMETRIC_MINISWHITE:
    2906           9 :             if (!setupMap(img))
    2907           0 :                 return (0);
    2908           9 :             break;
    2909           1 :         case PHOTOMETRIC_PALETTE:
    2910             :             /*
    2911             :              * Convert 16-bit colormap to 8-bit (unless it looks
    2912             :              * like an old-style 8-bit colormap).
    2913             :              */
    2914           1 :             if (checkcmap(img) == 16)
    2915           1 :                 cvtcmap(img);
    2916             :             else
    2917           0 :                 TIFFWarningExtR(img->tif, TIFFFileName(img->tif),
    2918             :                                 "Assuming 8-bit colormap");
    2919             :             /*
    2920             :              * Use mapping table and colormap to construct
    2921             :              * unpacking tables for samples < 8 bits.
    2922             :              */
    2923           1 :             if (img->bitspersample <= 8 && !makecmap(img))
    2924           0 :                 return (0);
    2925           1 :             break;
    2926             :     }
    2927          17 :     return (1);
    2928             : }
    2929             : 
    2930             : /*
    2931             :  * Select the appropriate conversion routine for packed data.
    2932             :  */
    2933          60 : static int PickContigCase(TIFFRGBAImage *img)
    2934             : {
    2935          60 :     img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
    2936          60 :     img->put.contig = NULL;
    2937          60 :     switch (img->photometric)
    2938             :     {
    2939          26 :         case PHOTOMETRIC_RGB:
    2940          26 :             switch (img->bitspersample)
    2941             :             {
    2942          26 :                 case 8:
    2943          26 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    2944          13 :                         img->samplesperpixel >= 4)
    2945          13 :                         img->put.contig = putRGBAAcontig8bittile;
    2946          13 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    2947          13 :                              img->samplesperpixel >= 4)
    2948             :                     {
    2949          13 :                         if (BuildMapUaToAa(img))
    2950          13 :                             img->put.contig = putRGBUAcontig8bittile;
    2951             :                     }
    2952           0 :                     else if (img->samplesperpixel >= 3)
    2953           0 :                         img->put.contig = putRGBcontig8bittile;
    2954          26 :                     break;
    2955           0 :                 case 16:
    2956           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    2957           0 :                         img->samplesperpixel >= 4)
    2958             :                     {
    2959           0 :                         if (BuildMapBitdepth16To8(img))
    2960           0 :                             img->put.contig = putRGBAAcontig16bittile;
    2961             :                     }
    2962           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    2963           0 :                              img->samplesperpixel >= 4)
    2964             :                     {
    2965           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    2966           0 :                             img->put.contig = putRGBUAcontig16bittile;
    2967             :                     }
    2968           0 :                     else if (img->samplesperpixel >= 3)
    2969             :                     {
    2970           0 :                         if (BuildMapBitdepth16To8(img))
    2971           0 :                             img->put.contig = putRGBcontig16bittile;
    2972             :                     }
    2973           0 :                     break;
    2974             :             }
    2975          26 :             break;
    2976           6 :         case PHOTOMETRIC_SEPARATED:
    2977           6 :             if (img->samplesperpixel >= 4 && buildMap(img))
    2978             :             {
    2979           6 :                 if (img->bitspersample == 8)
    2980             :                 {
    2981           6 :                     if (!img->Map)
    2982           6 :                         img->put.contig = putRGBcontig8bitCMYKtile;
    2983             :                     else
    2984           0 :                         img->put.contig = putRGBcontig8bitCMYKMaptile;
    2985             :                 }
    2986             :             }
    2987           6 :             break;
    2988           1 :         case PHOTOMETRIC_PALETTE:
    2989           1 :             if (buildMap(img))
    2990             :             {
    2991           1 :                 switch (img->bitspersample)
    2992             :                 {
    2993           1 :                     case 8:
    2994           1 :                         img->put.contig = put8bitcmaptile;
    2995           1 :                         break;
    2996           0 :                     case 4:
    2997           0 :                         img->put.contig = put4bitcmaptile;
    2998           0 :                         break;
    2999           0 :                     case 2:
    3000           0 :                         img->put.contig = put2bitcmaptile;
    3001           0 :                         break;
    3002           0 :                     case 1:
    3003           0 :                         img->put.contig = put1bitcmaptile;
    3004           0 :                         break;
    3005             :                 }
    3006           0 :             }
    3007           1 :             break;
    3008           9 :         case PHOTOMETRIC_MINISWHITE:
    3009             :         case PHOTOMETRIC_MINISBLACK:
    3010           9 :             if (buildMap(img))
    3011             :             {
    3012           9 :                 switch (img->bitspersample)
    3013             :                 {
    3014           0 :                     case 16:
    3015           0 :                         img->put.contig = put16bitbwtile;
    3016           0 :                         break;
    3017           9 :                     case 8:
    3018           9 :                         if (img->alpha && img->samplesperpixel == 2)
    3019           6 :                             img->put.contig = putagreytile;
    3020             :                         else
    3021           3 :                             img->put.contig = putgreytile;
    3022           9 :                         break;
    3023           0 :                     case 4:
    3024           0 :                         img->put.contig = put4bitbwtile;
    3025           0 :                         break;
    3026           0 :                     case 2:
    3027           0 :                         img->put.contig = put2bitbwtile;
    3028           0 :                         break;
    3029           0 :                     case 1:
    3030           0 :                         img->put.contig = put1bitbwtile;
    3031           0 :                         break;
    3032             :                 }
    3033           0 :             }
    3034           9 :             break;
    3035          17 :         case PHOTOMETRIC_YCBCR:
    3036          17 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3037             :             {
    3038          17 :                 if (initYCbCrConversion(img) != 0)
    3039             :                 {
    3040             :                     /*
    3041             :                      * The 6.0 spec says that subsampling must be
    3042             :                      * one of 1, 2, or 4, and that vertical subsampling
    3043             :                      * must always be <= horizontal subsampling; so
    3044             :                      * there are only a few possibilities and we just
    3045             :                      * enumerate the cases.
    3046             :                      * Joris: added support for the [1,2] case, nonetheless, to
    3047             :                      * accommodate some OJPEG files
    3048             :                      */
    3049             :                     uint16_t SubsamplingHor;
    3050             :                     uint16_t SubsamplingVer;
    3051          17 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3052             :                                           &SubsamplingHor, &SubsamplingVer);
    3053          17 :                     switch ((SubsamplingHor << 4) | SubsamplingVer)
    3054             :                     {
    3055           2 :                         case 0x44:
    3056           2 :                             img->put.contig = putcontig8bitYCbCr44tile;
    3057           2 :                             break;
    3058           2 :                         case 0x42:
    3059           2 :                             img->put.contig = putcontig8bitYCbCr42tile;
    3060           2 :                             break;
    3061           1 :                         case 0x41:
    3062           1 :                             img->put.contig = putcontig8bitYCbCr41tile;
    3063           1 :                             break;
    3064           3 :                         case 0x22:
    3065           3 :                             img->put.contig = putcontig8bitYCbCr22tile;
    3066           3 :                             break;
    3067           1 :                         case 0x21:
    3068           1 :                             img->put.contig = putcontig8bitYCbCr21tile;
    3069           1 :                             break;
    3070           1 :                         case 0x12:
    3071           1 :                             img->put.contig = putcontig8bitYCbCr12tile;
    3072           1 :                             break;
    3073           1 :                         case 0x11:
    3074           1 :                             img->put.contig = putcontig8bitYCbCr11tile;
    3075           1 :                             break;
    3076             :                     }
    3077          17 :                 }
    3078             :             }
    3079          17 :             break;
    3080           1 :         case PHOTOMETRIC_CIELAB:
    3081           1 :             if (img->samplesperpixel == 3 && buildMap(img))
    3082             :             {
    3083           1 :                 if (img->bitspersample == 8 || img->bitspersample == 16)
    3084           1 :                     img->put.contig = initCIELabConversion(img);
    3085           1 :                 break;
    3086             :             }
    3087             :     }
    3088          60 :     return ((img->get != NULL) && (img->put.contig != NULL));
    3089             : }
    3090             : 
    3091             : /*
    3092             :  * Select the appropriate conversion routine for unpacked data.
    3093             :  *
    3094             :  * NB: we assume that unpacked single channel data is directed
    3095             :  *   to the "packed routines.
    3096             :  */
    3097           3 : static int PickSeparateCase(TIFFRGBAImage *img)
    3098             : {
    3099           3 :     img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
    3100           3 :     img->put.separate = NULL;
    3101           3 :     switch (img->photometric)
    3102             :     {
    3103           3 :         case PHOTOMETRIC_MINISWHITE:
    3104             :         case PHOTOMETRIC_MINISBLACK:
    3105             :             /* greyscale images processed pretty much as RGB by gtTileSeparate
    3106             :              */
    3107             :         case PHOTOMETRIC_RGB:
    3108           3 :             switch (img->bitspersample)
    3109             :             {
    3110           3 :                 case 8:
    3111           3 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3112           0 :                         img->put.separate = putRGBAAseparate8bittile;
    3113           3 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3114             :                     {
    3115           0 :                         if (BuildMapUaToAa(img))
    3116           0 :                             img->put.separate = putRGBUAseparate8bittile;
    3117             :                     }
    3118             :                     else
    3119           3 :                         img->put.separate = putRGBseparate8bittile;
    3120           3 :                     break;
    3121           0 :                 case 16:
    3122           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3123             :                     {
    3124           0 :                         if (BuildMapBitdepth16To8(img))
    3125           0 :                             img->put.separate = putRGBAAseparate16bittile;
    3126             :                     }
    3127           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3128             :                     {
    3129           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    3130           0 :                             img->put.separate = putRGBUAseparate16bittile;
    3131             :                     }
    3132             :                     else
    3133             :                     {
    3134           0 :                         if (BuildMapBitdepth16To8(img))
    3135           0 :                             img->put.separate = putRGBseparate16bittile;
    3136             :                     }
    3137           0 :                     break;
    3138             :             }
    3139           3 :             break;
    3140           0 :         case PHOTOMETRIC_SEPARATED:
    3141           0 :             if (img->bitspersample == 8 && img->samplesperpixel == 4)
    3142             :             {
    3143           0 :                 img->alpha =
    3144             :                     1; // Not alpha, but seems like the only way to get 4th band
    3145           0 :                 img->put.separate = putCMYKseparate8bittile;
    3146             :             }
    3147           0 :             break;
    3148           0 :         case PHOTOMETRIC_YCBCR:
    3149           0 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3150             :             {
    3151           0 :                 if (initYCbCrConversion(img) != 0)
    3152             :                 {
    3153             :                     uint16_t hs, vs;
    3154           0 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3155             :                                           &hs, &vs);
    3156           0 :                     switch ((hs << 4) | vs)
    3157             :                     {
    3158           0 :                         case 0x11:
    3159           0 :                             img->put.separate = putseparate8bitYCbCr11tile;
    3160           0 :                             break;
    3161             :                             /* TODO: add other cases here */
    3162             :                     }
    3163           0 :                 }
    3164             :             }
    3165           0 :             break;
    3166             :     }
    3167           3 :     return ((img->get != NULL) && (img->put.separate != NULL));
    3168             : }
    3169             : 
    3170          13 : static int BuildMapUaToAa(TIFFRGBAImage *img)
    3171             : {
    3172             :     static const char module[] = "BuildMapUaToAa";
    3173             :     uint8_t *m;
    3174             :     uint16_t na, nv;
    3175          13 :     assert(img->UaToAa == NULL);
    3176          13 :     img->UaToAa = _TIFFmallocExt(img->tif, 65536);
    3177          13 :     if (img->UaToAa == NULL)
    3178             :     {
    3179           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3180           0 :         return (0);
    3181             :     }
    3182          13 :     m = img->UaToAa;
    3183        3341 :     for (na = 0; na < 256; na++)
    3184             :     {
    3185      855296 :         for (nv = 0; nv < 256; nv++)
    3186      851968 :             *m++ = (uint8_t)((nv * na + 127) / 255);
    3187             :     }
    3188          13 :     return (1);
    3189             : }
    3190             : 
    3191           0 : static int BuildMapBitdepth16To8(TIFFRGBAImage *img)
    3192             : {
    3193             :     static const char module[] = "BuildMapBitdepth16To8";
    3194             :     uint8_t *m;
    3195             :     uint32_t n;
    3196           0 :     assert(img->Bitdepth16To8 == NULL);
    3197           0 :     img->Bitdepth16To8 = _TIFFmallocExt(img->tif, 65536);
    3198           0 :     if (img->Bitdepth16To8 == NULL)
    3199             :     {
    3200           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3201           0 :         return (0);
    3202             :     }
    3203           0 :     m = img->Bitdepth16To8;
    3204           0 :     for (n = 0; n < 65536; n++)
    3205           0 :         *m++ = (uint8_t)((n + 128) / 257);
    3206           0 :     return (1);
    3207             : }
    3208             : 
    3209             : /*
    3210             :  * Read a whole strip off data from the file, and convert to RGBA form.
    3211             :  * If this is the last strip, then it will only contain the portion of
    3212             :  * the strip that is actually within the image space.  The result is
    3213             :  * organized in bottom to top form.
    3214             :  */
    3215             : 
    3216           0 : int TIFFReadRGBAStrip(TIFF *tif, uint32_t row, uint32_t *raster)
    3217             : 
    3218             : {
    3219           0 :     return TIFFReadRGBAStripExt(tif, row, raster, 0);
    3220             : }
    3221             : 
    3222          59 : int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
    3223             :                          int stop_on_error)
    3224             : 
    3225             : {
    3226          59 :     char emsg[EMSG_BUF_SIZE] = "";
    3227             :     TIFFRGBAImage img;
    3228             :     int ok;
    3229             :     uint32_t rowsperstrip, rows_to_read;
    3230             : 
    3231          59 :     if (TIFFIsTiled(tif))
    3232             :     {
    3233           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3234             :                       "Can't use TIFFReadRGBAStrip() with tiled file.");
    3235           0 :         return (0);
    3236             :     }
    3237             : 
    3238          59 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    3239             : 
    3240          59 :     if (rowsperstrip == 0)
    3241             :     {
    3242           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    3243           0 :         return (0);
    3244             :     }
    3245             : 
    3246          59 :     if ((row % rowsperstrip) != 0)
    3247             :     {
    3248           0 :         TIFFErrorExtR(
    3249             :             tif, TIFFFileName(tif),
    3250             :             "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
    3251           0 :         return (0);
    3252             :     }
    3253             : 
    3254         118 :     if (TIFFRGBAImageOK(tif, emsg) &&
    3255          59 :         TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3256             :     {
    3257          53 :         if (row >= img.height)
    3258             :         {
    3259           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    3260             :                           "Invalid row passed to TIFFReadRGBAStrip().");
    3261           0 :             TIFFRGBAImageEnd(&img);
    3262           0 :             return (0);
    3263             :         }
    3264             : 
    3265          53 :         img.row_offset = row;
    3266          53 :         img.col_offset = 0;
    3267             : 
    3268          53 :         if (row + rowsperstrip > img.height)
    3269          14 :             rows_to_read = img.height - row;
    3270             :         else
    3271          39 :             rows_to_read = rowsperstrip;
    3272             : 
    3273          53 :         ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read);
    3274             : 
    3275          53 :         TIFFRGBAImageEnd(&img);
    3276             :     }
    3277             :     else
    3278             :     {
    3279           6 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3280           6 :         ok = 0;
    3281             :     }
    3282             : 
    3283          59 :     return (ok);
    3284             : }
    3285             : 
    3286             : /*
    3287             :  * Read a whole tile off data from the file, and convert to RGBA form.
    3288             :  * The returned RGBA data is organized from bottom to top of tile,
    3289             :  * and may include zeroed areas if the tile extends off the image.
    3290             :  */
    3291             : 
    3292           0 : int TIFFReadRGBATile(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster)
    3293             : 
    3294             : {
    3295           0 :     return TIFFReadRGBATileExt(tif, col, row, raster, 0);
    3296             : }
    3297             : 
    3298           4 : int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
    3299             :                         int stop_on_error)
    3300             : {
    3301           4 :     char emsg[EMSG_BUF_SIZE] = "";
    3302             :     TIFFRGBAImage img;
    3303             :     int ok;
    3304             :     uint32_t tile_xsize, tile_ysize;
    3305             :     uint32_t read_xsize, read_ysize;
    3306             :     uint32_t i_row;
    3307             : 
    3308             :     /*
    3309             :      * Verify that our request is legal - on a tile file, and on a
    3310             :      * tile boundary.
    3311             :      */
    3312             : 
    3313           4 :     if (!TIFFIsTiled(tif))
    3314             :     {
    3315           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3316             :                       "Can't use TIFFReadRGBATile() with striped file.");
    3317           0 :         return (0);
    3318             :     }
    3319             : 
    3320           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
    3321           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
    3322           4 :     if (tile_xsize == 0 || tile_ysize == 0)
    3323             :     {
    3324           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3325             :                       "tile_xsize or tile_ysize is zero");
    3326           0 :         return (0);
    3327             :     }
    3328             : 
    3329           4 :     if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
    3330             :     {
    3331           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3332             :                       "Row/col passed to TIFFReadRGBATile() must be top"
    3333             :                       "left corner of a tile.");
    3334           0 :         return (0);
    3335             :     }
    3336             : 
    3337             :     /*
    3338             :      * Setup the RGBA reader.
    3339             :      */
    3340             : 
    3341           8 :     if (!TIFFRGBAImageOK(tif, emsg) ||
    3342           4 :         !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3343             :     {
    3344           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3345           0 :         return (0);
    3346             :     }
    3347             : 
    3348           4 :     if (col >= img.width || row >= img.height)
    3349             :     {
    3350           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3351             :                       "Invalid row/col passed to TIFFReadRGBATile().");
    3352           0 :         TIFFRGBAImageEnd(&img);
    3353           0 :         return (0);
    3354             :     }
    3355             : 
    3356             :     /*
    3357             :      * The TIFFRGBAImageGet() function doesn't allow us to get off the
    3358             :      * edge of the image, even to fill an otherwise valid tile.  So we
    3359             :      * figure out how much we can read, and fix up the tile buffer to
    3360             :      * a full tile configuration afterwards.
    3361             :      */
    3362             : 
    3363           4 :     if (row + tile_ysize > img.height)
    3364           4 :         read_ysize = img.height - row;
    3365             :     else
    3366           0 :         read_ysize = tile_ysize;
    3367             : 
    3368           4 :     if (col + tile_xsize > img.width)
    3369           4 :         read_xsize = img.width - col;
    3370             :     else
    3371           0 :         read_xsize = tile_xsize;
    3372             : 
    3373             :     /*
    3374             :      * Read the chunk of imagery.
    3375             :      */
    3376             : 
    3377           4 :     img.row_offset = row;
    3378           4 :     img.col_offset = col;
    3379             : 
    3380           4 :     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize);
    3381             : 
    3382           4 :     TIFFRGBAImageEnd(&img);
    3383             : 
    3384             :     /*
    3385             :      * If our read was incomplete we will need to fix up the tile by
    3386             :      * shifting the data around as if a full tile of data is being returned.
    3387             :      *
    3388             :      * This is all the more complicated because the image is organized in
    3389             :      * bottom to top format.
    3390             :      */
    3391             : 
    3392           4 :     if (read_xsize == tile_xsize && read_ysize == tile_ysize)
    3393           0 :         return (ok);
    3394             : 
    3395         500 :     for (i_row = 0; i_row < read_ysize; i_row++)
    3396             :     {
    3397         496 :         memmove(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize,
    3398         496 :                 raster + (size_t)(read_ysize - i_row - 1) * read_xsize,
    3399             :                 read_xsize * sizeof(uint32_t));
    3400         496 :         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize +
    3401             :                         read_xsize,
    3402         496 :                     0, sizeof(uint32_t) * (tile_xsize - read_xsize));
    3403             :     }
    3404             : 
    3405         468 :     for (i_row = read_ysize; i_row < tile_ysize; i_row++)
    3406             :     {
    3407         464 :         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize, 0,
    3408         464 :                     sizeof(uint32_t) * tile_xsize);
    3409             :     }
    3410             : 
    3411           4 :     return (ok);
    3412             : }

Generated by: LCOV version 1.14