Пример #1
0
        public DNGMatrix4x4(DNGMatrix m)
            : base(m)
        {
            // Input must be either 3x3 or 4x4.

            bool is3by3 = (m.Rows == 3 && m.Cols == 3);
            bool is4by4 = (m.Rows == 4 && m.Cols == 4);

            if (!is3by3 && !is4by4)
            {
                throw new ArgumentException("This is not a 3x3 or 4x4 Matrix");
            }

            // For 3x3 case, pad to 4x4 (equivalent 4x4 matrix).
            if (is3by3)
            {
                _rows = 4;
                _cols = 4;

                _data[0, 3] = 0.0;
                _data[1, 3] = 0.0;
                _data[2, 3] = 0.0;

                _data[3, 0] = 0.0;
                _data[3, 1] = 0.0;
                _data[3, 2] = 0.0;

                _data[3, 3] = 1.0;
            }
        }
Пример #2
0
        public static DNGMatrix operator *(DNGMatrix vec, double scale)
        {
            DNGMatrix ret = new DNGMatrix(vec);

            ret.Scale(scale);
            return(ret);
        }
Пример #3
0
        public static DNGMatrix Identity(uint size)
        {
            DNGMatrix mat = new DNGMatrix();

            mat.SetIdentity(size);
            return(mat);
        }
Пример #4
0
 public DNGMatrix4x3(DNGMatrix m)
     : base(m)
 {
     if (Rows != 4 || Cols != 3)
     {
         throw new ArgumentException("This is not a 4x3 Matrix");
     }
 }
Пример #5
0
        public DNGMatrix AsDiagonal()
        {
            DNGMatrix M = new DNGMatrix(Count, Count);

            for (uint j = 0; j < Count; j++)
            {
                M[j, j] = _data[j];
            }

            return(M);
        }
Пример #6
0
        public DNGMatrix AsColumn()
        {
            DNGMatrix M = new DNGMatrix(Count, 1);

            for (uint j = 0; j < Count; j++)
            {
                M[j, 0] = _data[j];
            }

            return(M);
        }
Пример #7
0
        public DNGMatrix(DNGMatrix aMatrix)
        {
            _rows = aMatrix.Rows;
            _cols = aMatrix.Cols;

            for (int row = 0; row < _rows; row++)
            {
                for (int col = 0; col < _cols; col++)
                {
                    _data[row, col] = aMatrix._data[row, col];
                }
            }
        }
Пример #8
0
 public DNGMatrix Invert(DNGMatrix hint)
 {
     if (Rows == Cols ||
         Rows != hint.Cols ||
         Cols != hint.Rows)
     {
         return(Invert());
     }
     else
     {
         // Use the specified hint matrix.
         return((hint * this).Invert() * hint);
     }
 }
Пример #9
0
        public DNGMatrix Transpose()
        {
            DNGMatrix B = new DNGMatrix(Cols, Rows);

            for (uint j = 0; j < B.Rows; j++)
            {
                for (uint k = 0; k < B.Cols; k++)
                {
                    B[j, k] = this[k, j];
                }
            }

            return(B);
        }
Пример #10
0
        private DNGMatrix Invert3x3()
        {
            if (Cols != 3 && Rows != 3)
            {
                throw new Exception("This only works on 3x3 matrices.");
            }

            double a00 = this[0, 0];
            double a01 = this[0, 1];
            double a02 = this[0, 2];
            double a10 = this[1, 0];
            double a11 = this[1, 1];
            double a12 = this[1, 2];
            double a20 = this[2, 0];
            double a21 = this[2, 1];
            double a22 = this[2, 2];

            double[,] temp = new double[3, 3];

            temp[0, 0] = a11 * a22 - a21 * a12;
            temp[0, 1] = a21 * a02 - a01 * a22;
            temp[0, 2] = a01 * a12 - a11 * a02;
            temp[1, 0] = a20 * a12 - a10 * a22;
            temp[1, 1] = a00 * a22 - a20 * a02;
            temp[1, 2] = a10 * a02 - a00 * a12;
            temp[2, 0] = a10 * a21 - a20 * a11;
            temp[2, 1] = a20 * a01 - a00 * a21;
            temp[2, 2] = a00 * a11 - a10 * a01;

            double det = (a00 * temp[0, 0] +
                          a01 * temp[1, 0] +
                          a02 * temp[2, 0]);

            if (Math.Abs(det) < NEAR_ZERO)
            {
                throw new Exception("The matrix determinant is too close to zero.");
            }

            DNGMatrix B = new DNGMatrix(3, 3);

            for (uint j = 0; j < 3; j++)
            {
                for (uint k = 0; k < 3; k++)
                {
                    B[j, k] = temp[j, k] / det;
                }
            }

            return(B);
        }
