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

Generated by: LCOV version 1.14