bool FileFormatInstance::ReadRGBWS( RGBColorSystem& rgbws ) { try { rgbws = RGBColorSystem(); if ( (*API->FileFormat->BeginRGBWSExtraction)( handle ) == api_false ) return false; float gamma = rgbws.Gamma(); api_bool issRGB = rgbws.IsSRGB(); FVector x = rgbws.ChromaticityXCoordinates(); FVector y = rgbws.ChromaticityYCoordinates(); FVector Y = rgbws.LuminanceCoefficients(); bool ok = (*API->FileFormat->GetImageRGBWS)( handle, &gamma, &issRGB, x.Begin(), y.Begin(), Y.Begin() ) != api_false; if ( ok ) rgbws = RGBColorSystem( gamma, issRGB, x, y, Y ); (*API->FileFormat->EndRGBWSExtraction)( handle ); return ok; } catch ( ... ) { (*API->FileFormat->EndRGBWSExtraction)( handle ); throw; } }
void FileFormatImplementation::EndRGBWSEmbedding() { WriteRGBWS( m_data->rgbws ); m_data->rgbws = RGBColorSystem(); }
void FileFormatImplementation::BeginRGBWSEmbedding() { BeginPrivate(); m_data->rgbws = RGBColorSystem(); }
void FileFormatImplementation::EndRGBWSExtraction() { m_data->rgbws = RGBColorSystem(); }
RGBColorSystem FileFormatImplementation::ReadRGBWS() { MANDATORY( "ReadRGBWS" ); return RGBColorSystem(); }
namespace pcl { // ---------------------------------------------------------------------------- /* * Standard RGB working spaces. * * All primaries are relative to the D50 reference white. For spaces originally * defined relative to other references (usually D65), the Bradford chromatic * adaptation algorithm has been used to perform the conversions to D50. * * Reference: Bruce Lindbloom - http://www.brucelindbloom.com/ */ /* * sRGB (D50) */ const float RGBColorSystem::sRGB_x[ 3 ] = { 0.648431F, 0.321152F, 0.155886F }; const float RGBColorSystem::sRGB_y[ 3 ] = { 0.330856F, 0.597871F, 0.066044F }; const float RGBColorSystem::sRGB_Y[ 3 ] = { 0.222491F, 0.716888F, 0.060621F }; /* * The default sRGB (D50) working space. */ const RGBColorSystem RGBColorSystem::sRGB = RGBColorSystem( 2.2F, true, sRGB_x, sRGB_y, sRGB_Y ); #ifdef __PCL_WITH_STANDARD_RGB_WORKING_SPACES /* * Adobe RGB 1998 */ const float RGBColorSystem::AdobeRGB1998_x[ 3 ] = { 0.648431F, 0.230154F, 0.155886F }; const float RGBColorSystem::AdobeRGB1998_y[ 3 ] = { 0.330856F, 0.701572F, 0.066044F }; const float RGBColorSystem::AdobeRGB1998_Y[ 3 ] = { 0.311114F, 0.625662F, 0.063224F }; /* * Apple RGB */ const float RGBColorSystem::AppleRGB_x[ 3 ] = { 0.634756F, 0.301775F, 0.162897F }; const float RGBColorSystem::AppleRGB_y[ 3 ] = { 0.340596F, 0.597511F, 0.079001F }; const float RGBColorSystem::AppleRGB_Y[ 3 ] = { 0.255166F, 0.672578F, 0.072256F }; /* * Best RGB */ const float RGBColorSystem::BestRGB_x[ 3 ] = { 0.734700F, 0.215000F, 0.130000F }; const float RGBColorSystem::BestRGB_y[ 3 ] = { 0.265300F, 0.775000F, 0.035000F }; const float RGBColorSystem::BestRGB_Y[ 3 ] = { 0.228457F, 0.737352F, 0.034191F }; /* * Beta RGB (by Bruce Lindbloom) */ const float RGBColorSystem::BetaRGB_x[ 3 ] = { 0.688800F, 0.198600F, 0.126500F }; const float RGBColorSystem::BetaRGB_y[ 3 ] = { 0.311200F, 0.755100F, 0.035200F }; const float RGBColorSystem::BetaRGB_Y[ 3 ] = { 0.303273F, 0.663786F, 0.032941F }; /* * Bruce RGB */ const float RGBColorSystem::BruceRGB_x[ 3 ] = { 0.648431F, 0.300115F, 0.155886F }; const float RGBColorSystem::BruceRGB_y[ 3 ] = { 0.330856F, 0.640960F, 0.066044F }; const float RGBColorSystem::BruceRGB_Y[ 3 ] = { 0.252141F, 0.684495F, 0.063364F }; /* * CIE RGB */ const float RGBColorSystem::CIERGB_x[ 3 ] = { 0.737385F, 0.266802F, 0.174329F }; const float RGBColorSystem::CIERGB_y[ 3 ] = { 0.264518F, 0.718404F, 0.000599F }; const float RGBColorSystem::CIERGB_Y[ 3 ] = { 0.174658F, 0.824754F, 0.000588F }; /* * Color Match RGB */ const float RGBColorSystem::ColorMatchRGB_x[ 3 ] = { 0.630000F, 0.295000F, 0.150000F }; const float RGBColorSystem::ColorMatchRGB_y[ 3 ] = { 0.340000F, 0.605000F, 0.075000F }; const float RGBColorSystem::ColorMatchRGB_Y[ 3 ] = { 0.274884F, 0.658132F, 0.066985F }; /* * NTSC RGB */ const float RGBColorSystem::NTSCRGB_x[ 3 ] = { 0.671910F, 0.222591F, 0.142783F }; const float RGBColorSystem::NTSCRGB_y[ 3 ] = { 0.329340F, 0.710647F, 0.096145F }; const float RGBColorSystem::NTSCRGB_Y[ 3 ] = { 0.310889F, 0.591737F, 0.097374F }; /* * PAL/SECAM RGB */ const float RGBColorSystem::PALSECAMRGB_x[ 3 ] = { 0.648431F, 0.311424F, 0.155886F }; const float RGBColorSystem::PALSECAMRGB_y[ 3 ] = { 0.330856F, 0.599693F, 0.066044F }; const float RGBColorSystem::PALSECAMRGB_Y[ 3 ] = { 0.232289F, 0.707805F, 0.059906F }; /* * ProPhoto RGB */ const float RGBColorSystem::ProPhotoRGB_x[ 3 ] = { 0.734700F, 0.159600F, 0.036600F }; const float RGBColorSystem::ProPhotoRGB_y[ 3 ] = { 0.265300F, 0.840400F, 0.000100F }; const float RGBColorSystem::ProPhotoRGB_Y[ 3 ] = { 0.288040F, 0.711874F, 0.000086F }; /* * SMPTE-C RGB */ const float RGBColorSystem::SMPTECRGB_x[ 3 ] = { 0.638852F, 0.331007F, 0.162897F }; const float RGBColorSystem::SMPTECRGB_y[ 3 ] = { 0.340194F, 0.592082F, 0.079001F }; const float RGBColorSystem::SMPTECRGB_Y[ 3 ] = { 0.221685F, 0.703264F, 0.075052F }; /* * Wide Gamut RGB */ const float RGBColorSystem::WideGamutRGB_x[ 3 ] = { 0.735000F, 0.115000F, 0.157000F }; const float RGBColorSystem::WideGamutRGB_y[ 3 ] = { 0.265000F, 0.826000F, 0.018000F }; const float RGBColorSystem::WideGamutRGB_Y[ 3 ] = { 0.258187F, 0.724938F, 0.016875F }; #endif // __PCL_WITH_STANDARD_RGB_WORKING_SPACES // ---------------------------------------------------------------------------- #define M11 M[0] #define M12 M[1] #define M13 M[2] #define M21 M[3] #define M22 M[4] #define M23 M[5] #define M31 M[6] #define M32 M[7] #define M33 M[8] #define M11_ M_[0] #define M12_ M_[1] #define M13_ M_[2] #define M21_ M_[3] #define M22_ M_[4] #define M23_ M_[5] #define M31_ M_[6] #define M32_ M_[7] #define M33_ M_[8] static Vector SetupMatrix( const FVector& x, const FVector& y, const FVector& Y ) { if ( x.Length() != 3 || y.Length() != 3 || Y.Length() != 3 ) throw Error( "Invalid vector length in RGB working color space initialization." ); if ( 1 + x[0] == 1 || 1 + x[1] == 1 || 1 + x[2] == 1 || 1 + y[0] == 1 || 1 + y[1] == 1 || 1 + y[2] == 1 ) throw Error( "Invalid chromaticity coordinates in RGB working color space initialization." ); if ( 1 + Y.Sum() == 1 ) throw Error( "Invalid luminance coefficients in RGB working color space initialization." ); Vector M( 9 ); M11 = Y[0]*x[0]/y[0]; M12 = Y[1]*x[1]/y[1]; M13 = Y[2]*x[2]/y[2]; M21 = Y[0]; M22 = Y[1]; M23 = Y[2]; M31 = Y[0]*(1 - x[0] - y[0])/y[0]; M32 = Y[1]*(1 - x[1] - y[1])/y[1]; M33 = Y[2]*(1 - x[2] - y[2])/y[2]; return M; } static Vector InverseMatrix( const Vector& M ) { // Determinant double d1 = M22*M33 - M23*M32; double d2 = M23*M31 - M21*M33; double d3 = M21*M32 - M22*M31; double d = M11*d1 + M12*d2 + M13*d3; if ( 1 + d == 1 ) throw Error( "Singular matrix in RGB working color space initialization." ); Vector M_( 9 ); M11_ = d1/d; M12_ = (M32*M13 - M33*M12)/d; M13_ = (M12*M23 - M13*M22)/d; M21_ = d2/d; M22_ = (M33*M11 - M31*M13)/d; M23_ = (M13*M21 - M11*M23)/d; M31_ = d3/d; M32_ = (M31*M12 - M32*M11)/d; M33_ = (M11*M22 - M12*M21)/d; return M_; } // ---------------------------------------------------------------------------- RGBColorSystem::Data::Data( float a_gamma, bool a_issRGB, const FVector& a_x, const FVector& a_y, const FVector& a_Y ) : ReferenceCounter(), gamma( a_gamma ), issRGB( a_issRGB ), isLinear( !issRGB && gamma == 1 ), x( a_x ), y( a_y ), Y( a_Y ) { Initialize(); } RGBColorSystem::Data::Data( const RGBColorSystem::Data& data ) : ReferenceCounter(), gamma( data.gamma ), issRGB( data.issRGB ), isLinear( data.isLinear ), x( data.x ), y( data.y ), Y( data.Y ), M( data.M ), M_( data.M_ ), mX( data.mX ), mZ( data.mZ ), abOffset( data.abOffset ), abDelta( data.abDelta ), cDelta( data.cDelta ) { } bool RGBColorSystem::Data::ValidateParameters( const FVector& x, const FVector& y, const FVector& Y ) { try { volatile Vector M_ = InverseMatrix( SetupMatrix( x, y, Y ) ); return true; } catch ( ... ) { return false; } } void RGBColorSystem::Data::Initialize() { /* * Normalize luminance coefficients */ double s = Y.Sum(); if ( 1 + s == 1 ) throw Error( "Invalid luminance coefficients in RGB working color space initialization." ); Y /= s; /* * RGB -> XYZ transformation matrix M */ M = SetupMatrix( x, y, Y ); /* * CIE X and CIE Z normalization coefficients */ mX = M11 + M12 + M13; mZ = M31 + M32 + M33; /* * XYZ -> RGB inverse matrix M_ */ M_ = InverseMatrix( M ); /* * Inverse gamma */ if ( 1 + gamma == 1 || gamma < 0 ) throw Error( "Invalid gamma value in RGB working color space initialization." ); gammaInv = 1/gamma; /* * Find normalization coefficients for CIE a, b, c channels * * The idea here is to maximize dynamic range usage for each channel * (coding efficiency) while ensuring that they will be constrained to the * nominal range [0,1]. */ sample minab = 100, maxab = -100, maxc = -100; int minabR = 0, minabG = 0, minabB = 0; int maxabR = 0, maxabG = 0, maxabB = 0; int maxcR = 0, maxcG = 0, maxcB = 0; for ( int ri = 0; ri < 10; ++ri ) { sample R = sample( ri/9.0 ); for ( int gi = 0; gi < 10; ++gi ) { sample G = sample( gi/9.0 ); for ( int bi = 0; bi < 10; ++bi ) { sample B = sample( bi/9.0 ); sample X, Y, Z; RGBToCIEXYZ( X, Y, Z, R, G, B ); RGBColorSystem::XYZLab( X ); RGBColorSystem::XYZLab( Y ); RGBColorSystem::XYZLab( Z ); sample a = 5*(X - Y); sample b = 2*(Y - Z); sample c = Sqrt( a*a + b*b ); sample mn = Min( a, b ); sample mx = Max( a, b ); if ( mn < minab ) { minab = mn; minabR = ri; minabG = gi; minabB = bi; } if ( mx > maxab ) { maxab = mx; maxabR = ri; maxabG = gi; maxabB = bi; } if ( c > maxc ) { maxc = c; maxcR = ri; maxcG = gi; maxcB = bi; } } } } sample R0, R1, G0, G1, B0, B1; R0 = Max( 0, minabR-1 )/9.0; R1 = Min( 9, minabR+1 )/9.0; G0 = Max( 0, minabG-1 )/9.0; G1 = Min( 9, minabG+1 )/9.0; B0 = Max( 0, minabB-1 )/9.0; B1 = Min( 9, minabB+1 )/9.0; for ( sample R = R0; R < R1; R += 0.01 ) for ( sample G = G0; G < G1; G += 0.01 ) for ( sample B = B0; B < B1; B += 0.01 ) { sample X, Y, Z; RGBToCIEXYZ( X, Y, Z, R, G, B ); RGBColorSystem::XYZLab( X ); RGBColorSystem::XYZLab( Y ); RGBColorSystem::XYZLab( Z ); sample mn = Min( 5*(X - Y), 2*(Y - Z) ); if ( mn < minab ) minab = mn; } R0 = Max( 0, maxabR-1 )/9.0; R1 = Min( 9, maxabR+1 )/9.0; G0 = Max( 0, maxabG-1 )/9.0; G1 = Min( 9, maxabG+1 )/9.0; B0 = Max( 0, maxabB-1 )/9.0; B1 = Min( 9, maxabB+1 )/9.0; for ( sample R = R0; R < R1; R += 0.01 ) for ( sample G = G0; G < G1; G += 0.01 ) for ( sample B = B0; B < B1; B += 0.01 ) { sample X, Y, Z; RGBToCIEXYZ( X, Y, Z, R, G, B ); RGBColorSystem::XYZLab( X ); RGBColorSystem::XYZLab( Y ); RGBColorSystem::XYZLab( Z ); sample mx = Max( 5*(X - Y), 2*(Y - Z) ); if ( mx > maxab ) maxab = mx; } R0 = Max( 0, maxcR-1 )/9.0; R1 = Min( 9, maxcR+1 )/9.0; G0 = Max( 0, maxcG-1 )/9.0; G1 = Min( 9, maxcG+1 )/9.0; B0 = Max( 0, maxcB-1 )/9.0; B1 = Min( 9, maxcB+1 )/9.0; for ( sample R = R0; R < R1; R += 0.01 ) for ( sample G = G0; G < G1; G += 0.01 ) for ( sample B = B0; B < B1; B += 0.01 ) { sample X, Y, Z; RGBToCIEXYZ( X, Y, Z, R, G, B ); RGBColorSystem::XYZLab( X ); RGBColorSystem::XYZLab( Y ); RGBColorSystem::XYZLab( Z ); sample a = 5*(X - Y); sample b = 2*(Y - Z); sample c = Sqrt( a*a + b*b ); if ( c > maxc ) maxc = c; } abOffset = -minab + 0.05; abDelta = maxab - minab + 0.1; cDelta = maxc + 0.05; } // ---------------------------------------------------------------------------- } // pcl