#include #include #include #include "pngoutput.h" #include "colourspace.h" #include "wavelength.h" const double brightness = 1.5; void output_srgb_scanline( double *output, int line, int width, int height ) { double ypos = (double) line / (double) ( height - 1 ); double wx, wy, wz; int i; ypos = 1.0 - ypos; /* use D65 */ xyy_to_xyz( 0.3127, 0.3290, brightness, &wx, &wy, &wz ); for( i = 0; i < width; i++ ) { double xpos = (double) i / (double) ( width - 1 ); double curX, curY, curZ; xyy_to_xyz( xpos, ypos, brightness, &curX, &curY, &curZ ); if( xy_in_gamut( xpos, ypos ) && curX >= 0.0 && curY >= 0.0 && curZ >= 0.0 ) { double r, g, b; double ri, gi, bi; xyz_to_srgb( curX, curY, curZ, &r, &g, &b ); if( r >= 0.0 && g >= 0.0 && b >= 0.0 ) { xyy_to_xyz( xpos, ypos, brightness + (brightness * 0.2), &curX, &curY, &curZ ); xyz_to_srgb( curX, curY, curZ, &r, &g, &b ); } closest_in_gamut_srgb( r, g, b, wx, wy, wz, &ri, &gi, &bi ); *output++ = ri; *output++ = gi; *output++ = bi; } else { *output++ = 0.0; *output++ = 0.0; *output++ = 0.0; } } } void quantize_srgb_scanline_8bit( unsigned char *output, double *input, int width ) { while( width-- ) { double r = *input++; double g = *input++; double b = *input++; double rp, gp, bp; linear_to_nonlinear_srgb( r, g, b, &rp, &gp, &bp ); *output++ = (unsigned char) ( ( rp * 255.0 ) + 0.5 ); *output++ = (unsigned char) ( ( gp * 255.0 ) + 0.5 ); *output++ = (unsigned char) ( ( bp * 255.0 ) + 0.5 ); } } void add_wavelengths( double *image, int width, int height ) { int i; for( i = 360; i < 831; i++ ) { double X, Y, Z; double x, y; int xpos, ypos; wavelength_to_xyz( i, &X, &Y, &Z ); x = X / ( X + Y + Z ); y = Y / ( X + Y + Z ); xpos = (int) ( ( x * (double) ( width - 1 ) ) + 0.5 ); ypos = (int) ( ( ( 1.0 - y ) * (double) ( height - 1 ) ) + 0.5 ); image[ ( ypos * width * 3 ) + ( xpos * 3 ) ] = 1.0; image[ ( ypos * width * 3 ) + ( xpos * 3 ) + 1 ] = 1.0; image[ ( ypos * width * 3 ) + ( xpos * 3 ) + 2 ] = 1.0; } } void add_d65( double *image, int width, int height ) { double x, y; int xpos, ypos; x = 0.3127; y = 0.3290; xpos = (int) ( ( x * (double) ( width - 1 ) ) + 0.5 ); ypos = (int) ( ( ( 1.0 - y ) * (double) ( height - 1 ) ) + 0.5 ); image[ ( ypos * width * 3 ) + ( xpos * 3 ) ] = 1.0; image[ ( ypos * width * 3 ) + ( xpos * 3 ) + 1 ] = 1.0; image[ ( ypos * width * 3 ) + ( xpos * 3 ) + 2 ] = 1.0; } int main( int argc, char **argv ) { int width = 800; int height = 600; unsigned char *output = (unsigned char *) malloc( width * 3 ); double *rgbimage = (double *) malloc( sizeof( double ) * width * height * 3 ); pngoutput_t *outfile; double biggest = 0.0; double scale; int i; assert( output ); assert( rgbimage ); outfile = pngoutput_new( "xy-srgb.png", width, height, 0.45 ); for( i = 0; i < height; i++ ) { output_srgb_scanline( &(rgbimage[ width * i * 3 ]), i, width, height ); } /* Scale the image so that we max at 1.0 in the worst case. */ for( i = 0; i < ( width * height * 3 ); i++ ) { if( rgbimage[ i ] > biggest ) biggest = rgbimage[ i ]; } scale = 1.0 / biggest; for( i = 0; i < ( width * height * 3 ); i++ ) { rgbimage[ i ] *= scale; } add_wavelengths( rgbimage, width, height ); add_d65( rgbimage, width, height ); for( i = 0; i < height; i++ ) { quantize_srgb_scanline_8bit( output, rgbimage + ( width * i * 3 ), width ); pngoutput_scanline( outfile, output ); } pngoutput_delete( outfile ); return 0; }