LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_color.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 110 116 94.8 %
Date: 2024-11-21 22:18:42 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1988-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             :  * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
      27             :  * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
      28             :  * the permission of John Cupitt, the VIPS author.
      29             :  */
      30             : 
      31             : /*
      32             :  * TIFF Library.
      33             :  *
      34             :  * Color space conversion routines.
      35             :  */
      36             : 
      37             : #include "tiffiop.h"
      38             : #include <math.h>
      39             : 
      40             : /*
      41             :  * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
      42             :  */
      43           1 : void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, int32_t b,
      44             :                      float *X, float *Y, float *Z)
      45             : {
      46           1 :     TIFFCIELab16ToXYZ(cielab, l * 257, a * 256, b * 256, X, Y, Z);
      47           1 : }
      48             : 
      49             : /*
      50             :  * For CIELab encoded in 16 bits, L is an unsigned integer range [0,65535].
      51             :  * The a* and b* components are signed integers range [-32768,32767]. The 16
      52             :  * bit chrominance values are encoded as 256 times the 1976 CIE a* and b*
      53             :  * values
      54             :  */
      55           1 : void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
      56             :                        int32_t b, float *X, float *Y, float *Z)
      57             : {
      58           1 :     float L = (float)l * 100.0F / 65535.0F;
      59             :     float cby, tmp;
      60             : 
      61           1 :     if (L < 8.856F)
      62             :     {
      63           0 :         *Y = (L * cielab->Y0) / 903.292F;
      64           0 :         cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
      65             :     }
      66             :     else
      67             :     {
      68           1 :         cby = (L + 16.0F) / 116.0F;
      69           1 :         *Y = cielab->Y0 * cby * cby * cby;
      70             :     }
      71             : 
      72           1 :     tmp = (float)a / 256.0F / 500.0F + cby;
      73           1 :     if (tmp < 0.2069F)
      74           0 :         *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
      75             :     else
      76           1 :         *X = cielab->X0 * tmp * tmp * tmp;
      77             : 
      78           1 :     tmp = cby - (float)b / 256.0F / 200.0F;
      79           1 :     if (tmp < 0.2069F)
      80           0 :         *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
      81             :     else
      82           1 :         *Z = cielab->Z0 * tmp * tmp * tmp;
      83           1 : }
      84             : 
      85             : #define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5) : ((R)-0.5)))
      86             : /*
      87             :  * Convert color value from the XYZ space to RGB.
      88             :  */
      89           1 : void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
      90             :                   uint32_t *r, uint32_t *g, uint32_t *b)
      91             : {
      92             :     size_t i;
      93             :     float Yr, Yg, Yb;
      94           1 :     float *matrix = &cielab->display.d_mat[0][0];
      95             : 
      96             :     /* Multiply through the matrix to get luminosity values. */
      97           1 :     Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
      98           1 :     Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
      99           1 :     Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
     100             : 
     101             :     /* Clip input */
     102           1 :     Yr = TIFFmax(Yr, cielab->display.d_Y0R);
     103           1 :     Yg = TIFFmax(Yg, cielab->display.d_Y0G);
     104           1 :     Yb = TIFFmax(Yb, cielab->display.d_Y0B);
     105             : 
     106             :     /* Avoid overflow in case of wrong input values */
     107           1 :     Yr = TIFFmin(Yr, cielab->display.d_YCR);
     108           1 :     Yg = TIFFmin(Yg, cielab->display.d_YCG);
     109           1 :     Yb = TIFFmin(Yb, cielab->display.d_YCB);
     110             : 
     111             :     /* Turn luminosity to colour value. */
     112           1 :     i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep);
     113           1 :     i = TIFFmin((size_t)cielab->range, i);
     114           1 :     *r = RINT(cielab->Yr2r[i]);
     115             : 
     116           1 :     i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep);
     117           1 :     i = TIFFmin((size_t)cielab->range, i);
     118           1 :     *g = RINT(cielab->Yg2g[i]);
     119             : 
     120           1 :     i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep);
     121           1 :     i = TIFFmin((size_t)cielab->range, i);
     122           1 :     *b = RINT(cielab->Yb2b[i]);
     123             : 
     124             :     /* Clip output. */
     125           1 :     *r = TIFFmin(*r, cielab->display.d_Vrwr);
     126           1 :     *g = TIFFmin(*g, cielab->display.d_Vrwg);
     127           1 :     *b = TIFFmin(*b, cielab->display.d_Vrwb);
     128           1 : }
     129             : #undef RINT
     130             : 
     131             : /*
     132             :  * Allocate conversion state structures and make look_up tables for
     133             :  * the Yr,Yb,Yg <=> r,g,b conversions.
     134             :  */
     135           1 : int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
     136             :                         float *refWhite)
     137             : {
     138             :     size_t i;
     139             :     double dfGamma;
     140             : 
     141           1 :     cielab->range = CIELABTORGB_TABLE_RANGE;
     142             : 
     143           1 :     _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
     144             : 
     145             :     /* Red */
     146           1 :     dfGamma = 1.0 / cielab->display.d_gammaR;
     147           1 :     cielab->rstep =
     148           1 :         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     149        1502 :     for (i = 0; i <= (size_t)cielab->range; i++)
     150             :     {
     151        1501 :         cielab->Yr2r[i] = cielab->display.d_Vrwr *
     152        1501 :                           ((float)pow((double)i / cielab->range, dfGamma));
     153             :     }
     154             : 
     155             :     /* Green */
     156           1 :     dfGamma = 1.0 / cielab->display.d_gammaG;
     157           1 :     cielab->gstep =
     158           1 :         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     159        1502 :     for (i = 0; i <= (size_t)cielab->range; i++)
     160             :     {
     161        1501 :         cielab->Yg2g[i] = cielab->display.d_Vrwg *
     162        1501 :                           ((float)pow((double)i / cielab->range, dfGamma));
     163             :     }
     164             : 
     165             :     /* Blue */
     166           1 :     dfGamma = 1.0 / cielab->display.d_gammaB;
     167           1 :     cielab->bstep =
     168           1 :         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     169        1502 :     for (i = 0; i <= (size_t)cielab->range; i++)
     170             :     {
     171        1501 :         cielab->Yb2b[i] = cielab->display.d_Vrwb *
     172        1501 :                           ((float)pow((double)i / cielab->range, dfGamma));
     173             :     }
     174             : 
     175             :     /* Init reference white point */
     176           1 :     cielab->X0 = refWhite[0];
     177           1 :     cielab->Y0 = refWhite[1];
     178           1 :     cielab->Z0 = refWhite[2];
     179             : 
     180           1 :     return 0;
     181             : }
     182             : 
     183             : /*
     184             :  * Convert color value from the YCbCr space to RGB.
     185             :  * The colorspace conversion algorithm comes from the IJG v5a code;
     186             :  * see below for more information on how it works.
     187             :  */
     188             : #define SHIFT 16
     189             : #define FIX(x) ((int32_t)((x) * (1L << SHIFT) + 0.5))
     190             : #define ONE_HALF ((int32_t)(1 << (SHIFT - 1)))
     191             : #define Code2V(c, RB, RW, CR)                                                  \
     192             :     ((((c) - (int32_t)(RB)) * (float)(CR)) /                                   \
     193             :      (float)(((RW) - (RB) != 0) ? ((RW) - (RB)) : 1))
     194             : /* !((f)>=(min)) written that way to deal with NaN */
     195             : #define CLAMP(f, min, max)                                                     \
     196             :     ((!((f) >= (min))) ? (min) : (f) > (max) ? (max) : (f))
     197             : #define HICLAMP(f, max) ((f) > (max) ? (max) : (f))
     198             : 
     199       65097 : void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32_t Y, int32_t Cb, int32_t Cr,
     200             :                     uint32_t *r, uint32_t *g, uint32_t *b)
     201             : {
     202             :     int32_t i;
     203             : 
     204             :     /* XXX: Only 8-bit YCbCr input supported for now */
     205       65097 :     Y = HICLAMP(Y, 255);
     206       65097 :     Cb = CLAMP(Cb, 0, 255);
     207       65097 :     Cr = CLAMP(Cr, 0, 255);
     208             : 
     209       65097 :     i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
     210       65097 :     *r = CLAMP(i, 0, 255);
     211       65097 :     i = ycbcr->Y_tab[Y] +
     212       65097 :         (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
     213       65097 :     *g = CLAMP(i, 0, 255);
     214       65097 :     i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
     215       65097 :     *b = CLAMP(i, 0, 255);
     216       65097 : }
     217             : 
     218             : /* Clamp function for sanitization purposes. Normally clamping should not */
     219             : /* occur for well behaved chroma and refBlackWhite coefficients */
     220       13056 : static float CLAMPw(float v, float vmin, float vmax)
     221             : {
     222       13056 :     if (v < vmin)
     223             :     {
     224             :         /* printf("%f clamped to %f\n", v, vmin); */
     225           0 :         return vmin;
     226             :     }
     227       13056 :     if (v > vmax)
     228             :     {
     229             :         /* printf("%f clamped to %f\n", v, vmax); */
     230           0 :         return vmax;
     231             :     }
     232       13056 :     return v;
     233             : }
     234             : 
     235             : /*
     236             :  * Initialize the YCbCr->RGB conversion tables.  The conversion
     237             :  * is done according to the 6.0 spec:
     238             :  *
     239             :  *    R = Y + Cr*(2 - 2*LumaRed)
     240             :  *    B = Y + Cb*(2 - 2*LumaBlue)
     241             :  *    G =   Y
     242             :  *        - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
     243             :  *        - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
     244             :  *
     245             :  * To avoid floating point arithmetic the fractional constants that
     246             :  * come out of the equations are represented as fixed point values
     247             :  * in the range 0...2^16.  We also eliminate multiplications by
     248             :  * pre-calculating possible values indexed by Cb and Cr (this code
     249             :  * assumes conversion is being done for 8-bit samples).
     250             :  */
     251          17 : int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
     252             : {
     253             :     TIFFRGBValue *clamptab;
     254             :     int i;
     255             : 
     256             : #define LumaRed luma[0]
     257             : #define LumaGreen luma[1]
     258             : #define LumaBlue luma[2]
     259             : 
     260          17 :     clamptab =
     261             :         (TIFFRGBValue *)((uint8_t *)ycbcr +
     262             :                          TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)));
     263          17 :     _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
     264          17 :     ycbcr->clamptab = (clamptab += 256);
     265        4369 :     for (i = 0; i < 256; i++)
     266        4352 :         clamptab[i] = (TIFFRGBValue)i;
     267          17 :     _TIFFmemset(clamptab + 256, 255, 2 * 256); /* v > 255 => 255 */
     268          17 :     ycbcr->Cr_r_tab = (int *)(clamptab + 3 * 256);
     269          17 :     ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
     270          17 :     ycbcr->Cr_g_tab = (int32_t *)(ycbcr->Cb_b_tab + 256);
     271          17 :     ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
     272          17 :     ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
     273             : 
     274             :     {
     275          17 :         float f1 = 2 - 2 * LumaRed;
     276          17 :         int32_t D1 = FIX(CLAMP(f1, 0.0F, 2.0F));
     277          17 :         float f2 = LumaRed * f1 / LumaGreen;
     278          17 :         int32_t D2 = -FIX(CLAMP(f2, 0.0F, 2.0F));
     279          17 :         float f3 = 2 - 2 * LumaBlue;
     280          17 :         int32_t D3 = FIX(CLAMP(f3, 0.0F, 2.0F));
     281          17 :         float f4 = LumaBlue * f3 / LumaGreen;
     282          17 :         int32_t D4 = -FIX(CLAMP(f4, 0.0F, 2.0F));
     283             :         int x;
     284             : 
     285             : #undef LumaBlue
     286             : #undef LumaGreen
     287             : #undef LumaRed
     288             : 
     289             :         /*
     290             :          * i is the actual input pixel value in the range 0..255
     291             :          * Cb and Cr values are in the range -128..127 (actually
     292             :          * they are in a range defined by the ReferenceBlackWhite
     293             :          * tag) so there is some range shifting to do here when
     294             :          * constructing tables indexed by the raw pixel data.
     295             :          */
     296        4369 :         for (i = 0, x = -128; i < 256; i++, x++)
     297             :         {
     298        4352 :             int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F,
     299             :                                                 refBlackWhite[5] - 128.0F, 127),
     300             :                                          -128.0F * 32, 128.0F * 32);
     301        4352 :             int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F,
     302             :                                                 refBlackWhite[3] - 128.0F, 127),
     303             :                                          -128.0F * 32, 128.0F * 32);
     304             : 
     305        4352 :             ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT);
     306        4352 :             ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT);
     307        4352 :             ycbcr->Cr_g_tab[i] = D2 * Cr;
     308        4352 :             ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF;
     309        4352 :             ycbcr->Y_tab[i] = (int32_t)CLAMPw(
     310        4352 :                 Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
     311             :                 -128.0F * 32, 128.0F * 32);
     312             :         }
     313             :     }
     314             : 
     315          17 :     return 0;
     316             : }
     317             : #undef HICLAMP
     318             : #undef CLAMP
     319             : #undef Code2V
     320             : #undef SHIFT
     321             : #undef ONE_HALF
     322             : #undef FIX

Generated by: LCOV version 1.14