예제 #1
0
        public static DNGVector operator *(DNGVector vec, double scale)
        {
            DNGVector ret = new DNGVector(vec);

            ret.Scale(scale);
            return(ret);
        }
예제 #2
0
        /// \brief Compute a 3x3 matrix which maps colors from white point white1 to
        /// white point white2
        ///
        /// Uses linearized Bradford adaptation matrix to compute a mapping from
        /// colors measured with one white point (white1) to another (white2).
        public static DNGMatrix3x3 MapWhiteMatrix(DNGxyCoord white1, DNGxyCoord white2)
        {
            // Use the linearized Bradford adaptation matrix.
            DNGMatrix3x3 Mb = new DNGMatrix3x3(0.8951, 0.2664, -0.1614,
                                               -0.7502, 1.7135, 0.0367,
                                               0.0389, -0.0685, 1.0296);

            DNGVector w1 = Mb * white1.XYtoXYZ();
            DNGVector w2 = Mb * white2.XYtoXYZ();

            // Negative white coordinates are kind of meaningless.
            w1[0] = Math.Max(w1[0], 0.0);
            w1[1] = Math.Max(w1[1], 0.0);
            w1[2] = Math.Max(w1[2], 0.0);

            w2[0] = Math.Max(w2[0], 0.0);
            w2[1] = Math.Max(w2[1], 0.0);
            w2[2] = Math.Max(w2[2], 0.0);

            // Limit scaling to something reasonable.
            DNGMatrix3x3 A = new DNGMatrix3x3();

            A[0, 0] = DNGUtils.Pin(0.1, w1[0] > 0.0 ? w2[0] / w1[0] : 10.0, 10.0);
            A[1, 1] = DNGUtils.Pin(0.1, w1[1] > 0.0 ? w2[1] / w1[1] : 10.0, 10.0);
            A[2, 2] = DNGUtils.Pin(0.1, w1[2] > 0.0 ? w2[2] / w1[2] : 10.0, 10.0);

            DNGMatrix3x3 B = new DNGMatrix3x3(Mb.Invert() * A * Mb);

            return(B);
        }
예제 #3
0
        public static DNGVector Identity(uint size)
        {
            DNGVector mat = new DNGVector();

            mat.SetIdentity(size);
            return(mat);
        }
예제 #4
0
 public DNGVector4(DNGVector v)
     : base(v)
 {
     if (Count != 4)
     {
         throw new ArgumentException("This is not a four element vector.");
     }
 }
예제 #5
0
 public DNGVector3(DNGVector v)
     : base(v)
 {
     if (Count != 3)
     {
         throw new ArgumentException("This is not a three element vector.");
     }
 }
예제 #6
0
        public DNGVector(DNGVector aVector)
        {
            _count = aVector.Count;

            for (uint index = 0; index < _count; index++)
            {
                _data[index] = aVector._data[index];
            }
        }
예제 #7
0
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (!(obj is DNGVector))
            {
                return(false);
            }

            DNGVector value = (DNGVector)obj;

            return(Equals(value));
        }
예제 #8
0
        public bool Equals(DNGVector value)
        {
            if (_count != value._count)
            {
                return(false);
            }

            for (uint index = 0; index < _count; index++)
            {
                if (_data[index] != value._data[index])
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #9
0
        public static double Dot(DNGVector a, DNGVector b)
        {
            uint count = a.Count;

            if (b.Count != count)
            {
                throw new ArgumentException("Vectors don't have same size.");
            }

            double sum = 0.0;

            for (uint i = 0; i < count; i++)
            {
                sum += a[i] * b[i];
            }

            return(sum);
        }
예제 #10
0
        public static DNGVector operator -(DNGVector a, DNGVector b)
        {
            uint count = a.Count;

            if (b.Count != count)
            {
                throw new ArgumentException("Vectors don't have same size.");
            }

            DNGVector ret = new DNGVector(count);

            for (uint i = 0; i < count; i++)
            {
                ret[i] = a[i] - b[i];
            }

            return(ret);
        }
예제 #11
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);
        }
예제 #12
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();
        }
예제 #13
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);
        }
예제 #14
0
        public static DNGVector operator *(DNGMatrix a, DNGVector b)
        {
            if (a.Cols != b.Count)
            {
                throw new ArgumentException("Matrix/Vector dimensions don't match.");
            }

            DNGVector ret = new DNGVector(a.Rows);

            for (uint j = 0; j < ret.Count; j++)
            {
                ret[j] = 0.0;
                for (uint m = 0; m < a.Cols; m++)
                {
                    double aa = a[j, m];
                    double bb = b[m];
                    ret[j] += aa * bb;
                }
            }

            return(ret);
        }
