tif_color.c 8.6 KB

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