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-05-03 15:49:35 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             :     /*
     771             :      *  Leftmost tile is clipped on left side if col_offset > 0.
     772             :      */
     773           3 :     leftmost_fromskew = img->col_offset % tw;
     774           3 :     leftmost_tw = tw - leftmost_fromskew;
     775           3 :     leftmost_toskew = toskew + leftmost_fromskew;
     776           6 :     for (row = 0; ret != 0 && row < h; row += nrow)
     777             :     {
     778           3 :         rowstoread = th - (row + img->row_offset) % th;
     779           3 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
     780           3 :         fromskew = leftmost_fromskew;
     781           3 :         this_tw = leftmost_tw;
     782           3 :         this_toskew = leftmost_toskew;
     783           3 :         tocol = 0;
     784           3 :         col = img->col_offset;
     785           5 :         while (tocol < w)
     786             :         {
     787           3 :             if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize, col,
     788           3 :                                             row + img->row_offset, 0,
     789           1 :                                             0) == (tmsize_t)(-1) &&
     790           1 :                 (buf == NULL || img->stoponerr))
     791             :             {
     792           1 :                 ret = 0;
     793           1 :                 break;
     794             :             }
     795           2 :             pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
     796           2 :                   ((tmsize_t)fromskew * img->samplesperpixel);
     797           2 :             if (tocol + this_tw > w)
     798             :             {
     799             :                 /*
     800             :                  * Rightmost tile is clipped on right side.
     801             :                  */
     802           2 :                 fromskew = tw - (w - tocol);
     803           2 :                 this_tw = tw - fromskew;
     804           2 :                 this_toskew = toskew + fromskew;
     805             :             }
     806           2 :             tmsize_t roffset = (tmsize_t)y * w + tocol;
     807           2 :             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
     808             :                    this_toskew, buf + pos);
     809           2 :             tocol += this_tw;
     810           2 :             col += this_tw;
     811             :             /*
     812             :              * After the leftmost tile, tiles are no longer clipped on left
     813             :              * side.
     814             :              */
     815           2 :             fromskew = 0;
     816           2 :             this_tw = tw;
     817           2 :             this_toskew = toskew;
     818             :         }
     819             : 
     820           3 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
     821             :     }
     822           3 :     _TIFFfreeExt(img->tif, buf);
     823             : 
     824           3 :     if (flip & FLIP_HORIZONTALLY)
     825             :     {
     826             :         uint32_t line;
     827             : 
     828           0 :         for (line = 0; line < h; line++)
     829             :         {
     830           0 :             uint32_t *left = raster + (line * w);
     831           0 :             uint32_t *right = left + w - 1;
     832             : 
     833           0 :             while (left < right)
     834             :             {
     835           0 :                 uint32_t temp = *left;
     836           0 :                 *left = *right;
     837           0 :                 *right = temp;
     838           0 :                 left++;
     839           0 :                 right--;
     840             :             }
     841             :         }
     842             :     }
     843             : 
     844           3 :     return (ret);
     845             : }
     846             : 
     847             : /*
     848             :  * Get an tile-organized image that has
     849             :  *   SamplesPerPixel > 1
     850             :  *   PlanarConfiguration separated
     851             :  * We assume that all such images are RGB.
     852             :  */
     853           1 : static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
     854             :                           uint32_t h)
     855             : {
     856           1 :     TIFF *tif = img->tif;
     857           1 :     tileSeparateRoutine put = img->put.separate;
     858             :     uint32_t col, row, y, rowstoread;
     859             :     tmsize_t pos;
     860             :     uint32_t tw, th;
     861           1 :     unsigned char *buf = NULL;
     862           1 :     unsigned char *p0 = NULL;
     863           1 :     unsigned char *p1 = NULL;
     864           1 :     unsigned char *p2 = NULL;
     865           1 :     unsigned char *pa = NULL;
     866             :     tmsize_t tilesize;
     867             :     tmsize_t bufsize;
     868             :     int32_t fromskew, toskew;
     869           1 :     int alpha = img->alpha;
     870             :     uint32_t nrow;
     871           1 :     int ret = 1, flip;
     872             :     uint16_t colorchannels;
     873             :     uint32_t this_tw, tocol;
     874             :     int32_t this_toskew, leftmost_toskew;
     875             :     int32_t leftmost_fromskew;
     876             :     uint32_t leftmost_tw;
     877             : 
     878           1 :     tilesize = TIFFTileSize(tif);
     879             :     bufsize =
     880           1 :         _TIFFMultiplySSize(tif, alpha ? 4 : 3, tilesize, "gtTileSeparate");
     881           1 :     if (bufsize == 0)
     882             :     {
     883           0 :         return (0);
     884             :     }
     885             : 
     886           1 :     TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
     887           1 :     TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
     888             : 
     889           1 :     flip = setorientation(img);
     890           1 :     if (flip & FLIP_VERTICALLY)
     891             :     {
     892           1 :         if ((tw + w) > INT_MAX)
     893             :         {
     894           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     895             :                           "unsupported tile size (too wide)");
     896           0 :             return (0);
     897             :         }
     898           1 :         y = h - 1;
     899           1 :         toskew = -(int32_t)(tw + w);
     900             :     }
     901             :     else
     902             :     {
     903           0 :         if (tw > (INT_MAX + w))
     904             :         {
     905           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "%s",
     906             :                           "unsupported tile size (too wide)");
     907           0 :             return (0);
     908             :         }
     909           0 :         y = 0;
     910           0 :         toskew = -(int32_t)(tw - w);
     911             :     }
     912             : 
     913           1 :     switch (img->photometric)
     914             :     {
     915           0 :         case PHOTOMETRIC_MINISWHITE:
     916             :         case PHOTOMETRIC_MINISBLACK:
     917             :         case PHOTOMETRIC_PALETTE:
     918           0 :             colorchannels = 1;
     919           0 :             break;
     920             : 
     921           1 :         default:
     922           1 :             colorchannels = 3;
     923           1 :             break;
     924             :     }
     925             : 
     926           1 :     if (tw == 0 || th == 0)
     927             :     {
     928           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero");
     929           0 :         return (0);
     930             :     }
     931             : 
     932             :     /*
     933             :      *  Leftmost tile is clipped on left side if col_offset > 0.
     934             :      */
     935           1 :     leftmost_fromskew = img->col_offset % tw;
     936           1 :     leftmost_tw = tw - leftmost_fromskew;
     937           1 :     leftmost_toskew = toskew + leftmost_fromskew;
     938           2 :     for (row = 0; ret != 0 && row < h; row += nrow)
     939             :     {
     940           1 :         rowstoread = th - (row + img->row_offset) % th;
     941           1 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
     942           1 :         fromskew = leftmost_fromskew;
     943           1 :         this_tw = leftmost_tw;
     944           1 :         this_toskew = leftmost_toskew;
     945           1 :         tocol = 0;
     946           1 :         col = img->col_offset;
     947           2 :         while (tocol < w)
     948             :         {
     949           1 :             if (buf == NULL)
     950             :             {
     951           1 :                 if (_TIFFReadTileAndAllocBuffer(tif, (void **)&buf, bufsize,
     952           1 :                                                 col, row + img->row_offset, 0,
     953           0 :                                                 0) == (tmsize_t)(-1) &&
     954           0 :                     (buf == NULL || img->stoponerr))
     955             :                 {
     956           0 :                     ret = 0;
     957           0 :                     break;
     958             :                 }
     959           1 :                 p0 = buf;
     960           1 :                 if (colorchannels == 1)
     961             :                 {
     962           0 :                     p2 = p1 = p0;
     963           0 :                     pa = (alpha ? (p0 + 3 * tilesize) : NULL);
     964             :                 }
     965             :                 else
     966             :                 {
     967           1 :                     p1 = p0 + tilesize;
     968           1 :                     p2 = p1 + tilesize;
     969           1 :                     pa = (alpha ? (p2 + tilesize) : NULL);
     970             :                 }
     971             :             }
     972           0 :             else if (TIFFReadTile(tif, p0, col, row + img->row_offset, 0, 0) ==
     973           0 :                          (tmsize_t)(-1) &&
     974           0 :                      img->stoponerr)
     975             :             {
     976           0 :                 ret = 0;
     977           0 :                 break;
     978             :             }
     979           2 :             if (colorchannels > 1 &&
     980           1 :                 TIFFReadTile(tif, p1, col, row + img->row_offset, 0, 1) ==
     981           0 :                     (tmsize_t)(-1) &&
     982           0 :                 img->stoponerr)
     983             :             {
     984           0 :                 ret = 0;
     985           0 :                 break;
     986             :             }
     987           2 :             if (colorchannels > 1 &&
     988           1 :                 TIFFReadTile(tif, p2, col, row + img->row_offset, 0, 2) ==
     989           0 :                     (tmsize_t)(-1) &&
     990           0 :                 img->stoponerr)
     991             :             {
     992           0 :                 ret = 0;
     993           0 :                 break;
     994             :             }
     995           1 :             if (alpha &&
     996           0 :                 TIFFReadTile(tif, pa, col, row + img->row_offset, 0,
     997           0 :                              colorchannels) == (tmsize_t)(-1) &&
     998           0 :                 img->stoponerr)
     999             :             {
    1000           0 :                 ret = 0;
    1001           0 :                 break;
    1002             :             }
    1003             : 
    1004           1 :             pos = ((row + img->row_offset) % th) * TIFFTileRowSize(tif) +
    1005           1 :                   ((tmsize_t)fromskew * img->samplesperpixel);
    1006           1 :             if (tocol + this_tw > w)
    1007             :             {
    1008             :                 /*
    1009             :                  * Rightmost tile is clipped on right side.
    1010             :                  */
    1011           1 :                 fromskew = tw - (w - tocol);
    1012           1 :                 this_tw = tw - fromskew;
    1013           1 :                 this_toskew = toskew + fromskew;
    1014             :             }
    1015           1 :             tmsize_t roffset = (tmsize_t)y * w + tocol;
    1016           1 :             (*put)(img, raster + roffset, tocol, y, this_tw, nrow, fromskew,
    1017             :                    this_toskew, p0 + pos, p1 + pos, p2 + pos,
    1018           0 :                    (alpha ? (pa + pos) : NULL));
    1019           1 :             tocol += this_tw;
    1020           1 :             col += this_tw;
    1021             :             /*
    1022             :              * After the leftmost tile, tiles are no longer clipped on left
    1023             :              * side.
    1024             :              */
    1025           1 :             fromskew = 0;
    1026           1 :             this_tw = tw;
    1027           1 :             this_toskew = toskew;
    1028             :         }
    1029             : 
    1030           1 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1031             :     }
    1032             : 
    1033           1 :     if (flip & FLIP_HORIZONTALLY)
    1034             :     {
    1035             :         uint32_t line;
    1036             : 
    1037           0 :         for (line = 0; line < h; line++)
    1038             :         {
    1039           0 :             uint32_t *left = raster + (line * w);
    1040           0 :             uint32_t *right = left + w - 1;
    1041             : 
    1042           0 :             while (left < right)
    1043             :             {
    1044           0 :                 uint32_t temp = *left;
    1045           0 :                 *left = *right;
    1046           0 :                 *right = temp;
    1047           0 :                 left++;
    1048           0 :                 right--;
    1049             :             }
    1050             :         }
    1051             :     }
    1052             : 
    1053           1 :     _TIFFfreeExt(img->tif, buf);
    1054           1 :     return (ret);
    1055             : }
    1056             : 
    1057             : /*
    1058             :  * Get a strip-organized image that has
    1059             :  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
    1060             :  * or
    1061             :  *  SamplesPerPixel == 1
    1062             :  */
    1063          51 : static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
    1064             :                          uint32_t h)
    1065             : {
    1066          51 :     TIFF *tif = img->tif;
    1067          51 :     tileContigRoutine put = img->put.contig;
    1068             :     uint32_t row, y, nrow, nrowsub, rowstoread;
    1069             :     tmsize_t pos;
    1070          51 :     unsigned char *buf = NULL;
    1071             :     uint32_t rowsperstrip;
    1072             :     uint16_t subsamplinghor, subsamplingver;
    1073          51 :     uint32_t imagewidth = img->width;
    1074             :     tmsize_t scanline;
    1075             :     int32_t fromskew, toskew;
    1076          51 :     int ret = 1, flip;
    1077             :     tmsize_t maxstripsize;
    1078             : 
    1079          51 :     TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor,
    1080             :                           &subsamplingver);
    1081          51 :     if (subsamplingver == 0)
    1082             :     {
    1083           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    1084             :                       "Invalid vertical YCbCr subsampling");
    1085           0 :         return (0);
    1086             :     }
    1087             : 
    1088          51 :     maxstripsize = TIFFStripSize(tif);
    1089             : 
    1090          51 :     flip = setorientation(img);
    1091          51 :     if (flip & FLIP_VERTICALLY)
    1092             :     {
    1093          51 :         if (w > INT_MAX)
    1094             :         {
    1095           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
    1096           0 :             return (0);
    1097             :         }
    1098          51 :         y = h - 1;
    1099          51 :         toskew = -(int32_t)(w + w);
    1100             :     }
    1101             :     else
    1102             :     {
    1103           0 :         y = 0;
    1104           0 :         toskew = -(int32_t)(w - w);
    1105             :     }
    1106             : 
    1107          51 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    1108          51 :     if (rowsperstrip == 0)
    1109             :     {
    1110           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    1111           0 :         return (0);
    1112             :     }
    1113             : 
    1114             : 
    1115          51 :     scanline = TIFFScanlineSize(tif);
    1116          51 :     fromskew = (w < imagewidth ? imagewidth - w : 0);
    1117         102 :     for (row = 0; row < h; row += nrow)
    1118             :     {
    1119             :         uint32_t temp;
    1120          51 :         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
    1121          51 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
    1122          51 :         nrowsub = nrow;
    1123          51 :         if ((nrowsub % subsamplingver) != 0)
    1124          11 :             nrowsub += subsamplingver - nrowsub % subsamplingver;
    1125          51 :         temp = (row + img->row_offset) % rowsperstrip + nrowsub;
    1126          51 :         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
    1127             :         {
    1128           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    1129             :                           "Integer overflow in gtStripContig");
    1130           0 :             return 0;
    1131             :         }
    1132          51 :         if (_TIFFReadEncodedStripAndAllocBuffer(
    1133          51 :                 tif, TIFFComputeStrip(tif, row + img->row_offset, 0),
    1134             :                 (void **)(&buf), maxstripsize,
    1135           0 :                 temp * scanline) == (tmsize_t)(-1) &&
    1136           0 :             (buf == NULL || img->stoponerr))
    1137             :         {
    1138           0 :             ret = 0;
    1139           0 :             break;
    1140             :         }
    1141             : 
    1142          51 :         pos = ((row + img->row_offset) % rowsperstrip) * scanline +
    1143          51 :               ((tmsize_t)img->col_offset * img->samplesperpixel);
    1144          51 :         tmsize_t roffset = (tmsize_t)y * w;
    1145          51 :         (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew,
    1146             :                buf + pos);
    1147          51 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1148             :     }
    1149             : 
    1150          51 :     if (flip & FLIP_HORIZONTALLY)
    1151             :     {
    1152             :         uint32_t line;
    1153             : 
    1154           0 :         for (line = 0; line < h; line++)
    1155             :         {
    1156           0 :             uint32_t *left = raster + (line * w);
    1157           0 :             uint32_t *right = left + w - 1;
    1158             : 
    1159           0 :             while (left < right)
    1160             :             {
    1161           0 :                 uint32_t temp = *left;
    1162           0 :                 *left = *right;
    1163           0 :                 *right = temp;
    1164           0 :                 left++;
    1165           0 :                 right--;
    1166             :             }
    1167             :         }
    1168             :     }
    1169             : 
    1170          51 :     _TIFFfreeExt(img->tif, buf);
    1171          51 :     return (ret);
    1172             : }
    1173             : 
    1174             : /*
    1175             :  * Get a strip-organized image with
    1176             :  *   SamplesPerPixel > 1
    1177             :  *   PlanarConfiguration separated
    1178             :  * We assume that all such images are RGB.
    1179             :  */
    1180           2 : static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w,
    1181             :                            uint32_t h)
    1182             : {
    1183           2 :     TIFF *tif = img->tif;
    1184           2 :     tileSeparateRoutine put = img->put.separate;
    1185           2 :     unsigned char *buf = NULL;
    1186           2 :     unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL;
    1187             :     uint32_t row, y, nrow, rowstoread;
    1188             :     tmsize_t pos;
    1189             :     tmsize_t scanline;
    1190             :     uint32_t rowsperstrip, offset_row;
    1191           2 :     uint32_t imagewidth = img->width;
    1192             :     tmsize_t stripsize;
    1193             :     tmsize_t bufsize;
    1194             :     int32_t fromskew, toskew;
    1195           2 :     int alpha = img->alpha;
    1196           2 :     int ret = 1, flip;
    1197             :     uint16_t colorchannels;
    1198             : 
    1199           2 :     stripsize = TIFFStripSize(tif);
    1200             :     bufsize =
    1201           2 :         _TIFFMultiplySSize(tif, alpha ? 4 : 3, stripsize, "gtStripSeparate");
    1202           2 :     if (bufsize == 0)
    1203             :     {
    1204           0 :         return (0);
    1205             :     }
    1206             : 
    1207           2 :     flip = setorientation(img);
    1208           2 :     if (flip & FLIP_VERTICALLY)
    1209             :     {
    1210           2 :         if (w > INT_MAX)
    1211             :         {
    1212           0 :             TIFFErrorExtR(tif, TIFFFileName(tif), "Width overflow");
    1213           0 :             return (0);
    1214             :         }
    1215           2 :         y = h - 1;
    1216           2 :         toskew = -(int32_t)(w + w);
    1217             :     }
    1218             :     else
    1219             :     {
    1220           0 :         y = 0;
    1221           0 :         toskew = -(int32_t)(w - w);
    1222             :     }
    1223             : 
    1224           2 :     switch (img->photometric)
    1225             :     {
    1226           1 :         case PHOTOMETRIC_MINISWHITE:
    1227             :         case PHOTOMETRIC_MINISBLACK:
    1228             :         case PHOTOMETRIC_PALETTE:
    1229           1 :             colorchannels = 1;
    1230           1 :             break;
    1231             : 
    1232           1 :         default:
    1233           1 :             colorchannels = 3;
    1234           1 :             break;
    1235             :     }
    1236             : 
    1237           2 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    1238           2 :     if (rowsperstrip == 0)
    1239             :     {
    1240           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    1241           0 :         return (0);
    1242             :     }
    1243             : 
    1244           2 :     scanline = TIFFScanlineSize(tif);
    1245           2 :     fromskew = (w < imagewidth ? imagewidth - w : 0);
    1246           4 :     for (row = 0; row < h; row += nrow)
    1247             :     {
    1248             :         uint32_t temp;
    1249           2 :         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
    1250           2 :         nrow = (row + rowstoread > h ? h - row : rowstoread);
    1251           2 :         offset_row = row + img->row_offset;
    1252           2 :         temp = (row + img->row_offset) % rowsperstrip + nrow;
    1253           2 :         if (scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline))
    1254             :         {
    1255           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    1256             :                           "Integer overflow in gtStripSeparate");
    1257           0 :             return 0;
    1258             :         }
    1259           2 :         if (buf == NULL)
    1260             :         {
    1261           2 :             if (_TIFFReadEncodedStripAndAllocBuffer(
    1262             :                     tif, TIFFComputeStrip(tif, offset_row, 0), (void **)&buf,
    1263           0 :                     bufsize, temp * scanline) == (tmsize_t)(-1) &&
    1264           0 :                 (buf == NULL || img->stoponerr))
    1265             :             {
    1266           0 :                 ret = 0;
    1267           0 :                 break;
    1268             :             }
    1269           2 :             p0 = buf;
    1270           2 :             if (colorchannels == 1)
    1271             :             {
    1272           1 :                 p2 = p1 = p0;
    1273           1 :                 pa = (alpha ? (p0 + 3 * stripsize) : NULL);
    1274             :             }
    1275             :             else
    1276             :             {
    1277           1 :                 p1 = p0 + stripsize;
    1278           1 :                 p2 = p1 + stripsize;
    1279           1 :                 pa = (alpha ? (p2 + stripsize) : NULL);
    1280             :             }
    1281             :         }
    1282           0 :         else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
    1283           0 :                                       p0, temp * scanline) == (tmsize_t)(-1) &&
    1284           0 :                  img->stoponerr)
    1285             :         {
    1286           0 :             ret = 0;
    1287           0 :             break;
    1288             :         }
    1289           3 :         if (colorchannels > 1 &&
    1290           1 :             TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), p1,
    1291           0 :                                  temp * scanline) == (tmsize_t)(-1) &&
    1292           0 :             img->stoponerr)
    1293             :         {
    1294           0 :             ret = 0;
    1295           0 :             break;
    1296             :         }
    1297           3 :         if (colorchannels > 1 &&
    1298           1 :             TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), p2,
    1299           0 :                                  temp * scanline) == (tmsize_t)(-1) &&
    1300           0 :             img->stoponerr)
    1301             :         {
    1302           0 :             ret = 0;
    1303           0 :             break;
    1304             :         }
    1305           2 :         if (alpha)
    1306             :         {
    1307           0 :             if (TIFFReadEncodedStrip(
    1308             :                     tif, TIFFComputeStrip(tif, offset_row, colorchannels), pa,
    1309           0 :                     temp * scanline) == (tmsize_t)(-1) &&
    1310           0 :                 img->stoponerr)
    1311             :             {
    1312           0 :                 ret = 0;
    1313           0 :                 break;
    1314             :             }
    1315             :         }
    1316             : 
    1317           2 :         pos = ((row + img->row_offset) % rowsperstrip) * scanline +
    1318           2 :               ((tmsize_t)img->col_offset * img->samplesperpixel);
    1319           2 :         tmsize_t roffset = (tmsize_t)y * w;
    1320           2 :         (*put)(img, raster + roffset, 0, y, w, nrow, fromskew, toskew, p0 + pos,
    1321           0 :                p1 + pos, p2 + pos, (alpha ? (pa + pos) : NULL));
    1322           2 :         y += ((flip & FLIP_VERTICALLY) ? -(int32_t)nrow : (int32_t)nrow);
    1323             :     }
    1324             : 
    1325           2 :     if (flip & FLIP_HORIZONTALLY)
    1326             :     {
    1327             :         uint32_t line;
    1328             : 
    1329           0 :         for (line = 0; line < h; line++)
    1330             :         {
    1331           0 :             uint32_t *left = raster + (line * w);
    1332           0 :             uint32_t *right = left + w - 1;
    1333             : 
    1334           0 :             while (left < right)
    1335             :             {
    1336           0 :                 uint32_t temp = *left;
    1337           0 :                 *left = *right;
    1338           0 :                 *right = temp;
    1339           0 :                 left++;
    1340           0 :                 right--;
    1341             :             }
    1342             :         }
    1343             :     }
    1344             : 
    1345           2 :     _TIFFfreeExt(img->tif, buf);
    1346           2 :     return (ret);
    1347             : }
    1348             : 
    1349             : /*
    1350             :  * The following routines move decoded data returned
    1351             :  * from the TIFF library into rasters filled with packed
    1352             :  * ABGR pixels (i.e. suitable for passing to lrecwrite.)
    1353             :  *
    1354             :  * The routines have been created according to the most
    1355             :  * important cases and optimized.  PickContigCase and
    1356             :  * PickSeparateCase analyze the parameters and select
    1357             :  * the appropriate "get" and "put" routine to use.
    1358             :  */
    1359             : #define REPEAT8(op)                                                            \
    1360             :     REPEAT4(op);                                                               \
    1361             :     REPEAT4(op)
    1362             : #define REPEAT4(op)                                                            \
    1363             :     REPEAT2(op);                                                               \
    1364             :     REPEAT2(op)
    1365             : #define REPEAT2(op)                                                            \
    1366             :     op;                                                                        \
    1367             :     op
    1368             : #define CASE8(x, op)                                                           \
    1369             :     switch (x)                                                                 \
    1370             :     {                                                                          \
    1371             :         case 7:                                                                \
    1372             :             op; /*-fallthrough*/                                               \
    1373             :         case 6:                                                                \
    1374             :             op; /*-fallthrough*/                                               \
    1375             :         case 5:                                                                \
    1376             :             op; /*-fallthrough*/                                               \
    1377             :         case 4:                                                                \
    1378             :             op; /*-fallthrough*/                                               \
    1379             :         case 3:                                                                \
    1380             :             op; /*-fallthrough*/                                               \
    1381             :         case 2:                                                                \
    1382             :             op; /*-fallthrough*/                                               \
    1383             :         case 1:                                                                \
    1384             :             op;                                                                \
    1385             :     }
    1386             : #define CASE4(x, op)                                                           \
    1387             :     switch (x)                                                                 \
    1388             :     {                                                                          \
    1389             :         case 3:                                                                \
    1390             :             op; /*-fallthrough*/                                               \
    1391             :         case 2:                                                                \
    1392             :             op; /*-fallthrough*/                                               \
    1393             :         case 1:                                                                \
    1394             :             op;                                                                \
    1395             :     }
    1396             : #define NOP
    1397             : 
    1398             : #define UNROLL8(w, op1, op2)                                                   \
    1399             :     {                                                                          \
    1400             :         uint32_t _x;                                                           \
    1401             :         for (_x = w; _x >= 8; _x -= 8)                                         \
    1402             :         {                                                                      \
    1403             :             op1;                                                               \
    1404             :             REPEAT8(op2);                                                      \
    1405             :         }                                                                      \
    1406             :         if (_x > 0)                                                            \
    1407             :         {                                                                      \
    1408             :             op1;                                                               \
    1409             :             CASE8(_x, op2);                                                    \
    1410             :         }                                                                      \
    1411             :     }
    1412             : #define UNROLL4(w, op1, op2)                                                   \
    1413             :     {                                                                          \
    1414             :         uint32_t _x;                                                           \
    1415             :         for (_x = w; _x >= 4; _x -= 4)                                         \
    1416             :         {                                                                      \
    1417             :             op1;                                                               \
    1418             :             REPEAT4(op2);                                                      \
    1419             :         }                                                                      \
    1420             :         if (_x > 0)                                                            \
    1421             :         {                                                                      \
    1422             :             op1;                                                               \
    1423             :             CASE4(_x, op2);                                                    \
    1424             :         }                                                                      \
    1425             :     }
    1426             : #define UNROLL2(w, op1, op2)                                                   \
    1427             :     {                                                                          \
    1428             :         uint32_t _x;                                                           \
    1429             :         for (_x = w; _x >= 2; _x -= 2)                                         \
    1430             :         {                                                                      \
    1431             :             op1;                                                               \
    1432             :             REPEAT2(op2);                                                      \
    1433             :         }                                                                      \
    1434             :         if (_x)                                                                \
    1435             :         {                                                                      \
    1436             :             op1;                                                               \
    1437             :             op2;                                                               \
    1438             :         }                                                                      \
    1439             :     }
    1440             : 
    1441             : #define SKEW(r, g, b, skew)                                                    \
    1442             :     {                                                                          \
    1443             :         r += skew;                                                             \
    1444             :         g += skew;                                                             \
    1445             :         b += skew;                                                             \
    1446             :     }
    1447             : #define SKEW4(r, g, b, a, skew)                                                \
    1448             :     {                                                                          \
    1449             :         r += skew;                                                             \
    1450             :         g += skew;                                                             \
    1451             :         b += skew;                                                             \
    1452             :         a += skew;                                                             \
    1453             :     }
    1454             : 
    1455             : #define A1 (((uint32_t)0xffL) << 24)
    1456             : #define PACK(r, g, b)                                                          \
    1457             :     ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) | A1)
    1458             : #define PACK4(r, g, b, a)                                                      \
    1459             :     ((uint32_t)(r) | ((uint32_t)(g) << 8) | ((uint32_t)(b) << 16) |            \
    1460             :      ((uint32_t)(a) << 24))
    1461             : #define W2B(v) (((v) >> 8) & 0xff)
    1462             : /* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */
    1463             : #define PACKW(r, g, b)                                                         \
    1464             :     ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) | A1)
    1465             : #define PACKW4(r, g, b, a)                                                     \
    1466             :     ((uint32_t)W2B(r) | ((uint32_t)W2B(g) << 8) | ((uint32_t)W2B(b) << 16) |   \
    1467             :      ((uint32_t)W2B(a) << 24))
    1468             : 
    1469             : #define DECLAREContigPutFunc(name)                                             \
    1470             :     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
    1471             :                      uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
    1472             :                      unsigned char *pp)
    1473             : 
    1474             : /*
    1475             :  * 8-bit palette => colormap/RGB
    1476             :  */
    1477           1 : DECLAREContigPutFunc(put8bitcmaptile)
    1478             : {
    1479           1 :     uint32_t **PALmap = img->PALmap;
    1480           1 :     int samplesperpixel = img->samplesperpixel;
    1481             : 
    1482             :     (void)y;
    1483          21 :     for (; h > 0; --h)
    1484             :     {
    1485         420 :         for (x = w; x > 0; --x)
    1486             :         {
    1487         400 :             *cp++ = PALmap[*pp][0];
    1488         400 :             pp += samplesperpixel;
    1489             :         }
    1490          20 :         cp += toskew;
    1491          20 :         pp += fromskew;
    1492             :     }
    1493           1 : }
    1494             : 
    1495             : /*
    1496             :  * 4-bit palette => colormap/RGB
    1497             :  */
    1498           0 : DECLAREContigPutFunc(put4bitcmaptile)
    1499             : {
    1500           0 :     uint32_t **PALmap = img->PALmap;
    1501             : 
    1502             :     (void)x;
    1503             :     (void)y;
    1504           0 :     fromskew /= 2;
    1505           0 :     for (; h > 0; --h)
    1506             :     {
    1507             :         uint32_t *bw;
    1508           0 :         UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1509           0 :         cp += toskew;
    1510           0 :         pp += fromskew;
    1511             :     }
    1512           0 : }
    1513             : 
    1514             : /*
    1515             :  * 2-bit palette => colormap/RGB
    1516             :  */
    1517           0 : DECLAREContigPutFunc(put2bitcmaptile)
    1518             : {
    1519           0 :     uint32_t **PALmap = img->PALmap;
    1520             : 
    1521             :     (void)x;
    1522             :     (void)y;
    1523           0 :     fromskew /= 4;
    1524           0 :     for (; h > 0; --h)
    1525             :     {
    1526             :         uint32_t *bw;
    1527           0 :         UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1528           0 :         cp += toskew;
    1529           0 :         pp += fromskew;
    1530             :     }
    1531           0 : }
    1532             : 
    1533             : /*
    1534             :  * 1-bit palette => colormap/RGB
    1535             :  */
    1536           0 : DECLAREContigPutFunc(put1bitcmaptile)
    1537             : {
    1538           0 :     uint32_t **PALmap = img->PALmap;
    1539             : 
    1540             :     (void)x;
    1541             :     (void)y;
    1542           0 :     fromskew /= 8;
    1543           0 :     for (; h > 0; --h)
    1544             :     {
    1545             :         uint32_t *bw;
    1546           0 :         UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
    1547           0 :         cp += toskew;
    1548           0 :         pp += fromskew;
    1549             :     }
    1550           0 : }
    1551             : 
    1552             : /*
    1553             :  * 8-bit greyscale => colormap/RGB
    1554             :  */
    1555           3 : DECLAREContigPutFunc(putgreytile)
    1556             : {
    1557           3 :     int samplesperpixel = img->samplesperpixel;
    1558           3 :     uint32_t **BWmap = img->BWmap;
    1559             : 
    1560             :     (void)y;
    1561          63 :     for (; h > 0; --h)
    1562             :     {
    1563        1260 :         for (x = w; x > 0; --x)
    1564             :         {
    1565        1200 :             *cp++ = BWmap[*pp][0];
    1566        1200 :             pp += samplesperpixel;
    1567             :         }
    1568          60 :         cp += toskew;
    1569          60 :         pp += fromskew;
    1570             :     }
    1571           3 : }
    1572             : 
    1573             : /*
    1574             :  * 8-bit greyscale with associated alpha => colormap/RGBA
    1575             :  */
    1576           6 : DECLAREContigPutFunc(putagreytile)
    1577             : {
    1578           6 :     int samplesperpixel = img->samplesperpixel;
    1579           6 :     uint32_t **BWmap = img->BWmap;
    1580             : 
    1581             :     (void)y;
    1582         156 :     for (; h > 0; --h)
    1583             :     {
    1584       24450 :         for (x = w; x > 0; --x)
    1585             :         {
    1586       24300 :             *cp++ = BWmap[*pp][0] & ((uint32_t) * (pp + 1) << 24 | ~A1);
    1587       24300 :             pp += samplesperpixel;
    1588             :         }
    1589         150 :         cp += toskew;
    1590         150 :         pp += fromskew;
    1591             :     }
    1592           6 : }
    1593             : 
    1594             : /*
    1595             :  * 16-bit greyscale => colormap/RGB
    1596             :  */
    1597           0 : DECLAREContigPutFunc(put16bitbwtile)
    1598             : {
    1599           0 :     int samplesperpixel = img->samplesperpixel;
    1600           0 :     uint32_t **BWmap = img->BWmap;
    1601             : 
    1602             :     (void)y;
    1603           0 :     for (; h > 0; --h)
    1604             :     {
    1605           0 :         uint16_t *wp = (uint16_t *)pp;
    1606             : 
    1607           0 :         for (x = w; x > 0; --x)
    1608             :         {
    1609             :             /* use high order byte of 16bit value */
    1610             : 
    1611           0 :             *cp++ = BWmap[*wp >> 8][0];
    1612           0 :             pp += 2 * samplesperpixel;
    1613           0 :             wp += samplesperpixel;
    1614             :         }
    1615           0 :         cp += toskew;
    1616           0 :         pp += fromskew;
    1617             :     }
    1618           0 : }
    1619             : 
    1620             : /*
    1621             :  * 1-bit bilevel => colormap/RGB
    1622             :  */
    1623           0 : DECLAREContigPutFunc(put1bitbwtile)
    1624             : {
    1625           0 :     uint32_t **BWmap = img->BWmap;
    1626             : 
    1627             :     (void)x;
    1628             :     (void)y;
    1629           0 :     fromskew /= 8;
    1630           0 :     for (; h > 0; --h)
    1631             :     {
    1632             :         uint32_t *bw;
    1633           0 :         UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1634           0 :         cp += toskew;
    1635           0 :         pp += fromskew;
    1636             :     }
    1637           0 : }
    1638             : 
    1639             : /*
    1640             :  * 2-bit greyscale => colormap/RGB
    1641             :  */
    1642           0 : DECLAREContigPutFunc(put2bitbwtile)
    1643             : {
    1644           0 :     uint32_t **BWmap = img->BWmap;
    1645             : 
    1646             :     (void)x;
    1647             :     (void)y;
    1648           0 :     fromskew /= 4;
    1649           0 :     for (; h > 0; --h)
    1650             :     {
    1651             :         uint32_t *bw;
    1652           0 :         UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1653           0 :         cp += toskew;
    1654           0 :         pp += fromskew;
    1655             :     }
    1656           0 : }
    1657             : 
    1658             : /*
    1659             :  * 4-bit greyscale => colormap/RGB
    1660             :  */
    1661           0 : DECLAREContigPutFunc(put4bitbwtile)
    1662             : {
    1663           0 :     uint32_t **BWmap = img->BWmap;
    1664             : 
    1665             :     (void)x;
    1666             :     (void)y;
    1667           0 :     fromskew /= 2;
    1668           0 :     for (; h > 0; --h)
    1669             :     {
    1670             :         uint32_t *bw;
    1671           0 :         UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1672           0 :         cp += toskew;
    1673           0 :         pp += fromskew;
    1674             :     }
    1675           0 : }
    1676             : 
    1677             : /*
    1678             :  * 8-bit packed samples, no Map => RGB
    1679             :  */
    1680           0 : DECLAREContigPutFunc(putRGBcontig8bittile)
    1681             : {
    1682           0 :     int samplesperpixel = img->samplesperpixel;
    1683             : 
    1684             :     (void)x;
    1685             :     (void)y;
    1686           0 :     fromskew *= samplesperpixel;
    1687           0 :     for (; h > 0; --h)
    1688             :     {
    1689           0 :         UNROLL8(w, NOP, *cp++ = PACK(pp[0], pp[1], pp[2]);
    1690             :                 pp += samplesperpixel);
    1691           0 :         cp += toskew;
    1692           0 :         pp += fromskew;
    1693             :     }
    1694           0 : }
    1695             : 
    1696             : /*
    1697             :  * 8-bit packed samples => RGBA w/ associated alpha
    1698             :  * (known to have Map == NULL)
    1699             :  */
    1700          13 : DECLAREContigPutFunc(putRGBAAcontig8bittile)
    1701             : {
    1702          13 :     int samplesperpixel = img->samplesperpixel;
    1703             : 
    1704             :     (void)x;
    1705             :     (void)y;
    1706          13 :     fromskew *= samplesperpixel;
    1707         163 :     for (; h > 0; --h)
    1708             :     {
    1709        3150 :         UNROLL8(w, NOP, *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
    1710             :                 pp += samplesperpixel);
    1711         150 :         cp += toskew;
    1712         150 :         pp += fromskew;
    1713             :     }
    1714          13 : }
    1715             : 
    1716             : /*
    1717             :  * 8-bit packed samples => RGBA w/ unassociated alpha
    1718             :  * (known to have Map == NULL)
    1719             :  */
    1720          13 : DECLAREContigPutFunc(putRGBUAcontig8bittile)
    1721             : {
    1722          13 :     int samplesperpixel = img->samplesperpixel;
    1723             :     (void)y;
    1724          13 :     fromskew *= samplesperpixel;
    1725         163 :     for (; h > 0; --h)
    1726             :     {
    1727             :         uint32_t r, g, b, a;
    1728             :         uint8_t *m;
    1729       24450 :         for (x = w; x > 0; --x)
    1730             :         {
    1731       24300 :             a = pp[3];
    1732       24300 :             m = img->UaToAa + ((size_t)a << 8);
    1733       24300 :             r = m[pp[0]];
    1734       24300 :             g = m[pp[1]];
    1735       24300 :             b = m[pp[2]];
    1736       24300 :             *cp++ = PACK4(r, g, b, a);
    1737       24300 :             pp += samplesperpixel;
    1738             :         }
    1739         150 :         cp += toskew;
    1740         150 :         pp += fromskew;
    1741             :     }
    1742          13 : }
    1743             : 
    1744             : /*
    1745             :  * 16-bit packed samples => RGB
    1746             :  */
    1747           0 : DECLAREContigPutFunc(putRGBcontig16bittile)
    1748             : {
    1749           0 :     int samplesperpixel = img->samplesperpixel;
    1750           0 :     uint16_t *wp = (uint16_t *)pp;
    1751             :     (void)y;
    1752           0 :     fromskew *= samplesperpixel;
    1753           0 :     for (; h > 0; --h)
    1754             :     {
    1755           0 :         for (x = w; x > 0; --x)
    1756             :         {
    1757           0 :             *cp++ = PACK(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1758             :                          img->Bitdepth16To8[wp[2]]);
    1759           0 :             wp += samplesperpixel;
    1760             :         }
    1761           0 :         cp += toskew;
    1762           0 :         wp += fromskew;
    1763             :     }
    1764           0 : }
    1765             : 
    1766             : /*
    1767             :  * 16-bit packed samples => RGBA w/ associated alpha
    1768             :  * (known to have Map == NULL)
    1769             :  */
    1770           0 : DECLAREContigPutFunc(putRGBAAcontig16bittile)
    1771             : {
    1772           0 :     int samplesperpixel = img->samplesperpixel;
    1773           0 :     uint16_t *wp = (uint16_t *)pp;
    1774             :     (void)y;
    1775           0 :     fromskew *= samplesperpixel;
    1776           0 :     for (; h > 0; --h)
    1777             :     {
    1778           0 :         for (x = w; x > 0; --x)
    1779             :         {
    1780           0 :             *cp++ = PACK4(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1781             :                           img->Bitdepth16To8[wp[2]], img->Bitdepth16To8[wp[3]]);
    1782           0 :             wp += samplesperpixel;
    1783             :         }
    1784           0 :         cp += toskew;
    1785           0 :         wp += fromskew;
    1786             :     }
    1787           0 : }
    1788             : 
    1789             : /*
    1790             :  * 16-bit packed samples => RGBA w/ unassociated alpha
    1791             :  * (known to have Map == NULL)
    1792             :  */
    1793           0 : DECLAREContigPutFunc(putRGBUAcontig16bittile)
    1794             : {
    1795           0 :     int samplesperpixel = img->samplesperpixel;
    1796           0 :     uint16_t *wp = (uint16_t *)pp;
    1797             :     (void)y;
    1798           0 :     fromskew *= samplesperpixel;
    1799           0 :     for (; h > 0; --h)
    1800             :     {
    1801             :         uint32_t r, g, b, a;
    1802             :         uint8_t *m;
    1803           0 :         for (x = w; x > 0; --x)
    1804             :         {
    1805           0 :             a = img->Bitdepth16To8[wp[3]];
    1806           0 :             m = img->UaToAa + ((size_t)a << 8);
    1807           0 :             r = m[img->Bitdepth16To8[wp[0]]];
    1808           0 :             g = m[img->Bitdepth16To8[wp[1]]];
    1809           0 :             b = m[img->Bitdepth16To8[wp[2]]];
    1810           0 :             *cp++ = PACK4(r, g, b, a);
    1811           0 :             wp += samplesperpixel;
    1812             :         }
    1813           0 :         cp += toskew;
    1814           0 :         wp += fromskew;
    1815             :     }
    1816           0 : }
    1817             : 
    1818             : /*
    1819             :  * 8-bit packed CMYK samples w/o Map => RGB
    1820             :  *
    1821             :  * NB: The conversion of CMYK->RGB is *very* crude.
    1822             :  */
    1823           6 : DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
    1824             : {
    1825           6 :     int samplesperpixel = img->samplesperpixel;
    1826             :     uint16_t r, g, b, k;
    1827             : 
    1828             :     (void)x;
    1829             :     (void)y;
    1830           6 :     fromskew *= samplesperpixel;
    1831         156 :     for (; h > 0; --h)
    1832             :     {
    1833        1050 :         UNROLL8(w, NOP, k = 255 - pp[3]; r = (k * (255 - pp[0])) / 255;
    1834             :                 g = (k * (255 - pp[1])) / 255; b = (k * (255 - pp[2])) / 255;
    1835             :                 *cp++ = PACK(r, g, b); pp += samplesperpixel);
    1836         150 :         cp += toskew;
    1837         150 :         pp += fromskew;
    1838             :     }
    1839           6 : }
    1840             : 
    1841             : /*
    1842             :  * 8-bit packed CMYK samples w/Map => RGB
    1843             :  *
    1844             :  * NB: The conversion of CMYK->RGB is *very* crude.
    1845             :  */
    1846           0 : DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
    1847             : {
    1848           0 :     int samplesperpixel = img->samplesperpixel;
    1849           0 :     TIFFRGBValue *Map = img->Map;
    1850             :     uint16_t r, g, b, k;
    1851             : 
    1852             :     (void)y;
    1853           0 :     fromskew *= samplesperpixel;
    1854           0 :     for (; h > 0; --h)
    1855             :     {
    1856           0 :         for (x = w; x > 0; --x)
    1857             :         {
    1858           0 :             k = 255 - pp[3];
    1859           0 :             r = (k * (255 - pp[0])) / 255;
    1860           0 :             g = (k * (255 - pp[1])) / 255;
    1861           0 :             b = (k * (255 - pp[2])) / 255;
    1862           0 :             *cp++ = PACK(Map[r], Map[g], Map[b]);
    1863           0 :             pp += samplesperpixel;
    1864             :         }
    1865           0 :         pp += fromskew;
    1866           0 :         cp += toskew;
    1867             :     }
    1868           0 : }
    1869             : 
    1870             : #define DECLARESepPutFunc(name)                                                \
    1871             :     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
    1872             :                      uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
    1873             :                      unsigned char *r, unsigned char *g, unsigned char *b,     \
    1874             :                      unsigned char *a)
    1875             : 
    1876             : /*
    1877             :  * 8-bit unpacked samples => RGB
    1878             :  */
    1879           3 : DECLARESepPutFunc(putRGBseparate8bittile)
    1880             : {
    1881             :     (void)img;
    1882             :     (void)x;
    1883             :     (void)y;
    1884             :     (void)a;
    1885         153 :     for (; h > 0; --h)
    1886             :     {
    1887        1050 :         UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
    1888         150 :         SKEW(r, g, b, fromskew);
    1889         150 :         cp += toskew;
    1890             :     }
    1891           3 : }
    1892             : 
    1893             : /*
    1894             :  * 8-bit unpacked samples => RGBA w/ associated alpha
    1895             :  */
    1896           0 : DECLARESepPutFunc(putRGBAAseparate8bittile)
    1897             : {
    1898             :     (void)img;
    1899             :     (void)x;
    1900             :     (void)y;
    1901           0 :     for (; h > 0; --h)
    1902             :     {
    1903           0 :         UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
    1904           0 :         SKEW4(r, g, b, a, fromskew);
    1905           0 :         cp += toskew;
    1906             :     }
    1907           0 : }
    1908             : 
    1909             : /*
    1910             :  * 8-bit unpacked CMYK samples => RGBA
    1911             :  */
    1912           0 : DECLARESepPutFunc(putCMYKseparate8bittile)
    1913             : {
    1914             :     (void)img;
    1915             :     (void)y;
    1916           0 :     for (; h > 0; --h)
    1917             :     {
    1918             :         uint32_t rv, gv, bv, kv;
    1919           0 :         for (x = w; x > 0; --x)
    1920             :         {
    1921           0 :             kv = 255 - *a++;
    1922           0 :             rv = (kv * (255 - *r++)) / 255;
    1923           0 :             gv = (kv * (255 - *g++)) / 255;
    1924           0 :             bv = (kv * (255 - *b++)) / 255;
    1925           0 :             *cp++ = PACK4(rv, gv, bv, 255);
    1926             :         }
    1927           0 :         SKEW4(r, g, b, a, fromskew);
    1928           0 :         cp += toskew;
    1929             :     }
    1930           0 : }
    1931             : 
    1932             : /*
    1933             :  * 8-bit unpacked samples => RGBA w/ unassociated alpha
    1934             :  */
    1935           0 : DECLARESepPutFunc(putRGBUAseparate8bittile)
    1936             : {
    1937             :     (void)img;
    1938             :     (void)y;
    1939           0 :     for (; h > 0; --h)
    1940             :     {
    1941             :         uint32_t rv, gv, bv, av;
    1942             :         uint8_t *m;
    1943           0 :         for (x = w; x > 0; --x)
    1944             :         {
    1945           0 :             av = *a++;
    1946           0 :             m = img->UaToAa + ((size_t)av << 8);
    1947           0 :             rv = m[*r++];
    1948           0 :             gv = m[*g++];
    1949           0 :             bv = m[*b++];
    1950           0 :             *cp++ = PACK4(rv, gv, bv, av);
    1951             :         }
    1952           0 :         SKEW4(r, g, b, a, fromskew);
    1953           0 :         cp += toskew;
    1954             :     }
    1955           0 : }
    1956             : 
    1957             : /*
    1958             :  * 16-bit unpacked samples => RGB
    1959             :  */
    1960           0 : DECLARESepPutFunc(putRGBseparate16bittile)
    1961             : {
    1962           0 :     uint16_t *wr = (uint16_t *)r;
    1963           0 :     uint16_t *wg = (uint16_t *)g;
    1964           0 :     uint16_t *wb = (uint16_t *)b;
    1965             :     (void)img;
    1966             :     (void)y;
    1967             :     (void)a;
    1968           0 :     for (; h > 0; --h)
    1969             :     {
    1970           0 :         for (x = 0; x < w; x++)
    1971           0 :             *cp++ = PACK(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    1972             :                          img->Bitdepth16To8[*wb++]);
    1973           0 :         SKEW(wr, wg, wb, fromskew);
    1974           0 :         cp += toskew;
    1975             :     }
    1976           0 : }
    1977             : 
    1978             : /*
    1979             :  * 16-bit unpacked samples => RGBA w/ associated alpha
    1980             :  */
    1981           0 : DECLARESepPutFunc(putRGBAAseparate16bittile)
    1982             : {
    1983           0 :     uint16_t *wr = (uint16_t *)r;
    1984           0 :     uint16_t *wg = (uint16_t *)g;
    1985           0 :     uint16_t *wb = (uint16_t *)b;
    1986           0 :     uint16_t *wa = (uint16_t *)a;
    1987             :     (void)img;
    1988             :     (void)y;
    1989           0 :     for (; h > 0; --h)
    1990             :     {
    1991           0 :         for (x = 0; x < w; x++)
    1992           0 :             *cp++ = PACK4(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    1993             :                           img->Bitdepth16To8[*wb++], img->Bitdepth16To8[*wa++]);
    1994           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    1995           0 :         cp += toskew;
    1996             :     }
    1997           0 : }
    1998             : 
    1999             : /*
    2000             :  * 16-bit unpacked samples => RGBA w/ unassociated alpha
    2001             :  */
    2002           0 : DECLARESepPutFunc(putRGBUAseparate16bittile)
    2003             : {
    2004           0 :     uint16_t *wr = (uint16_t *)r;
    2005           0 :     uint16_t *wg = (uint16_t *)g;
    2006           0 :     uint16_t *wb = (uint16_t *)b;
    2007           0 :     uint16_t *wa = (uint16_t *)a;
    2008             :     (void)img;
    2009             :     (void)y;
    2010           0 :     for (; h > 0; --h)
    2011             :     {
    2012             :         uint32_t r2, g2, b2, a2;
    2013             :         uint8_t *m;
    2014           0 :         for (x = w; x > 0; --x)
    2015             :         {
    2016           0 :             a2 = img->Bitdepth16To8[*wa++];
    2017           0 :             m = img->UaToAa + ((size_t)a2 << 8);
    2018           0 :             r2 = m[img->Bitdepth16To8[*wr++]];
    2019           0 :             g2 = m[img->Bitdepth16To8[*wg++]];
    2020           0 :             b2 = m[img->Bitdepth16To8[*wb++]];
    2021           0 :             *cp++ = PACK4(r2, g2, b2, a2);
    2022             :         }
    2023           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    2024           0 :         cp += toskew;
    2025             :     }
    2026           0 : }
    2027             : 
    2028             : /*
    2029             :  * 8-bit packed CIE L*a*b 1976 samples => RGB
    2030             :  */
    2031           1 : DECLAREContigPutFunc(putcontig8bitCIELab8)
    2032             : {
    2033             :     float X, Y, Z;
    2034             :     uint32_t r, g, b;
    2035             :     (void)y;
    2036           1 :     fromskew *= 3;
    2037           2 :     for (; h > 0; --h)
    2038             :     {
    2039           2 :         for (x = w; x > 0; --x)
    2040             :         {
    2041           1 :             TIFFCIELabToXYZ(img->cielab, (unsigned char)pp[0],
    2042           1 :                             (signed char)pp[1], (signed char)pp[2], &X, &Y, &Z);
    2043           1 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2044           1 :             *cp++ = PACK(r, g, b);
    2045           1 :             pp += 3;
    2046             :         }
    2047           1 :         cp += toskew;
    2048           1 :         pp += fromskew;
    2049             :     }
    2050           1 : }
    2051             : 
    2052             : /*
    2053             :  * 16-bit packed CIE L*a*b 1976 samples => RGB
    2054             :  */
    2055           0 : DECLAREContigPutFunc(putcontig8bitCIELab16)
    2056             : {
    2057             :     float X, Y, Z;
    2058             :     uint32_t r, g, b;
    2059           0 :     uint16_t *wp = (uint16_t *)pp;
    2060             :     (void)y;
    2061           0 :     fromskew *= 3;
    2062           0 :     for (; h > 0; --h)
    2063             :     {
    2064           0 :         for (x = w; x > 0; --x)
    2065             :         {
    2066           0 :             TIFFCIELab16ToXYZ(img->cielab, (uint16_t)wp[0], (int16_t)wp[1],
    2067           0 :                               (int16_t)wp[2], &X, &Y, &Z);
    2068           0 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2069           0 :             *cp++ = PACK(r, g, b);
    2070           0 :             wp += 3;
    2071             :         }
    2072           0 :         cp += toskew;
    2073           0 :         wp += fromskew;
    2074             :     }
    2075           0 : }
    2076             : 
    2077             : /*
    2078             :  * YCbCr -> RGB conversion and packing routines.
    2079             :  */
    2080             : 
    2081             : #define YCbCrtoRGB(dst, Y)                                                     \
    2082             :     {                                                                          \
    2083             :         uint32_t r, g, b;                                                      \
    2084             :         TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b);                   \
    2085             :         dst = PACK(r, g, b);                                                   \
    2086             :     }
    2087             : 
    2088             : /*
    2089             :  * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
    2090             :  */
    2091           2 : DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
    2092             : {
    2093           2 :     uint32_t *cp1 = cp + w + toskew;
    2094           2 :     uint32_t *cp2 = cp1 + w + toskew;
    2095           2 :     uint32_t *cp3 = cp2 + w + toskew;
    2096           2 :     int32_t incr = 3 * w + 4 * toskew;
    2097             : 
    2098             :     (void)y;
    2099             :     /* adjust fromskew */
    2100           2 :     fromskew = (fromskew / 4) * (4 * 2 + 2);
    2101           2 :     if ((h & 3) == 0 && (w & 3) == 0)
    2102             :     {
    2103          13 :         for (; h >= 4; h -= 4)
    2104             :         {
    2105          12 :             x = w >> 2;
    2106             :             do
    2107             :             {
    2108         144 :                 int32_t Cb = pp[16];
    2109         144 :                 int32_t Cr = pp[17];
    2110             : 
    2111         144 :                 YCbCrtoRGB(cp[0], pp[0]);
    2112         144 :                 YCbCrtoRGB(cp[1], pp[1]);
    2113         144 :                 YCbCrtoRGB(cp[2], pp[2]);
    2114         144 :                 YCbCrtoRGB(cp[3], pp[3]);
    2115         144 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2116         144 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2117         144 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2118         144 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2119         144 :                 YCbCrtoRGB(cp2[0], pp[8]);
    2120         144 :                 YCbCrtoRGB(cp2[1], pp[9]);
    2121         144 :                 YCbCrtoRGB(cp2[2], pp[10]);
    2122         144 :                 YCbCrtoRGB(cp2[3], pp[11]);
    2123         144 :                 YCbCrtoRGB(cp3[0], pp[12]);
    2124         144 :                 YCbCrtoRGB(cp3[1], pp[13]);
    2125         144 :                 YCbCrtoRGB(cp3[2], pp[14]);
    2126         144 :                 YCbCrtoRGB(cp3[3], pp[15]);
    2127             : 
    2128         144 :                 cp += 4;
    2129         144 :                 cp1 += 4;
    2130         144 :                 cp2 += 4;
    2131         144 :                 cp3 += 4;
    2132         144 :                 pp += 18;
    2133         144 :             } while (--x);
    2134          12 :             cp += incr;
    2135          12 :             cp1 += incr;
    2136          12 :             cp2 += incr;
    2137          12 :             cp3 += incr;
    2138          12 :             pp += fromskew;
    2139             :         }
    2140             :     }
    2141             :     else
    2142             :     {
    2143          10 :         while (h > 0)
    2144             :         {
    2145         110 :             for (x = w; x > 0;)
    2146             :             {
    2147         100 :                 int32_t Cb = pp[16];
    2148         100 :                 int32_t Cr = pp[17];
    2149         100 :                 switch (x)
    2150             :                 {
    2151          90 :                     default:
    2152          90 :                         switch (h)
    2153             :                         {
    2154          81 :                             default:
    2155          81 :                                 YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
    2156          90 :                             case 3:
    2157          90 :                                 YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
    2158          90 :                             case 2:
    2159          90 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2160          90 :                             case 1:
    2161          90 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2162             :                         }                                 /* FALLTHROUGH */
    2163         100 :                     case 3:
    2164         100 :                         switch (h)
    2165             :                         {
    2166          90 :                             default:
    2167          90 :                                 YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
    2168         100 :                             case 3:
    2169         100 :                                 YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
    2170         100 :                             case 2:
    2171         100 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2172         100 :                             case 1:
    2173         100 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2174             :                         }                                 /* FALLTHROUGH */
    2175         100 :                     case 2:
    2176         100 :                         switch (h)
    2177             :                         {
    2178          90 :                             default:
    2179          90 :                                 YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
    2180         100 :                             case 3:
    2181         100 :                                 YCbCrtoRGB(cp2[1], pp[9]); /* FALLTHROUGH */
    2182         100 :                             case 2:
    2183         100 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2184         100 :                             case 1:
    2185         100 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2186             :                         }                                 /* FALLTHROUGH */
    2187         100 :                     case 1:
    2188         100 :                         switch (h)
    2189             :                         {
    2190          90 :                             default:
    2191          90 :                                 YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
    2192         100 :                             case 3:
    2193         100 :                                 YCbCrtoRGB(cp2[0], pp[8]); /* FALLTHROUGH */
    2194         100 :                             case 2:
    2195         100 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2196         100 :                             case 1:
    2197         100 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2198             :                         }                                 /* FALLTHROUGH */
    2199             :                 }
    2200         100 :                 if (x < 4)
    2201             :                 {
    2202          10 :                     cp += x;
    2203          10 :                     cp1 += x;
    2204          10 :                     cp2 += x;
    2205          10 :                     cp3 += x;
    2206          10 :                     x = 0;
    2207             :                 }
    2208             :                 else
    2209             :                 {
    2210          90 :                     cp += 4;
    2211          90 :                     cp1 += 4;
    2212          90 :                     cp2 += 4;
    2213          90 :                     cp3 += 4;
    2214          90 :                     x -= 4;
    2215             :                 }
    2216         100 :                 pp += 18;
    2217             :             }
    2218          10 :             if (h <= 4)
    2219           1 :                 break;
    2220           9 :             h -= 4;
    2221           9 :             cp += incr;
    2222           9 :             cp1 += incr;
    2223           9 :             cp2 += incr;
    2224           9 :             cp3 += incr;
    2225           9 :             pp += fromskew;
    2226             :         }
    2227             :     }
    2228           2 : }
    2229             : 
    2230             : /*
    2231             :  * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
    2232             :  */
    2233           2 : DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
    2234             : {
    2235           2 :     uint32_t *cp1 = cp + w + toskew;
    2236           2 :     int32_t incr = 2 * toskew + w;
    2237             : 
    2238             :     (void)y;
    2239           2 :     fromskew = (fromskew / 4) * (4 * 2 + 2);
    2240           2 :     if ((w & 3) == 0 && (h & 1) == 0)
    2241             :     {
    2242          25 :         for (; h >= 2; h -= 2)
    2243             :         {
    2244          24 :             x = w >> 2;
    2245             :             do
    2246             :             {
    2247         288 :                 int32_t Cb = pp[8];
    2248         288 :                 int32_t Cr = pp[9];
    2249             : 
    2250         288 :                 YCbCrtoRGB(cp[0], pp[0]);
    2251         288 :                 YCbCrtoRGB(cp[1], pp[1]);
    2252         288 :                 YCbCrtoRGB(cp[2], pp[2]);
    2253         288 :                 YCbCrtoRGB(cp[3], pp[3]);
    2254         288 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2255         288 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2256         288 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2257         288 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2258             : 
    2259         288 :                 cp += 4;
    2260         288 :                 cp1 += 4;
    2261         288 :                 pp += 10;
    2262         288 :             } while (--x);
    2263          24 :             cp += incr;
    2264          24 :             cp1 += incr;
    2265          24 :             pp += fromskew;
    2266             :         }
    2267             :     }
    2268             :     else
    2269             :     {
    2270          20 :         while (h > 0)
    2271             :         {
    2272         220 :             for (x = w; x > 0;)
    2273             :             {
    2274         200 :                 int32_t Cb = pp[8];
    2275         200 :                 int32_t Cr = pp[9];
    2276         200 :                 switch (x)
    2277             :                 {
    2278         180 :                     default:
    2279         180 :                         switch (h)
    2280             :                         {
    2281         171 :                             default:
    2282         171 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2283         180 :                             case 1:
    2284         180 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2285             :                         }                                 /* FALLTHROUGH */
    2286         200 :                     case 3:
    2287         200 :                         switch (h)
    2288             :                         {
    2289         190 :                             default:
    2290         190 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2291         200 :                             case 1:
    2292         200 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2293             :                         }                                 /* FALLTHROUGH */
    2294         200 :                     case 2:
    2295         200 :                         switch (h)
    2296             :                         {
    2297         190 :                             default:
    2298         190 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2299         200 :                             case 1:
    2300         200 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2301             :                         }                                 /* FALLTHROUGH */
    2302         200 :                     case 1:
    2303         200 :                         switch (h)
    2304             :                         {
    2305         190 :                             default:
    2306         190 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2307         200 :                             case 1:
    2308         200 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2309             :                         }                                 /* FALLTHROUGH */
    2310             :                 }
    2311         200 :                 if (x < 4)
    2312             :                 {
    2313          20 :                     cp += x;
    2314          20 :                     cp1 += x;
    2315          20 :                     x = 0;
    2316             :                 }
    2317             :                 else
    2318             :                 {
    2319         180 :                     cp += 4;
    2320         180 :                     cp1 += 4;
    2321         180 :                     x -= 4;
    2322             :                 }
    2323         200 :                 pp += 10;
    2324             :             }
    2325          20 :             if (h <= 2)
    2326           1 :                 break;
    2327          19 :             h -= 2;
    2328          19 :             cp += incr;
    2329          19 :             cp1 += incr;
    2330          19 :             pp += fromskew;
    2331             :         }
    2332             :     }
    2333           2 : }
    2334             : 
    2335             : /*
    2336             :  * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
    2337             :  */
    2338           1 : DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
    2339             : {
    2340             :     (void)y;
    2341           1 :     fromskew = (fromskew / 4) * (4 * 1 + 2);
    2342             :     do
    2343             :     {
    2344          39 :         x = w >> 2;
    2345         390 :         while (x > 0)
    2346             :         {
    2347         351 :             int32_t Cb = pp[4];
    2348         351 :             int32_t Cr = pp[5];
    2349             : 
    2350         351 :             YCbCrtoRGB(cp[0], pp[0]);
    2351         351 :             YCbCrtoRGB(cp[1], pp[1]);
    2352         351 :             YCbCrtoRGB(cp[2], pp[2]);
    2353         351 :             YCbCrtoRGB(cp[3], pp[3]);
    2354             : 
    2355         351 :             cp += 4;
    2356         351 :             pp += 6;
    2357         351 :             x--;
    2358             :         }
    2359             : 
    2360          39 :         if ((w & 3) != 0)
    2361             :         {
    2362          39 :             int32_t Cb = pp[4];
    2363          39 :             int32_t Cr = pp[5];
    2364             : 
    2365          39 :             switch ((w & 3))
    2366             :             {
    2367          39 :                 case 3:
    2368          39 :                     YCbCrtoRGB(cp[2], pp[2]); /*-fallthrough*/
    2369          39 :                 case 2:
    2370          39 :                     YCbCrtoRGB(cp[1], pp[1]); /*-fallthrough*/
    2371          39 :                 case 1:
    2372          39 :                     YCbCrtoRGB(cp[0], pp[0]); /*-fallthrough*/
    2373          39 :                 case 0:
    2374          39 :                     break;
    2375             :             }
    2376             : 
    2377          39 :             cp += (w & 3);
    2378          39 :             pp += 6;
    2379             :         }
    2380             : 
    2381          39 :         cp += toskew;
    2382          39 :         pp += fromskew;
    2383          39 :     } while (--h);
    2384           1 : }
    2385             : 
    2386             : /*
    2387             :  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
    2388             :  */
    2389           2 : DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
    2390             : {
    2391             :     uint32_t *cp2;
    2392           2 :     int32_t incr = 2 * toskew + w;
    2393             :     (void)y;
    2394           2 :     fromskew = (fromskew / 2) * (2 * 2 + 2);
    2395           2 :     cp2 = cp + w + toskew;
    2396         127 :     while (h >= 2)
    2397             :     {
    2398         125 :         x = w;
    2399       12888 :         while (x >= 2)
    2400             :         {
    2401       12763 :             uint32_t Cb = pp[4];
    2402       12763 :             uint32_t Cr = pp[5];
    2403       12763 :             YCbCrtoRGB(cp[0], pp[0]);
    2404       12763 :             YCbCrtoRGB(cp[1], pp[1]);
    2405       12763 :             YCbCrtoRGB(cp2[0], pp[2]);
    2406       12763 :             YCbCrtoRGB(cp2[1], pp[3]);
    2407       12763 :             cp += 2;
    2408       12763 :             cp2 += 2;
    2409       12763 :             pp += 6;
    2410       12763 :             x -= 2;
    2411             :         }
    2412         125 :         if (x == 1)
    2413             :         {
    2414          19 :             uint32_t Cb = pp[4];
    2415          19 :             uint32_t Cr = pp[5];
    2416          19 :             YCbCrtoRGB(cp[0], pp[0]);
    2417          19 :             YCbCrtoRGB(cp2[0], pp[2]);
    2418          19 :             cp++;
    2419          19 :             cp2++;
    2420          19 :             pp += 6;
    2421             :         }
    2422         125 :         cp += incr;
    2423         125 :         cp2 += incr;
    2424         125 :         pp += fromskew;
    2425         125 :         h -= 2;
    2426             :     }
    2427           2 :     if (h == 1)
    2428             :     {
    2429           2 :         x = w;
    2430         138 :         while (x >= 2)
    2431             :         {
    2432         136 :             uint32_t Cb = pp[4];
    2433         136 :             uint32_t Cr = pp[5];
    2434         136 :             YCbCrtoRGB(cp[0], pp[0]);
    2435         136 :             YCbCrtoRGB(cp[1], pp[1]);
    2436         136 :             cp += 2;
    2437         136 :             cp2 += 2;
    2438         136 :             pp += 6;
    2439         136 :             x -= 2;
    2440             :         }
    2441           2 :         if (x == 1)
    2442             :         {
    2443           1 :             uint32_t Cb = pp[4];
    2444           1 :             uint32_t Cr = pp[5];
    2445           1 :             YCbCrtoRGB(cp[0], pp[0]);
    2446             :         }
    2447             :     }
    2448           2 : }
    2449             : 
    2450             : /*
    2451             :  * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
    2452             :  */
    2453           1 : DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
    2454             : {
    2455             :     (void)y;
    2456           1 :     fromskew = (fromskew / 2) * (2 * 1 + 2);
    2457             :     do
    2458             :     {
    2459          39 :         x = w >> 1;
    2460         780 :         while (x > 0)
    2461             :         {
    2462         741 :             int32_t Cb = pp[2];
    2463         741 :             int32_t Cr = pp[3];
    2464             : 
    2465         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2466         741 :             YCbCrtoRGB(cp[1], pp[1]);
    2467             : 
    2468         741 :             cp += 2;
    2469         741 :             pp += 4;
    2470         741 :             x--;
    2471             :         }
    2472             : 
    2473          39 :         if ((w & 1) != 0)
    2474             :         {
    2475          39 :             int32_t Cb = pp[2];
    2476          39 :             int32_t Cr = pp[3];
    2477             : 
    2478          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2479             : 
    2480          39 :             cp += 1;
    2481          39 :             pp += 4;
    2482             :         }
    2483             : 
    2484          39 :         cp += toskew;
    2485          39 :         pp += fromskew;
    2486          39 :     } while (--h);
    2487           1 : }
    2488             : 
    2489             : /*
    2490             :  * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
    2491             :  */
    2492           1 : DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
    2493             : {
    2494             :     uint32_t *cp2;
    2495           1 :     int32_t incr = 2 * toskew + w;
    2496             :     (void)y;
    2497           1 :     fromskew = (fromskew / 1) * (1 * 2 + 2);
    2498           1 :     cp2 = cp + w + toskew;
    2499          20 :     while (h >= 2)
    2500             :     {
    2501          19 :         x = w;
    2502             :         do
    2503             :         {
    2504         741 :             uint32_t Cb = pp[2];
    2505         741 :             uint32_t Cr = pp[3];
    2506         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2507         741 :             YCbCrtoRGB(cp2[0], pp[1]);
    2508         741 :             cp++;
    2509         741 :             cp2++;
    2510         741 :             pp += 4;
    2511         741 :         } while (--x);
    2512          19 :         cp += incr;
    2513          19 :         cp2 += incr;
    2514          19 :         pp += fromskew;
    2515          19 :         h -= 2;
    2516             :     }
    2517           1 :     if (h == 1)
    2518             :     {
    2519           1 :         x = w;
    2520             :         do
    2521             :         {
    2522          39 :             uint32_t Cb = pp[2];
    2523          39 :             uint32_t Cr = pp[3];
    2524          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2525          39 :             cp++;
    2526          39 :             pp += 4;
    2527          39 :         } while (--x);
    2528             :     }
    2529           1 : }
    2530             : 
    2531             : /*
    2532             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2533             :  */
    2534           1 : DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
    2535             : {
    2536             :     (void)y;
    2537           1 :     fromskew = (fromskew / 1) * (1 * 1 + 2);
    2538             :     do
    2539             :     {
    2540          39 :         x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
    2541             :         do
    2542             :         {
    2543        1521 :             int32_t Cb = pp[1];
    2544        1521 :             int32_t Cr = pp[2];
    2545             : 
    2546        1521 :             YCbCrtoRGB(*cp++, pp[0]);
    2547             : 
    2548        1521 :             pp += 3;
    2549        1521 :         } while (--x);
    2550          39 :         cp += toskew;
    2551          39 :         pp += fromskew;
    2552          39 :     } while (--h);
    2553           1 : }
    2554             : 
    2555             : /*
    2556             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2557             :  */
    2558           0 : DECLARESepPutFunc(putseparate8bitYCbCr11tile)
    2559             : {
    2560             :     (void)y;
    2561             :     (void)a;
    2562             :     /* TODO: naming of input vars is still off, change obfuscating declaration
    2563             :      * inside define, or resolve obfuscation */
    2564           0 :     for (; h > 0; --h)
    2565             :     {
    2566           0 :         x = w;
    2567             :         do
    2568             :         {
    2569             :             uint32_t dr, dg, db;
    2570           0 :             TIFFYCbCrtoRGB(img->ycbcr, *r++, *g++, *b++, &dr, &dg, &db);
    2571           0 :             *cp++ = PACK(dr, dg, db);
    2572           0 :         } while (--x);
    2573           0 :         SKEW(r, g, b, fromskew);
    2574           0 :         cp += toskew;
    2575             :     }
    2576           0 : }
    2577             : #undef YCbCrtoRGB
    2578             : 
    2579         102 : static int isInRefBlackWhiteRange(float f)
    2580             : {
    2581         102 :     return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF;
    2582             : }
    2583             : 
    2584          17 : static int initYCbCrConversion(TIFFRGBAImage *img)
    2585             : {
    2586             :     static const char module[] = "initYCbCrConversion";
    2587             : 
    2588             :     float *luma, *refBlackWhite;
    2589             : 
    2590          17 :     if (img->ycbcr == NULL)
    2591             :     {
    2592          17 :         img->ycbcr = (TIFFYCbCrToRGB *)_TIFFmallocExt(
    2593             :             img->tif, TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)) +
    2594             :                           4 * 256 * sizeof(TIFFRGBValue) +
    2595             :                           2 * 256 * sizeof(int) + 3 * 256 * sizeof(int32_t));
    2596          17 :         if (img->ycbcr == NULL)
    2597             :         {
    2598           0 :             TIFFErrorExtR(img->tif, module,
    2599             :                           "No space for YCbCr->RGB conversion state");
    2600           0 :             return (0);
    2601             :         }
    2602             :     }
    2603             : 
    2604          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
    2605          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
    2606             :                           &refBlackWhite);
    2607             : 
    2608             :     /* Do some validation to avoid later issues. Detect NaN for now */
    2609             :     /* and also if lumaGreen is zero since we divide by it later */
    2610          17 :     if (luma[0] != luma[0] || luma[1] != luma[1] || luma[1] == 0.0 ||
    2611          17 :         luma[2] != luma[2])
    2612             :     {
    2613           0 :         TIFFErrorExtR(img->tif, module,
    2614             :                       "Invalid values for YCbCrCoefficients tag");
    2615           0 :         return (0);
    2616             :     }
    2617             : 
    2618          34 :     if (!isInRefBlackWhiteRange(refBlackWhite[0]) ||
    2619          34 :         !isInRefBlackWhiteRange(refBlackWhite[1]) ||
    2620          34 :         !isInRefBlackWhiteRange(refBlackWhite[2]) ||
    2621          34 :         !isInRefBlackWhiteRange(refBlackWhite[3]) ||
    2622          34 :         !isInRefBlackWhiteRange(refBlackWhite[4]) ||
    2623          17 :         !isInRefBlackWhiteRange(refBlackWhite[5]))
    2624             :     {
    2625           0 :         TIFFErrorExtR(img->tif, module,
    2626             :                       "Invalid values for ReferenceBlackWhite tag");
    2627           0 :         return (0);
    2628             :     }
    2629             : 
    2630          17 :     if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
    2631           0 :         return (0);
    2632          17 :     return (1);
    2633             : }
    2634             : 
    2635           1 : static tileContigRoutine initCIELabConversion(TIFFRGBAImage *img)
    2636             : {
    2637             :     static const char module[] = "initCIELabConversion";
    2638             : 
    2639             :     float *whitePoint;
    2640             :     float refWhite[3];
    2641             : 
    2642           1 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
    2643           1 :     if (whitePoint[1] == 0.0f)
    2644             :     {
    2645           0 :         TIFFErrorExtR(img->tif, module, "Invalid value for WhitePoint tag.");
    2646           0 :         return NULL;
    2647             :     }
    2648             : 
    2649           1 :     if (!img->cielab)
    2650             :     {
    2651           1 :         img->cielab = (TIFFCIELabToRGB *)_TIFFmallocExt(
    2652             :             img->tif, sizeof(TIFFCIELabToRGB));
    2653           1 :         if (!img->cielab)
    2654             :         {
    2655           0 :             TIFFErrorExtR(img->tif, module,
    2656             :                           "No space for CIE L*a*b*->RGB conversion state.");
    2657           0 :             return NULL;
    2658             :         }
    2659             :     }
    2660             : 
    2661           1 :     refWhite[1] = 100.0F;
    2662           1 :     refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
    2663           1 :     refWhite[2] =
    2664           1 :         (1.0F - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
    2665           1 :     if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0)
    2666             :     {
    2667           0 :         TIFFErrorExtR(img->tif, module,
    2668             :                       "Failed to initialize CIE L*a*b*->RGB conversion state.");
    2669           0 :         _TIFFfreeExt(img->tif, img->cielab);
    2670           0 :         return NULL;
    2671             :     }
    2672             : 
    2673           1 :     if (img->bitspersample == 8)
    2674           1 :         return putcontig8bitCIELab8;
    2675           0 :     else if (img->bitspersample == 16)
    2676           0 :         return putcontig8bitCIELab16;
    2677           0 :     return NULL;
    2678             : }
    2679             : 
    2680             : /*
    2681             :  * Greyscale images with less than 8 bits/sample are handled
    2682             :  * with a table to avoid lots of shifts and masks.  The table
    2683             :  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
    2684             :  * pixel values simply by indexing into the table with one
    2685             :  * number.
    2686             :  */
    2687           9 : static int makebwmap(TIFFRGBAImage *img)
    2688             : {
    2689           9 :     TIFFRGBValue *Map = img->Map;
    2690           9 :     int bitspersample = img->bitspersample;
    2691           9 :     int nsamples = 8 / bitspersample;
    2692             :     int i;
    2693             :     uint32_t *p;
    2694             : 
    2695           9 :     if (nsamples == 0)
    2696           0 :         nsamples = 1;
    2697             : 
    2698          18 :     img->BWmap = (uint32_t **)_TIFFmallocExt(
    2699             :         img->tif,
    2700           9 :         256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
    2701           9 :     if (img->BWmap == NULL)
    2702             :     {
    2703           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2704             :                       "No space for B&W mapping table");
    2705           0 :         return (0);
    2706             :     }
    2707           9 :     p = (uint32_t *)(img->BWmap + 256);
    2708        2313 :     for (i = 0; i < 256; i++)
    2709             :     {
    2710             :         TIFFRGBValue c;
    2711        2304 :         img->BWmap[i] = p;
    2712        2304 :         switch (bitspersample)
    2713             :         {
    2714             : #define GREY(x)                                                                \
    2715             :     c = Map[x];                                                                \
    2716             :     *p++ = PACK(c, c, c);
    2717           0 :             case 1:
    2718           0 :                 GREY(i >> 7);
    2719           0 :                 GREY((i >> 6) & 1);
    2720           0 :                 GREY((i >> 5) & 1);
    2721           0 :                 GREY((i >> 4) & 1);
    2722           0 :                 GREY((i >> 3) & 1);
    2723           0 :                 GREY((i >> 2) & 1);
    2724           0 :                 GREY((i >> 1) & 1);
    2725           0 :                 GREY(i & 1);
    2726           0 :                 break;
    2727           0 :             case 2:
    2728           0 :                 GREY(i >> 6);
    2729           0 :                 GREY((i >> 4) & 3);
    2730           0 :                 GREY((i >> 2) & 3);
    2731           0 :                 GREY(i & 3);
    2732           0 :                 break;
    2733           0 :             case 4:
    2734           0 :                 GREY(i >> 4);
    2735           0 :                 GREY(i & 0xf);
    2736           0 :                 break;
    2737        2304 :             case 8:
    2738             :             case 16:
    2739        2304 :                 GREY(i);
    2740        2304 :                 break;
    2741             :         }
    2742             : #undef GREY
    2743        2304 :     }
    2744           9 :     return (1);
    2745             : }
    2746             : 
    2747             : /*
    2748             :  * Construct a mapping table to convert from the range
    2749             :  * of the data samples to [0,255] --for display.  This
    2750             :  * process also handles inverting B&W images when needed.
    2751             :  */
    2752           9 : static int setupMap(TIFFRGBAImage *img)
    2753             : {
    2754             :     int32_t x, range;
    2755             : 
    2756           9 :     range = (int32_t)((1L << img->bitspersample) - 1);
    2757             : 
    2758             :     /* treat 16 bit the same as eight bit */
    2759           9 :     if (img->bitspersample == 16)
    2760           0 :         range = (int32_t)255;
    2761             : 
    2762          18 :     img->Map = (TIFFRGBValue *)_TIFFmallocExt(
    2763           9 :         img->tif, (range + 1) * sizeof(TIFFRGBValue));
    2764           9 :     if (img->Map == NULL)
    2765             :     {
    2766           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2767             :                       "No space for photometric conversion table");
    2768           0 :         return (0);
    2769             :     }
    2770           9 :     if (img->photometric == PHOTOMETRIC_MINISWHITE)
    2771             :     {
    2772           0 :         for (x = 0; x <= range; x++)
    2773           0 :             img->Map[x] = (TIFFRGBValue)(((range - x) * 255) / range);
    2774             :     }
    2775             :     else
    2776             :     {
    2777        2313 :         for (x = 0; x <= range; x++)
    2778        2304 :             img->Map[x] = (TIFFRGBValue)((x * 255) / range);
    2779             :     }
    2780           9 :     if (img->bitspersample <= 16 &&
    2781           9 :         (img->photometric == PHOTOMETRIC_MINISBLACK ||
    2782           0 :          img->photometric == PHOTOMETRIC_MINISWHITE))
    2783             :     {
    2784             :         /*
    2785             :          * Use photometric mapping table to construct
    2786             :          * unpacking tables for samples <= 8 bits.
    2787             :          */
    2788           9 :         if (!makebwmap(img))
    2789           0 :             return (0);
    2790             :         /* no longer need Map, free it */
    2791           9 :         _TIFFfreeExt(img->tif, img->Map);
    2792           9 :         img->Map = NULL;
    2793             :     }
    2794           9 :     return (1);
    2795             : }
    2796             : 
    2797           1 : static int checkcmap(TIFFRGBAImage *img)
    2798             : {
    2799           1 :     uint16_t *r = img->redcmap;
    2800           1 :     uint16_t *g = img->greencmap;
    2801           1 :     uint16_t *b = img->bluecmap;
    2802           1 :     long n = 1L << img->bitspersample;
    2803             : 
    2804           2 :     while (n-- > 0)
    2805           2 :         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
    2806           1 :             return (16);
    2807           0 :     return (8);
    2808             : }
    2809             : 
    2810           1 : static void cvtcmap(TIFFRGBAImage *img)
    2811             : {
    2812           1 :     uint16_t *r = img->redcmap;
    2813           1 :     uint16_t *g = img->greencmap;
    2814           1 :     uint16_t *b = img->bluecmap;
    2815             :     long i;
    2816             : 
    2817         257 :     for (i = (1L << img->bitspersample) - 1; i >= 0; i--)
    2818             :     {
    2819             : #define CVT(x) ((uint16_t)((x) >> 8))
    2820         256 :         r[i] = CVT(r[i]);
    2821         256 :         g[i] = CVT(g[i]);
    2822         256 :         b[i] = CVT(b[i]);
    2823             : #undef CVT
    2824             :     }
    2825           1 : }
    2826             : 
    2827             : /*
    2828             :  * Palette images with <= 8 bits/sample are handled
    2829             :  * with a table to avoid lots of shifts and masks.  The table
    2830             :  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
    2831             :  * pixel values simply by indexing into the table with one
    2832             :  * number.
    2833             :  */
    2834           1 : static int makecmap(TIFFRGBAImage *img)
    2835             : {
    2836           1 :     int bitspersample = img->bitspersample;
    2837           1 :     int nsamples = 8 / bitspersample;
    2838           1 :     uint16_t *r = img->redcmap;
    2839           1 :     uint16_t *g = img->greencmap;
    2840           1 :     uint16_t *b = img->bluecmap;
    2841             :     uint32_t *p;
    2842             :     int i;
    2843             : 
    2844           2 :     img->PALmap = (uint32_t **)_TIFFmallocExt(
    2845             :         img->tif,
    2846           1 :         256 * sizeof(uint32_t *) + (256 * nsamples * sizeof(uint32_t)));
    2847           1 :     if (img->PALmap == NULL)
    2848             :     {
    2849           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2850             :                       "No space for Palette mapping table");
    2851           0 :         return (0);
    2852             :     }
    2853           1 :     p = (uint32_t *)(img->PALmap + 256);
    2854         257 :     for (i = 0; i < 256; i++)
    2855             :     {
    2856             :         TIFFRGBValue c;
    2857         256 :         img->PALmap[i] = p;
    2858             : #define CMAP(x)                                                                \
    2859             :     c = (TIFFRGBValue)x;                                                       \
    2860             :     *p++ = PACK(r[c] & 0xff, g[c] & 0xff, b[c] & 0xff);
    2861         256 :         switch (bitspersample)
    2862             :         {
    2863           0 :             case 1:
    2864           0 :                 CMAP(i >> 7);
    2865           0 :                 CMAP((i >> 6) & 1);
    2866           0 :                 CMAP((i >> 5) & 1);
    2867           0 :                 CMAP((i >> 4) & 1);
    2868           0 :                 CMAP((i >> 3) & 1);
    2869           0 :                 CMAP((i >> 2) & 1);
    2870           0 :                 CMAP((i >> 1) & 1);
    2871           0 :                 CMAP(i & 1);
    2872           0 :                 break;
    2873           0 :             case 2:
    2874           0 :                 CMAP(i >> 6);
    2875           0 :                 CMAP((i >> 4) & 3);
    2876           0 :                 CMAP((i >> 2) & 3);
    2877           0 :                 CMAP(i & 3);
    2878           0 :                 break;
    2879           0 :             case 4:
    2880           0 :                 CMAP(i >> 4);
    2881           0 :                 CMAP(i & 0xf);
    2882           0 :                 break;
    2883         256 :             case 8:
    2884         256 :                 CMAP(i);
    2885         256 :                 break;
    2886             :         }
    2887             : #undef CMAP
    2888         256 :     }
    2889           1 :     return (1);
    2890             : }
    2891             : 
    2892             : /*
    2893             :  * Construct any mapping table used
    2894             :  * by the associated put routine.
    2895             :  */
    2896          17 : static int buildMap(TIFFRGBAImage *img)
    2897             : {
    2898          17 :     switch (img->photometric)
    2899             :     {
    2900           6 :         case PHOTOMETRIC_RGB:
    2901             :         case PHOTOMETRIC_YCBCR:
    2902             :         case PHOTOMETRIC_SEPARATED:
    2903           6 :             if (img->bitspersample == 8)
    2904           6 :                 break;
    2905             :             /* fall through... */
    2906             :         case PHOTOMETRIC_MINISBLACK:
    2907             :         case PHOTOMETRIC_MINISWHITE:
    2908           9 :             if (!setupMap(img))
    2909           0 :                 return (0);
    2910           9 :             break;
    2911           1 :         case PHOTOMETRIC_PALETTE:
    2912             :             /*
    2913             :              * Convert 16-bit colormap to 8-bit (unless it looks
    2914             :              * like an old-style 8-bit colormap).
    2915             :              */
    2916           1 :             if (checkcmap(img) == 16)
    2917           1 :                 cvtcmap(img);
    2918             :             else
    2919           0 :                 TIFFWarningExtR(img->tif, TIFFFileName(img->tif),
    2920             :                                 "Assuming 8-bit colormap");
    2921             :             /*
    2922             :              * Use mapping table and colormap to construct
    2923             :              * unpacking tables for samples < 8 bits.
    2924             :              */
    2925           1 :             if (img->bitspersample <= 8 && !makecmap(img))
    2926           0 :                 return (0);
    2927           1 :             break;
    2928             :     }
    2929          17 :     return (1);
    2930             : }
    2931             : 
    2932             : /*
    2933             :  * Select the appropriate conversion routine for packed data.
    2934             :  */
    2935          60 : static int PickContigCase(TIFFRGBAImage *img)
    2936             : {
    2937          60 :     img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
    2938          60 :     img->put.contig = NULL;
    2939          60 :     switch (img->photometric)
    2940             :     {
    2941          26 :         case PHOTOMETRIC_RGB:
    2942          26 :             switch (img->bitspersample)
    2943             :             {
    2944          26 :                 case 8:
    2945          26 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    2946          13 :                         img->samplesperpixel >= 4)
    2947          13 :                         img->put.contig = putRGBAAcontig8bittile;
    2948          13 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    2949          13 :                              img->samplesperpixel >= 4)
    2950             :                     {
    2951          13 :                         if (BuildMapUaToAa(img))
    2952          13 :                             img->put.contig = putRGBUAcontig8bittile;
    2953             :                     }
    2954           0 :                     else if (img->samplesperpixel >= 3)
    2955           0 :                         img->put.contig = putRGBcontig8bittile;
    2956          26 :                     break;
    2957           0 :                 case 16:
    2958           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    2959           0 :                         img->samplesperpixel >= 4)
    2960             :                     {
    2961           0 :                         if (BuildMapBitdepth16To8(img))
    2962           0 :                             img->put.contig = putRGBAAcontig16bittile;
    2963             :                     }
    2964           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    2965           0 :                              img->samplesperpixel >= 4)
    2966             :                     {
    2967           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    2968           0 :                             img->put.contig = putRGBUAcontig16bittile;
    2969             :                     }
    2970           0 :                     else if (img->samplesperpixel >= 3)
    2971             :                     {
    2972           0 :                         if (BuildMapBitdepth16To8(img))
    2973           0 :                             img->put.contig = putRGBcontig16bittile;
    2974             :                     }
    2975           0 :                     break;
    2976             :             }
    2977          26 :             break;
    2978           6 :         case PHOTOMETRIC_SEPARATED:
    2979           6 :             if (img->samplesperpixel >= 4 && buildMap(img))
    2980             :             {
    2981           6 :                 if (img->bitspersample == 8)
    2982             :                 {
    2983           6 :                     if (!img->Map)
    2984           6 :                         img->put.contig = putRGBcontig8bitCMYKtile;
    2985             :                     else
    2986           0 :                         img->put.contig = putRGBcontig8bitCMYKMaptile;
    2987             :                 }
    2988             :             }
    2989           6 :             break;
    2990           1 :         case PHOTOMETRIC_PALETTE:
    2991           1 :             if (buildMap(img))
    2992             :             {
    2993           1 :                 switch (img->bitspersample)
    2994             :                 {
    2995           1 :                     case 8:
    2996           1 :                         img->put.contig = put8bitcmaptile;
    2997           1 :                         break;
    2998           0 :                     case 4:
    2999           0 :                         img->put.contig = put4bitcmaptile;
    3000           0 :                         break;
    3001           0 :                     case 2:
    3002           0 :                         img->put.contig = put2bitcmaptile;
    3003           0 :                         break;
    3004           0 :                     case 1:
    3005           0 :                         img->put.contig = put1bitcmaptile;
    3006           0 :                         break;
    3007             :                 }
    3008           0 :             }
    3009           1 :             break;
    3010           9 :         case PHOTOMETRIC_MINISWHITE:
    3011             :         case PHOTOMETRIC_MINISBLACK:
    3012           9 :             if (buildMap(img))
    3013             :             {
    3014           9 :                 switch (img->bitspersample)
    3015             :                 {
    3016           0 :                     case 16:
    3017           0 :                         img->put.contig = put16bitbwtile;
    3018           0 :                         break;
    3019           9 :                     case 8:
    3020           9 :                         if (img->alpha && img->samplesperpixel == 2)
    3021           6 :                             img->put.contig = putagreytile;
    3022             :                         else
    3023           3 :                             img->put.contig = putgreytile;
    3024           9 :                         break;
    3025           0 :                     case 4:
    3026           0 :                         img->put.contig = put4bitbwtile;
    3027           0 :                         break;
    3028           0 :                     case 2:
    3029           0 :                         img->put.contig = put2bitbwtile;
    3030           0 :                         break;
    3031           0 :                     case 1:
    3032           0 :                         img->put.contig = put1bitbwtile;
    3033           0 :                         break;
    3034             :                 }
    3035           0 :             }
    3036           9 :             break;
    3037          17 :         case PHOTOMETRIC_YCBCR:
    3038          17 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3039             :             {
    3040          17 :                 if (initYCbCrConversion(img) != 0)
    3041             :                 {
    3042             :                     /*
    3043             :                      * The 6.0 spec says that subsampling must be
    3044             :                      * one of 1, 2, or 4, and that vertical subsampling
    3045             :                      * must always be <= horizontal subsampling; so
    3046             :                      * there are only a few possibilities and we just
    3047             :                      * enumerate the cases.
    3048             :                      * Joris: added support for the [1,2] case, nonetheless, to
    3049             :                      * accommodate some OJPEG files
    3050             :                      */
    3051             :                     uint16_t SubsamplingHor;
    3052             :                     uint16_t SubsamplingVer;
    3053          17 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3054             :                                           &SubsamplingHor, &SubsamplingVer);
    3055          17 :                     switch ((SubsamplingHor << 4) | SubsamplingVer)
    3056             :                     {
    3057           2 :                         case 0x44:
    3058           2 :                             img->put.contig = putcontig8bitYCbCr44tile;
    3059           2 :                             break;
    3060           2 :                         case 0x42:
    3061           2 :                             img->put.contig = putcontig8bitYCbCr42tile;
    3062           2 :                             break;
    3063           1 :                         case 0x41:
    3064           1 :                             img->put.contig = putcontig8bitYCbCr41tile;
    3065           1 :                             break;
    3066           3 :                         case 0x22:
    3067           3 :                             img->put.contig = putcontig8bitYCbCr22tile;
    3068           3 :                             break;
    3069           1 :                         case 0x21:
    3070           1 :                             img->put.contig = putcontig8bitYCbCr21tile;
    3071           1 :                             break;
    3072           1 :                         case 0x12:
    3073           1 :                             img->put.contig = putcontig8bitYCbCr12tile;
    3074           1 :                             break;
    3075           1 :                         case 0x11:
    3076           1 :                             img->put.contig = putcontig8bitYCbCr11tile;
    3077           1 :                             break;
    3078             :                     }
    3079          17 :                 }
    3080             :             }
    3081          17 :             break;
    3082           1 :         case PHOTOMETRIC_CIELAB:
    3083           1 :             if (img->samplesperpixel == 3 && buildMap(img))
    3084             :             {
    3085           1 :                 if (img->bitspersample == 8 || img->bitspersample == 16)
    3086           1 :                     img->put.contig = initCIELabConversion(img);
    3087           1 :                 break;
    3088             :             }
    3089             :     }
    3090          60 :     return ((img->get != NULL) && (img->put.contig != NULL));
    3091             : }
    3092             : 
    3093             : /*
    3094             :  * Select the appropriate conversion routine for unpacked data.
    3095             :  *
    3096             :  * NB: we assume that unpacked single channel data is directed
    3097             :  *   to the "packed routines.
    3098             :  */
    3099           3 : static int PickSeparateCase(TIFFRGBAImage *img)
    3100             : {
    3101           3 :     img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
    3102           3 :     img->put.separate = NULL;
    3103           3 :     switch (img->photometric)
    3104             :     {
    3105           3 :         case PHOTOMETRIC_MINISWHITE:
    3106             :         case PHOTOMETRIC_MINISBLACK:
    3107             :             /* greyscale images processed pretty much as RGB by gtTileSeparate
    3108             :              */
    3109             :         case PHOTOMETRIC_RGB:
    3110           3 :             switch (img->bitspersample)
    3111             :             {
    3112           3 :                 case 8:
    3113           3 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3114           0 :                         img->put.separate = putRGBAAseparate8bittile;
    3115           3 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3116             :                     {
    3117           0 :                         if (BuildMapUaToAa(img))
    3118           0 :                             img->put.separate = putRGBUAseparate8bittile;
    3119             :                     }
    3120             :                     else
    3121           3 :                         img->put.separate = putRGBseparate8bittile;
    3122           3 :                     break;
    3123           0 :                 case 16:
    3124           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3125             :                     {
    3126           0 :                         if (BuildMapBitdepth16To8(img))
    3127           0 :                             img->put.separate = putRGBAAseparate16bittile;
    3128             :                     }
    3129           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3130             :                     {
    3131           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    3132           0 :                             img->put.separate = putRGBUAseparate16bittile;
    3133             :                     }
    3134             :                     else
    3135             :                     {
    3136           0 :                         if (BuildMapBitdepth16To8(img))
    3137           0 :                             img->put.separate = putRGBseparate16bittile;
    3138             :                     }
    3139           0 :                     break;
    3140             :             }
    3141           3 :             break;
    3142           0 :         case PHOTOMETRIC_SEPARATED:
    3143           0 :             if (img->bitspersample == 8 && img->samplesperpixel == 4)
    3144             :             {
    3145           0 :                 img->alpha =
    3146             :                     1; // Not alpha, but seems like the only way to get 4th band
    3147           0 :                 img->put.separate = putCMYKseparate8bittile;
    3148             :             }
    3149           0 :             break;
    3150           0 :         case PHOTOMETRIC_YCBCR:
    3151           0 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3152             :             {
    3153           0 :                 if (initYCbCrConversion(img) != 0)
    3154             :                 {
    3155             :                     uint16_t hs, vs;
    3156           0 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3157             :                                           &hs, &vs);
    3158           0 :                     switch ((hs << 4) | vs)
    3159             :                     {
    3160           0 :                         case 0x11:
    3161           0 :                             img->put.separate = putseparate8bitYCbCr11tile;
    3162           0 :                             break;
    3163             :                             /* TODO: add other cases here */
    3164             :                     }
    3165           0 :                 }
    3166             :             }
    3167           0 :             break;
    3168             :     }
    3169           3 :     return ((img->get != NULL) && (img->put.separate != NULL));
    3170             : }
    3171             : 
    3172          13 : static int BuildMapUaToAa(TIFFRGBAImage *img)
    3173             : {
    3174             :     static const char module[] = "BuildMapUaToAa";
    3175             :     uint8_t *m;
    3176             :     uint16_t na, nv;
    3177          13 :     assert(img->UaToAa == NULL);
    3178          13 :     img->UaToAa = _TIFFmallocExt(img->tif, 65536);
    3179          13 :     if (img->UaToAa == NULL)
    3180             :     {
    3181           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3182           0 :         return (0);
    3183             :     }
    3184          13 :     m = img->UaToAa;
    3185        3341 :     for (na = 0; na < 256; na++)
    3186             :     {
    3187      855296 :         for (nv = 0; nv < 256; nv++)
    3188      851968 :             *m++ = (uint8_t)((nv * na + 127) / 255);
    3189             :     }
    3190          13 :     return (1);
    3191             : }
    3192             : 
    3193           0 : static int BuildMapBitdepth16To8(TIFFRGBAImage *img)
    3194             : {
    3195             :     static const char module[] = "BuildMapBitdepth16To8";
    3196             :     uint8_t *m;
    3197             :     uint32_t n;
    3198           0 :     assert(img->Bitdepth16To8 == NULL);
    3199           0 :     img->Bitdepth16To8 = _TIFFmallocExt(img->tif, 65536);
    3200           0 :     if (img->Bitdepth16To8 == NULL)
    3201             :     {
    3202           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3203           0 :         return (0);
    3204             :     }
    3205           0 :     m = img->Bitdepth16To8;
    3206           0 :     for (n = 0; n < 65536; n++)
    3207           0 :         *m++ = (uint8_t)((n + 128) / 257);
    3208           0 :     return (1);
    3209             : }
    3210             : 
    3211             : /*
    3212             :  * Read a whole strip off data from the file, and convert to RGBA form.
    3213             :  * If this is the last strip, then it will only contain the portion of
    3214             :  * the strip that is actually within the image space.  The result is
    3215             :  * organized in bottom to top form.
    3216             :  */
    3217             : 
    3218           0 : int TIFFReadRGBAStrip(TIFF *tif, uint32_t row, uint32_t *raster)
    3219             : 
    3220             : {
    3221           0 :     return TIFFReadRGBAStripExt(tif, row, raster, 0);
    3222             : }
    3223             : 
    3224          59 : int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
    3225             :                          int stop_on_error)
    3226             : 
    3227             : {
    3228          59 :     char emsg[EMSG_BUF_SIZE] = "";
    3229             :     TIFFRGBAImage img;
    3230             :     int ok;
    3231             :     uint32_t rowsperstrip, rows_to_read;
    3232             : 
    3233          59 :     if (TIFFIsTiled(tif))
    3234             :     {
    3235           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3236             :                       "Can't use TIFFReadRGBAStrip() with tiled file.");
    3237           0 :         return (0);
    3238             :     }
    3239             : 
    3240          59 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    3241             : 
    3242          59 :     if (rowsperstrip == 0)
    3243             :     {
    3244           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    3245           0 :         return (0);
    3246             :     }
    3247             : 
    3248          59 :     if ((row % rowsperstrip) != 0)
    3249             :     {
    3250           0 :         TIFFErrorExtR(
    3251             :             tif, TIFFFileName(tif),
    3252             :             "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
    3253           0 :         return (0);
    3254             :     }
    3255             : 
    3256         118 :     if (TIFFRGBAImageOK(tif, emsg) &&
    3257          59 :         TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3258             :     {
    3259          53 :         if (row >= img.height)
    3260             :         {
    3261           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    3262             :                           "Invalid row passed to TIFFReadRGBAStrip().");
    3263           0 :             TIFFRGBAImageEnd(&img);
    3264           0 :             return (0);
    3265             :         }
    3266             : 
    3267          53 :         img.row_offset = row;
    3268          53 :         img.col_offset = 0;
    3269             : 
    3270          53 :         if (row + rowsperstrip > img.height)
    3271          14 :             rows_to_read = img.height - row;
    3272             :         else
    3273          39 :             rows_to_read = rowsperstrip;
    3274             : 
    3275          53 :         ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read);
    3276             : 
    3277          53 :         TIFFRGBAImageEnd(&img);
    3278             :     }
    3279             :     else
    3280             :     {
    3281           6 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3282           6 :         ok = 0;
    3283             :     }
    3284             : 
    3285          59 :     return (ok);
    3286             : }
    3287             : 
    3288             : /*
    3289             :  * Read a whole tile off data from the file, and convert to RGBA form.
    3290             :  * The returned RGBA data is organized from bottom to top of tile,
    3291             :  * and may include zeroed areas if the tile extends off the image.
    3292             :  */
    3293             : 
    3294           0 : int TIFFReadRGBATile(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster)
    3295             : 
    3296             : {
    3297           0 :     return TIFFReadRGBATileExt(tif, col, row, raster, 0);
    3298             : }
    3299             : 
    3300           4 : int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
    3301             :                         int stop_on_error)
    3302             : {
    3303           4 :     char emsg[EMSG_BUF_SIZE] = "";
    3304             :     TIFFRGBAImage img;
    3305             :     int ok;
    3306             :     uint32_t tile_xsize, tile_ysize;
    3307             :     uint32_t read_xsize, read_ysize;
    3308             :     uint32_t i_row;
    3309             : 
    3310             :     /*
    3311             :      * Verify that our request is legal - on a tile file, and on a
    3312             :      * tile boundary.
    3313             :      */
    3314             : 
    3315           4 :     if (!TIFFIsTiled(tif))
    3316             :     {
    3317           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3318             :                       "Can't use TIFFReadRGBATile() with striped file.");
    3319           0 :         return (0);
    3320             :     }
    3321             : 
    3322           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
    3323           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
    3324           4 :     if (tile_xsize == 0 || tile_ysize == 0)
    3325             :     {
    3326           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "tile_xsize or tile_ysize is zero");
    3327           0 :         return (0);
    3328             :     }
    3329             : 
    3330           4 :     if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
    3331             :     {
    3332           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3333             :                       "Row/col passed to TIFFReadRGBATile() must be top"
    3334             :                       "left corner of a tile.");
    3335           0 :         return (0);
    3336             :     }
    3337             : 
    3338             :     /*
    3339             :      * Setup the RGBA reader.
    3340             :      */
    3341             : 
    3342           8 :     if (!TIFFRGBAImageOK(tif, emsg) ||
    3343           4 :         !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3344             :     {
    3345           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3346           0 :         return (0);
    3347             :     }
    3348             : 
    3349           4 :     if (col >= img.width || row >= img.height)
    3350             :     {
    3351           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3352             :                       "Invalid row/col passed to TIFFReadRGBATile().");
    3353           0 :         TIFFRGBAImageEnd(&img);
    3354           0 :         return (0);
    3355             :     }
    3356             : 
    3357             :     /*
    3358             :      * The TIFFRGBAImageGet() function doesn't allow us to get off the
    3359             :      * edge of the image, even to fill an otherwise valid tile.  So we
    3360             :      * figure out how much we can read, and fix up the tile buffer to
    3361             :      * a full tile configuration afterwards.
    3362             :      */
    3363             : 
    3364           4 :     if (row + tile_ysize > img.height)
    3365           4 :         read_ysize = img.height - row;
    3366             :     else
    3367           0 :         read_ysize = tile_ysize;
    3368             : 
    3369           4 :     if (col + tile_xsize > img.width)
    3370           4 :         read_xsize = img.width - col;
    3371             :     else
    3372           0 :         read_xsize = tile_xsize;
    3373             : 
    3374             :     /*
    3375             :      * Read the chunk of imagery.
    3376             :      */
    3377             : 
    3378           4 :     img.row_offset = row;
    3379           4 :     img.col_offset = col;
    3380             : 
    3381           4 :     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize);
    3382             : 
    3383           4 :     TIFFRGBAImageEnd(&img);
    3384             : 
    3385             :     /*
    3386             :      * If our read was incomplete we will need to fix up the tile by
    3387             :      * shifting the data around as if a full tile of data is being returned.
    3388             :      *
    3389             :      * This is all the more complicated because the image is organized in
    3390             :      * bottom to top format.
    3391             :      */
    3392             : 
    3393           4 :     if (read_xsize == tile_xsize && read_ysize == tile_ysize)
    3394           0 :         return (ok);
    3395             : 
    3396         500 :     for (i_row = 0; i_row < read_ysize; i_row++)
    3397             :     {
    3398         496 :         memmove(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize,
    3399         496 :                 raster + (size_t)(read_ysize - i_row - 1) * read_xsize,
    3400             :                 read_xsize * sizeof(uint32_t));
    3401         496 :         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize +
    3402             :                         read_xsize,
    3403         496 :                     0, sizeof(uint32_t) * (tile_xsize - read_xsize));
    3404             :     }
    3405             : 
    3406         468 :     for (i_row = read_ysize; i_row < tile_ysize; i_row++)
    3407             :     {
    3408         464 :         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize, 0,
    3409         464 :                     sizeof(uint32_t) * tile_xsize);
    3410             :     }
    3411             : 
    3412           4 :     return (ok);
    3413             : }

Generated by: LCOV version 1.14