예제 #15
0
        private ImageFileDirectory SetMembers()
        {
            ImageFileDirectory rawIFD = null;

            //find the IFD with the RAW Bayer image
            for (int i = 0; i < mIfds.Count; i++)
            {
                //well, it should actually be somewhere in IFD0...
                if (mIfds[i].GetEntry <IFDPhotometricInterpretation>() != null)
                {
                    if (mIfds[i].GetEntry <IFDPhotometricInterpretation>().Value ==
                        IFDPhotometricInterpretation.PhotometricInterpretation.CFA)
                    {
                        rawIFD = mIfds[i];
                        break;
                    }
                }
            }

            //no root IFD seems to contain RAW bayer, search for Sub-IFDs
            if (rawIFD == null)
            {
                //find the IFD with the RAW Bayer image
                for (int i = 0; i < mIfds.Count; i++)
                {
                    IFDSubIFDs subIFD = mIfds[i].GetEntry <IFDSubIFDs>();
                    if (subIFD == null)
                    {
                        continue;
                    }
                    for (int j = 0; j < subIFD.Value.Count; j++)
                    {
                        if (subIFD.Value[j].GetEntry <IFDPhotometricInterpretation>().Value ==
                            IFDPhotometricInterpretation.PhotometricInterpretation.CFA)
                        {
                            rawIFD = subIFD.Value[j];
                            break;
                        }
                    }
                }
            }

            if (rawIFD == null)
            {
                throw new ArgumentException("Can't find IFD with Bayer RAW image.");
            }

            mLinearizationTable = rawIFD.GetEntry <IFDDNGLinearizationTable>();
            mWidth  = (int)rawIFD.GetEntry <IFDImageWidth>().Value;
            mHeight = (int)rawIFD.GetEntry <IFDImageLength>().Value;
            if (mIfds[0].GetEntry <IFDDateTime>() != null)
            {
                mRecordingDate = mIfds[0].GetEntry <IFDDateTime>().Value;
            }

            //in case of Pentax this will have succes:
            IFDDNGPrivateData privateData = mIfds[0].GetEntry <IFDDNGPrivateData>();

            if (privateData != null)
            {
                MNLevelInfo levelInfo = privateData.PentaxMakerNotes.GetEntry <MNLevelInfo>();
                if (levelInfo != null)
                {
                    mRollAngle        = levelInfo.Value.RollAngle;
                    mRollAnglePresent = true;
                }
            }

            IFDExif exif = mIfds[0].GetEntry <IFDExif>();

            if (exif != null)
            {
                mISO           = exif.GetEntry <ExifISOSpeedRatings>().Value;
                mExposureTime  = exif.GetEntry <ExifExposureTime>().Value;
                mRecordingDate = (exif.GetEntry <ExifDateTimeDigitized>()?.Value).GetValueOrDefault(mRecordingDate);
            }
            else if (rawIFD.GetEntry <IFDISOSpeedRatings>() != null)
            {
                mISO = rawIFD.GetEntry <IFDISOSpeedRatings>().Value;
                //very likely that exposure time is also present
                mExposureTime = rawIFD.GetEntry <IFDExposureTime>().Value;
            }
            else if (mIfds[0].GetEntry <IFDISOSpeedRatings>() != null)
            {
                mISO = mIfds[0].GetEntry <IFDISOSpeedRatings>().Value;
                //very likely that exposure time is also present
                mExposureTime = mIfds[0].GetEntry <IFDExposureTime>().Value;
            }

            mBitDepth = rawIFD.GetEntry <IFDBitsPerSample>().Value[0];

            int bayerWidth  = rawIFD.GetEntry <IFDCFARepeatPatternDim>().Value[0];
            int bayerHeight = rawIFD.GetEntry <IFDCFARepeatPatternDim>().Value[1];

            if (bayerHeight != 2 || bayerWidth != 2)
            {
                throw new ArgumentException("This file has a bayer pattern size different than 2x2. Can't decode that.");
            }

            ExifCFAPattern.BayerColor[] bayer = rawIFD.GetEntry <IFDCFAPattern>().Value;
            mBayerPattern = new BayerColor[bayer.Length];
            for (int i = 0; i < bayer.Length; i++)
            {
                mBayerPattern[i] = (BayerColor)(int)bayer[i];
            }

            IFDDNGCFAPlaneColor planeColor = rawIFD.GetEntry <IFDDNGCFAPlaneColor>();

            int[] planeColorHelper = new int[] { 0, 1, 2 };
            if (planeColor != null) //did it ever differ from 0,1,2?
            {
                //0 = red, 1 = gree, 2 = blue.
                //The debayer algo creates images with plane order red/green/blue.
                //If this order differs, we need to re-order the planes in order to
                //have the color matrices correct.

                //reset colorTwist matrix:
                mColorTwist = new float[3, 4];
                if (planeColor.Value.Length > 3 || planeColor.Value.Length < 3)
                {
                    throw new ArgumentException("This image doesn't contain three color planes.");
                }

                for (int i = 0; i < planeColor.Value.Length; i++)
                {
                    int color = planeColor.Value[i];
                    planeColorHelper[i] = color;
                    if (color > 2)
                    {
                        throw new ArgumentException("This image contains colors different than red/green/blue.");
                    }
                    mColorTwist[color, i] = 1;

                    if (color != i)
                    {
                        mColorTwistIsIdentity = false;
                    }
                }
            }

            mColorSpec = new DNGColorSpec(3, mIfds[0], rawIFD);

            IFDDNGWhiteLevel whiteLevel = rawIFD.GetEntry <IFDDNGWhiteLevel>();
            IFDDNGBlackLevel blackLevel = rawIFD.GetEntry <IFDDNGBlackLevel>();

            mBlackLevel = new float[3];
            if (blackLevel != null)
            {
                //only one value for all colors
                if (blackLevel.Value.Length == 1)
                {
                    mBlackLevel[0] = (float)blackLevel.Value[0].Value;
                    mBlackLevel[1] = (float)blackLevel.Value[0].Value;
                    mBlackLevel[2] = (float)blackLevel.Value[0].Value;
                }

                //values per color channel
                if (blackLevel.Value.Length == 3)
                {
                    mBlackLevel[planeColorHelper[0]] = (float)blackLevel.Value[0].Value;
                    mBlackLevel[planeColorHelper[1]] = (float)blackLevel.Value[1].Value;
                    mBlackLevel[planeColorHelper[2]] = (float)blackLevel.Value[2].Value;
                }

                //values per color bayer pattern
                if (blackLevel.Value.Length == 4)
                {
                    //red
                    int indexR = -1;
                    for (int i = 0; i < mBayerPattern.Length; i++)
                    {
                        if (mBayerPattern[i] == BayerColor.Red)
                        {
                            indexR = i;
                            break;
                        }
                    }
                    mBlackLevel[0] = (float)blackLevel.Value[indexR].Value;

                    //blue
                    int indexB = -1;
                    for (int i = 0; i < mBayerPattern.Length; i++)
                    {
                        if (mBayerPattern[i] == BayerColor.Blue)
                        {
                            indexB = i;
                            break;
                        }
                    }
                    mBlackLevel[2] = (float)blackLevel.Value[indexB].Value;

                    //green, the two remaining indices
                    int indexG1 = -1, indexG2 = -1;
                    for (int i = 0; i < mBayerPattern.Length; i++)
                    {
                        if (mBayerPattern[i] == BayerColor.Green && indexG1 == -1)
                        {
                            indexG1 = i;
                        }
                        if (mBayerPattern[i] == BayerColor.Green && indexG1 != -1)
                        {
                            indexG2 = i;
                        }
                    }
                    float g1 = (float)blackLevel.Value[indexG1].Value;
                    float g2 = (float)blackLevel.Value[indexG2].Value;

                    mBlackLevel[1] = Math.Max(g1, g2); //well, one could distinguish the two greens, but what for?
                }
            }
            mWhiteLevel    = new float[3];
            mWhiteLevel[0] = (float)whiteLevel.Value[0];
            mWhiteLevel[1] = (float)whiteLevel.Value[0];
            mWhiteLevel[2] = (float)whiteLevel.Value[0];

            //subtract black level from white level
            mWhiteLevel[0] -= mBlackLevel[0];
            mWhiteLevel[1] -= mBlackLevel[1];
            mWhiteLevel[2] -= mBlackLevel[2];

            //get white balance from color spec
            DNGVector wb = mColorSpec.CameraWhite;

            mWhiteBalance = new float[3];
            mWhiteBalance[planeColorHelper[0]] = 1.0f / (float)wb[0];
            mWhiteBalance[planeColorHelper[1]] = 1.0f / (float)wb[1];
            mWhiteBalance[planeColorHelper[2]] = 1.0f / (float)wb[2];


            //look for orientation tag. If RAW ifd has the tag, choose that one
            if (rawIFD.GetEntry <IFDOrientation>() != null)
            {
                mOrientation = new DNGOrientation(rawIFD.GetEntry <IFDOrientation>().Value);
            }
            else if (mIfds[0].GetEntry <IFDOrientation>() != null)
            {
                mOrientation = new DNGOrientation(mIfds[0].GetEntry <IFDOrientation>().Value);
            }
            else
            {
                //no tag found, use default
                mOrientation = new DNGOrientation(DNGOrientation.Orientation.Normal);
            }

            //default Values:
            int cropLeft      = 0;
            int cropTop       = 0;
            int croppedWidth  = mWidth;
            int croppedHeight = mHeight;

            IFDDNGActiveArea activeArea = rawIFD.GetEntry <IFDDNGActiveArea>();

            //if active area is defined:
            if (activeArea != null)
            {
                int top, left, bottom, right;
                top    = (int)activeArea.Value[0];
                left   = (int)activeArea.Value[1];
                bottom = (int)activeArea.Value[2];
                right  = (int)activeArea.Value[3];

                cropLeft     += left;
                cropTop      += top;
                croppedWidth  = right - left;
                croppedHeight = bottom - top;

                //CFA pattern is defined on active area. If top/left is uneven we need to shift the CFA pattern accordingly
                if (top % 2 != 0)
                {
                    BayerColor bayer0 = BayerPattern[0];
                    BayerColor bayer1 = BayerPattern[1];
                    BayerPattern[0] = BayerPattern[2];
                    BayerPattern[1] = BayerPattern[3];
                    BayerPattern[2] = bayer0;
                    BayerPattern[3] = bayer1;
                }

                if (left % 2 != 0)
                {
                    BayerColor bayer0 = BayerPattern[0];
                    BayerColor bayer2 = BayerPattern[2];
                    BayerPattern[0] = BayerPattern[1];
                    BayerPattern[2] = BayerPattern[3];
                    BayerPattern[1] = bayer0;
                    BayerPattern[3] = bayer2;
                }
            }

            IFDDNGDefaultCropOrigin cropOrigin = rawIFD.GetEntry <IFDDNGDefaultCropOrigin>();
            IFDDNGDefaultCropSize   cropSize   = rawIFD.GetEntry <IFDDNGDefaultCropSize>();

            if (cropOrigin != null && cropSize != null)
            {
                int top, left, width, height;
                left   = (int)(cropOrigin.Value[0].Value);
                top    = (int)(cropOrigin.Value[0].Value);
                width  = (int)(cropSize.Value[0].Value);
                height = (int)(cropSize.Value[0].Value);

                cropLeft += left;
                cropTop  += top;

                croppedWidth  = width;
                croppedHeight = height;
            }

            //we always crop at least two pixels because of our algos...
            mCropLeft = Math.Max(2, cropLeft);
            mCropTop  = Math.Max(2, cropTop);

            mCroppedWidth  = croppedWidth - Math.Max(0, (cropLeft + croppedWidth) - (mWidth - 2));
            mCroppedHeight = croppedHeight - Math.Max(0, (cropTop + croppedHeight) - (mHeight - 2));

            IFDDNGNoiseProfile noise = rawIFD.GetEntry <IFDDNGNoiseProfile>();

            if (noise == null)
            {
                noise = mIfds[0].GetEntry <IFDDNGNoiseProfile>();
            }
            if (noise != null)
            {
                //if noise level is given for all channels,
                //take the green one as it is usually scalled to one
                if (noise.Value.Length > 2)
                {
                    mNoiseModelAlpha = (float)noise.Value[planeColorHelper[1] * 2];
                    mNoiseModelBeta  = (float)noise.Value[planeColorHelper[1] * 2 + 1];
                }
                else
                {
                    mNoiseModelAlpha = (float)noise.Value[0];
                    mNoiseModelBeta  = (float)noise.Value[1];
                }
            }

            mMake            = mIfds[0].GetEntry <IFDMake>().Value;
            mUniqueModelName = mIfds[0].GetEntry <IFDDNGUniqueCameraModel>().Value;

            return(rawIFD);
        }
예제 #16
0
        public static double Distance(DNGVector a, DNGVector b)
        {
            DNGVector c = a - b;

            return(Math.Sqrt(Dot(c, c)));
        }
예제 #17
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;
        }
예제 #18
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;
        }