Example #1
0
/*
 * R T _ S P E C T _ M A K E _ N T S C _ R G B
 *
 * Using the "Representative set of camera taking sensitivities"
 * for a NTSC television camera, from Benson "Television Engineering
 * Handbook" page 4.58, convert an RGB value in range 0..1 to
 * a spectral curve also in range 0..1.
 *
 * These curves should be used in converting spectral samples
 * to NTSC RGB values.
 */
void
spect_make_NTSC_RGB(struct bn_tabdata **rp,
		    struct bn_tabdata **gp,
		    struct bn_tabdata **bp,
		    const struct bn_table *tabp)
{
    BN_CK_TABLE(tabp);

    /* Convert array of number pairs into bn_tabdata & bn_table */
    rt_NTSC_r_tabdata = bn_tabdata_from_array(&rt_NTSC_R[0][0]);
    rt_NTSC_g_tabdata = bn_tabdata_from_array(&rt_NTSC_G[0][0]);
    rt_NTSC_b_tabdata = bn_tabdata_from_array(&rt_NTSC_B[0][0]);

    bu_log("ntsc_R: area=%g\n", bn_tabdata_area2(rt_NTSC_r_tabdata));
    bn_print_table_and_tabdata("/dev/tty", rt_NTSC_r_tabdata);
    bu_log("ntsc_G: area=%g\n", bn_tabdata_area2(rt_NTSC_g_tabdata));
    bn_print_table_and_tabdata("/dev/tty", rt_NTSC_g_tabdata);
    bu_log("ntsc_B: area=%g\n", bn_tabdata_area2(rt_NTSC_b_tabdata));
    bn_print_table_and_tabdata("/dev/tty", rt_NTSC_b_tabdata);

    /* Resample original NTSC curves to match given bn_table sampling */
#if 0
    /* just to test the routine */
    *rp = bn_tabdata_resample_avg(tabp, rt_NTSC_r_tabdata);
    *gp = bn_tabdata_resample_avg(tabp, rt_NTSC_g_tabdata);
    *bp = bn_tabdata_resample_avg(tabp, rt_NTSC_b_tabdata);
#else
    /* use this one for real */
    *rp = bn_tabdata_resample_max(tabp, rt_NTSC_r_tabdata);
    *gp = bn_tabdata_resample_max(tabp, rt_NTSC_g_tabdata);
    *bp = bn_tabdata_resample_max(tabp, rt_NTSC_b_tabdata);
#endif
}
Example #2
0
/*
 * R T _ S P E C T _ C U R V E _ T O _ X Y Z
 *
 * Convenience routine.
 * Serves same function as Roy Hall's CLR_spect_to_xyz(), pg 233.
 * The normalization xyz_scale = 1.0 / bn_tabdata_area2(cie_y);
 * has been folded into spect_make_CIE_XYZ();
 */
void
spect_curve_to_xyz(point_t xyz,
		   const struct bn_tabdata *tabp,
		   const struct bn_tabdata *cie_x,
		   const struct bn_tabdata *cie_y,
		   const struct bn_tabdata *cie_z)
{
    fastf_t tab_area;

    BN_CK_TABDATA(tabp);

#if 0
    tab_area = bn_tabdata_area2(tabp);
    bu_log(" tab_area = %g\n", tab_area);
    if (fabs(tab_area) < VDIVIDE_TOL) {
	bu_log("spect_curve_to_xyz(): Area = 0 (no luminance) in this part of the spectrum\n");
	VSETALL(xyz, 0);
	return;
    }
    tab_area = 1 / tab_area;
#else
    /* This is what Roy says to do, but I'm not certain */
    tab_area = 1;
#endif

    xyz[X] = bn_tabdata_mul_area2(tabp, cie_x) * tab_area;
    xyz[Y] = bn_tabdata_mul_area2(tabp, cie_y) * tab_area;
    xyz[Z] = bn_tabdata_mul_area2(tabp, cie_z) * tab_area;
}
Example #3
0
static int
test_bn_tabdata_area2(int argc, char *argv[])
{
    struct bn_table *tab_in;
    struct bn_tabdata *td_in;
    fastf_t expected, actual;

    if (argc != 5) {
	bu_exit(1, "<args> format: table tabdata expected_result [%s]\n", argv[0]);
    }

    scan_tab_args(argv[2], &tab_in);
    scan_tabdata_args(argv[3], &td_in, tab_in);
    sscanf(argv[4], "%lg", &expected);

    actual = bn_tabdata_area2(td_in);

    bu_log("Result: %g\n", actual);

    return !NEAR_EQUAL(expected, actual, BN_TOL_DIST);
}
Example #4
0
/**
 * R T _ S P E C T _ M A K E _ C I E _ X Y Z
 *
 * Given as input a spectral sampling distribution, generate the 3
 * curves to match the human eye's response in CIE color parameters X,
 * Y, and Z.  XYZ space can be readily converted to RGB with a 3x3
 * matrix.
 *
 * The tabulated data is linearly interpolated.
 *
 * Pointers to the three spectral weighting functions are "returned",
 * storage for the X, Y, and Z curves is allocated by this routine and
 * must be freed by the caller.
 */
