Beispiel #1
0
        public void             UpdateBitmap()
        {
            if (m_Bitmap == null)
            {
                return;
            }

            int W = m_Bitmap.Width;
            int H = m_Bitmap.Height;

            using (Graphics G = Graphics.FromImage(m_Bitmap))
            {
                using (SolidBrush B = new SolidBrush(Color.Black))
                    G.FillRectangle(B, 0, 0, W, H);

                if (m_CameraCalibration != null && m_Thumbnail != null)
                {
                    // Draw thumbnail
                    RectangleF ClientRect = ImageClientRect();
                    G.DrawImage(m_Thumbnail, ClientRect, new RectangleF(0, 0, m_Thumbnail.Width, m_Thumbnail.Height), GraphicsUnit.Pixel);

                    // Draw probe measurement circles if available
                    for (int ProbeIndex = 0; ProbeIndex < 6; ProbeIndex++)
                    {
                        CameraCalibration.Probe P = m_CameraCalibration.m_Reflectances[ProbeIndex];
                        if (!P.m_MeasurementDiscIsAvailable)
                        {
                            continue;
                        }

                        PointF ClientPos    = ImageUV2Client(new PointF(P.m_MeasurementCenterX, P.m_MeasurementCenterY));
                        float  ClientRadius = ClientRect.Width * P.m_MeasurementRadius;

//						G.DrawEllipse( m_PenProbeShadow, ClientPos.X - ClientRadius, ClientPos.Y - ClientRadius, 2*ClientRadius, 2*ClientRadius );
                        G.DrawEllipse(P.m_IsAvailable ? m_PenProbe : m_PenProbeInvalid, ClientPos.X - ClientRadius, ClientPos.Y - ClientRadius, 2 * ClientRadius, 2 * ClientRadius);
                    }
                }
            }

            Invalidate();
        }
