/// <summary> /// Convert a linear sRGB color to an sRGB color /// </summary> public static tMat3x3 CalcColorSpaceConversion_RGB_to_XYZ(Chromaticities chromaticities) { return(CalcColorSpaceConversion_RGB_to_XYZ( new tVec2(chromaticities.RedX, chromaticities.RedY), new tVec2(chromaticities.GreenX, chromaticities.GreenY), new tVec2(chromaticities.BlueX, chromaticities.BlueY), new tVec2(chromaticities.WhiteX, chromaticities.WhiteY))); }
/// <summary> /// Attempts to handle an ICC profile by name /// </summary> /// <param name="_ProfilName"></param> /// <returns>True if the profile was recognized</returns> protected bool HandleICCProfileString( string _ProfilName ) { if ( _ProfilName.IndexOf( "sRGB IEC61966-2.1" ) != -1 ) { m_Chromaticities = Chromaticities.sRGB; return true; } else if ( _ProfilName.IndexOf( "Adobe RGB (1998)" ) != -1 ) { m_Chromaticities = Chromaticities.AdobeRGB_D65; return true; } else if ( _ProfilName.IndexOf( "ProPhoto" ) != -1 ) { m_Chromaticities = Chromaticities.ProPhoto; return true; } return false; }
private bool Equals( Chromaticities other ) { return Equals( R, other.R ) && Equals( G, other.G ) && Equals( B, other.B ) && Equals( W, other.W ); }
/// <summary> /// Build from a standard profile /// </summary> /// <param name="_Profile"></param> public ColorProfile( STANDARD_PROFILE _Profile ) { switch ( _Profile ) { case STANDARD_PROFILE.LINEAR: m_Chromaticities = Chromaticities.sRGB; m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; break; case STANDARD_PROFILE.sRGB: m_Chromaticities = Chromaticities.sRGB; m_GammaCurve = GAMMA_CURVE.sRGB; m_Gamma = GAMMA_EXPONENT_sRGB; break; case STANDARD_PROFILE.ADOBE_RGB_D50: m_Chromaticities = Chromaticities.AdobeRGB_D50; m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = GAMMA_EXPONENT_ADOBE; break; case STANDARD_PROFILE.ADOBE_RGB_D65: m_Chromaticities = Chromaticities.AdobeRGB_D65; m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = GAMMA_EXPONENT_ADOBE; break; case STANDARD_PROFILE.PRO_PHOTO: m_Chromaticities = Chromaticities.ProPhoto; m_GammaCurve = GAMMA_CURVE.PRO_PHOTO; m_Gamma = GAMMA_EXPONENT_PRO_PHOTO; break; case STANDARD_PROFILE.RADIANCE: m_Chromaticities = Chromaticities.Radiance; m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; break; default: throw new Exception( "Unsupported standard profile!" ); } BuildTransformFromChroma( true ); }
/// <summary> /// Attempts to handle a color profile from the EXIF ColorSpace tag /// </summary> /// <param name="_ColorSpace"></param> /// <returns>True if the profile was recognized</returns> protected bool HandleEXIFColorSpace( int _ColorSpace ) { switch ( _ColorSpace ) { case 1: m_Chromaticities = Chromaticities.sRGB; // This is definitely sRGB return true; // We now know the profile ! case 2: m_Chromaticities = Chromaticities.AdobeRGB_D65; // This is not official but sometimes it's AdobeRGB return true; // We now know the profile ! } return false; }
protected void EnumerateMetaDataPNG( BitmapMetadata _MetaData, out bool _bProfileFound, out bool _bGammaWasSpecified ) { bool bGammaWasSpecified = false; bool bProfileFound = false; EnumerateMetaData( _MetaData, // Read chromaticities new MetaDataProcessor( "/cHRM", ( object v ) => { BitmapMetadata ChromaData = v as BitmapMetadata; Chromaticities TempChroma = Chromaticities.Empty; EnumerateMetaData( ChromaData, new MetaDataProcessor( "/RedX", ( object v2 ) => { TempChroma.R.x = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/RedY", ( object v2 ) => { TempChroma.R.y = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/GreenX", ( object v2 ) => { TempChroma.G.x = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/GreenY", ( object v2 ) => { TempChroma.G.y = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/BlueX", ( object v2 ) => { TempChroma.B.x = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/BlueY", ( object v2 ) => { TempChroma.B.y = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/WhitePointX", ( object v2 ) => { TempChroma.W.x = 0.00001f * (uint) v2; } ), new MetaDataProcessor( "/WhitePointY", ( object v2 ) => { TempChroma.W.y = 0.00001f * (uint) v2; } ) ); if ( TempChroma.RecognizedChromaticity != STANDARD_PROFILE.INVALID ) { // Assign new chroma values m_Chromaticities = TempChroma; bProfileFound = true; } } ), // Read gamma new MetaDataProcessor( "/gAMA/ImageGamma", ( object v ) => { m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f / (0.00001f * (uint) v); bGammaWasSpecified = true; } ), // Read explicit sRGB new MetaDataProcessor( "/sRGB/RenderingIntent", ( object v ) => { m_Chromaticities = Chromaticities.sRGB; bProfileFound = true; bGammaWasSpecified = false; } ), // Read string profile from iTXT new MetaDataProcessor( "/iTXt/TextEntry", ( object v ) => { if ( bProfileFound ) return; // No need... // Hack content ! string XMLContent = v as string; string ICCProfile = FindAttribute( XMLContent, "photoshop:ICCProfile" ); if ( ICCProfile != null && (bProfileFound = HandleICCProfileString( ICCProfile )) ) return; string ColorSpace = FindAttribute( XMLContent, "exif:ColorSpace" ); if ( ColorSpace != null ) bProfileFound = HandleEXIFColorSpace( ColorSpace ); } ) ); _bGammaWasSpecified = bGammaWasSpecified; _bProfileFound = bProfileFound; }
/// <summary> /// Creates a color profile from chromaticities /// </summary> /// <param name="_Chromaticities">The chromaticities for this profile</param> /// <param name="_GammaCurve">The type of gamma curve to use</param> /// <param name="_Gamma">The gamma power</param> public ColorProfile( Chromaticities _Chromaticities, GAMMA_CURVE _GammaCurve, float _Gamma ) { m_Chromaticities = _Chromaticities; m_GammaCurve = _GammaCurve; m_Gamma = _Gamma; BuildTransformFromChroma( true ); }
/// <summary> /// Creates the color profile from metadata embedded in the image file /// </summary> /// <param name="_MetaData"></param> /// <param name="_FileType"></param> public ColorProfile( BitmapMetadata _MetaData, Bitmap.FILE_TYPE _FileType ) { string MetaDump = _MetaData != null ? DumpMetaData( _MetaData ) : null; bool bGammaFoundInFile = false; switch ( _FileType ) { case Bitmap.FILE_TYPE.JPEG: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 2.2f; // JPG uses a 2.2 gamma by default m_Chromaticities = Chromaticities.sRGB; // Default for JPEGs is sRGB EnumerateMetaDataJPG( _MetaData, out m_bProfileFoundInFile, out bGammaFoundInFile ); if ( !m_bProfileFoundInFile && !bGammaFoundInFile ) bGammaFoundInFile = true; // Unless specified otherwise, we override the gamma no matter what since JPEGs use a 2.2 gamma by default anyway break; case Bitmap.FILE_TYPE.PNG: m_GammaCurve = GAMMA_CURVE.sRGB; m_Gamma = GAMMA_EXPONENT_sRGB; m_Chromaticities = Chromaticities.sRGB; // Default for PNGs is standard sRGB EnumerateMetaDataPNG( _MetaData, out m_bProfileFoundInFile, out bGammaFoundInFile ); break; case Bitmap.FILE_TYPE.TIFF: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; // Linear gamma by default m_Chromaticities = Chromaticities.sRGB; // Default for TIFFs is sRGB EnumerateMetaDataTIFF( _MetaData, out m_bProfileFoundInFile, out bGammaFoundInFile ); break; case Bitmap.FILE_TYPE.GIF: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; m_Chromaticities = Chromaticities.sRGB; // Default for GIFs is standard sRGB with no gamma break; case Bitmap.FILE_TYPE.BMP: // BMP Don't have metadata! m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; m_Chromaticities = Chromaticities.sRGB; // Default for BMPs is standard sRGB with no gamma break; case Bitmap.FILE_TYPE.CRW: // Raw files have no correction case Bitmap.FILE_TYPE.CR2: case Bitmap.FILE_TYPE.DNG: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; m_Chromaticities = Chromaticities.sRGB; // Default for BMPs is standard sRGB with no gamma break; } BuildTransformFromChroma( bGammaFoundInFile ); }