LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_color.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 101 97 96.0 %
Date: 2012-12-26 Functions: 5 5 100.0 %

       1                 : /* $Id: tif_color.c,v 1.19 2010-12-14 02:22:42 faxguy Exp $ */
       2                 : 
       3                 : /*
       4                 :  * Copyright (c) 1988-1997 Sam Leffler
       5                 :  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
       6                 :  *
       7                 :  * Permission to use, copy, modify, distribute, and sell this software and 
       8                 :  * its documentation for any purpose is hereby granted without fee, provided
       9                 :  * that (i) the above copyright notices and this permission notice appear in
      10                 :  * all copies of the software and related documentation, and (ii) the names of
      11                 :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      12                 :  * publicity relating to the software without the specific, prior written
      13                 :  * permission of Sam Leffler and Silicon Graphics.
      14                 :  * 
      15                 :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
      16                 :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
      17                 :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
      18                 :  * 
      19                 :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      20                 :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      21                 :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      22                 :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
      23                 :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
      24                 :  * OF THIS SOFTWARE.
      25                 :  */
      26                 : 
      27                 : /*
      28                 :  * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
      29                 :  * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
      30                 :  * the permission of John Cupitt, the VIPS author.
      31                 :  */
      32                 : 
      33                 : /*
      34                 :  * TIFF Library.
      35                 :  *
      36                 :  * Color space conversion routines.
      37                 :  */
      38                 : 
      39                 : #include "tiffiop.h"
      40                 : #include <math.h>
      41                 : 
      42                 : /*
      43                 :  * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
      44                 :  */
      45                 : void
      46               1 : TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
      47                 :     float *X, float *Y, float *Z)
      48                 : {
      49               1 :   float L = (float)l * 100.0F / 255.0F;
      50                 :   float cby, tmp;
      51                 : 
      52               1 :   if( L < 8.856F ) {
      53               0 :     *Y = (L * cielab->Y0) / 903.292F;
      54               0 :     cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
      55                 :   } else {
      56               1 :     cby = (L + 16.0F) / 116.0F;
      57               1 :     *Y = cielab->Y0 * cby * cby * cby;
      58                 :   }
      59                 : 
      60               1 :   tmp = (float)a / 500.0F + cby;
      61               1 :   if( tmp < 0.2069F )
      62               0 :     *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
      63                 :   else    
      64               1 :     *X = cielab->X0 * tmp * tmp * tmp;
      65                 : 
      66               1 :   tmp = cby - (float)b / 200.0F;
      67               1 :   if( tmp < 0.2069F )
      68               0 :     *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
      69                 :   else    
      70               1 :     *Z = cielab->Z0 * tmp * tmp * tmp;
      71               1 : }
      72                 : 
      73                 : #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
      74                 : /*
      75                 :  * Convert color value from the XYZ space to RGB.
      76                 :  */
      77                 : void
      78               1 : TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
      79                 :        uint32 *r, uint32 *g, uint32 *b)
      80                 : {
      81                 :   int i;
      82                 :   float Yr, Yg, Yb;
      83               1 :   float *matrix = &cielab->display.d_mat[0][0];
      84                 : 
      85                 :   /* Multiply through the matrix to get luminosity values. */
      86               1 :   Yr =  matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
      87               1 :   Yg =  matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
      88               1 :   Yb =  matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
      89                 : 
      90                 :   /* Clip input */
      91               1 :   Yr = TIFFmax(Yr, cielab->display.d_Y0R);
      92               1 :   Yg = TIFFmax(Yg, cielab->display.d_Y0G);
      93               1 :   Yb = TIFFmax(Yb, cielab->display.d_Y0B);
      94                 : 
      95                 :   /* Avoid overflow in case of wrong input values */
      96               1 :   Yr = TIFFmin(Yr, cielab->display.d_YCR);
      97               1 :   Yg = TIFFmin(Yg, cielab->display.d_YCG);
      98               1 :   Yb = TIFFmin(Yb, cielab->display.d_YCB);
      99                 : 
     100                 :   /* Turn luminosity to colour value. */
     101               1 :   i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
     102               1 :   i = TIFFmin(cielab->range, i);
     103               1 :   *r = RINT(cielab->Yr2r[i]);
     104                 : 
     105               1 :   i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
     106               1 :   i = TIFFmin(cielab->range, i);
     107               1 :   *g = RINT(cielab->Yg2g[i]);
     108                 : 
     109               1 :   i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
     110               1 :   i = TIFFmin(cielab->range, i);
     111               1 :   *b = RINT(cielab->Yb2b[i]);
     112                 : 
     113                 :   /* Clip output. */
     114               1 :   *r = TIFFmin(*r, cielab->display.d_Vrwr);
     115               1 :   *g = TIFFmin(*g, cielab->display.d_Vrwg);
     116               1 :   *b = TIFFmin(*b, cielab->display.d_Vrwb);
     117               1 : }
     118                 : #undef RINT
     119                 : 
     120                 : /* 
     121                 :  * Allocate conversion state structures and make look_up tables for
     122                 :  * the Yr,Yb,Yg <=> r,g,b conversions.
     123                 :  */
     124                 : int
     125               1 : TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
     126                 :         const TIFFDisplay *display, float *refWhite)
     127                 : {
     128                 :   int i;
     129                 :   double gamma;
     130                 : 
     131               1 :   cielab->range = CIELABTORGB_TABLE_RANGE;
     132                 : 
     133               1 :   _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
     134                 : 
     135                 :   /* Red */
     136               1 :   gamma = 1.0 / cielab->display.d_gammaR ;
     137               1 :   cielab->rstep =
     138               1 :     (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     139            1502 :   for(i = 0; i <= cielab->range; i++) {
     140            3002 :     cielab->Yr2r[i] = cielab->display.d_Vrwr
     141            1501 :         * ((float)pow((double)i / cielab->range, gamma));
     142                 :   }
     143                 : 
     144                 :   /* Green */
     145               1 :   gamma = 1.0 / cielab->display.d_gammaG ;
     146               1 :   cielab->gstep =
     147               1 :       (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     148            1502 :   for(i = 0; i <= cielab->range; i++) {
     149            3002 :     cielab->Yg2g[i] = cielab->display.d_Vrwg
     150            1501 :         * ((float)pow((double)i / cielab->range, gamma));
     151                 :   }
     152                 : 
     153                 :   /* Blue */
     154               1 :   gamma = 1.0 / cielab->display.d_gammaB ;
     155               1 :   cielab->bstep =
     156               1 :       (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
     157            1502 :   for(i = 0; i <= cielab->range; i++) {
     158            3002 :     cielab->Yb2b[i] = cielab->display.d_Vrwb
     159            1501 :         * ((float)pow((double)i / cielab->range, gamma));
     160                 :   }
     161                 : 
     162                 :   /* Init reference white point */
     163               1 :   cielab->X0 = refWhite[0];
     164               1 :   cielab->Y0 = refWhite[1];
     165               1 :   cielab->Z0 = refWhite[2];
     166                 : 
     167               1 :   return 0;
     168                 : }
     169                 : 
     170                 : /* 
     171                 :  * Convert color value from the YCbCr space to CIE XYZ.
     172                 :  * The colorspace conversion algorithm comes from the IJG v5a code;
     173                 :  * see below for more information on how it works.
     174                 :  */
     175                 : #define SHIFT     16
     176                 : #define FIX(x)      ((int32)((x) * (1L<<SHIFT) + 0.5))
     177                 : #define ONE_HALF    ((int32)(1<<(SHIFT-1)))
     178                 : #define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
     179                 : #define CLAMP(f,min,max)  ((f)<(min)?(min):(f)>(max)?(max):(f))
     180                 : #define HICLAMP(f,max)    ((f)>(max)?(max):(f))
     181                 : 
     182                 : void
     183           49842 : TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
     184                 :          uint32 *r, uint32 *g, uint32 *b)
     185                 : {
     186                 :   int32 i;
     187                 : 
     188                 :   /* XXX: Only 8-bit YCbCr input supported for now */
     189           49842 :   Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255);
     190                 : 
     191           49842 :   i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
     192           49842 :   *r = CLAMP(i, 0, 255);
     193           99684 :   i = ycbcr->Y_tab[Y]
     194           49842 :       + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
     195           49842 :   *g = CLAMP(i, 0, 255);
     196           49842 :   i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
     197           49842 :   *b = CLAMP(i, 0, 255);
     198           49842 : }
     199                 : 
     200                 : /*
     201                 :  * Initialize the YCbCr->RGB conversion tables.  The conversion
     202                 :  * is done according to the 6.0 spec:
     203                 :  *
     204                 :  *    R = Y + Cr*(2 - 2*LumaRed)
     205                 :  *    B = Y + Cb*(2 - 2*LumaBlue)
     206                 :  *    G =   Y
     207                 :  *        - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
     208                 :  *        - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
     209                 :  *
     210                 :  * To avoid floating point arithmetic the fractional constants that
     211                 :  * come out of the equations are represented as fixed point values
     212                 :  * in the range 0...2^16.  We also eliminate multiplications by
     213                 :  * pre-calculating possible values indexed by Cb and Cr (this code
     214                 :  * assumes conversion is being done for 8-bit samples).
     215                 :  */
     216                 : int
     217               1 : TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
     218                 : {
     219                 :     TIFFRGBValue* clamptab;
     220                 :     int i;
     221                 :     
     222                 : #define LumaRed     luma[0]
     223                 : #define LumaGreen   luma[1]
     224                 : #define LumaBlue    luma[2]
     225                 : 
     226               1 :     clamptab = (TIFFRGBValue*)(
     227                 :   (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long)));  
     228               1 :     _TIFFmemset(clamptab, 0, 256);    /* v < 0 => 0 */
     229               1 :     ycbcr->clamptab = (clamptab += 256);
     230             257 :     for (i = 0; i < 256; i++)
     231             256 :   clamptab[i] = (TIFFRGBValue) i;
     232               1 :     _TIFFmemset(clamptab+256, 255, 2*256);  /* v > 255 => 255 */
     233               1 :     ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
     234               1 :     ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
     235               1 :     ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
     236               1 :     ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
     237               1 :     ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
     238                 : 
     239               1 :     { float f1 = 2-2*LumaRed;   int32 D1 = FIX(f1);
     240               1 :       float f2 = LumaRed*f1/LumaGreen;  int32 D2 = -FIX(f2);
     241               1 :       float f3 = 2-2*LumaBlue;    int32 D3 = FIX(f3);
     242               1 :       float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4);
     243                 :       int x;
     244                 : 
     245                 : #undef LumaBlue
     246                 : #undef LumaGreen
     247                 : #undef LumaRed
     248                 :       
     249                 :       /*
     250                 :        * i is the actual input pixel value in the range 0..255
     251                 :        * Cb and Cr values are in the range -128..127 (actually
     252                 :        * they are in a range defined by the ReferenceBlackWhite
     253                 :        * tag) so there is some range shifting to do here when
     254                 :        * constructing tables indexed by the raw pixel data.
     255                 :        */
     256             257 :       for (i = 0, x = -128; i < 256; i++, x++) {
     257             256 :       int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F,
     258                 :           refBlackWhite[5] - 128.0F, 127);
     259             256 :       int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F,
     260                 :           refBlackWhite[3] - 128.0F, 127);
     261                 : 
     262             256 :       ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
     263             256 :       ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
     264             256 :       ycbcr->Cr_g_tab[i] = D2*Cr;
     265             256 :       ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
     266             512 :       ycbcr->Y_tab[i] =
     267             256 :         (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255);
     268                 :       }
     269                 :     }
     270                 : 
     271               1 :     return 0;
     272                 : }
     273                 : #undef  HICLAMP
     274                 : #undef  CLAMP
     275                 : #undef  Code2V
     276                 : #undef  SHIFT
     277                 : #undef  ONE_HALF
     278                 : #undef  FIX
     279                 : 
     280                 : /* vim: set ts=8 sts=8 sw=8 noet: */
     281                 : /*
     282                 :  * Local Variables:
     283                 :  * mode: c
     284                 :  * c-basic-offset: 8
     285                 :  * fill-column: 78
     286                 :  * End:
     287                 :  */

Generated by: LCOV version 1.7