void
rt_spect_make_CIE_XYZ(struct bn_tabdata **x, struct bn_tabdata **y, struct bn_tabdata **z, const struct bn_table *tabp)
{
    struct bn_tabdata	*a, *b, *c;
    fastf_t	xyz_scale;
    int	i;
    int	j;

    BN_CK_TABLE(tabp);

    i = bn_table_interval_num_samples( tabp, 430., 650. );
    if ( i <= 4 )  bu_log("rt_spect_make_CIE_XYZ: insufficient samples (%d) in visible band\n", i);

    BN_GET_TABDATA( a, tabp );
    BN_GET_TABDATA( b, tabp );
    BN_GET_TABDATA( c, tabp );
    *x = a;
    *y = b;
    *z = c;

    /* No CIE data below 380 nm */
    for ( j=0; tabp->x[j] < 380 && j < tabp->nx; j++ )  {
	a->y[j] = b->y[j] = c->y[j] = 0;
    }

    /* Traverse the CIE table.  Produce as many output values as
     * possible before advancing to next CIE table entry.
     */
    for ( i = 0; i < 81-1; i++ )  {
	fastf_t	fract;		/* fraction from [i] to [i+1] */

    again:
	if ( j >= tabp->nx )  break;
	if ( tabp->x[j] < rt_CIE_XYZ[i][0] ) bu_bomb("rt_spect_make_CIE_XYZ assertion1 failed\n");
	if ( tabp->x[j] >= rt_CIE_XYZ[i+1][0] )  continue;
	/* The CIE table has 5nm spacing */
	fract = (tabp->x[j] - rt_CIE_XYZ[i][0] ) / 5;
	if ( fract < 0 || fract > 1 )  bu_bomb("rt_spect_make_CIE_XYZ assertion2 failed\n");
	a->y[j] = (1-fract) * rt_CIE_XYZ[i][1] + fract * rt_CIE_XYZ[i+1][1];
	b->y[j] = (1-fract) * rt_CIE_XYZ[i][2] + fract * rt_CIE_XYZ[i+1][2];
	c->y[j] = (1-fract) * rt_CIE_XYZ[i][3] + fract * rt_CIE_XYZ[i+1][3];
	j++;
	goto again;
    }

    /* No CIE data above 780 nm */
    for (; j < tabp->nx; j++ )  {
	a->y[j] = b->y[j] = c->y[j] = 0;
    }

    /* Normalize the curves so that area under Y curve is 1.0 */
    xyz_scale = bn_tabdata_area2( b );
    if ( fabs(xyz_scale) < VDIVIDE_TOL )  {
	bu_log("rt_spect_make_CIE_XYZ(): Area = 0 (no luminance) in this part of the spectrum, skipping normalization step\n");
	return;
    }
    xyz_scale = 1 / xyz_scale;
    bn_tabdata_scale( a, a, xyz_scale );
    bn_tabdata_scale( b, b, xyz_scale );
    bn_tabdata_scale( c, c, xyz_scale );
}