LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_getimage.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 1054 1796 58.7 %
Date: 2026-06-03 16:29:47 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 :     const tmsize_t fromskewLocal =
    1751           0 :         (tmsize_t)fromskew * (tmsize_t)(2 * samplesperpixel);
    1752             : 
    1753             :     (void)y;
    1754           0 :     for (; h > 0; --h)
    1755             :     {
    1756           0 :         uint16_t *wp = (uint16_t *)pp;
    1757             : 
    1758           0 :         for (x = w; x > 0; --x)
    1759             :         {
    1760             :             /* use high order byte of 16bit value */
    1761             : 
    1762           0 :             *cp++ = BWmap[*wp >> 8][0];
    1763           0 :             pp += 2 * samplesperpixel;
    1764           0 :             wp += samplesperpixel;
    1765             :         }
    1766           0 :         cp += toskew;
    1767           0 :         pp += fromskewLocal;
    1768             :     }
    1769           0 : }
    1770             : 
    1771             : /*
    1772             :  * 1-bit bilevel => colormap/RGB
    1773             :  */
    1774           0 : DECLAREContigPutFunc(put1bitbwtile)
    1775             : {
    1776           0 :     uint32_t **BWmap = img->BWmap;
    1777             : 
    1778             :     (void)x;
    1779             :     (void)y;
    1780           0 :     fromskew /= 8;
    1781           0 :     for (; h > 0; --h)
    1782             :     {
    1783             :         uint32_t *bw;
    1784           0 :         UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1785           0 :         cp += toskew;
    1786           0 :         pp += fromskew;
    1787             :     }
    1788           0 : }
    1789             : 
    1790             : /*
    1791             :  * 2-bit greyscale => colormap/RGB
    1792             :  */
    1793           0 : DECLAREContigPutFunc(put2bitbwtile)
    1794             : {
    1795           0 :     uint32_t **BWmap = img->BWmap;
    1796             : 
    1797             :     (void)x;
    1798             :     (void)y;
    1799           0 :     fromskew /= 4;
    1800           0 :     for (; h > 0; --h)
    1801             :     {
    1802             :         uint32_t *bw;
    1803           0 :         UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1804           0 :         cp += toskew;
    1805           0 :         pp += fromskew;
    1806             :     }
    1807           0 : }
    1808             : 
    1809             : /*
    1810             :  * 4-bit greyscale => colormap/RGB
    1811             :  */
    1812           0 : DECLAREContigPutFunc(put4bitbwtile)
    1813             : {
    1814           0 :     uint32_t **BWmap = img->BWmap;
    1815             : 
    1816             :     (void)x;
    1817             :     (void)y;
    1818           0 :     fromskew /= 2;
    1819           0 :     for (; h > 0; --h)
    1820             :     {
    1821             :         uint32_t *bw;
    1822           0 :         UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
    1823           0 :         cp += toskew;
    1824           0 :         pp += fromskew;
    1825             :     }
    1826           0 : }
    1827             : 
    1828             : /*
    1829             :  * 8-bit packed samples, no Map => RGB
    1830             :  */
    1831           0 : DECLAREContigPutFunc(putRGBcontig8bittile)
    1832             : {
    1833           0 :     int samplesperpixel = img->samplesperpixel;
    1834             : 
    1835             :     (void)x;
    1836             :     (void)y;
    1837           0 :     const tmsize_t fromskewLocal =
    1838           0 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1839           0 :     for (; h > 0; --h)
    1840             :     {
    1841           0 :         UNROLL8(w, NOP, *cp++ = PACK(pp[0], pp[1], pp[2]);
    1842             :                 pp += samplesperpixel);
    1843           0 :         cp += toskew;
    1844           0 :         pp += fromskewLocal;
    1845             :     }
    1846           0 : }
    1847             : 
    1848             : /*
    1849             :  * 8-bit packed samples => RGBA w/ associated alpha
    1850             :  * (known to have Map == NULL)
    1851             :  */
    1852          13 : DECLAREContigPutFunc(putRGBAAcontig8bittile)
    1853             : {
    1854          13 :     int samplesperpixel = img->samplesperpixel;
    1855             : 
    1856             :     (void)x;
    1857             :     (void)y;
    1858          13 :     const tmsize_t fromskewLocal =
    1859          13 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1860         163 :     for (; h > 0; --h)
    1861             :     {
    1862        3150 :         UNROLL8(w, NOP, *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
    1863             :                 pp += samplesperpixel);
    1864         150 :         cp += toskew;
    1865         150 :         pp += fromskewLocal;
    1866             :     }
    1867          13 : }
    1868             : 
    1869             : /*
    1870             :  * 8-bit packed samples => RGBA w/ unassociated alpha
    1871             :  * (known to have Map == NULL)
    1872             :  */
    1873          13 : DECLAREContigPutFunc(putRGBUAcontig8bittile)
    1874             : {
    1875          13 :     int samplesperpixel = img->samplesperpixel;
    1876             :     (void)y;
    1877          13 :     const tmsize_t fromskewLocal =
    1878          13 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1879         163 :     for (; h > 0; --h)
    1880             :     {
    1881             :         uint32_t r, g, b, a;
    1882             :         uint8_t *m;
    1883       24450 :         for (x = w; x > 0; --x)
    1884             :         {
    1885       24300 :             a = pp[3];
    1886       24300 :             m = img->UaToAa + ((size_t)a << 8);
    1887       24300 :             r = m[pp[0]];
    1888       24300 :             g = m[pp[1]];
    1889       24300 :             b = m[pp[2]];
    1890       24300 :             *cp++ = PACK4(r, g, b, a);
    1891       24300 :             pp += samplesperpixel;
    1892             :         }
    1893         150 :         cp += toskew;
    1894         150 :         pp += fromskewLocal;
    1895             :     }
    1896          13 : }
    1897             : 
    1898             : /*
    1899             :  * 16-bit packed samples => RGB
    1900             :  */
    1901           0 : DECLAREContigPutFunc(putRGBcontig16bittile)
    1902             : {
    1903           0 :     int samplesperpixel = img->samplesperpixel;
    1904           0 :     uint16_t *wp = (uint16_t *)pp;
    1905             :     (void)y;
    1906           0 :     const tmsize_t fromskewLocal =
    1907           0 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1908           0 :     for (; h > 0; --h)
    1909             :     {
    1910           0 :         for (x = w; x > 0; --x)
    1911             :         {
    1912           0 :             *cp++ = PACK(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1913             :                          img->Bitdepth16To8[wp[2]]);
    1914           0 :             wp += samplesperpixel;
    1915             :         }
    1916           0 :         cp += toskew;
    1917           0 :         wp += fromskewLocal;
    1918             :     }
    1919           0 : }
    1920             : 
    1921             : /*
    1922             :  * 16-bit packed samples => RGBA w/ associated alpha
    1923             :  * (known to have Map == NULL)
    1924             :  */
    1925           0 : DECLAREContigPutFunc(putRGBAAcontig16bittile)
    1926             : {
    1927           0 :     int samplesperpixel = img->samplesperpixel;
    1928           0 :     uint16_t *wp = (uint16_t *)pp;
    1929             :     (void)y;
    1930           0 :     const tmsize_t fromskewLocal =
    1931           0 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1932           0 :     for (; h > 0; --h)
    1933             :     {
    1934           0 :         for (x = w; x > 0; --x)
    1935             :         {
    1936           0 :             *cp++ = PACK4(img->Bitdepth16To8[wp[0]], img->Bitdepth16To8[wp[1]],
    1937             :                           img->Bitdepth16To8[wp[2]], img->Bitdepth16To8[wp[3]]);
    1938           0 :             wp += samplesperpixel;
    1939             :         }
    1940           0 :         cp += toskew;
    1941           0 :         wp += fromskewLocal;
    1942             :     }
    1943           0 : }
    1944             : 
    1945             : /*
    1946             :  * 16-bit packed samples => RGBA w/ unassociated alpha
    1947             :  * (known to have Map == NULL)
    1948             :  */
    1949           0 : DECLAREContigPutFunc(putRGBUAcontig16bittile)
    1950             : {
    1951           0 :     int samplesperpixel = img->samplesperpixel;
    1952           0 :     uint16_t *wp = (uint16_t *)pp;
    1953             :     (void)y;
    1954           0 :     const tmsize_t fromskewLocal =
    1955           0 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1956           0 :     for (; h > 0; --h)
    1957             :     {
    1958             :         uint32_t r, g, b, a;
    1959             :         uint8_t *m;
    1960           0 :         for (x = w; x > 0; --x)
    1961             :         {
    1962           0 :             a = img->Bitdepth16To8[wp[3]];
    1963           0 :             m = img->UaToAa + ((size_t)a << 8);
    1964           0 :             r = m[img->Bitdepth16To8[wp[0]]];
    1965           0 :             g = m[img->Bitdepth16To8[wp[1]]];
    1966           0 :             b = m[img->Bitdepth16To8[wp[2]]];
    1967           0 :             *cp++ = PACK4(r, g, b, a);
    1968           0 :             wp += samplesperpixel;
    1969             :         }
    1970           0 :         cp += toskew;
    1971           0 :         wp += fromskewLocal;
    1972             :     }
    1973           0 : }
    1974             : 
    1975             : /*
    1976             :  * 8-bit packed CMYK samples w/o Map => RGB
    1977             :  *
    1978             :  * NB: The conversion of CMYK->RGB is *very* crude.
    1979             :  */
    1980           6 : DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
    1981             : {
    1982           6 :     int samplesperpixel = img->samplesperpixel;
    1983             :     uint16_t r, g, b, k;
    1984             : 
    1985             :     (void)x;
    1986             :     (void)y;
    1987           6 :     const tmsize_t fromskewLocal =
    1988           6 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    1989         156 :     for (; h > 0; --h)
    1990             :     {
    1991        1050 :         UNROLL8(w, NOP, k = (uint16_t)(255 - pp[3]);
    1992             :                 r = (uint16_t)((k * (uint16_t)(255 - pp[0])) / 255);
    1993             :                 g = (uint16_t)((k * (uint16_t)(255 - pp[1])) / 255);
    1994             :                 b = (uint16_t)((k * (uint16_t)(255 - pp[2])) / 255);
    1995             :                 *cp++ = PACK(r, g, b); pp += samplesperpixel);
    1996         150 :         cp += toskew;
    1997         150 :         pp += fromskewLocal;
    1998             :     }
    1999           6 : }
    2000             : 
    2001             : /*
    2002             :  * 8-bit packed CMYK samples w/Map => RGB
    2003             :  *
    2004             :  * NB: The conversion of CMYK->RGB is *very* crude.
    2005             :  */
    2006           0 : DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
    2007             : {
    2008           0 :     int samplesperpixel = img->samplesperpixel;
    2009           0 :     TIFFRGBValue *Map = img->Map;
    2010             :     unsigned int r, g, b, k;
    2011             : 
    2012             :     (void)y;
    2013           0 :     const tmsize_t fromskewLocal =
    2014           0 :         (tmsize_t)fromskew * (tmsize_t)samplesperpixel;
    2015           0 :     for (; h > 0; --h)
    2016             :     {
    2017           0 :         for (x = w; x > 0; --x)
    2018             :         {
    2019           0 :             k = 255U - pp[3];
    2020           0 :             r = (k * (255U - pp[0])) / 255U;
    2021           0 :             g = (k * (255U - pp[1])) / 255U;
    2022           0 :             b = (k * (255U - pp[2])) / 255U;
    2023           0 :             *cp++ = PACK(Map[r], Map[g], Map[b]);
    2024           0 :             pp += samplesperpixel;
    2025             :         }
    2026           0 :         pp += fromskewLocal;
    2027           0 :         cp += toskew;
    2028             :     }
    2029           0 : }
    2030             : 
    2031             : #define DECLARESepPutFunc(name)                                                \
    2032             :     static void name(TIFFRGBAImage *img, uint32_t *cp, uint32_t x, uint32_t y, \
    2033             :                      uint32_t w, uint32_t h, int32_t fromskew, int32_t toskew, \
    2034             :                      unsigned char *r, unsigned char *g, unsigned char *b,     \
    2035             :                      unsigned char *a)
    2036             : 
    2037             : /*
    2038             :  * 8-bit unpacked samples => RGB
    2039             :  */
    2040           3 : DECLARESepPutFunc(putRGBseparate8bittile)
    2041             : {
    2042             :     (void)img;
    2043             :     (void)x;
    2044             :     (void)y;
    2045             :     (void)a;
    2046         153 :     for (; h > 0; --h)
    2047             :     {
    2048        1050 :         UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
    2049         150 :         SKEW(r, g, b, fromskew);
    2050         150 :         cp += toskew;
    2051             :     }
    2052           3 : }
    2053             : 
    2054             : /*
    2055             :  * 8-bit unpacked samples => RGBA w/ associated alpha
    2056             :  */
    2057           0 : DECLARESepPutFunc(putRGBAAseparate8bittile)
    2058             : {
    2059             :     (void)img;
    2060             :     (void)x;
    2061             :     (void)y;
    2062           0 :     for (; h > 0; --h)
    2063             :     {
    2064           0 :         UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
    2065           0 :         SKEW4(r, g, b, a, fromskew);
    2066           0 :         cp += toskew;
    2067             :     }
    2068           0 : }
    2069             : 
    2070             : /*
    2071             :  * 8-bit unpacked CMYK samples => RGBA
    2072             :  */
    2073           0 : DECLARESepPutFunc(putCMYKseparate8bittile)
    2074             : {
    2075             :     (void)img;
    2076             :     (void)y;
    2077           0 :     for (; h > 0; --h)
    2078             :     {
    2079             :         unsigned int rv, gv, bv, kv;
    2080           0 :         for (x = w; x > 0; --x)
    2081             :         {
    2082           0 :             kv = 255U - *a++;
    2083           0 :             rv = (kv * (255U - *r++)) / 255U;
    2084           0 :             gv = (kv * (255U - *g++)) / 255U;
    2085           0 :             bv = (kv * (255U - *b++)) / 255U;
    2086           0 :             *cp++ = PACK4(rv, gv, bv, 255);
    2087             :         }
    2088           0 :         SKEW4(r, g, b, a, fromskew);
    2089           0 :         cp += toskew;
    2090             :     }
    2091           0 : }
    2092             : 
    2093             : /*
    2094             :  * 8-bit unpacked samples => RGBA w/ unassociated alpha
    2095             :  */
    2096           0 : DECLARESepPutFunc(putRGBUAseparate8bittile)
    2097             : {
    2098             :     (void)img;
    2099             :     (void)y;
    2100           0 :     for (; h > 0; --h)
    2101             :     {
    2102             :         uint32_t rv, gv, bv, av;
    2103             :         uint8_t *m;
    2104           0 :         for (x = w; x > 0; --x)
    2105             :         {
    2106           0 :             av = *a++;
    2107           0 :             m = img->UaToAa + ((size_t)av << 8);
    2108           0 :             rv = m[*r++];
    2109           0 :             gv = m[*g++];
    2110           0 :             bv = m[*b++];
    2111           0 :             *cp++ = PACK4(rv, gv, bv, av);
    2112             :         }
    2113           0 :         SKEW4(r, g, b, a, fromskew);
    2114           0 :         cp += toskew;
    2115             :     }
    2116           0 : }
    2117             : 
    2118             : /*
    2119             :  * 16-bit unpacked samples => RGB
    2120             :  */
    2121           0 : DECLARESepPutFunc(putRGBseparate16bittile)
    2122             : {
    2123           0 :     uint16_t *wr = (uint16_t *)r;
    2124           0 :     uint16_t *wg = (uint16_t *)g;
    2125           0 :     uint16_t *wb = (uint16_t *)b;
    2126             :     (void)img;
    2127             :     (void)y;
    2128             :     (void)a;
    2129           0 :     for (; h > 0; --h)
    2130             :     {
    2131           0 :         for (x = 0; x < w; x++)
    2132           0 :             *cp++ = PACK(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    2133             :                          img->Bitdepth16To8[*wb++]);
    2134           0 :         SKEW(wr, wg, wb, fromskew);
    2135           0 :         cp += toskew;
    2136             :     }
    2137           0 : }
    2138             : 
    2139             : /*
    2140             :  * 16-bit unpacked samples => RGBA w/ associated alpha
    2141             :  */
    2142           0 : DECLARESepPutFunc(putRGBAAseparate16bittile)
    2143             : {
    2144           0 :     uint16_t *wr = (uint16_t *)r;
    2145           0 :     uint16_t *wg = (uint16_t *)g;
    2146           0 :     uint16_t *wb = (uint16_t *)b;
    2147           0 :     uint16_t *wa = (uint16_t *)a;
    2148             :     (void)img;
    2149             :     (void)y;
    2150           0 :     for (; h > 0; --h)
    2151             :     {
    2152           0 :         for (x = 0; x < w; x++)
    2153           0 :             *cp++ = PACK4(img->Bitdepth16To8[*wr++], img->Bitdepth16To8[*wg++],
    2154             :                           img->Bitdepth16To8[*wb++], img->Bitdepth16To8[*wa++]);
    2155           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    2156           0 :         cp += toskew;
    2157             :     }
    2158           0 : }
    2159             : 
    2160             : /*
    2161             :  * 16-bit unpacked samples => RGBA w/ unassociated alpha
    2162             :  */
    2163           0 : DECLARESepPutFunc(putRGBUAseparate16bittile)
    2164             : {
    2165           0 :     uint16_t *wr = (uint16_t *)r;
    2166           0 :     uint16_t *wg = (uint16_t *)g;
    2167           0 :     uint16_t *wb = (uint16_t *)b;
    2168           0 :     uint16_t *wa = (uint16_t *)a;
    2169             :     (void)img;
    2170             :     (void)y;
    2171           0 :     for (; h > 0; --h)
    2172             :     {
    2173             :         uint32_t r2, g2, b2, a2;
    2174             :         uint8_t *m;
    2175           0 :         for (x = w; x > 0; --x)
    2176             :         {
    2177           0 :             a2 = img->Bitdepth16To8[*wa++];
    2178           0 :             m = img->UaToAa + ((size_t)a2 << 8);
    2179           0 :             r2 = m[img->Bitdepth16To8[*wr++]];
    2180           0 :             g2 = m[img->Bitdepth16To8[*wg++]];
    2181           0 :             b2 = m[img->Bitdepth16To8[*wb++]];
    2182           0 :             *cp++ = PACK4(r2, g2, b2, a2);
    2183             :         }
    2184           0 :         SKEW4(wr, wg, wb, wa, fromskew);
    2185           0 :         cp += toskew;
    2186             :     }
    2187           0 : }
    2188             : 
    2189             : /*
    2190             :  * 8-bit packed CIE L*a*b 1976 samples => RGB
    2191             :  */
    2192           1 : DECLAREContigPutFunc(putcontig8bitCIELab8)
    2193             : {
    2194             :     float X, Y, Z;
    2195             :     uint32_t r, g, b;
    2196             :     (void)y;
    2197           1 :     const tmsize_t fromskewLocal = (tmsize_t)fromskew * (tmsize_t)3;
    2198           2 :     for (; h > 0; --h)
    2199             :     {
    2200           2 :         for (x = w; x > 0; --x)
    2201             :         {
    2202           1 :             TIFFCIELabToXYZ(img->cielab, (unsigned char)pp[0],
    2203           1 :                             (signed char)pp[1], (signed char)pp[2], &X, &Y, &Z);
    2204           1 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2205           1 :             *cp++ = PACK(r, g, b);
    2206           1 :             pp += 3;
    2207             :         }
    2208           1 :         cp += toskew;
    2209           1 :         pp += fromskewLocal;
    2210             :     }
    2211           1 : }
    2212             : 
    2213             : /*
    2214             :  * 16-bit packed CIE L*a*b 1976 samples => RGB
    2215             :  */
    2216           0 : DECLAREContigPutFunc(putcontig8bitCIELab16)
    2217             : {
    2218             :     float X, Y, Z;
    2219             :     uint32_t r, g, b;
    2220           0 :     uint16_t *wp = (uint16_t *)pp;
    2221             :     (void)y;
    2222           0 :     const tmsize_t fromskewLocal = (tmsize_t)fromskew * (tmsize_t)3;
    2223           0 :     for (; h > 0; --h)
    2224             :     {
    2225           0 :         for (x = w; x > 0; --x)
    2226             :         {
    2227           0 :             TIFFCIELab16ToXYZ(img->cielab, (uint16_t)wp[0], (int16_t)wp[1],
    2228           0 :                               (int16_t)wp[2], &X, &Y, &Z);
    2229           0 :             TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
    2230           0 :             *cp++ = PACK(r, g, b);
    2231           0 :             wp += 3;
    2232             :         }
    2233           0 :         cp += toskew;
    2234           0 :         wp += fromskewLocal;
    2235             :     }
    2236           0 : }
    2237             : 
    2238             : /*
    2239             :  * YCbCr -> RGB conversion and packing routines.
    2240             :  */
    2241             : 
    2242             : #define YCbCrtoRGB(dst, Y)                                                     \
    2243             :     {                                                                          \
    2244             :         uint32_t r, g, b;                                                      \
    2245             :         TIFFYCbCrtoRGB(img->ycbcr, (Y), (int32_t)Cb, (int32_t)Cr, &r, &g, &b); \
    2246             :         dst = PACK(r, g, b);                                                   \
    2247             :     }
    2248             : 
    2249             : /*
    2250             :  * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
    2251             :  */
    2252           2 : DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
    2253             : {
    2254           2 :     uint32_t *cp1 = cp + w + toskew;
    2255           2 :     uint32_t *cp2 = cp1 + w + toskew;
    2256           2 :     uint32_t *cp3 = cp2 + w + toskew;
    2257           2 :     const tmsize_t incr = 3 * (tmsize_t)w + 4 * (tmsize_t)toskew;
    2258             : 
    2259             :     (void)y;
    2260             :     /* adjust fromskew */
    2261           2 :     const tmsize_t fromskewLocal =
    2262           2 :         (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 4 + 2);
    2263           2 :     if ((h & 3) == 0 && (w & 3) == 0)
    2264             :     {
    2265          13 :         for (; h >= 4; h -= 4)
    2266             :         {
    2267          12 :             x = w >> 2;
    2268             :             do
    2269             :             {
    2270         144 :                 int32_t Cb = pp[16];
    2271         144 :                 int32_t Cr = pp[17];
    2272             : 
    2273         144 :                 YCbCrtoRGB(cp[0], pp[0]);
    2274         144 :                 YCbCrtoRGB(cp[1], pp[1]);
    2275         144 :                 YCbCrtoRGB(cp[2], pp[2]);
    2276         144 :                 YCbCrtoRGB(cp[3], pp[3]);
    2277         144 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2278         144 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2279         144 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2280         144 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2281         144 :                 YCbCrtoRGB(cp2[0], pp[8]);
    2282         144 :                 YCbCrtoRGB(cp2[1], pp[9]);
    2283         144 :                 YCbCrtoRGB(cp2[2], pp[10]);
    2284         144 :                 YCbCrtoRGB(cp2[3], pp[11]);
    2285         144 :                 YCbCrtoRGB(cp3[0], pp[12]);
    2286         144 :                 YCbCrtoRGB(cp3[1], pp[13]);
    2287         144 :                 YCbCrtoRGB(cp3[2], pp[14]);
    2288         144 :                 YCbCrtoRGB(cp3[3], pp[15]);
    2289             : 
    2290         144 :                 cp += 4;
    2291         144 :                 cp1 += 4;
    2292         144 :                 cp2 += 4;
    2293         144 :                 cp3 += 4;
    2294         144 :                 pp += 18;
    2295         144 :             } while (--x);
    2296          12 :             cp += incr;
    2297          12 :             cp1 += incr;
    2298          12 :             cp2 += incr;
    2299          12 :             cp3 += incr;
    2300          12 :             pp += fromskewLocal;
    2301             :         }
    2302             :     }
    2303             :     else
    2304             :     {
    2305          10 :         while (h > 0)
    2306             :         {
    2307         110 :             for (x = w; x > 0;)
    2308             :             {
    2309         100 :                 int32_t Cb = pp[16];
    2310         100 :                 int32_t Cr = pp[17];
    2311         100 :                 switch (x)
    2312             :                 {
    2313          90 :                     default:
    2314          90 :                         switch (h)
    2315             :                         {
    2316          81 :                             default:
    2317          81 :                                 YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
    2318          90 :                             case 3:
    2319          90 :                                 YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
    2320          90 :                             case 2:
    2321          90 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2322          90 :                             case 1:
    2323          90 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2324             :                         } /* FALLTHROUGH */
    2325         100 :                     case 3:
    2326         100 :                         switch (h)
    2327             :                         {
    2328          90 :                             default:
    2329          90 :                                 YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
    2330         100 :                             case 3:
    2331         100 :                                 YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
    2332         100 :                             case 2:
    2333         100 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2334         100 :                             case 1:
    2335         100 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2336             :                         } /* FALLTHROUGH */
    2337         100 :                     case 2:
    2338         100 :                         switch (h)
    2339             :                         {
    2340          90 :                             default:
    2341          90 :                                 YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
    2342         100 :                             case 3:
    2343         100 :                                 YCbCrtoRGB(cp2[1], pp[9]); /* FALLTHROUGH */
    2344         100 :                             case 2:
    2345         100 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2346         100 :                             case 1:
    2347         100 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2348             :                         } /* FALLTHROUGH */
    2349         100 :                     case 1:
    2350         100 :                         switch (h)
    2351             :                         {
    2352          90 :                             default:
    2353          90 :                                 YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
    2354         100 :                             case 3:
    2355         100 :                                 YCbCrtoRGB(cp2[0], pp[8]); /* FALLTHROUGH */
    2356         100 :                             case 2:
    2357         100 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2358         100 :                             case 1:
    2359         100 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2360             :                         } /* FALLTHROUGH */
    2361             :                 }
    2362         100 :                 if (x < 4)
    2363             :                 {
    2364          10 :                     cp += x;
    2365          10 :                     cp1 += x;
    2366          10 :                     cp2 += x;
    2367          10 :                     cp3 += x;
    2368          10 :                     x = 0;
    2369             :                 }
    2370             :                 else
    2371             :                 {
    2372          90 :                     cp += 4;
    2373          90 :                     cp1 += 4;
    2374          90 :                     cp2 += 4;
    2375          90 :                     cp3 += 4;
    2376          90 :                     x -= 4;
    2377             :                 }
    2378         100 :                 pp += 18;
    2379             :             }
    2380          10 :             if (h <= 4)
    2381           1 :                 break;
    2382           9 :             h -= 4;
    2383           9 :             cp += incr;
    2384           9 :             cp1 += incr;
    2385           9 :             cp2 += incr;
    2386           9 :             cp3 += incr;
    2387           9 :             pp += fromskewLocal;
    2388             :         }
    2389             :     }
    2390           2 : }
    2391             : 
    2392             : /*
    2393             :  * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
    2394             :  */
    2395           2 : DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
    2396             : {
    2397           2 :     uint32_t *cp1 = cp + w + toskew;
    2398           2 :     const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
    2399             : 
    2400             :     (void)y;
    2401           2 :     const tmsize_t fromskewLocal =
    2402           2 :         (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 2 + 2);
    2403           2 :     if ((w & 3) == 0 && (h & 1) == 0)
    2404             :     {
    2405          25 :         for (; h >= 2; h -= 2)
    2406             :         {
    2407          24 :             x = w >> 2;
    2408             :             do
    2409             :             {
    2410         288 :                 int32_t Cb = pp[8];
    2411         288 :                 int32_t Cr = pp[9];
    2412             : 
    2413         288 :                 YCbCrtoRGB(cp[0], pp[0]);
    2414         288 :                 YCbCrtoRGB(cp[1], pp[1]);
    2415         288 :                 YCbCrtoRGB(cp[2], pp[2]);
    2416         288 :                 YCbCrtoRGB(cp[3], pp[3]);
    2417         288 :                 YCbCrtoRGB(cp1[0], pp[4]);
    2418         288 :                 YCbCrtoRGB(cp1[1], pp[5]);
    2419         288 :                 YCbCrtoRGB(cp1[2], pp[6]);
    2420         288 :                 YCbCrtoRGB(cp1[3], pp[7]);
    2421             : 
    2422         288 :                 cp += 4;
    2423         288 :                 cp1 += 4;
    2424         288 :                 pp += 10;
    2425         288 :             } while (--x);
    2426          24 :             cp += incr;
    2427          24 :             cp1 += incr;
    2428          24 :             pp += fromskewLocal;
    2429             :         }
    2430             :     }
    2431             :     else
    2432             :     {
    2433          20 :         while (h > 0)
    2434             :         {
    2435         220 :             for (x = w; x > 0;)
    2436             :             {
    2437         200 :                 int32_t Cb = pp[8];
    2438         200 :                 int32_t Cr = pp[9];
    2439         200 :                 switch (x)
    2440             :                 {
    2441         180 :                     default:
    2442         180 :                         switch (h)
    2443             :                         {
    2444         171 :                             default:
    2445         171 :                                 YCbCrtoRGB(cp1[3], pp[7]); /* FALLTHROUGH */
    2446         180 :                             case 1:
    2447         180 :                                 YCbCrtoRGB(cp[3], pp[3]); /* FALLTHROUGH */
    2448             :                         } /* FALLTHROUGH */
    2449         200 :                     case 3:
    2450         200 :                         switch (h)
    2451             :                         {
    2452         190 :                             default:
    2453         190 :                                 YCbCrtoRGB(cp1[2], pp[6]); /* FALLTHROUGH */
    2454         200 :                             case 1:
    2455         200 :                                 YCbCrtoRGB(cp[2], pp[2]); /* FALLTHROUGH */
    2456             :                         } /* FALLTHROUGH */
    2457         200 :                     case 2:
    2458         200 :                         switch (h)
    2459             :                         {
    2460         190 :                             default:
    2461         190 :                                 YCbCrtoRGB(cp1[1], pp[5]); /* FALLTHROUGH */
    2462         200 :                             case 1:
    2463         200 :                                 YCbCrtoRGB(cp[1], pp[1]); /* FALLTHROUGH */
    2464             :                         } /* FALLTHROUGH */
    2465         200 :                     case 1:
    2466         200 :                         switch (h)
    2467             :                         {
    2468         190 :                             default:
    2469         190 :                                 YCbCrtoRGB(cp1[0], pp[4]); /* FALLTHROUGH */
    2470         200 :                             case 1:
    2471         200 :                                 YCbCrtoRGB(cp[0], pp[0]); /* FALLTHROUGH */
    2472             :                         } /* FALLTHROUGH */
    2473             :                 }
    2474         200 :                 if (x < 4)
    2475             :                 {
    2476          20 :                     cp += x;
    2477          20 :                     cp1 += x;
    2478          20 :                     x = 0;
    2479             :                 }
    2480             :                 else
    2481             :                 {
    2482         180 :                     cp += 4;
    2483         180 :                     cp1 += 4;
    2484         180 :                     x -= 4;
    2485             :                 }
    2486         200 :                 pp += 10;
    2487             :             }
    2488          20 :             if (h <= 2)
    2489           1 :                 break;
    2490          19 :             h -= 2;
    2491          19 :             cp += incr;
    2492          19 :             cp1 += incr;
    2493          19 :             pp += fromskewLocal;
    2494             :         }
    2495             :     }
    2496           2 : }
    2497             : 
    2498             : /*
    2499             :  * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
    2500             :  */
    2501           1 : DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
    2502             : {
    2503             :     (void)y;
    2504           1 :     const tmsize_t fromskewLocal =
    2505           1 :         (tmsize_t)(fromskew / 4) * (tmsize_t)(4 * 1 + 2);
    2506             :     do
    2507             :     {
    2508          39 :         x = w >> 2;
    2509         390 :         while (x > 0)
    2510             :         {
    2511         351 :             int32_t Cb = pp[4];
    2512         351 :             int32_t Cr = pp[5];
    2513             : 
    2514         351 :             YCbCrtoRGB(cp[0], pp[0]);
    2515         351 :             YCbCrtoRGB(cp[1], pp[1]);
    2516         351 :             YCbCrtoRGB(cp[2], pp[2]);
    2517         351 :             YCbCrtoRGB(cp[3], pp[3]);
    2518             : 
    2519         351 :             cp += 4;
    2520         351 :             pp += 6;
    2521         351 :             x--;
    2522             :         }
    2523             : 
    2524          39 :         if ((w & 3) != 0)
    2525             :         {
    2526          39 :             int32_t Cb = pp[4];
    2527          39 :             int32_t Cr = pp[5];
    2528             : 
    2529          39 :             switch ((w & 3))
    2530             :             {
    2531          39 :                 case 3:
    2532          39 :                     YCbCrtoRGB(cp[2], pp[2]); /*-fallthrough*/
    2533          39 :                 case 2:
    2534          39 :                     YCbCrtoRGB(cp[1], pp[1]); /*-fallthrough*/
    2535          39 :                 case 1:
    2536          39 :                     YCbCrtoRGB(cp[0], pp[0]); /*-fallthrough*/
    2537          39 :                 case 0:
    2538          39 :                     break;
    2539           0 :                 default:
    2540           0 :                     break;
    2541             :             }
    2542             : 
    2543          39 :             cp += (w & 3);
    2544          39 :             pp += 6;
    2545             :         }
    2546             : 
    2547          39 :         cp += toskew;
    2548          39 :         pp += fromskewLocal;
    2549          39 :     } while (--h);
    2550           1 : }
    2551             : 
    2552             : /*
    2553             :  * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
    2554             :  */
    2555           2 : DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
    2556             : {
    2557             :     uint32_t *cp2;
    2558           2 :     const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
    2559             :     (void)y;
    2560           2 :     const tmsize_t fromskewLocal =
    2561           2 :         (tmsize_t)(fromskew / 2) * (tmsize_t)(2 * 2 + 2);
    2562           2 :     cp2 = cp + w + toskew;
    2563         127 :     while (h >= 2)
    2564             :     {
    2565         125 :         x = w;
    2566       12888 :         while (x >= 2)
    2567             :         {
    2568       12763 :             uint32_t Cb = pp[4];
    2569       12763 :             uint32_t Cr = pp[5];
    2570       12763 :             YCbCrtoRGB(cp[0], pp[0]);
    2571       12763 :             YCbCrtoRGB(cp[1], pp[1]);
    2572       12763 :             YCbCrtoRGB(cp2[0], pp[2]);
    2573       12763 :             YCbCrtoRGB(cp2[1], pp[3]);
    2574       12763 :             cp += 2;
    2575       12763 :             cp2 += 2;
    2576       12763 :             pp += 6;
    2577       12763 :             x -= 2;
    2578             :         }
    2579         125 :         if (x == 1)
    2580             :         {
    2581          19 :             uint32_t Cb = pp[4];
    2582          19 :             uint32_t Cr = pp[5];
    2583          19 :             YCbCrtoRGB(cp[0], pp[0]);
    2584          19 :             YCbCrtoRGB(cp2[0], pp[2]);
    2585          19 :             cp++;
    2586          19 :             cp2++;
    2587          19 :             pp += 6;
    2588             :         }
    2589         125 :         cp += incr;
    2590         125 :         cp2 += incr;
    2591         125 :         pp += fromskewLocal;
    2592         125 :         h -= 2;
    2593             :     }
    2594           2 :     if (h == 1)
    2595             :     {
    2596           2 :         x = w;
    2597         138 :         while (x >= 2)
    2598             :         {
    2599         136 :             uint32_t Cb = pp[4];
    2600         136 :             uint32_t Cr = pp[5];
    2601         136 :             YCbCrtoRGB(cp[0], pp[0]);
    2602         136 :             YCbCrtoRGB(cp[1], pp[1]);
    2603         136 :             cp += 2;
    2604         136 :             cp2 += 2;
    2605         136 :             pp += 6;
    2606         136 :             x -= 2;
    2607             :         }
    2608           2 :         if (x == 1)
    2609             :         {
    2610           1 :             uint32_t Cb = pp[4];
    2611           1 :             uint32_t Cr = pp[5];
    2612           1 :             YCbCrtoRGB(cp[0], pp[0]);
    2613             :         }
    2614             :     }
    2615           2 : }
    2616             : 
    2617             : /*
    2618             :  * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
    2619             :  */
    2620           1 : DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
    2621             : {
    2622             :     (void)y;
    2623           1 :     const tmsize_t fromskewLocal =
    2624           1 :         (tmsize_t)(fromskew / 2) * (tmsize_t)(2 * 1 + 2);
    2625             :     do
    2626             :     {
    2627          39 :         x = w >> 1;
    2628         780 :         while (x > 0)
    2629             :         {
    2630         741 :             int32_t Cb = pp[2];
    2631         741 :             int32_t Cr = pp[3];
    2632             : 
    2633         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2634         741 :             YCbCrtoRGB(cp[1], pp[1]);
    2635             : 
    2636         741 :             cp += 2;
    2637         741 :             pp += 4;
    2638         741 :             x--;
    2639             :         }
    2640             : 
    2641          39 :         if ((w & 1) != 0)
    2642             :         {
    2643          39 :             int32_t Cb = pp[2];
    2644          39 :             int32_t Cr = pp[3];
    2645             : 
    2646          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2647             : 
    2648          39 :             cp += 1;
    2649          39 :             pp += 4;
    2650             :         }
    2651             : 
    2652          39 :         cp += toskew;
    2653          39 :         pp += fromskewLocal;
    2654          39 :     } while (--h);
    2655           1 : }
    2656             : 
    2657             : /*
    2658             :  * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
    2659             :  */
    2660           1 : DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
    2661             : {
    2662             :     uint32_t *cp2;
    2663           1 :     const tmsize_t incr = 2 * (tmsize_t)toskew + (tmsize_t)w;
    2664             :     (void)y;
    2665           1 :     const tmsize_t fromskewLocal =
    2666           1 :         (tmsize_t)(fromskew / 1) * (tmsize_t)(1 * 2 + 2);
    2667           1 :     cp2 = cp + w + toskew;
    2668          20 :     while (h >= 2)
    2669             :     {
    2670          19 :         x = w;
    2671             :         do
    2672             :         {
    2673         741 :             uint32_t Cb = pp[2];
    2674         741 :             uint32_t Cr = pp[3];
    2675         741 :             YCbCrtoRGB(cp[0], pp[0]);
    2676         741 :             YCbCrtoRGB(cp2[0], pp[1]);
    2677         741 :             cp++;
    2678         741 :             cp2++;
    2679         741 :             pp += 4;
    2680         741 :         } while (--x);
    2681          19 :         cp += incr;
    2682          19 :         cp2 += incr;
    2683          19 :         pp += fromskewLocal;
    2684          19 :         h -= 2;
    2685             :     }
    2686           1 :     if (h == 1)
    2687             :     {
    2688           1 :         x = w;
    2689             :         do
    2690             :         {
    2691          39 :             uint32_t Cb = pp[2];
    2692          39 :             uint32_t Cr = pp[3];
    2693          39 :             YCbCrtoRGB(cp[0], pp[0]);
    2694          39 :             cp++;
    2695          39 :             pp += 4;
    2696          39 :         } while (--x);
    2697             :     }
    2698           1 : }
    2699             : 
    2700             : /*
    2701             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2702             :  */
    2703           1 : DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
    2704             : {
    2705             :     (void)y;
    2706           1 :     const tmsize_t fromskewLocal =
    2707           1 :         (tmsize_t)(fromskew / 1) * (tmsize_t)(1 * 1 + 2);
    2708             :     do
    2709             :     {
    2710          39 :         x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
    2711             :         do
    2712             :         {
    2713        1521 :             int32_t Cb = pp[1];
    2714        1521 :             int32_t Cr = pp[2];
    2715             : 
    2716        1521 :             YCbCrtoRGB(*cp++, pp[0]);
    2717             : 
    2718        1521 :             pp += 3;
    2719        1521 :         } while (--x);
    2720          39 :         cp += toskew;
    2721          39 :         pp += fromskewLocal;
    2722          39 :     } while (--h);
    2723           1 : }
    2724             : 
    2725             : /*
    2726             :  * 8-bit packed YCbCr samples w/ no subsampling => RGB
    2727             :  */
    2728           0 : DECLARESepPutFunc(putseparate8bitYCbCr11tile)
    2729             : {
    2730             :     (void)y;
    2731             :     (void)a;
    2732             :     /* TODO: naming of input vars is still off, change obfuscating declaration
    2733             :      * inside define, or resolve obfuscation */
    2734           0 :     for (; h > 0; --h)
    2735             :     {
    2736           0 :         x = w;
    2737             :         do
    2738             :         {
    2739             :             uint32_t dr, dg, db;
    2740           0 :             TIFFYCbCrtoRGB(img->ycbcr, *r++, *g++, *b++, &dr, &dg, &db);
    2741           0 :             *cp++ = PACK(dr, dg, db);
    2742           0 :         } while (--x);
    2743           0 :         SKEW(r, g, b, fromskew);
    2744           0 :         cp += toskew;
    2745             :     }
    2746           0 : }
    2747             : #undef YCbCrtoRGB
    2748             : 
    2749         102 : static int isInRefBlackWhiteRange(float f)
    2750             : {
    2751         102 :     return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF;
    2752             : }
    2753             : 
    2754          17 : static int initYCbCrConversion(TIFFRGBAImage *img)
    2755             : {
    2756             :     static const char module[] = "initYCbCrConversion";
    2757             : 
    2758             :     float *luma, *refBlackWhite;
    2759             : 
    2760          17 :     if (img->ycbcr == NULL)
    2761             :     {
    2762          17 :         img->ycbcr = (TIFFYCbCrToRGB *)_TIFFmallocExt(
    2763             :             img->tif, TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)) +
    2764             :                           4 * 256 * sizeof(TIFFRGBValue) +
    2765             :                           2 * 256 * sizeof(int) + 3 * 256 * sizeof(int32_t));
    2766          17 :         if (img->ycbcr == NULL)
    2767             :         {
    2768           0 :             TIFFErrorExtR(img->tif, module,
    2769             :                           "No space for YCbCr->RGB conversion state");
    2770           0 :             return (0);
    2771             :         }
    2772             :     }
    2773             : 
    2774          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
    2775          17 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
    2776             :                           &refBlackWhite);
    2777             : 
    2778             :     /* Do some validation to avoid later issues. Detect NaN for now */
    2779             :     /* and also if lumaGreen is zero since we divide by it later */
    2780          17 :     if (isnan(luma[0]) || isnan(luma[1]) || TIFF_FLOAT_EQ(luma[1], 0.0f) ||
    2781          17 :         isnan(luma[2]))
    2782             :     {
    2783           0 :         TIFFErrorExtR(img->tif, module,
    2784             :                       "Invalid values for YCbCrCoefficients tag");
    2785           0 :         return (0);
    2786             :     }
    2787             : 
    2788          34 :     if (!isInRefBlackWhiteRange(refBlackWhite[0]) ||
    2789          34 :         !isInRefBlackWhiteRange(refBlackWhite[1]) ||
    2790          34 :         !isInRefBlackWhiteRange(refBlackWhite[2]) ||
    2791          34 :         !isInRefBlackWhiteRange(refBlackWhite[3]) ||
    2792          34 :         !isInRefBlackWhiteRange(refBlackWhite[4]) ||
    2793          17 :         !isInRefBlackWhiteRange(refBlackWhite[5]))
    2794             :     {
    2795           0 :         TIFFErrorExtR(img->tif, module,
    2796             :                       "Invalid values for ReferenceBlackWhite tag");
    2797           0 :         return (0);
    2798             :     }
    2799             : 
    2800          17 :     if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
    2801           0 :         return (0);
    2802          17 :     return (1);
    2803             : }
    2804             : 
    2805           1 : static tileContigRoutine initCIELabConversion(TIFFRGBAImage *img)
    2806             : {
    2807             :     static const char module[] = "initCIELabConversion";
    2808             : 
    2809             :     float *whitePoint;
    2810             :     float refWhite[3];
    2811             : 
    2812           1 :     TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
    2813           1 :     if (TIFF_FLOAT_EQ(whitePoint[1], 0.0f))
    2814             :     {
    2815           0 :         TIFFErrorExtR(img->tif, module, "Invalid value for WhitePoint tag.");
    2816           0 :         return NULL;
    2817             :     }
    2818             : 
    2819           1 :     if (!img->cielab)
    2820             :     {
    2821           1 :         img->cielab = (TIFFCIELabToRGB *)_TIFFmallocExt(
    2822             :             img->tif, sizeof(TIFFCIELabToRGB));
    2823           1 :         if (!img->cielab)
    2824             :         {
    2825           0 :             TIFFErrorExtR(img->tif, module,
    2826             :                           "No space for CIE L*a*b*->RGB conversion state.");
    2827           0 :             return NULL;
    2828             :         }
    2829             :     }
    2830             : 
    2831           1 :     refWhite[1] = 100.0f;
    2832           1 :     refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
    2833           1 :     refWhite[2] =
    2834           1 :         (1.0f - whitePoint[0] - whitePoint[1]) / whitePoint[1] * refWhite[1];
    2835           1 :     if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0)
    2836             :     {
    2837           0 :         TIFFErrorExtR(img->tif, module,
    2838             :                       "Failed to initialize CIE L*a*b*->RGB conversion state.");
    2839           0 :         _TIFFfreeExt(img->tif, img->cielab);
    2840           0 :         return NULL;
    2841             :     }
    2842             : 
    2843           1 :     if (img->bitspersample == 8)
    2844           1 :         return putcontig8bitCIELab8;
    2845           0 :     else if (img->bitspersample == 16)
    2846           0 :         return putcontig8bitCIELab16;
    2847           0 :     return NULL;
    2848             : }
    2849             : 
    2850             : /*
    2851             :  * Greyscale images with less than 8 bits/sample are handled
    2852             :  * with a table to avoid lots of shifts and masks.  The table
    2853             :  * is setup so that put*bwtile (below) can retrieve 8/bitspersample
    2854             :  * pixel values simply by indexing into the table with one
    2855             :  * number.
    2856             :  */
    2857           9 : static int makebwmap(TIFFRGBAImage *img)
    2858             : {
    2859           9 :     TIFFRGBValue *Map = img->Map;
    2860           9 :     int bitspersample = img->bitspersample;
    2861           9 :     int nsamples = 8 / bitspersample;
    2862             :     int i;
    2863             :     uint32_t *p;
    2864             : 
    2865           9 :     if (nsamples == 0)
    2866           0 :         nsamples = 1;
    2867             : 
    2868          18 :     img->BWmap = (uint32_t **)_TIFFmallocExt(
    2869             :         img->tif,
    2870           9 :         (tmsize_t)((size_t)256 * sizeof(uint32_t *) +
    2871           9 :                    ((size_t)256 * (size_t)nsamples * sizeof(uint32_t))));
    2872           9 :     if (img->BWmap == NULL)
    2873             :     {
    2874           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2875             :                       "No space for B&W mapping table");
    2876           0 :         return (0);
    2877             :     }
    2878           9 :     p = (uint32_t *)(img->BWmap + 256);
    2879        2313 :     for (i = 0; i < 256; i++)
    2880             :     {
    2881             :         TIFFRGBValue c;
    2882        2304 :         img->BWmap[i] = p;
    2883        2304 :         switch (bitspersample)
    2884             :         {
    2885             : #define GREY(x)                                                                \
    2886             :     c = Map[x];                                                                \
    2887             :     *p++ = PACK(c, c, c);
    2888           0 :             case 1:
    2889           0 :                 GREY(i >> 7);
    2890           0 :                 GREY((i >> 6) & 1);
    2891           0 :                 GREY((i >> 5) & 1);
    2892           0 :                 GREY((i >> 4) & 1);
    2893           0 :                 GREY((i >> 3) & 1);
    2894           0 :                 GREY((i >> 2) & 1);
    2895           0 :                 GREY((i >> 1) & 1);
    2896           0 :                 GREY(i & 1);
    2897           0 :                 break;
    2898           0 :             case 2:
    2899           0 :                 GREY(i >> 6);
    2900           0 :                 GREY((i >> 4) & 3);
    2901           0 :                 GREY((i >> 2) & 3);
    2902           0 :                 GREY(i & 3);
    2903           0 :                 break;
    2904           0 :             case 4:
    2905           0 :                 GREY(i >> 4);
    2906           0 :                 GREY(i & 0xf);
    2907           0 :                 break;
    2908        2304 :             case 8:
    2909             :             case 16:
    2910        2304 :                 GREY(i);
    2911        2304 :                 break;
    2912           0 :             default:
    2913           0 :                 break;
    2914             :         }
    2915             : #undef GREY
    2916             :     }
    2917           9 :     return (1);
    2918             : }
    2919             : 
    2920             : /*
    2921             :  * Construct a mapping table to convert from the range
    2922             :  * of the data samples to [0,255] --for display.  This
    2923             :  * process also handles inverting B&W images when needed.
    2924             :  */
    2925           9 : static int setupMap(TIFFRGBAImage *img)
    2926             : {
    2927             :     int32_t x, range;
    2928             : 
    2929           9 :     range = (int32_t)((1U << img->bitspersample) - 1U);
    2930             : 
    2931             :     /* treat 16 bit the same as eight bit */
    2932           9 :     if (img->bitspersample == 16)
    2933           0 :         range = 255;
    2934             : 
    2935          18 :     img->Map = (TIFFRGBValue *)_TIFFmallocExt(
    2936           9 :         img->tif, (tmsize_t)((size_t)(range + 1) * sizeof(TIFFRGBValue)));
    2937           9 :     if (img->Map == NULL)
    2938             :     {
    2939           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    2940             :                       "No space for photometric conversion table");
    2941           0 :         return (0);
    2942             :     }
    2943           9 :     if (img->photometric == PHOTOMETRIC_MINISWHITE)
    2944             :     {
    2945           0 :         for (x = 0; x <= range; x++)
    2946           0 :             img->Map[x] = (TIFFRGBValue)(((range - x) * 255) / range);
    2947             :     }
    2948             :     else
    2949             :     {
    2950        2313 :         for (x = 0; x <= range; x++)
    2951        2304 :             img->Map[x] = (TIFFRGBValue)((x * 255) / range);
    2952             :     }
    2953           9 :     if (img->bitspersample <= 16 &&
    2954           9 :         (img->photometric == PHOTOMETRIC_MINISBLACK ||
    2955           0 :          img->photometric == PHOTOMETRIC_MINISWHITE))
    2956             :     {
    2957             :         /*
    2958             :          * Use photometric mapping table to construct
    2959             :          * unpacking tables for samples <= 8 bits.
    2960             :          */
    2961           9 :         if (!makebwmap(img))
    2962           0 :             return (0);
    2963             :         /* no longer need Map, free it */
    2964           9 :         _TIFFfreeExt(img->tif, img->Map);
    2965           9 :         img->Map = NULL;
    2966             :     }
    2967           9 :     return (1);
    2968             : }
    2969             : 
    2970           1 : static int checkcmap(TIFFRGBAImage *img)
    2971             : {
    2972           1 :     uint16_t *r = img->redcmap;
    2973           1 :     uint16_t *g = img->greencmap;
    2974           1 :     uint16_t *b = img->bluecmap;
    2975           1 :     long n = 1L << img->bitspersample;
    2976             : 
    2977           2 :     while (n-- > 0)
    2978           2 :         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
    2979           1 :             return (16);
    2980           0 :     return (8);
    2981             : }
    2982             : 
    2983           1 : static void cvtcmap(TIFFRGBAImage *img)
    2984             : {
    2985           1 :     uint16_t *r = img->redcmap;
    2986           1 :     uint16_t *g = img->greencmap;
    2987           1 :     uint16_t *b = img->bluecmap;
    2988             :     long i;
    2989             : 
    2990         257 :     for (i = (1L << img->bitspersample) - 1; i >= 0; i--)
    2991             :     {
    2992             : #define CVT(x) ((uint16_t)((x) >> 8))
    2993         256 :         r[i] = CVT(r[i]);
    2994         256 :         g[i] = CVT(g[i]);
    2995         256 :         b[i] = CVT(b[i]);
    2996             : #undef CVT
    2997             :     }
    2998           1 : }
    2999             : 
    3000             : /*
    3001             :  * Palette images with <= 8 bits/sample are handled
    3002             :  * with a table to avoid lots of shifts and masks.  The table
    3003             :  * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
    3004             :  * pixel values simply by indexing into the table with one
    3005             :  * number.
    3006             :  */
    3007           1 : static int makecmap(TIFFRGBAImage *img)
    3008             : {
    3009           1 :     int bitspersample = img->bitspersample;
    3010           1 :     int nsamples = 8 / bitspersample;
    3011           1 :     uint16_t *r = img->redcmap;
    3012           1 :     uint16_t *g = img->greencmap;
    3013           1 :     uint16_t *b = img->bluecmap;
    3014             :     uint32_t *p;
    3015             :     int i;
    3016             : 
    3017           2 :     img->PALmap = (uint32_t **)_TIFFmallocExt(
    3018             :         img->tif,
    3019           1 :         (tmsize_t)((size_t)256 * sizeof(uint32_t *) +
    3020           1 :                    ((size_t)256 * (size_t)nsamples * sizeof(uint32_t))));
    3021           1 :     if (img->PALmap == NULL)
    3022             :     {
    3023           0 :         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    3024             :                       "No space for Palette mapping table");
    3025           0 :         return (0);
    3026             :     }
    3027           1 :     p = (uint32_t *)(img->PALmap + 256);
    3028         257 :     for (i = 0; i < 256; i++)
    3029             :     {
    3030             :         TIFFRGBValue c;
    3031         256 :         img->PALmap[i] = p;
    3032             : #define CMAP(x)                                                                \
    3033             :     c = (TIFFRGBValue)x;                                                       \
    3034             :     *p++ = PACK(r[c] & 0xff, g[c] & 0xff, b[c] & 0xff);
    3035         256 :         switch (bitspersample)
    3036             :         {
    3037           0 :             case 1:
    3038           0 :                 CMAP(i >> 7);
    3039           0 :                 CMAP((i >> 6) & 1);
    3040           0 :                 CMAP((i >> 5) & 1);
    3041           0 :                 CMAP((i >> 4) & 1);
    3042           0 :                 CMAP((i >> 3) & 1);
    3043           0 :                 CMAP((i >> 2) & 1);
    3044           0 :                 CMAP((i >> 1) & 1);
    3045           0 :                 CMAP(i & 1);
    3046           0 :                 break;
    3047           0 :             case 2:
    3048           0 :                 CMAP(i >> 6);
    3049           0 :                 CMAP((i >> 4) & 3);
    3050           0 :                 CMAP((i >> 2) & 3);
    3051           0 :                 CMAP(i & 3);
    3052           0 :                 break;
    3053           0 :             case 4:
    3054           0 :                 CMAP(i >> 4);
    3055           0 :                 CMAP(i & 0xf);
    3056           0 :                 break;
    3057         256 :             case 8:
    3058         256 :                 CMAP(i);
    3059         256 :                 break;
    3060           0 :             default:
    3061           0 :                 break;
    3062             :         }
    3063             : #undef CMAP
    3064             :     }
    3065           1 :     return (1);
    3066             : }
    3067             : 
    3068             : /*
    3069             :  * Construct any mapping table used
    3070             :  * by the associated put routine.
    3071             :  */
    3072          17 : static int buildMap(TIFFRGBAImage *img)
    3073             : {
    3074          17 :     switch (img->photometric)
    3075             :     {
    3076           6 :         case PHOTOMETRIC_RGB:
    3077             :         case PHOTOMETRIC_YCBCR:
    3078             :         case PHOTOMETRIC_SEPARATED:
    3079           6 :             if (img->bitspersample == 8)
    3080           6 :                 break;
    3081             :             /* fall through... */
    3082             :         case PHOTOMETRIC_MINISBLACK:
    3083             :         case PHOTOMETRIC_MINISWHITE:
    3084           9 :             if (!setupMap(img))
    3085           0 :                 return (0);
    3086           9 :             break;
    3087           1 :         case PHOTOMETRIC_PALETTE:
    3088             :             /*
    3089             :              * Convert 16-bit colormap to 8-bit (unless it looks
    3090             :              * like an old-style 8-bit colormap).
    3091             :              */
    3092           1 :             if (checkcmap(img) == 16)
    3093           1 :                 cvtcmap(img);
    3094             :             else
    3095           0 :                 TIFFWarningExtR(img->tif, TIFFFileName(img->tif),
    3096             :                                 "Assuming 8-bit colormap");
    3097             :             /*
    3098             :              * Use mapping table and colormap to construct
    3099             :              * unpacking tables for samples < 8 bits.
    3100             :              */
    3101           1 :             if (img->bitspersample <= 8 && !makecmap(img))
    3102           0 :                 return (0);
    3103           1 :             break;
    3104           1 :         default:
    3105           1 :             break;
    3106             :     }
    3107          17 :     return (1);
    3108             : }
    3109             : 
    3110             : /*
    3111             :  * Select the appropriate conversion routine for packed data.
    3112             :  */
    3113          60 : static int PickContigCase(TIFFRGBAImage *img)
    3114             : {
    3115          60 :     img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
    3116          60 :     img->put.contig = NULL;
    3117          60 :     switch (img->photometric)
    3118             :     {
    3119          26 :         case PHOTOMETRIC_RGB:
    3120          26 :             switch (img->bitspersample)
    3121             :             {
    3122          26 :                 case 8:
    3123          26 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    3124          13 :                         img->samplesperpixel >= 4)
    3125          13 :                         img->put.contig = putRGBAAcontig8bittile;
    3126          13 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    3127          13 :                              img->samplesperpixel >= 4)
    3128             :                     {
    3129          13 :                         if (BuildMapUaToAa(img))
    3130          13 :                             img->put.contig = putRGBUAcontig8bittile;
    3131             :                     }
    3132           0 :                     else if (img->samplesperpixel >= 3)
    3133           0 :                         img->put.contig = putRGBcontig8bittile;
    3134          26 :                     break;
    3135           0 :                 case 16:
    3136           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA &&
    3137           0 :                         img->samplesperpixel >= 4)
    3138             :                     {
    3139           0 :                         if (BuildMapBitdepth16To8(img))
    3140           0 :                             img->put.contig = putRGBAAcontig16bittile;
    3141             :                     }
    3142           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA &&
    3143           0 :                              img->samplesperpixel >= 4)
    3144             :                     {
    3145           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    3146           0 :                             img->put.contig = putRGBUAcontig16bittile;
    3147             :                     }
    3148           0 :                     else if (img->samplesperpixel >= 3)
    3149             :                     {
    3150           0 :                         if (BuildMapBitdepth16To8(img))
    3151           0 :                             img->put.contig = putRGBcontig16bittile;
    3152             :                     }
    3153           0 :                     break;
    3154           0 :                 default:
    3155           0 :                     break;
    3156             :             }
    3157          26 :             break;
    3158           6 :         case PHOTOMETRIC_SEPARATED:
    3159           6 :             if (img->samplesperpixel >= 4 && buildMap(img))
    3160             :             {
    3161           6 :                 if (img->bitspersample == 8)
    3162             :                 {
    3163           6 :                     if (!img->Map)
    3164           6 :                         img->put.contig = putRGBcontig8bitCMYKtile;
    3165             :                     else
    3166           0 :                         img->put.contig = putRGBcontig8bitCMYKMaptile;
    3167             :                 }
    3168             :             }
    3169           6 :             break;
    3170           1 :         case PHOTOMETRIC_PALETTE:
    3171           1 :             if (buildMap(img))
    3172             :             {
    3173           1 :                 switch (img->bitspersample)
    3174             :                 {
    3175           1 :                     case 8:
    3176           1 :                         img->put.contig = put8bitcmaptile;
    3177           1 :                         break;
    3178           0 :                     case 4:
    3179           0 :                         img->put.contig = put4bitcmaptile;
    3180           0 :                         break;
    3181           0 :                     case 2:
    3182           0 :                         img->put.contig = put2bitcmaptile;
    3183           0 :                         break;
    3184           0 :                     case 1:
    3185           0 :                         img->put.contig = put1bitcmaptile;
    3186           0 :                         break;
    3187           0 :                     default:
    3188           0 :                         break;
    3189             :                 }
    3190           0 :             }
    3191           1 :             break;
    3192           9 :         case PHOTOMETRIC_MINISWHITE:
    3193             :         case PHOTOMETRIC_MINISBLACK:
    3194           9 :             if (buildMap(img))
    3195             :             {
    3196           9 :                 switch (img->bitspersample)
    3197             :                 {
    3198           0 :                     case 16:
    3199           0 :                         img->put.contig = put16bitbwtile;
    3200           0 :                         break;
    3201           9 :                     case 8:
    3202           9 :                         if (img->alpha && img->samplesperpixel == 2)
    3203           6 :                             img->put.contig = putagreytile;
    3204             :                         else
    3205           3 :                             img->put.contig = putgreytile;
    3206           9 :                         break;
    3207           0 :                     case 4:
    3208           0 :                         img->put.contig = put4bitbwtile;
    3209           0 :                         break;
    3210           0 :                     case 2:
    3211           0 :                         img->put.contig = put2bitbwtile;
    3212           0 :                         break;
    3213           0 :                     case 1:
    3214           0 :                         img->put.contig = put1bitbwtile;
    3215           0 :                         break;
    3216           0 :                     default:
    3217           0 :                         break;
    3218             :                 }
    3219           0 :             }
    3220           9 :             break;
    3221          17 :         case PHOTOMETRIC_YCBCR:
    3222          17 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3223             :             {
    3224          17 :                 if (initYCbCrConversion(img) != 0)
    3225             :                 {
    3226             :                     /*
    3227             :                      * The 6.0 spec says that subsampling must be
    3228             :                      * one of 1, 2, or 4, and that vertical subsampling
    3229             :                      * must always be <= horizontal subsampling; so
    3230             :                      * there are only a few possibilities and we just
    3231             :                      * enumerate the cases.
    3232             :                      * Joris: added support for the [1,2] case, nonetheless, to
    3233             :                      * accommodate some OJPEG files
    3234             :                      */
    3235             :                     uint16_t SubsamplingHor;
    3236             :                     uint16_t SubsamplingVer;
    3237          17 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3238             :                                           &SubsamplingHor, &SubsamplingVer);
    3239             :                     /* Validate that the image dimensions are compatible with
    3240             :                     the subsampling block. All putcontig8bitYCbCrXYtile routines
    3241             :                     assume width >= X and height >= Y. */
    3242          17 :                     if (img->width < SubsamplingHor ||
    3243          17 :                         img->height < SubsamplingVer)
    3244             :                     {
    3245           0 :                         TIFFErrorExtR(img->tif, TIFFFileName(img->tif),
    3246             :                                       "YCbCr subsampling (%u,%u) incompatible "
    3247             :                                       "with image size %ux%u",
    3248             :                                       SubsamplingHor, SubsamplingVer,
    3249             :                                       img->width, img->height);
    3250           0 :                         return (0);
    3251             :                     }
    3252          17 :                     switch ((SubsamplingHor << 4) | SubsamplingVer)
    3253             :                     {
    3254           2 :                         case 0x44:
    3255           2 :                             img->put.contig = putcontig8bitYCbCr44tile;
    3256           2 :                             break;
    3257           2 :                         case 0x42:
    3258           2 :                             img->put.contig = putcontig8bitYCbCr42tile;
    3259           2 :                             break;
    3260           1 :                         case 0x41:
    3261           1 :                             img->put.contig = putcontig8bitYCbCr41tile;
    3262           1 :                             break;
    3263           3 :                         case 0x22:
    3264           3 :                             img->put.contig = putcontig8bitYCbCr22tile;
    3265           3 :                             break;
    3266           1 :                         case 0x21:
    3267           1 :                             img->put.contig = putcontig8bitYCbCr21tile;
    3268           1 :                             break;
    3269           1 :                         case 0x12:
    3270           1 :                             img->put.contig = putcontig8bitYCbCr12tile;
    3271           1 :                             break;
    3272           1 :                         case 0x11:
    3273           1 :                             img->put.contig = putcontig8bitYCbCr11tile;
    3274           1 :                             break;
    3275           6 :                         default:
    3276           6 :                             break;
    3277             :                     }
    3278             :                 }
    3279             :             }
    3280          17 :             break;
    3281           1 :         case PHOTOMETRIC_CIELAB:
    3282           1 :             if (img->samplesperpixel == 3 && buildMap(img))
    3283             :             {
    3284           1 :                 if (img->bitspersample == 8 || img->bitspersample == 16)
    3285           1 :                     img->put.contig = initCIELabConversion(img);
    3286           1 :                 break;
    3287             :             }
    3288           0 :             break;
    3289           0 :         default:
    3290           0 :             break;
    3291             :     }
    3292          60 :     return ((img->get != NULL) && (img->put.contig != NULL));
    3293             : }
    3294             : 
    3295             : /*
    3296             :  * Select the appropriate conversion routine for unpacked data.
    3297             :  *
    3298             :  * NB: we assume that unpacked single channel data is directed
    3299             :  *   to the "packed routines.
    3300             :  */
    3301           3 : static int PickSeparateCase(TIFFRGBAImage *img)
    3302             : {
    3303           3 :     img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
    3304           3 :     img->put.separate = NULL;
    3305           3 :     switch (img->photometric)
    3306             :     {
    3307           3 :         case PHOTOMETRIC_MINISWHITE:
    3308             :         case PHOTOMETRIC_MINISBLACK:
    3309             :             /* greyscale images processed pretty much as RGB by gtTileSeparate
    3310             :              */
    3311             :         case PHOTOMETRIC_RGB:
    3312           3 :             switch (img->bitspersample)
    3313             :             {
    3314           3 :                 case 8:
    3315           3 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3316           0 :                         img->put.separate = putRGBAAseparate8bittile;
    3317           3 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3318             :                     {
    3319           0 :                         if (BuildMapUaToAa(img))
    3320           0 :                             img->put.separate = putRGBUAseparate8bittile;
    3321             :                     }
    3322             :                     else
    3323           3 :                         img->put.separate = putRGBseparate8bittile;
    3324           3 :                     break;
    3325           0 :                 case 16:
    3326           0 :                     if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
    3327             :                     {
    3328           0 :                         if (BuildMapBitdepth16To8(img))
    3329           0 :                             img->put.separate = putRGBAAseparate16bittile;
    3330             :                     }
    3331           0 :                     else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
    3332             :                     {
    3333           0 :                         if (BuildMapBitdepth16To8(img) && BuildMapUaToAa(img))
    3334           0 :                             img->put.separate = putRGBUAseparate16bittile;
    3335             :                     }
    3336             :                     else
    3337             :                     {
    3338           0 :                         if (BuildMapBitdepth16To8(img))
    3339           0 :                             img->put.separate = putRGBseparate16bittile;
    3340             :                     }
    3341           0 :                     break;
    3342           0 :                 default:
    3343           0 :                     break;
    3344             :             }
    3345           3 :             break;
    3346           0 :         case PHOTOMETRIC_SEPARATED:
    3347           0 :             if (img->bitspersample == 8 && img->samplesperpixel == 4)
    3348             :             {
    3349             :                 /* Not alpha, but seems like the only way to get 4th band */
    3350           0 :                 img->alpha = 1;
    3351           0 :                 img->put.separate = putCMYKseparate8bittile;
    3352             :             }
    3353           0 :             break;
    3354           0 :         case PHOTOMETRIC_YCBCR:
    3355           0 :             if ((img->bitspersample == 8) && (img->samplesperpixel == 3))
    3356             :             {
    3357           0 :                 if (initYCbCrConversion(img) != 0)
    3358             :                 {
    3359             :                     uint16_t hs, vs;
    3360           0 :                     TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING,
    3361             :                                           &hs, &vs);
    3362           0 :                     switch ((hs << 4) | vs)
    3363             :                     {
    3364           0 :                         case 0x11:
    3365           0 :                             img->put.separate = putseparate8bitYCbCr11tile;
    3366           0 :                             break;
    3367             :                             /* TODO: add other cases here */
    3368           0 :                         default:
    3369           0 :                             break;
    3370             :                     }
    3371             :                 }
    3372             :             }
    3373           0 :             break;
    3374           0 :         default:
    3375           0 :             break;
    3376             :     }
    3377           3 :     return ((img->get != NULL) && (img->put.separate != NULL));
    3378             : }
    3379             : 
    3380          13 : static int BuildMapUaToAa(TIFFRGBAImage *img)
    3381             : {
    3382             :     static const char module[] = "BuildMapUaToAa";
    3383             :     uint8_t *m;
    3384             :     uint16_t na, nv;
    3385          13 :     assert(img->UaToAa == NULL);
    3386          13 :     img->UaToAa = (uint8_t *)_TIFFmallocExt(img->tif, 65536);
    3387          13 :     if (img->UaToAa == NULL)
    3388             :     {
    3389           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3390           0 :         return (0);
    3391             :     }
    3392          13 :     m = img->UaToAa;
    3393        3341 :     for (na = 0; na < 256; na++)
    3394             :     {
    3395      855296 :         for (nv = 0; nv < 256; nv++)
    3396      851968 :             *m++ = (uint8_t)((nv * na + 127) / 255);
    3397             :     }
    3398          13 :     return (1);
    3399             : }
    3400             : 
    3401           0 : static int BuildMapBitdepth16To8(TIFFRGBAImage *img)
    3402             : {
    3403             :     static const char module[] = "BuildMapBitdepth16To8";
    3404             :     uint8_t *m;
    3405             :     uint32_t n;
    3406           0 :     assert(img->Bitdepth16To8 == NULL);
    3407           0 :     img->Bitdepth16To8 = (uint8_t *)_TIFFmallocExt(img->tif, 65536);
    3408           0 :     if (img->Bitdepth16To8 == NULL)
    3409             :     {
    3410           0 :         TIFFErrorExtR(img->tif, module, "Out of memory");
    3411           0 :         return (0);
    3412             :     }
    3413           0 :     m = img->Bitdepth16To8;
    3414           0 :     for (n = 0; n < 65536; n++)
    3415           0 :         *m++ = (uint8_t)((n + 128) / 257);
    3416           0 :     return (1);
    3417             : }
    3418             : 
    3419             : /*
    3420             :  * Read a whole strip off data from the file, and convert to RGBA form.
    3421             :  * If this is the last strip, then it will only contain the portion of
    3422             :  * the strip that is actually within the image space.  The result is
    3423             :  * organized in bottom to top form.
    3424             :  */
    3425             : 
    3426           0 : int TIFFReadRGBAStrip(TIFF *tif, uint32_t row, uint32_t *raster)
    3427             : 
    3428             : {
    3429           0 :     return TIFFReadRGBAStripExt(tif, row, raster, 0);
    3430             : }
    3431             : 
    3432          59 : int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster,
    3433             :                          int stop_on_error)
    3434             : 
    3435             : {
    3436          59 :     char emsg[EMSG_BUF_SIZE] = "";
    3437             :     TIFFRGBAImage img;
    3438             :     int ok;
    3439             :     uint32_t rowsperstrip, rows_to_read;
    3440             : 
    3441          59 :     if (TIFFIsTiled(tif))
    3442             :     {
    3443           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3444             :                       "Can't use TIFFReadRGBAStrip() with tiled file.");
    3445           0 :         return (0);
    3446             :     }
    3447             : 
    3448          59 :     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    3449             : 
    3450          59 :     if (rowsperstrip == 0)
    3451             :     {
    3452           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero");
    3453           0 :         return (0);
    3454             :     }
    3455             : 
    3456          59 :     if ((row % rowsperstrip) != 0)
    3457             :     {
    3458           0 :         TIFFErrorExtR(
    3459             :             tif, TIFFFileName(tif),
    3460             :             "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
    3461           0 :         return (0);
    3462             :     }
    3463             : 
    3464          59 :     if (TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3465             :     {
    3466          53 :         if (row >= img.height)
    3467             :         {
    3468           0 :             TIFFErrorExtR(tif, TIFFFileName(tif),
    3469             :                           "Invalid row passed to TIFFReadRGBAStrip().");
    3470           0 :             TIFFRGBAImageEnd(&img);
    3471           0 :             return (0);
    3472             :         }
    3473             : 
    3474          53 :         img.row_offset = (int)row;
    3475          53 :         img.col_offset = 0;
    3476             : 
    3477          53 :         if (row + rowsperstrip > img.height)
    3478          14 :             rows_to_read = img.height - row;
    3479             :         else
    3480          39 :             rows_to_read = rowsperstrip;
    3481             : 
    3482          53 :         ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read);
    3483             : 
    3484          53 :         TIFFRGBAImageEnd(&img);
    3485             :     }
    3486             :     else
    3487             :     {
    3488           6 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3489           6 :         ok = 0;
    3490             :     }
    3491             : 
    3492          59 :     return (ok);
    3493             : }
    3494             : 
    3495             : /*
    3496             :  * Read a whole tile off data from the file, and convert to RGBA form.
    3497             :  * The returned RGBA data is organized from bottom to top of tile,
    3498             :  * and may include zeroed areas if the tile extends off the image.
    3499             :  */
    3500             : 
    3501           0 : int TIFFReadRGBATile(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster)
    3502             : 
    3503             : {
    3504           0 :     return TIFFReadRGBATileExt(tif, col, row, raster, 0);
    3505             : }
    3506             : 
    3507           4 : int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster,
    3508             :                         int stop_on_error)
    3509             : {
    3510           4 :     char emsg[EMSG_BUF_SIZE] = "";
    3511             :     TIFFRGBAImage img;
    3512             :     int ok;
    3513             :     uint32_t tile_xsize, tile_ysize;
    3514             :     uint32_t read_xsize, read_ysize;
    3515             :     uint32_t i_row;
    3516             : 
    3517             :     /*
    3518             :      * Verify that our request is legal - on a tile file, and on a
    3519             :      * tile boundary.
    3520             :      */
    3521             : 
    3522           4 :     if (!TIFFIsTiled(tif))
    3523             :     {
    3524           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3525             :                       "Can't use TIFFReadRGBATile() with striped file.");
    3526           0 :         return (0);
    3527             :     }
    3528             : 
    3529           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
    3530           4 :     TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
    3531           4 :     if (tile_xsize == 0 || tile_ysize == 0)
    3532             :     {
    3533           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3534             :                       "tile_xsize or tile_ysize is zero");
    3535           0 :         return (0);
    3536             :     }
    3537             : 
    3538           4 :     if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
    3539             :     {
    3540           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3541             :                       "Row/col passed to TIFFReadRGBATile() must be top"
    3542             :                       "left corner of a tile.");
    3543           0 :         return (0);
    3544             :     }
    3545             : 
    3546             :     /*
    3547             :      * Setup the RGBA reader.
    3548             :      */
    3549             : 
    3550           4 :     if (!TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg))
    3551             :     {
    3552           0 :         TIFFErrorExtR(tif, TIFFFileName(tif), "%s", emsg);
    3553           0 :         return (0);
    3554             :     }
    3555             : 
    3556           4 :     if (col >= img.width || row >= img.height)
    3557             :     {
    3558           0 :         TIFFErrorExtR(tif, TIFFFileName(tif),
    3559             :                       "Invalid row/col passed to TIFFReadRGBATile().");
    3560           0 :         TIFFRGBAImageEnd(&img);
    3561           0 :         return (0);
    3562             :     }
    3563             : 
    3564             :     /*
    3565             :      * The TIFFRGBAImageGet() function doesn't allow us to get off the
    3566             :      * edge of the image, even to fill an otherwise valid tile.  So we
    3567             :      * figure out how much we can read, and fix up the tile buffer to
    3568             :      * a full tile configuration afterwards.
    3569             :      */
    3570             : 
    3571           4 :     if (row + tile_ysize > img.height)
    3572           4 :         read_ysize = img.height - row;
    3573             :     else
    3574           0 :         read_ysize = tile_ysize;
    3575             : 
    3576           4 :     if (col + tile_xsize > img.width)
    3577           4 :         read_xsize = img.width - col;
    3578             :     else
    3579           0 :         read_xsize = tile_xsize;
    3580             : 
    3581             :     /*
    3582             :      * Read the chunk of imagery.
    3583             :      */
    3584             : 
    3585           4 :     img.row_offset = (int)row;
    3586           4 :     img.col_offset = (int)col;
    3587             : 
    3588           4 :     ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize);
    3589             : 
    3590           4 :     TIFFRGBAImageEnd(&img);
    3591             : 
    3592             :     /*
    3593             :      * If our read was incomplete we will need to fix up the tile by
    3594             :      * shifting the data around as if a full tile of data is being returned.
    3595             :      *
    3596             :      * This is all the more complicated because the image is organized in
    3597             :      * bottom to top format.
    3598             :      */
    3599             : 
    3600           4 :     if (read_xsize == tile_xsize && read_ysize == tile_ysize)
    3601           0 :         return (ok);
    3602             : 
    3603         500 :     for (i_row = 0; i_row < read_ysize; i_row++)
    3604             :     {
    3605         496 :         memmove(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize,
    3606         496 :                 raster + (size_t)(read_ysize - i_row - 1) * read_xsize,
    3607             :                 read_xsize * sizeof(uint32_t));
    3608         496 :         _TIFFmemset(
    3609         496 :             raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize + read_xsize,
    3610             :             0,
    3611         496 :             (tmsize_t)(sizeof(uint32_t) * (size_t)(tile_xsize - read_xsize)));
    3612             :     }
    3613             : 
    3614         468 :     for (i_row = read_ysize; i_row < tile_ysize; i_row++)
    3615             :     {
    3616         464 :         _TIFFmemset(raster + (size_t)(tile_ysize - i_row - 1) * tile_xsize, 0,
    3617         464 :                     (tmsize_t)(sizeof(uint32_t) * (size_t)tile_xsize));
    3618             :     }
    3619             : 
    3620           4 :     return (ok);
    3621             : }

Generated by: LCOV version 1.14