/* @(#) Turn XYZ files into displayable rgb. * @(#) * @(#) Usage: * @(#) int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) * @(#) * @(#) Returns: -1 on error, else 0 * * Author: J-P. Laurent * Modified: * 15/11/94 JC * - error message added * - out->Type set to IM_TYPE_RGB * - memory leak fixed * 16/11/94 JC * - uses im_wrapone() * 15/2/95 JC * - oops! now uses PEL, not float for output pointer * 2/1/96 JC * - sometimes produced incorrect result at extrema * - reformatted * - now uses IM_RINT() and clip() * 18/9/96 JC * - some speed-ups ... 3x faster * - slightly less accurate, but who cares * - added out-of-mem check for table build */ /* This file is part of VIPS. VIPS is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk */ #ifdef HAVE_CONFIG_H #include #endif /*HAVE_CONFIG_H*/ #include #include #include #include #ifdef WITH_DMALLOC #include #endif /*WITH_DMALLOC*/ /* Process a buffer of data. */ void imb_XYZ2disp( float *p, PEL *q, int n, struct im_col_tab_disp *table, struct im_col_display *d ) { int x; float rstep = (d->d_YCR - d->d_Y0R) / 1500.0; float gstep = (d->d_YCG - d->d_Y0G) / 1500.0; float bstep = (d->d_YCB - d->d_Y0B) / 1500.0; for( x = 0; x < n; x++ ) { float Yr, Yg, Yb; int i; int r, g, b; float X = p[0]; float Y = p[1]; float Z = p[2]; p += 3; /* Multiply through the matrix to get luminosity values. */ Yr = table->mat_XYZ2lum[0][0] * X + table->mat_XYZ2lum[0][1] * Y + table->mat_XYZ2lum[0][2] * Z; Yg = table->mat_XYZ2lum[1][0] * X + table->mat_XYZ2lum[1][1] * Y + table->mat_XYZ2lum[1][2] * Z; Yb = table->mat_XYZ2lum[2][0] * X + table->mat_XYZ2lum[2][1] * Y + table->mat_XYZ2lum[2][2] * Z; /* Clip -ves. */ Yr = IM_MAX( Yr, d->d_Y0R ); Yg = IM_MAX( Yg, d->d_Y0G ); Yb = IM_MAX( Yb, d->d_Y0B ); /* Turn luminosity to colour value. */ i = IM_MIN( 1500, (Yr - d->d_Y0R) / rstep ); r = table->t_Yr2r[i]; i = IM_MIN( 1500, (Yg - d->d_Y0G) / gstep ); g = table->t_Yg2g[i]; i = IM_MIN( 1500, (Yb - d->d_Y0B) / bstep ); b = table->t_Yb2b[i]; /* Clip output. */ r = IM_MIN( r, d->d_Vrwr ); g = IM_MIN( g, d->d_Vrwg ); b = IM_MIN( b, d->d_Vrwb ); q[0] = r; q[1] = g; q[2] = b; q += 3; } } int im_XYZ2disp( IMAGE *in, IMAGE *out, struct im_col_display *d ) { struct im_col_tab_disp *table; /* Check input image. */ if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT || in->Coding != IM_CODING_NONE ) { im_error( "im_XYZ2disp", "%s", _( "3-band uncoded float only" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Bbits = IM_BBITS_BYTE; out->BandFmt = IM_BANDFMT_UCHAR; out->Type = IM_TYPE_RGB; /* Build the lookup tables */ if( !(table = im_col_make_tables_RGB( out, d )) ) return( -1 ); /* Do the processing. */ if( im_wrapone( in, out, (im_wrapone_fn) imb_XYZ2disp, table, d ) ) return( -1 ); return( 0 ); }