LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_getimage.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 1015 1712 59.3 %
Date: 2025-05-31 00:00:17 Functions: 38 64 59.4 %

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

Generated by: LCOV version 1.14