#include #include #include #include "pngoutput.h" #include "colourspace.h" #include "wavelength.h" const double brightness = 1.0; 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; double natY = brightness; get_natural_Y( xpos, ypos, brightness, &natY ); xyy_to_xyz( xpos, ypos, natY, &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 ); xyz_to_srgb( xpos, ypos, 1.0 - xpos - ypos, &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 ); } else { /* double newxpos, newypos, newnatY, newX, newY, newZ; closest_in_gamut_xy( xpos, ypos, 0.3127, 0.3290, // white 0.64, 0.33, // red 0.30, 0.60, // green 0.15, 0.06, // blue &newxpos, &newypos ); newnatY = brightness; get_natural_Y( newxpos, newypos, brightness, &newnatY ); xyy_to_xyz( newxpos, newypos, newnatY, &newX, &newY, &newZ ); xyz_to_srgb( newX, newY, newZ, &r, &g, &b ); // closest_in_gamut_srgb( r, g, b, wx, wy, wz, &ri, &gi, &bi ); */ } 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; } double coords[][2] = { { 0.640, 0.330 }, { 0.300, 0.600 }, { 0.150, 0.060 }, { 0.67, 0.33 }, { 0.21, 0.71 }, { 0.14, 0.08 }, /* { 0.64, 0.33 }, { 0.29, 0.60 }, { 0.15, 0.06 }, */ { 0.630, 0.340 }, { 0.310, 0.595 }, { 0.155, 0.070 } }; void add_coords( double *image, int width, int height ) { double x, y; int xpos, ypos; int i; for( i = 0; i < 9; i++ ) { x = coords[ i ][ 0 ]; y = coords[ i ][ 1 ]; fprintf( stderr, "%f, %f\n", x, y ); 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; fprintf( stderr, "%f, %f, xpos %d ypos %d\n", x, y, xpos, ypos ); } } 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 ); memset( &rgbimage[ width * i * 3 ], 0, width * 3 ); } /* 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 ); add_coords( 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; }