public PEFFile(string aFileName)
            : base(aFileName)
        {
            byte a = mFileReader.ReadByte();
            byte b = mFileReader.ReadByte();

            bool fileIsLittleEndian;

            if (a == b && b == 'I')
            {
                fileIsLittleEndian = true;
            }
            else
            if (a == b && b == 'M')
            {
                fileIsLittleEndian = false;
            }
            else
            {
                throw new FileLoadException("Could not determine file endianess. Is this a proper TIFF/PEF file?", aFileName);
            }

            mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;

            ushort magicNumber = ReadUI2();

            if (magicNumber != 42)
            {
                throw new FileLoadException("This is not a valid TIFF/PEF file: Magic number is not 42.", aFileName);
            }

            uint offsetToFirstIFD = ReadUI4();

            mFile.Seek(offsetToFirstIFD, SeekOrigin.Begin);
            List <ImageFileDirectory> ifds = new List <ImageFileDirectory>();

            while (true)
            {
                ImageFileDirectory ifd = new ImageFileDirectory(this);
                ifds.Add(ifd);
                uint offsetToNext = ReadUI4();
                if (offsetToNext == 0)
                {
                    break;
                }
                Seek(offsetToNext, System.IO.SeekOrigin.Begin);
            }

            //Raw Data:
            ImageFileDirectory raw  = ifds[0];
            IFDExif            exif = raw.GetEntry <IFDExif>();

            mISO      = exif.GetEntry <ExifEntry.ExifISOSpeedRatings>().Value;
            mBitDepth = raw.GetEntry <IFDBitsPerSample>().Value;
            ExifEntry.ExifMakerNote makernote = exif.GetEntry <ExifEntry.ExifMakerNote>();
            mBayerPattern = exif.GetEntry <ExifEntry.ExifCFAPattern>().Value;
            mBayerWidth   = exif.GetEntry <ExifEntry.ExifCFAPattern>().xCount;
            mBayerHeight  = exif.GetEntry <ExifEntry.ExifCFAPattern>().yCount;
            MNHuffmanTable huffmanTable = makernote.Value.GetEntry <MNHuffmanTable>();

            mWhiteLevel = makernote.Value.GetEntry <MNWhiteLevel>();
            mWhitePoint = makernote.Value.GetEntry <MNWhitePoint>();
            mBlackPoint = makernote.Value.GetEntry <MNBlackPoint>();
            mScaling    = makernote.Value.GetEntry <MNDataScaling>();

            mWidth  = (int)raw.GetEntry <IFDImageWidth>().Value;
            mHeight = (int)raw.GetEntry <IFDImageLength>().Value;
            uint offset = raw.GetEntry <IFDStripOffsets>().Value[0];

            Seek(offset, SeekOrigin.Begin);
            mRawImage    = new ushort[mHeight, mWidth];
            int[,] vpred = new int[2, 2];
            int[] hpred = new int[2];

            unsafe
            {
                fixed(ushort *huff = huffmanTable.Value)
                {
                    getbithuff(-1, null);

                    for (int row = 0; row < mHeight; row++)
                    {
                        for (int col = 0; col < mWidth; col++)
                        {
                            int diff = ljpeg_diff(huff);
                            if (col < 2)
                            {
                                hpred[col] = vpred[row & 1, col] += diff;
                            }
                            else
                            {
                                hpred[col & 1] += diff;
                            }
                            mRawImage[row, col] = (ushort)hpred[col & 1];
                        }
                    }
                }
            }
        }
        private ImageFileDirectory SetMembers()
        {
            //Raw Data:
            ImageFileDirectory raw  = mIfds[0];
            IFDExif            exif = raw.GetEntry <IFDExif>();

            mISO           = exif.GetEntry <ExifISOSpeedRatings>().Value;
            mExposureTime  = exif.GetEntry <ExifExposureTime>().Value;
            mRecordingDate = exif.GetEntry <ExifDateTimeDigitized>().Value;
            mBitDepth      = raw.GetEntry <IFDBitsPerSample>().Value[0];
            ExifMakerNote makernote = exif.GetEntry <ExifMakerNote>();

            //needed to decompress image data:
            mHhuffmanTable = makernote.Value.GetEntry <MNHuffmanTable>();
            ExifCFAPattern.BayerColor[] bayer = exif.GetEntry <ExifCFAPattern>().Value;
            mBayerPattern = new BayerColor[bayer.Length];
            for (int i = 0; i < bayer.Length; i++)
            {
                mBayerPattern[i] = (BayerColor)(int)bayer[i];
            }

            MNWhiteLevel  whiteLevel = makernote.Value.GetEntry <MNWhiteLevel>();
            MNWhitePoint  whitePoint = makernote.Value.GetEntry <MNWhitePoint>();
            MNBlackPoint  blackPoint = makernote.Value.GetEntry <MNBlackPoint>();
            MNDataScaling scaling    = makernote.Value.GetEntry <MNDataScaling>();

            float whiteLevelAll = (float)Math.Pow(2, mBitDepth);

            if (whiteLevel != null)
            {
                whiteLevelAll = whiteLevel.Value;
            }

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

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

                //values per color bayer pattern
                if (blackPoint.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)blackPoint.Value[indexR];

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

                    //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)blackPoint.Value[indexG1];
                    float g2 = (float)blackPoint.Value[indexG2];

                    mBlackLevel[1] = Math.Max(g1, g2); //well, one could distinguish the two greens, but what for?
                }
            }

            mWhiteLevel     = new float[] { whiteLevelAll, whiteLevelAll, whiteLevelAll };
            mWhiteLevel[0] -= mBlackLevel[0];
            mWhiteLevel[1] -= mBlackLevel[1];
            mWhiteLevel[2] -= mBlackLevel[2];
            float scale = scaling.Value;

            mWhiteBalance = new float[] { whitePoint.Value[0] / scale, whitePoint.Value[1] / scale, whitePoint.Value[3] / scale };

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

            mWidth  = (int)raw.GetEntry <IFDImageWidth>().Value;
            mHeight = (int)raw.GetEntry <IFDImageLength>().Value;


            //look for orientation tag.
            if (raw.GetEntry <IFDOrientation>() != null)
            {
                mOrientation = new DNGOrientation(raw.GetEntry <IFDOrientation>().Value);
            }
            else
            {
                //no tag found, use default
                mOrientation = new DNGOrientation(DNGOrientation.Orientation.Normal);
            }

            //we always crop at least two pixels because of our algos...
            mCropLeft = 2;
            mCropTop  = 2;

            mCroppedWidth  = mWidth - 4;
            mCroppedHeight = mHeight - 4;


            mMake            = raw.GetEntry <IFDMake>().Value;
            mUniqueModelName = raw.GetEntry <IFDModel>().Value;

            //missing data, like noise model, crop area, etc..., must be loaded afterwards!
            double[] colorMatrix = new double[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
            mColorSpec = new DNGColorSpec(colorMatrix, colorMatrix, IFDDNGCalibrationIlluminant.Illuminant.D50, IFDDNGCalibrationIlluminant.Illuminant.D50, mWhiteBalance);
            return(raw);
        }
        public PEFFile(string aFileName, bool HeaderOnly)
            : base(aFileName)
        {
            byte a = mFileReader.ReadByte();
            byte b = mFileReader.ReadByte();

            bool fileIsLittleEndian;

            if (a == b && b == 'I')
            {
                fileIsLittleEndian = true;
            }
            else
            if (a == b && b == 'M')
            {
                fileIsLittleEndian = false;
            }
            else
            {
                throw new FileLoadException("Could not determine file endianess. Is this a proper TIFF/PEF file?", aFileName);
            }

            mEndianSwap = fileIsLittleEndian != BitConverter.IsLittleEndian;

            ushort magicNumber = ReadUI2();

            if (magicNumber != 42)
            {
                throw new FileLoadException("This is not a valid TIFF/PEF file: Magic number is not 42.", aFileName);
            }

            uint offsetToFirstIFD = ReadUI4();

            mFile.Seek(offsetToFirstIFD, SeekOrigin.Begin);
            List <ImageFileDirectory> ifds = new List <ImageFileDirectory>();

            while (true)
            {
                ImageFileDirectory ifd = new ImageFileDirectory(this);
                ifds.Add(ifd);
                uint offsetToNext = ReadUI4();
                if (offsetToNext == 0)
                {
                    break;
                }
                Seek(offsetToNext, System.IO.SeekOrigin.Begin);
            }

            //Raw Data:
            ImageFileDirectory raw  = ifds[0];
            IFDExif            exif = raw.GetEntry <IFDExif>();

            mISO      = exif.GetEntry <ExifEntry.ExifISOSpeedRatings>().Value;
            mBitDepth = raw.GetEntry <IFDBitsPerSample>().Value;
            ExifEntry.ExifMakerNote makernote = exif.GetEntry <ExifEntry.ExifMakerNote>();
            mBayerPattern = exif.GetEntry <ExifEntry.ExifCFAPattern>().Value;
            mBayerWidth   = exif.GetEntry <ExifEntry.ExifCFAPattern>().xCount;
            mBayerHeight  = exif.GetEntry <ExifEntry.ExifCFAPattern>().yCount;
            MNHuffmanTable huffmanTable = makernote.Value.GetEntry <MNHuffmanTable>();

            mWhiteLevel = makernote.Value.GetEntry <MNWhiteLevel>();
            mWhitePoint = makernote.Value.GetEntry <MNWhitePoint>();
            mBlackPoint = makernote.Value.GetEntry <MNBlackPoint>();
            mScaling    = makernote.Value.GetEntry <MNDataScaling>();

            mWidth  = (int)raw.GetEntry <IFDImageWidth>().Value;
            mHeight = (int)raw.GetEntry <IFDImageLength>().Value;
            uint offset = raw.GetEntry <IFDStripOffsets>().Value[0];
        }