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

Generated by: LCOV version 1.14