#include #include #include #include #include #include #include "colourspace.h" #include "pngoutput.h" static void read_image( int infd, double *luma, double *cb, double *cr, int width, int height ) { int i; for( i = 0; i < width * height; i++ ) { unsigned char cur; read( infd, &cur, 1 ); *luma++ = ( (double) ( cur - 16 ) ) / 219.0; } for( i = 0; i < ((width/2) * (height/2)); i++ ) { unsigned char cur; read( infd, &cur, 1 ); *cb++ = ( (double) ( cur - 128 ) ) / 224.0; } for( i = 0; i < ((width/2) * (height/2)); i++ ) { unsigned char cur; read( infd, &cur, 1 ); *cr++ = ( (double) ( cur - 128 ) ) / 224.0; } } int main( int argc, char **argv ) { double *luma; double *cbin; double *crin; double *cb444; double *cr444; unsigned char *scanline; matrix_t *fcc_to_xyz; pngoutput_t *pngout; int infd, width, height, i, j; fcc_to_xyz = build_rgb_xyz_matrix_from_chromaticities( /* 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, 0.310, 0.316 ); */ /* 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, 0.3127, 0.3290 ); */ 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, 0.3127, 0.3290 ); infd = open( argv[ 1 ], O_RDONLY ); if( infd < 0 ) { fprintf( stderr, "Can't open %s.\n", argv[ 1 ] ); return 1; } read( infd, &width, sizeof( int ) ); read( infd, &height, sizeof( int ) ); fprintf( stderr, "ycbcrtorgb: Input is %dx%d resolution.\n", width, height ); pngout = pngoutput_new( argv[ 2 ], width, height, 0.45 ); if( !pngout ) { fprintf( stderr, "ycbcrtorgb: Can't open output file %s.\n", argv[ 2 ] ); close( infd ); return 1; } luma = (double *) malloc( width * height * sizeof( double ) ); cbin = (double *) malloc( (width/2) * (height/2) * sizeof( double ) ); crin = (double *) malloc( (width/2) * (height/2) * sizeof( double ) ); cb444 = (double *) malloc( width * height * sizeof( double ) ); cr444 = (double *) malloc( width * height * sizeof( double ) ); scanline = (unsigned char *) malloc( width * 3 ); if( !luma || !cbin || !crin || !cb444 || !cr444 || !scanline ) { fprintf( stderr, "ycbcrtorgb: Can't allocate memory.\n" ); pngoutput_delete( pngout ); close( infd ); return 1; } read_image( infd, luma, cbin, crin, width, height ); resample_chroma_420_to_444( cbin, cb444, width/2, height/2 ); resample_chroma_420_to_444( crin, cr444, width/2, height/2 ); for( i = 0; i < height; i++ ) { unsigned char *s = scanline; for( j = 0; j < width; j++ ) { double yp = luma[ (i * width) + j ]; double pb = cb444[ (i * width) + j ]; double pr = cr444[ (i * width) + j ]; double rfcc, gfcc, bfcc; double rfccl, gfccl, bfccl; double x, y, z; double r, g, b; double rp, gp, bp; mpeg2_ypbpr_to_rgb_fcc( yp, pb, pr, &rfcc, &gfcc, &bfcc ); nonlinear_to_linear_rec709( rfcc, gfcc, bfcc, &rfccl, &gfccl, &bfccl ); matrix_rgb_to_xyz( fcc_to_xyz, rfccl, gfccl, bfccl, &x, &y, &z ); xyz_to_srgb( x, y, z, &r, &g, &b ); if( r < 0.0 || r > 1.0 || g < 0.0 || g > 1.0 || b < 0.0 || b > 1.0 ) { r = g = b = 0.0; } linear_to_nonlinear_srgb( r, g, b, &rp, &gp, &bp ); /* //mpeg2_ypbpr_to_rgb_fcc( yp, pb, pr, &rp, &gp, &bp ); mpeg2_ypbpr_to_rgb_rec709( yp, pb, pr, &rp, &gp, &bp ); if( rp < 0.0 || rp > 1.0 || gp < 0.0 || gp > 1.0 || bp < 0.0 || bp > 1.0 ) { rp = gp = bp = 0.0; } */ *s++ = (unsigned char) ( ( rp * 255.0 ) + 0.5 ); *s++ = (unsigned char) ( ( gp * 255.0 ) + 0.5 ); *s++ = (unsigned char) ( ( bp * 255.0 ) + 0.5 ); } pngoutput_scanline( pngout, scanline ); } pngoutput_delete( pngout ); close( infd ); return 0; }