protected void TestConvertLDR2HDR( System.IO.FileInfo[] _LDRImageFileNames, bool _responseCurveOnly, bool _RAW ) { try { // Load the LDR images List< ImageFile > LDRImages = new List< ImageFile >(); foreach ( System.IO.FileInfo LDRImageFileName in _LDRImageFileNames ) LDRImages.Add( new ImageFile( LDRImageFileName ) ); // Retrieve the shutter speeds List< float > shutterSpeeds = new List< float >(); foreach ( ImageFile LDRImage in LDRImages ) { shutterSpeeds.Add( LDRImage.Metadata.ExposureTime ); } // Retrieve filter type Bitmap.FILTER_TYPE filterType = Bitmap.FILTER_TYPE.NONE; if ( radioButtonFilterNone.Checked ) { filterType = Bitmap.FILTER_TYPE.NONE; } else if ( radioButtonFilterGaussian.Checked ) { filterType = Bitmap.FILTER_TYPE.SMOOTHING_GAUSSIAN; } else if ( radioButtonFilterGaussian2Pass.Checked ) { filterType = Bitmap.FILTER_TYPE.SMOOTHING_GAUSSIAN_2_PASSES; } else if ( radioButtonFilterTent.Checked ) { filterType = Bitmap.FILTER_TYPE.SMOOTHING_TENT; } else if ( radioButtonFilterCurveFitting.Checked ) { filterType = Bitmap.FILTER_TYPE.GAUSSIAN_PLUS_CURVE_FITTING; } // Check EXR save is working! // ImageFile pipo = new ImageFile(); // pipo.ConvertFrom( LDRImages[0], ImageFile.PIXEL_FORMAT.RGB32F ); // pipo.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromJPG\Result.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_DEFAULT ); // Check bitmap->tone mapped image file is working // { // Bitmap tempBitmap = new Bitmap(); // List< float > responseCurve = new List< float >( 256 ); // for ( int i=0; i < 256; i++ ) // responseCurve.Add( (float) (Math.Log( (1+i) / 256.0 ) / Math.Log(2)) ); // tempBitmap.LDR2HDR( new ImageFile[] { LDRImages[4] }, new float[] { 1.0f }, responseCurve, 1.0f ); // // ImageFile tempHDR = new ImageFile(); // tempBitmap.ToImageFile( tempHDR, new ColorProfile( ColorProfile.STANDARD_PROFILE.LINEAR ) ); // // ImageFile tempToneMappedHDR = new ImageFile(); // tempToneMappedHDR.ToneMapFrom( tempHDR,( float3 _HDRColor, ref float3 _LDRColor ) => { // // Just do gamma un-correction, don't care about actual HDR range... // _LDRColor.x = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.x ), 1.0f / 2.2f ); // Here we need to clamp negative values that we sometimes get in EXR format // _LDRColor.y = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.y ), 1.0f / 2.2f ); // (must be coming from the log encoding I suppose) // _LDRColor.z = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.z ), 1.0f / 2.2f ); // } ); // // panel1.Bitmap = tempToneMappedHDR.AsBitmap; // return; // } ////////////////////////////////////////////////////////////////////////////////////////////// // Build the HDR device-independent bitmap // uint bitsPerPixel = _RAW ? 12U : 8U; uint bitsPerPixel = _RAW ? 8U : 8U; float quality = _RAW ? 3.0f : 3.0f; Bitmap.HDRParms parms = new Bitmap.HDRParms() { _inputBitsPerComponent = bitsPerPixel, _luminanceFactor = 1.0f, _curveSmoothnessConstraint = 1.0f, _quality = quality, _responseCurveFilterType = filterType }; ImageUtility.Bitmap HDRImage = new ImageUtility.Bitmap(); // HDRImage.LDR2HDR( LDRImages.ToArray(), shutterSpeeds.ToArray(), parms ); // Compute response curve List< float > responseCurve = new List< float >(); Bitmap.ComputeCameraResponseCurve( LDRImages.ToArray(), shutterSpeeds.ToArray(), parms._inputBitsPerComponent, parms._curveSmoothnessConstraint, parms._quality, responseCurve ); // Filter List< float > responseCurve_filtered = new List< float >(); // Bitmap.FilterCameraResponseCurve( responseCurve, responseCurve_filtered, Bitmap.FILTER_TYPE.CURVE_FITTING ); Bitmap.FilterCameraResponseCurve( responseCurve, responseCurve_filtered, filterType ); // using ( System.IO.FileStream S = new System.IO.FileInfo( "../../responseCurve3.float" ).Create() ) // using ( System.IO.BinaryWriter W = new System.IO.BinaryWriter( S ) ) { // for ( int i=0; i < 256; i++ ) // W.Write( responseCurve[i] ); // } // Write info string info = "Exposures:\r\n"; foreach ( float shutterSpeed in shutterSpeeds ) info += " " + shutterSpeed + "s + "; info += "\r\nLog2 exposures (EV):\r\n"; foreach ( float shutterSpeed in shutterSpeeds ) info += " " + (float) (Math.Log( shutterSpeed ) / Math.Log(2)) + "EV + "; info += "\r\n\r\n"; if ( _responseCurveOnly ) { ////////////////////////////////////////////////////////////////////////////////////////////// // Render the response curve as a graph ImageFile tempCurveBitmap = new ImageFile( 1024, 768, ImageFile.PIXEL_FORMAT.RGB8, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); int responseCurveSizeMax = responseCurve.Count-1; float2 rangeX = new float2( 0, responseCurveSizeMax+1 ); float2 rangeY = new float2( 0, 500 ); tempCurveBitmap.Clear( new float4( 1, 1, 1, 1 ) ); // tempCurveBitmap.PlotGraphAutoRangeY( red, rangeX, ref rangeY, ( float x ) => { tempCurveBitmap.PlotGraph( red, rangeX, rangeY, ( float x ) => { int i0 = (int) Math.Min( responseCurveSizeMax, Math.Floor( x ) ); int i1 = (int) Math.Min( responseCurveSizeMax, i0+1 ); float g0 = responseCurve[i0]; float g1 = responseCurve[i1]; float t = x - i0; // return g0 + (g1-g0) * t; return (float) Math.Pow( 2.0f, g0 + (g1-g0) * t ); } ); tempCurveBitmap.PlotGraph( blue, rangeX, rangeY, ( float x ) => { int i0 = (int) Math.Min( responseCurveSizeMax, Math.Floor( x ) ); int i1 = (int) Math.Min( responseCurveSizeMax, i0+1 ); float g0 = responseCurve_filtered[i0]; float g1 = responseCurve_filtered[i1]; float t = x - i0; // return g0 + (g1-g0) * t; return (float) Math.Pow( 2.0f, g0 + (g1-g0) * t ); } ); // tempCurveBitmap.PlotAxes( black, rangeX, rangeY, 8, 2 ); info += "• Linear range Y = [" + rangeY.x + ", " + rangeY.y + "]\r\n"; rangeY = new float2( -4, 4 ); tempCurveBitmap.PlotLogGraphAutoRangeY( black, rangeX, ref rangeY, ( float x ) => { // tempCurveBitmap.PlotLogGraph( black, rangeX, rangeY, ( float x ) => { int i0 = (int) Math.Min( responseCurveSizeMax, Math.Floor( x ) ); int i1 = (int) Math.Min( responseCurveSizeMax, i0+1 ); float g0 = responseCurve[i0]; float g1 = responseCurve[i1]; float t = x - i0; // return g0 + (g1-g0) * t; return (float) Math.Pow( 2.0f, g0 + (g1-g0) * t ); }, -1.0f, 2.0f ); tempCurveBitmap.PlotLogGraph( blue, rangeX, rangeY, ( float x ) => { // tempCurveBitmap.PlotLogGraph( black, rangeX, rangeY, ( float x ) => { int i0 = (int) Math.Min( responseCurveSizeMax, Math.Floor( x ) ); int i1 = (int) Math.Min( responseCurveSizeMax, i0+1 ); float g0 = responseCurve_filtered[i0]; float g1 = responseCurve_filtered[i1]; float t = x - i0; // return g0 + (g1-g0) * t; return (float) Math.Pow( 2.0f, g0 + (g1-g0) * t ); }, -1.0f, 2.0f ); tempCurveBitmap.PlotLogAxes( black, rangeX, rangeY, -16, 2 ); info += "• Log2 range Y = [" + rangeY.x + ", " + rangeY.y + "]\r\n"; panelOutputHDR.Bitmap = tempCurveBitmap.AsBitmap; } else { ////////////////////////////////////////////////////////////////////////////////////////////// // Recompose the HDR image HDRImage.LDR2HDR( LDRImages.ToArray(), shutterSpeeds.ToArray(), responseCurve_filtered, 1.0f ); // Display as a tone-mapped bitmap ImageFile tempHDR = new ImageFile(); HDRImage.ToImageFile( tempHDR, new ColorProfile( ColorProfile.STANDARD_PROFILE.LINEAR ) ); if ( _RAW ) { tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromRAW\Result.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_DEFAULT ); tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromRAW\Result_B44LC.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_B44 | ImageFile.SAVE_FLAGS.SF_EXR_LC ); tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromRAW\Result_noLZW.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_NONE ); } else { tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromJPG\Result.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_DEFAULT ); tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromJPG\Result_B44LC.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_B44 | ImageFile.SAVE_FLAGS.SF_EXR_LC ); tempHDR.Save( new System.IO.FileInfo( @"..\..\Images\Out\LDR2HDR\FromJPG\Result_noLZW.exr" ), ImageFile.FILE_FORMAT.EXR, ImageFile.SAVE_FLAGS.SF_EXR_NONE ); } ImageFile tempToneMappedHDR = new ImageFile(); tempToneMappedHDR.ToneMapFrom( tempHDR,( float3 _HDRColor, ref float3 _LDRColor ) => { // Just do gamma un-correction, don't care about actual HDR range... _LDRColor.x = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.x ), 1.0f / 2.2f ); // Here we need to clamp negative values that we sometimes get in EXR format _LDRColor.y = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.y ), 1.0f / 2.2f ); // (must be coming from the log encoding I suppose) _LDRColor.z = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.z ), 1.0f / 2.2f ); } ); panelOutputHDR.Bitmap = tempToneMappedHDR.AsBitmap; } textBoxHDR.Text = info; } catch ( Exception _e ) { MessageBox.Show( "Error: " + _e.Message ); // Show debug image // panelLoad.Bitmap = Bitmap.DEBUG.AsBitmap; } }
void TestLoadImage( LOADING_TESTS _type ) { try { switch ( _type ) { // BMP case LOADING_TESTS.BMP_RGB: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\BMP\RGB8.bmp" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; case LOADING_TESTS.BMP_RGBA: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\BMP\RGBA8.bmp" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // GIF case LOADING_TESTS.GIF_RGB8P: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\GIF\RGB8P.gif" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // JPG case LOADING_TESTS.JPEG_R8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\JPG\R8.jpg" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; case LOADING_TESTS.JPEG_RGB8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\JPG\RGB8.jpg" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\JPG\RGB8_ICC.jpg" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // PNG // 8-bits case LOADING_TESTS.PNG_R8P: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\R8P.png" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; case LOADING_TESTS.PNG_RGB8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\RGB8.png" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\RGB8_SaveforWeb.png" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; case LOADING_TESTS.PNG_RGBA8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\RGBA8.png" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\RGBA8_SaveforWeb.png" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // 16-bits case LOADING_TESTS.PNG_RGB16: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\PNG\RGB16.png" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // TGA // @TODO => Check why I can't retrieve my custom metas! case LOADING_TESTS.TGA_RGB8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TGA\RGB8.tga" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; case LOADING_TESTS.TGA_RGBA8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TGA\RGBA8.tga" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // TIFF // 8-bits case LOADING_TESTS.TIFF_RGB8: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB8.tif" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB8_ICC.tif" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // 16-bits case LOADING_TESTS.TIFF_RGB16: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB16.tif" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB16_ICC.tif" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; // RAW case LOADING_TESTS.CRW: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\CRW\CRW_7967.CRW" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7971.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7971.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7972.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7973.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7974.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7975.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7976.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7977.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7978.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7979.crw" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\LDR2HDR\FromRAW\CRW_7980.crw" ) ); panelLoad.Bitmap = m_imageFile.AsBitmap; break; default: // High-Dynamic Range Images switch ( _type ) { // HDR case LOADING_TESTS.HDR_RGBE: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\HDR\RGB32F.hdr" ) ); break; // EXR case LOADING_TESTS.EXR_RGB32F: m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\EXR\RGB32F.exr" ) ); break; // TIFF case LOADING_TESTS.TIFF_RGB16F: // 16-bits floating-point m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB16F.tif" ) ); // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB16F_ICC.tif" ) ); break; // Pom (2016-11-14) This crashes as FreeImage is not capable of reading 32-bits floating point TIFs but I think I don't care, we have enough formats! // case LOADING_TESTS.TIFF_RGB32F: // // 32-bits floating-point // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB32F.tif" ) ); // // m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\TIFF\RGB32F_ICC.tif" ) ); // break; default: throw new Exception( "Unhandled format!" ); } ImageFile tempLDR = new ImageFile(); tempLDR.ToneMapFrom( m_imageFile, ( float3 _HDRColor, ref float3 _LDRColor ) => { // Do nothing (linear space to gamma space without care!) // _LDRColor = _HDRColor; // Just do gamma un-correction, don't care about actual HDR range... _LDRColor.x = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.x ), 1.0f / 2.2f ); // Here we need to clamp negative values that we sometimes get in EXR format _LDRColor.y = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.y ), 1.0f / 2.2f ); // (must be coming from the log encoding I suppose) _LDRColor.z = (float) Math.Pow( Math.Max( 0.0f, _HDRColor.z ), 1.0f / 2.2f ); } ); panelLoad.Bitmap = tempLDR.AsBitmap; break; } // Write out metadata MetaData MD = m_imageFile.Metadata; ColorProfile Profile = MD.ColorProfile; textBoxEXIF.Lines = new string[] { "File Format: " + m_imageFile.FileFormat, "Pixel Format: " + m_imageFile.PixelFormat + (m_imageFile.HasAlpha ? " (ALPHA)" : " (NO ALPHA)"), "", "Profile:", " • Chromaticities: ", " R = " + Profile.Chromas.Red.ToString(), " G = " + Profile.Chromas.Green.ToString(), " B = " + Profile.Chromas.Blue.ToString(), " W = " + Profile.Chromas.White.ToString(), " Recognized chromaticities = " + Profile.Chromas.RecognizedChromaticity, " • Gamma Curve: " + Profile.GammaCurve.ToString(), " • Gamma Exponent: " + Profile.GammaExponent.ToString(), "", "Gamma Found in File = " + MD.GammaSpecifiedInFile, "", "MetaData:", " • ISO Speed = " + (MD.ISOSpeed_isValid ? MD.ISOSpeed.ToString() : "N/A"), " • Exposure Time = " + (MD.ExposureTime_isValid? (MD.ExposureTime > 1.0f ? (MD.ExposureTime + " seconds") : ("1/" + (1.0f / MD.ExposureTime) + " seconds")) : "N/A"), " • Tv = " + (MD.Tv_isValid ? MD.Tv + " EV" : "N/A"), " • Av = " + (MD.Av_isValid ? MD.Av + " EV" : "N/A"), " • F = 1/" + (MD.FNumber_isValid ? MD.FNumber + " stops" : "N/A"), " • Focal Length = " + (MD.FocalLength_isValid ? MD.FocalLength + " mm" : "N/A"), }; } catch ( Exception _e ) { MessageBox.Show( "Error: " + _e.Message ); } }