Beispiel #2
0
        /// <summary>
        /// Prepares the interpolated calibration table to process the pixels in an image shot with the specified shot infos
        /// </summary>
        /// <param name="_ISOSpeed"></param>
        /// <param name="_ShutterSpeed"></param>
        /// <param name="_Aperture"></param>
        public void     PrepareCalibrationFor(float _ISOSpeed, float _ShutterSpeed, float _Aperture)
        {
            if (m_RootNode == null)
            {
                throw new Exception("Calibration grid hasn't been built: did you provide a valid database path? Does the path contain camera calibration data?");
            }

            if (IsPreparedFor(_ISOSpeed, _ShutterSpeed, _Aperture))
            {
                return;                 // Already prepared!
            }
            //////////////////////////////////////////////////////////////////////////
            // Find the 8 nodes encompassing our values
            // I'm making the delicate assumption that, although the starting node is chosen on the
            //	condition its EV values are strictly inferior to the target we're looking for, all
            //	neighbor nodes should satisfy the condition they're properly placed.
            //
            // This is true for the direct neighbors +X, +Y, +Z that are immediately above target values
            //	but for example, neighbor (+X +Y) may have a very bad aperture value (Z) that may be
            //	above the target aperture...
            //
            // Let's hope the user won't provide too fancy calibrations...
            // (anyway, interpolants are clamped in [0,1] so there's no risk of overshooting)
            //
            ImageUtility.float3 EV;
            GridNode.Convert2EV(_ISOSpeed, _ShutterSpeed, _Aperture, out EV.x, out EV.y, out EV.z);

            // Find the start node
            GridNode StartNode = FindStartNode(EV.x, EV.y, EV.z);

            m_InterpolationStartNode = StartNode;

            // Build the 8 grid nodes from it
            GridNode[,,]    Grid = new GridNode[2, 2, 2];
            Grid[0, 0, 0]        = StartNode;
            Grid[1, 0, 0]        = StartNode.m_Neighbors[0][1] != null ? StartNode.m_Neighbors[0][1] : StartNode;               // +X
            Grid[0, 1, 0]        = StartNode.m_Neighbors[1][1] != null ? StartNode.m_Neighbors[1][1] : StartNode;               // +Y
            Grid[0, 0, 1]        = StartNode.m_Neighbors[2][1] != null ? StartNode.m_Neighbors[2][1] : StartNode;               // +Z
            Grid[1, 1, 0]        = Grid[1, 0, 0].m_Neighbors[1][1] != null ? Grid[1, 0, 0].m_Neighbors[1][1] : Grid[1, 0, 0];   // +X +Y
            Grid[0, 1, 1]        = Grid[0, 1, 0].m_Neighbors[2][1] != null ? Grid[0, 1, 0].m_Neighbors[2][1] : Grid[0, 1, 0];   // +Y +Z
            Grid[1, 0, 1]        = Grid[0, 0, 1].m_Neighbors[0][1] != null ? Grid[0, 0, 1].m_Neighbors[0][1] : Grid[0, 0, 1];   // +X +Z
            Grid[1, 1, 1]        = Grid[1, 1, 0].m_Neighbors[2][1] != null ? Grid[1, 1, 0].m_Neighbors[2][1] : Grid[1, 1, 0];   // +X +Y +Z

            //////////////////////////////////////////////////////////////////////////
            // Create the successive interpolants for trilinear interpolation
            //
            // Assume we interpolate on X first (ISO speed), so we need 4 distinct values
            ImageUtility.float4 tX = new ImageUtility.float4(
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 0, 0].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 0, 0].m_EV_ISOSpeed - Grid[0, 0, 0].m_EV_ISOSpeed))),                              // Y=0 Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 1, 0].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 1, 0].m_EV_ISOSpeed - Grid[0, 1, 0].m_EV_ISOSpeed))),                              // Y=1 Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 0, 1].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 0, 1].m_EV_ISOSpeed - Grid[0, 0, 1].m_EV_ISOSpeed))),                              // Y=0 Z=1
                Math.Max(0.0f, Math.Min(1.0f, (EV.x - Grid[0, 1, 1].m_EV_ISOSpeed) / Math.Max(1e-6f, Grid[1, 1, 1].m_EV_ISOSpeed - Grid[0, 1, 1].m_EV_ISOSpeed)))                               // Y=1 Z=1
                );
            ImageUtility.float4 rX = new ImageUtility.float4(1.0f - tX.x, 1.0f - tX.y, 1.0f - tX.z, 1.0f - tX.w);

            // Compute the 4 interpolated shutter speeds & apertures
            ImageUtility.float4 ShutterSpeedsX = new ImageUtility.float4(
                rX.x * Grid[0, 0, 0].m_EV_ShutterSpeed + tX.x * Grid[1, 0, 0].m_EV_ShutterSpeed,                        // Y=0 Z=0
                rX.y * Grid[0, 1, 0].m_EV_ShutterSpeed + tX.y * Grid[1, 1, 0].m_EV_ShutterSpeed,                        // Y=1 Z=0
                rX.z * Grid[0, 0, 1].m_EV_ShutterSpeed + tX.z * Grid[1, 0, 1].m_EV_ShutterSpeed,                        // Y=0 Z=1
                rX.w * Grid[0, 1, 1].m_EV_ShutterSpeed + tX.w * Grid[1, 1, 1].m_EV_ShutterSpeed                         // Y=1 Z=1
                );
            ImageUtility.float4 AperturesX = new ImageUtility.float4(
                rX.x * Grid[0, 0, 0].m_EV_Aperture + tX.x * Grid[1, 0, 0].m_EV_Aperture,                                        // Y=0 Z=0
                rX.y * Grid[0, 1, 0].m_EV_Aperture + tX.y * Grid[1, 1, 0].m_EV_Aperture,                                        // Y=1 Z=0
                rX.z * Grid[0, 0, 1].m_EV_Aperture + tX.z * Grid[1, 0, 1].m_EV_Aperture,                                        // Y=0 Z=1
                rX.w * Grid[0, 1, 1].m_EV_Aperture + tX.w * Grid[1, 1, 1].m_EV_Aperture                                         // Y=1 Z=1
                );

            // Next we interpolate on Y (Shutter speed), so we need 2 distinct values
            ImageUtility.float2 tY = new ImageUtility.float2(
                Math.Max(0.0f, Math.Min(1.0f, (EV.y - ShutterSpeedsX.x) / Math.Max(1e-6f, ShutterSpeedsX.y - ShutterSpeedsX.x))),                               // Z=0
                Math.Max(0.0f, Math.Min(1.0f, (EV.y - ShutterSpeedsX.z) / Math.Max(1e-6f, ShutterSpeedsX.w - ShutterSpeedsX.z)))                                // Z=1
                );
            ImageUtility.float2 rY = new ImageUtility.float2(1.0f - tY.x, 1.0f - tY.y);

            // Compute the 2 apertures
            ImageUtility.float2 AperturesY = new ImageUtility.float2(
                rY.x * AperturesX.x + tY.x * AperturesX.y,
                rY.y * AperturesX.z + tY.y * AperturesX.w
                );

            // Finally, we interpolate on Z (Aperture), we need only 1 single value
            float tZ = Math.Max(0.0f, Math.Min(1.0f, (EV.z - AperturesY.x) / Math.Max(1e-6f, AperturesY.y - AperturesY.x)));
            float rZ = 1.0f - tZ;


            //////////////////////////////////////////////////////////////////////////
            // Create the special camera calibration that is the result of the interpolation of the 8 nearest ones in the grid
            m_InterpolatedCalibration = new CameraCalibration();
            m_InterpolatedCalibration.m_CameraShotInfos.m_ISOSpeed     = _ISOSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_ShutterSpeed = _ShutterSpeed;
            m_InterpolatedCalibration.m_CameraShotInfos.m_Aperture     = _Aperture;

            for (int ProbeIndex = 0; ProbeIndex < REQUIRED_PROBES_COUNT; ProbeIndex++)
            {
                CameraCalibration.Probe TargetProbe = m_InterpolatedCalibration.m_Reflectances[ProbeIndex];

                float L000 = Grid[0, 0, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L100 = Grid[1, 0, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L010 = Grid[0, 1, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L110 = Grid[1, 1, 0].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L001 = Grid[0, 0, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L101 = Grid[1, 0, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L011 = Grid[0, 1, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;
                float L111 = Grid[1, 1, 1].m_CameraCalibration.m_Reflectances[ProbeIndex].m_LuminanceMeasured;

                // Interpolate on X (ISO speed)
                float L00 = rX.x * L000 + tX.x * L100;
                float L10 = rX.y * L010 + tX.y * L110;
                float L01 = rX.z * L001 + tX.z * L101;
                float L11 = rX.w * L011 + tX.w * L111;

                // Interpolate on Y (shutter speed)
                float L0 = rY.x * L00 + tY.x * L10;
                float L1 = rY.y * L01 + tY.y * L11;

                // Interpolate on Z (aperture)
                float L = rZ * L0 + tZ * L1;

                TargetProbe.m_IsAvailable       = true;
                TargetProbe.m_LuminanceMeasured = L;
            }

            // Fill missing values
            m_InterpolatedCalibration.UpdateAllLuminances();

            // Reset white reflectance reference because it was set for another setup
            WhiteReflectanceReference = new ImageUtility.float3(0, 0, -1);
        }