--- ray/src/common/spec_rgb.c 2003/02/22 02:07:22 2.11
+++ ray/src/common/spec_rgb.c 2011/05/20 02:06:38 2.23
@@ -1,5 +1,5 @@
#ifndef lint
-static const char RCSid[] = "$Id: spec_rgb.c,v 2.11 2003/02/22 02:07:22 greg Exp $";
+static const char RCSid[] = "$Id: spec_rgb.c,v 2.23 2011/05/20 02:06:38 greg Exp $";
#endif
/*
* Convert colors and spectral ranges.
@@ -8,65 +8,11 @@ static const char RCSid[] = "$Id: spec_rgb.c,v 2.11 20
* Externals declared in color.h
*/
-/* ====================================================================
- * The Radiance Software License, Version 1.0
- *
- * Copyright (c) 1990 - 2002 The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes Radiance software
- * (http://radsite.lbl.gov/)
- * developed by the Lawrence Berkeley National Laboratory
- * (http://www.lbl.gov/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
- * and "The Regents of the University of California" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact radiance@radsite.lbl.gov.
- *
- * 5. Products derived from this software may not be called "Radiance",
- * nor may "Radiance" appear in their name, without prior written
- * permission of Lawrence Berkeley National Laboratory.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of Lawrence Berkeley National Laboratory. For more
- * information on Lawrence Berkeley National Laboratory, please see
- * .
- */
+#include "copyright.h"
-#include "color.h"
+#include
#include
+#include "color.h"
#define CEPS 1e-4 /* color epsilon */
@@ -92,7 +38,7 @@ float xyneu[2] = {1./3., 1./3.}; /* neutral xy chroma
#define INCWL 10 /* wavelength increment */
#define NINC 40 /* # of values */
-static BYTE chroma[3][NINC] = {
+static uby8 chroma[3][NINC] = {
{ /* X */
0, 0, 0, 2, 6, 13, 22, 30, 36, 41,
42, 43, 43, 44, 46, 52, 60, 71, 87, 106,
@@ -145,9 +91,11 @@ COLORMAT ivkmat = { /* inverse Sharp primary matrix
void
-spec_rgb(col, s, e) /* compute RGB color from spectral range */
-COLOR col;
-int s, e;
+spec_rgb( /* compute RGB color from spectral range */
+COLOR col,
+int s,
+int e
+)
{
COLOR ciecolor;
@@ -157,9 +105,11 @@ int s, e;
void
-spec_cie(col, s, e) /* compute a color from a spectral range */
-COLOR col; /* returned color */
-int s, e; /* starting and ending wavelengths */
+spec_cie( /* compute a color from a spectral range */
+COLOR col, /* returned color */
+int s, /* starting and ending wavelengths */
+int e
+)
{
register int i, d, r;
@@ -192,9 +142,10 @@ int s, e; /* starting and ending wavelengths */
void
-cie_rgb(rgb, xyz) /* convert CIE color to standard RGB */
-COLOR rgb;
-COLOR xyz;
+cie_rgb( /* convert CIE color to standard RGB */
+COLOR rgb,
+COLOR xyz
+)
{
colortrans(rgb, xyz2rgbmat, xyz);
clipgamut(rgb, xyz[CIEY], CGAMUT_LOWER, cblack, cwhite);
@@ -202,11 +153,13 @@ COLOR xyz;
int
-clipgamut(col, brt, gamut, lower, upper) /* clip to gamut cube */
-COLOR col;
-double brt;
-int gamut;
-COLOR lower, upper;
+clipgamut( /* clip to gamut cube */
+COLOR col,
+double brt,
+int gamut,
+COLOR lower,
+COLOR upper
+)
{
int rflags = 0;
double brtmin, brtmax, v, vv;
@@ -232,11 +185,11 @@ COLOR lower, upper;
vv = 1.; /* check each limit */
for (i = 0; i < 3; i++)
if (gamut & CGAMUT_LOWER && col[i] < lower[i]) {
- v = (lower[i]+CEPS - cgry[i])/(col[i] - cgry[i]);
+ v = (lower[i] - cgry[i])/(col[i] - cgry[i]);
if (v < vv) vv = v;
rflags |= CGAMUT_LOWER;
} else if (gamut & CGAMUT_UPPER && col[i] > upper[i]) {
- v = (upper[i]-CEPS - cgry[i])/(col[i] - cgry[i]);
+ v = (upper[i] - cgry[i])/(col[i] - cgry[i]);
if (v < vv) vv = v;
rflags |= CGAMUT_UPPER;
}
@@ -248,10 +201,11 @@ COLOR lower, upper;
void
-colortrans(c2, mat, c1) /* convert c1 by mat and put into c2 */
-register COLOR c2;
-register COLORMAT mat;
-register COLOR c1;
+colortrans( /* convert c1 by mat and put into c2 */
+register COLOR c2,
+register COLORMAT mat,
+register COLOR c1
+)
{
COLOR cout;
@@ -264,9 +218,11 @@ register COLOR c1;
void
-multcolormat(m3, m2, m1) /* multiply m1 by m2 and put into m3 */
-COLORMAT m3; /* m3 can be either m1 or m2 w/o harm */
-COLORMAT m2, m1;
+multcolormat( /* multiply m1 by m2 and put into m3 */
+COLORMAT m3, /* m3 can be either m1 or m2 w/o harm */
+COLORMAT m2,
+COLORMAT m1
+)
{
COLORMAT mt;
register int i, j;
@@ -280,30 +236,68 @@ COLORMAT m2, m1;
}
-void
-compxyz2rgbmat(mat, pr) /* compute conversion from CIE to RGB space */
-COLORMAT mat;
-register RGBPRIMS pr;
+int
+colorprimsOK( /* are color primaries reasonable? */
+RGBPRIMS pr
+)
{
+ int i, j;
+
+ for (i = 0; i < 3; i++) {
+ if ((pr[i][CIEX] <= -1.) | (pr[i][CIEY] <= -1.))
+ return(0);
+ if ((pr[i][CIEX] >= 2.) | (pr[i][CIEY] >= 2.))
+ return(0);
+ if (pr[i][CIEX] + pr[i][CIEY] <= -1.)
+ return(0);
+ if (pr[i][CIEX] + pr[i][CIEY] >= 2.)
+ return(0);
+ }
+ if ((pr[3][CIEX] <= 0.) | (pr[3][CIEX] >= 1.) |
+ (pr[3][CIEY] <= 0.) | (pr[3][CIEY] >= 1.))
+ return(0);
+ for (i = 0; i < 4; i++)
+ for (j = i+1; j < 4; j++)
+ if (CEQ(pr[i][CIEX],pr[j][CIEX]) &&
+ CEQ(pr[i][CIEY],pr[j][CIEY]))
+ return(0);
+ return(1);
+}
+
+
+
+int
+compxyz2rgbmat( /* compute conversion from CIE to RGB space */
+COLORMAT mat,
+register RGBPRIMS pr
+)
+{
double C_rD, C_gD, C_bD;
if (pr == stdprims) { /* can use xyz2rgbmat */
cpcolormat(mat, xyz2rgbmat);
- return;
+ return(1);
}
+ if (CEQ(pr[WHT][CIEX],0.) | CEQ(pr[WHT][CIEY],0.))
+ return(0);
C_rD = (1./pr[WHT][CIEY]) *
( pr[WHT][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) -
pr[WHT][CIEY]*(pr[GRN][CIEX] - pr[BLU][CIEX]) +
pr[GRN][CIEX]*pr[BLU][CIEY] - pr[BLU][CIEX]*pr[GRN][CIEY] ) ;
+ if (CEQ(C_rD,0.))
+ return(0);
C_gD = (1./pr[WHT][CIEY]) *
( pr[WHT][CIEX]*(pr[BLU][CIEY] - pr[RED][CIEY]) -
pr[WHT][CIEY]*(pr[BLU][CIEX] - pr[RED][CIEX]) -
pr[RED][CIEX]*pr[BLU][CIEY] + pr[BLU][CIEX]*pr[RED][CIEY] ) ;
+ if (CEQ(C_gD,0.))
+ return(0);
C_bD = (1./pr[WHT][CIEY]) *
( pr[WHT][CIEX]*(pr[RED][CIEY] - pr[GRN][CIEY]) -
pr[WHT][CIEY]*(pr[RED][CIEX] - pr[GRN][CIEX]) +
pr[RED][CIEX]*pr[GRN][CIEY] - pr[GRN][CIEX]*pr[RED][CIEY] ) ;
-
+ if (CEQ(C_bD,0.))
+ return(0);
mat[0][0] = (pr[GRN][CIEY] - pr[BLU][CIEY] -
pr[BLU][CIEX]*pr[GRN][CIEY] +
pr[BLU][CIEY]*pr[GRN][CIEX])/C_rD ;
@@ -328,20 +322,24 @@ register RGBPRIMS pr;
pr[RED][CIEX]*pr[GRN][CIEY])/C_bD ;
mat[2][2] = (pr[RED][CIEX]*pr[GRN][CIEY] -
pr[GRN][CIEX]*pr[RED][CIEY])/C_bD ;
+ return(1);
}
-void
-comprgb2xyzmat(mat, pr) /* compute conversion from RGB to CIE space */
-COLORMAT mat;
-register RGBPRIMS pr;
+int
+comprgb2xyzmat( /* compute conversion from RGB to CIE space */
+COLORMAT mat,
+register RGBPRIMS pr
+)
{
double C_rD, C_gD, C_bD, D;
if (pr == stdprims) { /* can use rgb2xyzmat */
cpcolormat(mat, rgb2xyzmat);
- return;
+ return(1);
}
+ if (CEQ(pr[WHT][CIEX],0.) | CEQ(pr[WHT][CIEY],0.))
+ return(0);
C_rD = (1./pr[WHT][CIEY]) *
( pr[WHT][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) -
pr[WHT][CIEY]*(pr[GRN][CIEX] - pr[BLU][CIEX]) +
@@ -357,6 +355,8 @@ register RGBPRIMS pr;
D = pr[RED][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) +
pr[GRN][CIEX]*(pr[BLU][CIEY] - pr[RED][CIEY]) +
pr[BLU][CIEX]*(pr[RED][CIEY] - pr[GRN][CIEY]) ;
+ if (CEQ(D,0.))
+ return(0);
mat[0][0] = pr[RED][CIEX]*C_rD/D;
mat[0][1] = pr[GRN][CIEX]*C_gD/D;
mat[0][2] = pr[BLU][CIEX]*C_bD/D;
@@ -366,13 +366,16 @@ register RGBPRIMS pr;
mat[2][0] = (1.-pr[RED][CIEX]-pr[RED][CIEY])*C_rD/D;
mat[2][1] = (1.-pr[GRN][CIEX]-pr[GRN][CIEY])*C_gD/D;
mat[2][2] = (1.-pr[BLU][CIEX]-pr[BLU][CIEY])*C_bD/D;
+ return(1);
}
-void
-comprgb2rgbmat(mat, pr1, pr2) /* compute conversion from RGB1 to RGB2 */
-COLORMAT mat;
-RGBPRIMS pr1, pr2;
+int
+comprgb2rgbmat( /* compute conversion from RGB1 to RGB2 */
+COLORMAT mat,
+RGBPRIMS pr1,
+RGBPRIMS pr2
+)
{
COLORMAT pr1toxyz, xyztopr2;
@@ -380,35 +383,46 @@ RGBPRIMS pr1, pr2;
mat[0][0] = mat[1][1] = mat[2][2] = 1.0;
mat[0][1] = mat[0][2] = mat[1][0] =
mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
- return;
+ return(1);
}
- comprgb2xyzmat(pr1toxyz, pr1);
- compxyz2rgbmat(xyztopr2, pr2);
+ if (!comprgb2xyzmat(pr1toxyz, pr1))
+ return(0);
+ if (!compxyz2rgbmat(xyztopr2, pr2))
+ return(0);
/* combine transforms */
multcolormat(mat, pr1toxyz, xyztopr2);
+ return(1);
}
-void
-compxyzWBmat(mat, wht1, wht2) /* CIE von Kries transform from wht1 to wht2 */
-COLORMAT mat;
-float wht1[2], wht2[2];
+int
+compxyzWBmat( /* CIE von Kries transform from wht1 to wht2 */
+COLORMAT mat,
+float wht1[2],
+float wht2[2]
+)
{
COLOR cw1, cw2;
if (XYEQ(wht1,wht2)) {
mat[0][0] = mat[1][1] = mat[2][2] = 1.0;
mat[0][1] = mat[0][2] = mat[1][0] =
mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
- return;
+ return(1);
}
+ if (CEQ(wht1[CIEX],0.) | CEQ(wht1[CIEY],0.))
+ return(0);
cw1[RED] = wht1[CIEX]/wht1[CIEY];
cw1[GRN] = 1.;
cw1[BLU] = (1. - wht1[CIEX] - wht1[CIEY])/wht1[CIEY];
colortrans(cw1, vkmat, cw1);
+ if (CEQ(wht2[CIEX],0.) | CEQ(wht2[CIEY],0.))
+ return(0);
cw2[RED] = wht2[CIEX]/wht2[CIEY];
cw2[GRN] = 1.;
cw2[BLU] = (1. - wht2[CIEX] - wht2[CIEY])/wht2[CIEY];
colortrans(cw2, vkmat, cw2);
+ if (CEQ(cw1[RED],0.) | CEQ(cw1[GRN],0.) | CEQ(cw1[BLU],0.))
+ return(0);
mat[0][0] = cw2[RED]/cw1[RED];
mat[1][1] = cw2[GRN]/cw1[GRN];
mat[2][2] = cw2[BLU]/cw1[BLU];
@@ -416,41 +430,52 @@ float wht1[2], wht2[2];
mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
multcolormat(mat, vkmat, mat);
multcolormat(mat, mat, ivkmat);
+ return(1);
}
-void
-compxyz2rgbWBmat(mat, pr) /* von Kries conversion from CIE to RGB space */
-COLORMAT mat;
-RGBPRIMS pr;
+int
+compxyz2rgbWBmat( /* von Kries conversion from CIE to RGB space */
+COLORMAT mat,
+RGBPRIMS pr
+)
{
COLORMAT wbmat;
- compxyz2rgbmat(mat, pr);
+ if (!compxyz2rgbmat(mat, pr))
+ return(0);
if (XYEQ(pr[WHT],xyneu))
- return;
- compxyzWBmat(wbmat, xyneu, pr[WHT]);
+ return(1);
+ if (!compxyzWBmat(wbmat, xyneu, pr[WHT]))
+ return(0);
multcolormat(mat, wbmat, mat);
+ return(1);
}
-void
-comprgb2xyzWBmat(mat, pr) /* von Kries conversion from RGB to CIE space */
-COLORMAT mat;
-RGBPRIMS pr;
+int
+comprgb2xyzWBmat( /* von Kries conversion from RGB to CIE space */
+COLORMAT mat,
+RGBPRIMS pr
+)
{
COLORMAT wbmat;
- comprgb2xyzmat(mat, pr);
+ if (!comprgb2xyzmat(mat, pr))
+ return(0);
if (XYEQ(pr[WHT],xyneu))
- return;
- compxyzWBmat(wbmat, pr[WHT], xyneu);
+ return(1);
+ if (!compxyzWBmat(wbmat, pr[WHT], xyneu))
+ return(0);
multcolormat(mat, mat, wbmat);
+ return(1);
}
-void
-comprgb2rgbWBmat(mat, pr1, pr2) /* von Kries conversion from RGB1 to RGB2 */
-COLORMAT mat;
-RGBPRIMS pr1, pr2;
+int
+comprgb2rgbWBmat( /* von Kries conversion from RGB1 to RGB2 */
+COLORMAT mat,
+RGBPRIMS pr1,
+RGBPRIMS pr2
+)
{
COLORMAT pr1toxyz, xyztopr2, wbmat;
@@ -458,12 +483,16 @@ RGBPRIMS pr1, pr2;
mat[0][0] = mat[1][1] = mat[2][2] = 1.0;
mat[0][1] = mat[0][2] = mat[1][0] =
mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
- return;
+ return(1);
}
- comprgb2xyzmat(pr1toxyz, pr1);
- compxyzWBmat(wbmat, pr1[WHT], pr2[WHT]);
- compxyz2rgbmat(xyztopr2, pr2);
+ if (!comprgb2xyzmat(pr1toxyz, pr1))
+ return(0);
+ if (!compxyzWBmat(wbmat, pr1[WHT], pr2[WHT]))
+ return(0);
+ if (!compxyz2rgbmat(xyztopr2, pr2))
+ return(0);
/* combine transforms */
multcolormat(mat, pr1toxyz, wbmat);
multcolormat(mat, mat, xyztopr2);
+ return(1);
}