Пример #11
0
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (!(obj is DNGMatrix))
            {
                return(false);
            }

            DNGMatrix value = (DNGMatrix)obj;

            return(Equals(value));
        }
Пример #12
0
        public static DNGMatrix operator +(DNGMatrix a, DNGMatrix b)
        {
            if (a.Cols != b.Cols || a.Rows != b.Rows)
            {
                throw new ArgumentException("Matrices don't have the same size.");
            }

            DNGMatrix ret = new DNGMatrix(a);

            for (uint j = 0; j < ret.Rows; j++)
            {
                for (uint k = 0; k < ret.Cols; k++)
                {
                    ret[j, k] += b[j, k];
                }
            }
            return(ret);
        }
Пример #13
0
        private DNGMatrix NormalizeForwardMatrix(DNGMatrix m)
        {
            if (m == null)
            {
                return(new DNGMatrix());
            }

            if (m.NotEmpty())
            {
                DNGVector cameraOne = DNGVector.Identity(m.Cols);

                DNGVector xyz = m * cameraOne;

                m = DNGxyCoord.PCStoXYZ.AsDiagonal() *
                    (xyz.AsDiagonal().Invert()) * m;
            }
            return(m);
        }
Пример #14
0
        public bool AlmostEqual(DNGMatrix m, double slop = 1.0e-8)
        {
            if (_rows != m._rows || _cols != m._cols)
            {
                return(false);
            }

            for (uint j = 0; j < _rows; j++)
            {
                for (uint k = 0; k < _cols; k++)
                {
                    if (Math.Abs(_data[j, k] - m[j, k]) > slop)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Пример #15
0
        public bool Equals(DNGMatrix value)
        {
            if (_rows != value._rows || _cols != value._cols)
            {
                return(false);
            }

            for (int row = 0; row < _rows; row++)
            {
                for (int col = 0; col < _cols; col++)
                {
                    if (_data[row, col] != value._data[row, col])
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Пример #16
0
        public DNGColorSpace(DNGMatrix3x3 toPCS)
        {
            // The matrix values are often rounded, so adjust to
            // get them to convert device white exactly to the PCS.
            DNGVector W1 = toPCS * new DNGVector3(1.0, 1.0, 1.0);
            DNGVector W2 = DNGxyCoord.PCStoXYZ;

            double s0 = W2[0] / W1[0];
            double s1 = W2[1] / W1[1];
            double s2 = W2[2] / W1[2];

            DNGMatrix3x3 S = new DNGMatrix3x3(s0, 0, 0,
                                              0, s1, 0,
                                              0, 0, s2);

            mToPCS = S * toPCS;

            // Find reverse matrix.
            mFromPCS = mToPCS.Invert();
        }
Пример #17
0
        /// Return the XY value to use for SetWhiteXY for a given camera color
        /// space coordinate as the white point.
        /// \param neutral A camera color space value to use for white point.
        /// Components range from 0.0 to 1.0 and should be normalized such that
        /// the largest value is 1.0 .
        /// \retval White point in XY space that makes neutral map to this
        /// XY value as closely as possible.
        public DNGxyCoord NeutralToXY(DNGVector neutral)
        {
            const uint kMaxPasses = 30;

            if (fChannels == 1)
            {
                return(DNGxyCoord.PCStoXY);
            }

            DNGxyCoord last = DNGxyCoord.D50;

            for (uint pass = 0; pass < kMaxPasses; pass++)
            {
                DNGMatrix nullMat     = null;
                DNGMatrix xyzToCamera = FindXYZtoCamera(last, ref nullMat, ref nullMat, ref nullMat);

                DNGMatrix  inv  = xyzToCamera.Invert();
                DNGVector  vec  = inv * neutral;
                DNGVector3 vec3 = new DNGVector3(vec);

                DNGxyCoord next = DNGxyCoord.XYZtoXY(new DNGVector3(xyzToCamera.Invert() * neutral));

                if (Math.Abs(next.X - last.X) +
                    Math.Abs(next.Y - last.Y) < 0.0000001)
                {
                    return(next);
                }

                // If we reach the limit without converging, we are most likely
                // in a two value oscillation.  So take the average of the last
                // two estimates and give up.
                if (pass == kMaxPasses - 1)
                {
                    next.X = (last.X + next.X) * 0.5;
                    next.Y = (last.Y + next.Y) * 0.5;
                }
                last = next;
            }
            return(last);
        }
Пример #18
0
        public DNGMatrix Invert()
        {
            if (Rows < 2 || Cols < 2)
            {
                throw new Exception("Can't invert a matrix smaller than 2x2");
            }

            if (Rows == Cols)
            {
                if (Rows == 3)
                {
                    return(Invert3x3());
                }
                return(InvertNxN());
            }
            else
            {
                // Compute the pseudo inverse.
                DNGMatrix B = Transpose();
                return((B * this).Invert() * B);
            }
        }
Пример #19
0
        public static DNGMatrix operator *(DNGMatrix a, DNGMatrix b)
        {
            if (a.Cols != b.Rows)
            {
                throw new ArgumentException("Matrix dimensions don't match.");
            }

            DNGMatrix ret = new DNGMatrix(a.Rows, b.Cols);

            for (uint j = 0; j < ret.Rows; j++)
            {
                for (uint k = 0; k < ret.Cols; k++)
                {
                    ret[j, k] = 0.0;
                    for (uint m = 0; m < a.Cols; m++)
                    {
                        double aa = a[j, m];
                        double bb = b[m, k];
                        ret[j, k] += aa * bb;
                    }
                }
            }
            return(ret);
        }
Пример #20
0
        private DNGMatrix FindXYZtoCamera(DNGxyCoord white, ref DNGMatrix forwardMatrix,
                                          ref DNGMatrix reductionMatrix, ref DNGMatrix cameraCalibration)
        {
            // Convert to temperature/offset space.
            DNGTemperature td = new DNGTemperature(white);

            // Find fraction to weight the first calibration.
            double g;

            if (td.Temperature <= fTemperature1)
            {
                g = 1.0;
            }

            else if (td.Temperature >= fTemperature2)
            {
                g = 0.0;
            }

            else
            {
                double invT = 1.0 / td.Temperature;

                g = (invT - (1.0 / fTemperature2)) /
                    ((1.0 / fTemperature1) - (1.0 / fTemperature2));
            }

            // Interpolate the color matrix.

            DNGMatrix colorMatrix;

            if (g >= 1.0)
            {
                colorMatrix = fColorMatrix1;
            }

            else if (g <= 0.0)
            {
                colorMatrix = fColorMatrix2;
            }

            else
            {
                colorMatrix = (g) * fColorMatrix1 +
                              (1.0 - g) * fColorMatrix2;
            }

            // Interpolate forward matrix, if any.
            if (forwardMatrix != null)
            {
                bool has1 = fForwardMatrix1.NotEmpty();
                bool has2 = fForwardMatrix2.NotEmpty();

                if (has1 && has2)
                {
                    if (g >= 1.0)
                    {
                        forwardMatrix = fForwardMatrix1;
                    }

                    else if (g <= 0.0)
                    {
                        forwardMatrix = fForwardMatrix2;
                    }

                    else
                    {
                        forwardMatrix = (g) * fForwardMatrix1 +
                                        (1.0 - g) * fForwardMatrix2;
                    }
                }
                else if (has1)
                {
                    forwardMatrix = fForwardMatrix1;
                }
                else if (has2)
                {
                    forwardMatrix = fForwardMatrix2;
                }
                else
                {
                    forwardMatrix.Clear();
                }
            }

            // Interpolate reduction matrix, if any.
            if (reductionMatrix != null)
            {
                bool has1 = fReductionMatrix1.NotEmpty();
                bool has2 = fReductionMatrix2.NotEmpty();

                if (has1 && has2)
                {
                    if (g >= 1.0)
                    {
                        reductionMatrix = fReductionMatrix1;
                    }
                    else if (g <= 0.0)
                    {
                        reductionMatrix = fReductionMatrix2;
                    }
                    else
                    {
                        reductionMatrix = (g) * fReductionMatrix1 +
                                          (1.0 - g) * fReductionMatrix2;
                    }
                }
                else if (has1)
                {
                    reductionMatrix = fReductionMatrix1;
                }
                else if (has2)
                {
                    reductionMatrix = fReductionMatrix2;
                }
                else
                {
                    reductionMatrix.Clear();
                }
            }

            // Interpolate camera calibration matrix.
            if (cameraCalibration != null)
            {
                if (g >= 1.0)
                {
                    cameraCalibration = fCameraCalibration1;
                }
                else if (g <= 0.0)
                {
                    cameraCalibration = fCameraCalibration2;
                }
                else
                {
                    cameraCalibration = (g) * fCameraCalibration1 +
                                        (1.0 - g) * fCameraCalibration2;
                }
            }

            // Return the interpolated color matrix.
            return(colorMatrix);
        }
Пример #21
0
        public DNGColorSpec(uint aChannels, ImageFileDirectory ifd0, ImageFileDirectory raw)
        {
            fChannels = aChannels;
            if (GetTag <IFDDNGCalibrationIlluminant1>(ifd0, raw) != null)
            {
                fTemperature1 = ConvertIlluminantToTemperature(GetTag <IFDDNGCalibrationIlluminant1>(ifd0, raw).Value);
            }
            else
            {
                fTemperature1 = 0.0;
            }
            if (GetTag <IFDDNGCalibrationIlluminant2>(ifd0, raw) != null)
            {
                fTemperature2 = ConvertIlluminantToTemperature(GetTag <IFDDNGCalibrationIlluminant2>(ifd0, raw).Value);
            }
            else
            {
                fTemperature2 = 0.0;
            }

            fColorMatrix1 = GetTag <IFDDNGColorMatrix1>(ifd0, raw)?.Matrix;
            if (fColorMatrix1 == null)
            {
                fColorMatrix1 = DNGMatrix.Identity(fChannels); //best choice if nothing is given...
            }
            fColorMatrix2 = GetTag <IFDDNGColorMatrix2>(ifd0, raw)?.Matrix;
            if (fColorMatrix2 == null)
            {
                fColorMatrix2 = new DNGMatrix();
            }

            fForwardMatrix1 = GetTag <IFDDNGForwardMatrix1>(ifd0, raw)?.Matrix;
            if (fForwardMatrix1 == null)
            {
                fForwardMatrix1 = new DNGMatrix();
            }
            fForwardMatrix2 = GetTag <IFDDNGForwardMatrix2>(ifd0, raw)?.Matrix;
            if (fForwardMatrix2 == null)
            {
                fForwardMatrix2 = new DNGMatrix();
            }

            fReductionMatrix1 = GetTag <IFDDNGReductionMatrix1>(ifd0, raw)?.Matrix;
            if (fReductionMatrix1 == null)
            {
                fReductionMatrix1 = new DNGMatrix();
            }
            fReductionMatrix2 = GetTag <IFDDNGReductionMatrix2>(ifd0, raw)?.Matrix;
            if (fReductionMatrix2 == null)
            {
                fReductionMatrix2 = new DNGMatrix();
            }

            fCameraCalibration1 = GetTag <IFDDNGCameraCalibration1>(ifd0, raw)?.Matrix;
            fCameraCalibration2 = GetTag <IFDDNGCameraCalibration1>(ifd0, raw)?.Matrix;
            if (fCameraCalibration1 == null)
            {
                fCameraCalibration1 = DNGMatrix.Identity(fChannels);
            }
            if (fCameraCalibration2 == null)
            {
                fCameraCalibration2 = DNGMatrix.Identity(fChannels);
            }

            fAnalogBalance = GetTag <IFDDNGAnalogBalance>(ifd0, raw)?.Vector.AsDiagonal();
            if (fAnalogBalance == null)
            {
                fAnalogBalance = DNGMatrix.Identity(fChannels);
            }

            fForwardMatrix1 = NormalizeForwardMatrix(fForwardMatrix1);

            fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1;

            if (fColorMatrix2.IsEmpty() ||
                fTemperature1 <= 0.0 ||
                fTemperature2 <= 0.0 ||
                fTemperature1 == fTemperature2)
            {
                fTemperature1 = 5000.0;
                fTemperature2 = 5000.0;

                fColorMatrix2       = fColorMatrix1;
                fForwardMatrix2     = fForwardMatrix1;
                fReductionMatrix2   = fReductionMatrix1;
                fCameraCalibration2 = fCameraCalibration1;
            }
            else
            {
                fForwardMatrix2 = NormalizeForwardMatrix(fForwardMatrix2);
                fColorMatrix2   = fAnalogBalance * fCameraCalibration2 * fColorMatrix2;

                // Swap values if temperatures are out of order.
                if (fTemperature1 > fTemperature2)
                {
                    double temp = fTemperature1;
                    fTemperature1 = fTemperature2;
                    fTemperature2 = temp;

                    DNGMatrix T = fColorMatrix1;
                    fColorMatrix1 = fColorMatrix2;
                    fColorMatrix2 = T;

                    T = fForwardMatrix1;
                    fForwardMatrix1 = fForwardMatrix2;
                    fForwardMatrix2 = T;

                    T = fReductionMatrix1;
                    fReductionMatrix1 = fReductionMatrix2;
                    fReductionMatrix2 = T;

                    T = fCameraCalibration1;
                    fCameraCalibration1 = fCameraCalibration2;
                    fCameraCalibration2 = T;
                }
            }

            IFDDNGAsShotNeutral neutral = GetTag <IFDDNGAsShotNeutral>(ifd0, raw);
            IFDDNGAsShotWhiteXY asShot  = GetTag <IFDDNGAsShotWhiteXY>(ifd0, raw);
            DNGxyCoord          white;

            if (asShot == null)
            {
                if (neutral == null)
                {
                    throw new ArgumentException("The DNG spec says that one of the As Shot White balance tags must be present.");
                }

                DNGVector vec = new DNGVector((uint)neutral.Value.Length);

                for (uint c = 0; c < neutral.Value.Length; c++)
                {
                    vec[c] = neutral.Value[c].Value;
                }

                double unify = 1.0 / vec.MaxEntry();
                vec = unify * vec;

                white = NeutralToXY(vec);
            }
            else
            {
                double x = asShot.Value[0].Value;
                double y = asShot.Value[1].Value;
                white = new DNGxyCoord(x, y);
            }
            WhiteXY = white;
        }
Пример #22
0
        public DNGColorSpec(double[] colorMatrix1, double[] colorMatrix2,
                            IFDDNGCalibrationIlluminant.Illuminant illuminant1, IFDDNGCalibrationIlluminant.Illuminant illuminant2, float[] whiteBalance)
        {
            fChannels     = 3;
            fTemperature1 = ConvertIlluminantToTemperature(illuminant1);
            fTemperature2 = ConvertIlluminantToTemperature(illuminant2);


            if (colorMatrix1 == null)
            {
                fColorMatrix1 = DNGMatrix.Identity(fChannels); //best choice if nothing is given...
            }
            else
            {
                fColorMatrix1 = new DNGMatrix3x3(colorMatrix1);
            }

            if (colorMatrix2 == null)
            {
                fColorMatrix2 = new DNGMatrix();
            }
            else
            {
                fColorMatrix2 = new DNGMatrix3x3(colorMatrix2);
            }

            fForwardMatrix1 = new DNGMatrix();
            fForwardMatrix2 = new DNGMatrix();

            fReductionMatrix1 = new DNGMatrix();
            fReductionMatrix2 = new DNGMatrix();

            fCameraCalibration1 = DNGMatrix.Identity(fChannels);
            fCameraCalibration2 = DNGMatrix.Identity(fChannels);

            fAnalogBalance = DNGMatrix.Identity(fChannels);

            fForwardMatrix1 = NormalizeForwardMatrix(fForwardMatrix1);

            fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1;

            if (fColorMatrix2.IsEmpty() ||
                fTemperature1 <= 0.0 ||
                fTemperature2 <= 0.0 ||
                fTemperature1 == fTemperature2)
            {
                fTemperature1 = 5000.0;
                fTemperature2 = 5000.0;

                fColorMatrix2       = fColorMatrix1;
                fForwardMatrix2     = fForwardMatrix1;
                fReductionMatrix2   = fReductionMatrix1;
                fCameraCalibration2 = fCameraCalibration1;
            }
            else
            {
                fForwardMatrix2 = NormalizeForwardMatrix(fForwardMatrix2);
                fColorMatrix2   = fAnalogBalance * fCameraCalibration2 * fColorMatrix2;

                // Swap values if temperatures are out of order.
                if (fTemperature1 > fTemperature2)
                {
                    double temp = fTemperature1;
                    fTemperature1 = fTemperature2;
                    fTemperature2 = temp;

                    DNGMatrix T = fColorMatrix1;
                    fColorMatrix1 = fColorMatrix2;
                    fColorMatrix2 = T;

                    T = fForwardMatrix1;
                    fForwardMatrix1 = fForwardMatrix2;
                    fForwardMatrix2 = T;

                    T = fReductionMatrix1;
                    fReductionMatrix1 = fReductionMatrix2;
                    fReductionMatrix2 = T;

                    T = fCameraCalibration1;
                    fCameraCalibration1 = fCameraCalibration2;
                    fCameraCalibration2 = T;
                }
            }

            DNGxyCoord white;
            DNGVector  vec = new DNGVector((uint)whiteBalance.Length);

            for (uint c = 0; c < whiteBalance.Length; c++)
            {
                //white point is given as a multiplicatice factor
                //actual white point is hence 1/value
                vec[c] = 1.0f / whiteBalance[c];
            }

            double unify = 1.0 / vec.MaxEntry();

            vec = unify * vec;

            white = NeutralToXY(vec);

            WhiteXY = white;
        }
Пример #23
0
 public bool AlmostIdentity(double slop = 1.0e-8)
 {
     return(AlmostEqual(DNGMatrix.Identity(_rows), slop));
 }
Пример #24
0
        private DNGMatrix InvertNxN()
        {
            uint i;
            uint j;
            uint k;

            uint n = Rows;
            uint augmented_cols = 2 * n;

            double[,] temp = new double[MAX_COLOR_PLANES, MAX_COLOR_PLANES * 2];


            for (i = 0; i < n; i++)
            {
                for (j = 0; j < n; j++)
                {
                    temp[i, j]     = this[i, j];
                    temp[i, j + n] = (i == j? 1.0 : 0.0);
                }
            }

            for (i = 0; i < n; i++)
            {
                // Find row iMax with largest absolute entry in column i.
                uint   iMax = i;
                double vMax = -1.0;

                for (k = i; k < n; k++)
                {
                    double v = Math.Abs(this[k, i]);

                    if (v > vMax)
                    {
                        vMax = v;
                        iMax = k;
                    }
                }

                double alpha = temp[iMax, i];

                if (Math.Abs(alpha) < NEAR_ZERO)
                {
                    throw new Exception("This matrix is not invertible");
                }

                // Swap rows i and iMax, column by column.
                if (i != iMax)
                {
                    for (j = 0; j < augmented_cols; j++)
                    {
                        double t = temp[iMax, j];
                        temp[iMax, j] = temp[i, j];
                        temp[i, j]    = t;
                    }
                }

                for (j = 0; j < augmented_cols; j++)
                {
                    temp[i, j] /= alpha;
                }

                for (k = 0; k < n; k++)
                {
                    if (i != k)
                    {
                        double beta = temp[k, i];

                        for (j = 0; j < augmented_cols; j++)
                        {
                            temp[k, j] -= beta * temp[i, j];
                        }
                    }
                }
            }

            DNGMatrix B = new DNGMatrix(n, n);

            for (i = 0; i < n; i++)
            {
                for (j = 0; j < n; j++)
                {
                    B[i, j] = temp[i, j + n];
                }
            }

            return(B);
        }