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

Generated by: LCOV version 1.14