Ejemplo n.º 1
0
        public DNGFile(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);
            }

            IFDDNGVersion version = ifds[0].GetEntry <IFDDNGVersion>();

            isDNGVersionLarge = version == null;
            if (version != null)
            {
                isDNGVersionLarge = version.Value[1] > 1;
            }

            IFDSubIFDs sub = ifds[0].GetEntry <IFDSubIFDs>();

            mWidth  = (int)sub.Value[0].GetEntry <IFDImageWidth>().Value;
            mHeight = (int)sub.Value[0].GetEntry <IFDImageLength>().Value;
            IFDExif exif = ifds[0].GetEntry <IFDExif>();

            mISO      = exif.GetEntry <ExifEntry.ExifISOSpeedRatings>().Value;
            mBitDepth = sub.Value[0].GetEntry <IFDBitsPerSample>().Value;

            mBayerPattern = sub.Value[0].GetEntry <IFDCFAPattern>().Value;
            mBayerWidth   = sub.Value[0].GetEntry <IFDCFARepeatPatternDim>().Value[0];
            mBayerHeight  = sub.Value[0].GetEntry <IFDCFARepeatPatternDim>().Value[1];
            mWhiteLevel   = sub.Value[0].GetEntry <IFDDNGWhiteLevel>();
            mBlackLevel   = sub.Value[0].GetEntry <IFDDNGBlackLevel>();

            mAsShotNeutral = sub.Value[0].GetEntry <IFDDNGAsShotNeutral>();

            mLinearizationTable = sub.Value[0].GetEntry <IFDDNGLinearizationTable>();
            mMinVal             = new float[3];
            mMinVal[0]          = (float)mBlackLevel.Value[0].Value;
            mMinVal[1]          = (float)mBlackLevel.Value[mBlackLevel.Value.Length > 1 ? 1 : 0].Value;
            mMinVal[2]          = (float)mBlackLevel.Value[mBlackLevel.Value.Length > 3 ? 3 : 0].Value;

            mMaxVal    = new float[3];
            mMaxVal[0] = (float)mWhiteLevel.Value[0];
            mMaxVal[1] = (float)mWhiteLevel.Value[mWhiteLevel.Value.Length > 1 ? 1 : 0];
            mMaxVal[2] = (float)mWhiteLevel.Value[mWhiteLevel.Value.Length > 3 ? 3 : 0];

            int tileWidth  = (int)sub.Value[0].GetEntry <IFDTileWidth>().Value;
            int tileHeight = (int)sub.Value[0].GetEntry <IFDTileLength>().Value;

            uint[] offsets    = sub.Value[0].GetEntry <IFDTileOffsets>().Value;
            uint[] byteCounts = sub.Value[0].GetEntry <IFDTileByteCounts>().Value;

            mRawImage = new ushort[mHeight, mWidth];

            int row = 0;
            int col = 0;

            for (int tile = 0; tile < offsets.Length; tile++)
            {
                byte[] data;
                Seek(offsets[tile], SeekOrigin.Begin);
                data = mFileReader.ReadBytes((int)byteCounts[tile]);
                MemoryStream ms = new MemoryStream(data);
                ms.Seek(0, SeekOrigin.Begin);
                jhead jh = new jhead();
                int   ret = ljpeg_start(jh, 0, ms);
                int   jrow, jcol;
                if (ret > 0 && jh != null)
                {
                    int jwide = jh.wide;
                    jwide *= jh.clrs;


                    unsafe
                    {
                        if (jh.algo == 0xc3) //lossless JPEG
                        {
                            for (jrow = 0; jrow < jh.high; jrow++)
                            {
                                fixed(ushort *ptr = jh.row)
                                {
                                    jh.rowPtr = ptr;
                                    ushort *rp = ljpeg_row(jrow, jh, ms);

                                    for (jcol = 0; jcol < jwide; jcol++)
                                    {
                                        if (jcol + col < mWidth && jrow + row < mHeight)
                                        {
                                            if (mLinearizationTable != null)
                                            {
                                                mRawImage[row + jrow, col + jcol] = mLinearizationTable.Value[rp[jcol] < mLinearizationTable.Value.Length ? rp[jcol] : mLinearizationTable.Value.Length - 1];
                                            }
                                            else
                                            {
                                                mRawImage[row + jrow, col + jcol] = rp[jcol];
                                            }
                                        }
                                    }
                                    jh.rowPtr = null;
                                }
                            }
                        }
                    }
                }
                col += tileWidth;
                if (col > mWidth)
                {
                    col  = 0;
                    row += tileHeight;
                }
            }
        }
Ejemplo n.º 2
0
        unsafe int ljpeg_start(jhead jh, int info_only, Stream s)
        {
            int c, tag, len;

            byte[] data = new byte[0x10000];
            byte * dp;

            //jh = new jhead();

            jh.restart = int.MaxValue;

            s.ReadByte();
            if ((s.ReadByte()) != 0xd8)
            {
                return(0);
            }
            do
            {
                //s.Read(data, 0, 4);
                if (4 != s.Read(data, 0, 4))
                {
                    return(0);
                }
                tag = data[0] << 8 | data[1];
                len = (data[2] << 8 | data[3]) - 2;
                if (tag <= 0xff00)
                {
                    return(0);
                }

                s.Read(data, 0, len);
                //fread(data, 1, len, ifp);
                switch (tag)
                {
                case 0xffc3:
                    jh.sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
                    jh.algo = tag & 0xff;
                    jh.bits = data[0];
                    jh.high = data[1] << 8 | data[2];
                    jh.wide = data[3] << 8 | data[4];
                    jh.clrs = data[5] + jh.sraw;
                    //if (len == 9 && !dng_version) getc(ifp);
                    break;

                case 0xffc1:
                case 0xffc0:
                    jh.algo = tag & 0xff;
                    jh.bits = data[0];
                    jh.high = data[1] << 8 | data[2];
                    jh.wide = data[3] << 8 | data[4];
                    jh.clrs = data[5] + jh.sraw;
                    //if (len == 9 && !dng_version) getc(ifp);
                    break;

                case 0xffc4:
                    //if (info_only) break;
                    fixed(byte *ptr = data)
                    {
                        for (dp = ptr; dp < ptr + len && ((c = *dp++) & -20) == 0;)
                        {
                            jh.free[c] = jh.huff[c] = make_decoder_ref(&dp);
                        }
                    }

                    break;

                case 0xffda:
                    jh.psv   = data[1 + data[0] * 2];
                    jh.bits -= data[3 + data[0] * 2] & 15;
                    break;

                case 0xffdb:
                    for (c = 0; c < 64; c++)
                    {
                        jh.quant[c] = (ushort)(data[c * 2 + 1] << 8 | data[c * 2 + 2]);
                    }
                    break;

                case 0xffdd:
                    jh.restart = data[0] << 8 | data[1];
                    break;
                }
            } while (tag != 0xffda);

            for (c = 0; c < 19; c++)
            {
                if (jh.huff[c + 1] == null)
                {
                    jh.huff[c + 1] = jh.huff[c];
                }
            }

            //if (jh.sraw) {

            //       FORC(4)        jh->huff[2 + c] = jh->huff[1];

            //       FORC(jh->sraw) jh->huff[1 + c] = jh->huff[0];
            //}
            jh.row = new ushort[jh.wide * jh.clrs * 2]; //(ushort*)calloc(jh->wide* jh->clrs, 4);
            //merror(jh->row, "ljpeg_start()");
            return(1);
        }
Ejemplo n.º 3
0
        private unsafe ushort *ljpeg_row(int jrow, jhead jh, Stream s)
        {
            int    col, c, diff, pred, spred = 0;
            ushort mark = 0;

            ushort *[] row = new ushort *[3];

            if (jrow * jh.wide % jh.restart == 0)
            {
                for (c = 0; c < 6; c++)
                {
                    jh.vpred[c] = 1 << (jh.bits - 1);
                }

                if (jrow > 0)
                {
                    s.Seek(-2, SeekOrigin.Current);
                    //fseek(ifp, -2, SEEK_CUR);
                    do
                    {
                        mark = (ushort)((mark << 8) + (c = s.ReadByte()));
                    }while (s.Position < s.Length - 1 && mark >> 4 != 0xffd);
                }
                getbithuff(-1, null, s);
            }

            for (c = 0; c < 3; c++)
            {
                row[c] = jh.rowPtr + jh.wide * jh.clrs * ((jrow + c) & 1);
            }

            for (col = 0; col < jh.wide; col++)
            {
                for (c = 0; c < jh.clrs; c++)
                {
                    fixed(ushort *ptr = jh.huff[c])
                    {
                        diff = ljpeg_diff(ptr, s);
                        if (jh.sraw > 0 && c <= jh.sraw && (col | c) > 0)
                        {
                            pred = spred;
                        }
                        else if (col > 0)
                        {
                            pred = row[0][-jh.clrs];
                        }
                        else
                        {
                            pred = (jh.vpred[c] += diff) - diff;
                        }
                        if (jrow > 0 && col > 0)
                        {
                            switch (jh.psv)
                            {
                            case 1: break;

                            case 2: pred = row[1][0]; break;

                            case 3: pred = row[1][-jh.clrs]; break;

                            case 4: pred = pred + row[1][0] - row[1][-jh.clrs]; break;

                            case 5: pred = pred + ((row[1][0] - row[1][-jh.clrs]) >> 1); break;

                            case 6: pred = row[1][0] + ((pred - row[1][-jh.clrs]) >> 1); break;

                            case 7: pred = (pred + row[1][0]) >> 1; break;

                            default: pred = 0;
                                break;
                            }
                        }
                        if ((*row[0] = (ushort)(pred + diff)) >> jh.bits != 0)
                        {
                            return(null);
                        }
                        if (c <= jh.sraw)
                        {
                            spred = *row[0];
                        }
                        row[0]++; row[1]++;
                    }
                }
            }
            return(row[2]);
        }
Ejemplo n.º 4
0
        public DNGFile(string aFileName)
            : base(aFileName)
        {
            IFDDNGVersion version = mIfds[0].GetEntry <IFDDNGVersion>();

            isDNGVersionLarge = version == null;
            if (version != null)
            {
                isDNGVersionLarge = version.Value[1] > 1;
            }


            ImageFileDirectory rawIFD = SetMembers();

            //try to read additional noise models
            try
            {
                ExtraCameraProfiles profiles = ExtraCameraProfiles.Load("ExtraCameraProfiles.xml");
                string make        = mIfds[0].GetEntry <IFDMake>()?.Value;
                string uniqueModel = mIfds[0].GetEntry <IFDDNGUniqueCameraModel>()?.Value;

                ExtraCameraProfile profile = profiles.GetProfile(make, uniqueModel);

                double a, b;
                (a, b) = profile.NoiseModel.GetValue(mISO);

                if (a != 0.0)
                {
                    mNoiseModelAlpha = (float)a;
                    mNoiseModelBeta  = (float)b;
                }
            }
            catch (Exception)
            {
            }

            //get non-global blacklevels
            ushort[] blackLevelV = new ushort[mHeight];
            ushort[] blackLevelH = new ushort[mWidth];

            int maxBlackLevel                 = 0;
            IFDDNGBlackLevelDeltaV deltaV     = rawIFD.GetEntry <IFDDNGBlackLevelDeltaV>();
            IFDDNGActiveArea       activeArea = rawIFD.GetEntry <IFDDNGActiveArea>();

            int blackOffsetH = 0;
            int blackOffsetV = 0;
            int borderBottom = 0;
            int borderRight  = 0;

            if (activeArea != null)
            {
                blackOffsetV = (int)activeArea.Value[0];
                blackOffsetH = (int)activeArea.Value[1];
                borderBottom = mHeight - (int)activeArea.Value[2];
                borderRight  = mWidth - (int)activeArea.Value[3];
            }


            if (deltaV != null)
            {
                if (deltaV.Value.Length + blackOffsetV + borderBottom != mHeight)
                {
                    throw new Exception("Count in IFDDNGBlackLevelDeltaV doesn't fit image height");
                }

                for (int i = 0; i < deltaV.Value.Length; i++)
                {
                    blackLevelV[blackOffsetV + i] = (ushort)deltaV.Value[i].Value;
                }
            }

            IFDDNGBlackLevelDeltaH deltaH = rawIFD.GetEntry <IFDDNGBlackLevelDeltaH>();

            if (deltaH != null)
            {
                if (deltaH.Value.Length + blackOffsetH + borderRight != mWidth)
                {
                    throw new Exception("Count in IFDDNGBlackLevelDeltaH doesn't fit image width");
                }

                for (int i = 0; i < deltaH.Value.Length; i++)
                {
                    blackLevelH[blackOffsetH + i] = (ushort)deltaH.Value[i].Value;
                }
            }

            //read actual image data

            //data stored in tiles:
            if (rawIFD.GetEntry <IFDTileWidth>() != null)
            {
                int tileWidth  = (int)rawIFD.GetEntry <IFDTileWidth>().Value;
                int tileHeight = (int)rawIFD.GetEntry <IFDTileLength>().Value;

                uint[] offsets    = rawIFD.GetEntry <IFDTileOffsets>().Value;
                uint[] byteCounts = rawIFD.GetEntry <IFDTileByteCounts>().Value;

                mRawImage = new ushort[mHeight, mWidth];

                int row = 0;
                int col = 0;



                if (rawIFD.GetEntry <IFDCompression>().Value == IFDCompression.Compression.LosslessJPEG)
                {
                    for (int tile = 0; tile < offsets.Length; tile++)
                    {
                        byte[] data;
                        Seek(offsets[tile], SeekOrigin.Begin);
                        data = mFileReader.ReadBytes((int)byteCounts[tile]);
                        MemoryStream ms = new MemoryStream(data);
                        ms.Seek(0, SeekOrigin.Begin);
                        jhead jh = new jhead();
                        int   ret = ljpeg_start(jh, 0, ms);
                        int   jrow, jcol;
                        if (ret > 0 && jh != null)
                        {
                            int jwide = jh.wide;
                            jwide *= jh.clrs;


                            unsafe
                            {
                                if (jh.algo == 0xc3) //lossless JPEG
                                {
                                    for (jrow = 0; jrow < jh.high; jrow++)
                                    {
                                        fixed(ushort *ptr = jh.row)
                                        {
                                            jh.rowPtr = ptr;
                                            ushort *rp = ljpeg_row(jrow, jh, ms);

                                            for (jcol = 0; jcol < jwide; jcol++)
                                            {
                                                if (jcol + col < mWidth && jrow + row < mHeight)
                                                {
                                                    int black = blackLevelH[jcol + col];
                                                    black        += blackLevelV[jrow + row];
                                                    maxBlackLevel = Math.Max(maxBlackLevel, black);
                                                    if (mLinearizationTable != null)
                                                    {
                                                        mRawImage[row + jrow, col + jcol] = (ushort)Math.Max(0, (int)(mLinearizationTable.Value[rp[jcol] < mLinearizationTable.Value.Length ? rp[jcol] : mLinearizationTable.Value.Length - 1]) - black);
                                                    }
                                                    else
                                                    {
                                                        mRawImage[row + jrow, col + jcol] = (ushort)Math.Max(0, (int)(rp[jcol] - black));
                                                    }
                                                }
                                            }
                                            jh.rowPtr = null;
                                        }
                                    }
                                }
                            }
                        }
                        col += tileWidth;
                        if (col >= mWidth)
                        {
                            col  = 0;
                            row += tileHeight;
                        }
                    }
                }
                else
                {
                    throw new ArgumentException("I don't know how to read that file :(");
                }
            }
            //data stored in strips:
            else if (rawIFD.GetEntry <IFDStripOffsets>() != null)
            {
                uint[] offsets      = rawIFD.GetEntry <IFDStripOffsets>().Value;
                uint[] byteCounts   = rawIFD.GetEntry <IFDStripByteCounts>().Value;
                uint   rowsPerStrip = rawIFD.GetEntry <IFDRowsPerStrip>().Value;

                if (rawIFD.GetEntry <IFDCompression>().Value == IFDCompression.Compression.LosslessJPEG)
                {
                    mRawImage = new ushort[mHeight, mWidth];
                    for (int strip = 0; strip < offsets.Length; strip++)
                    {
                        byte[] data;
                        Seek(offsets[strip], SeekOrigin.Begin);
                        data = mFileReader.ReadBytes((int)byteCounts[strip]);
                        MemoryStream ms = new MemoryStream(data);
                        ms.Seek(0, SeekOrigin.Begin);
                        jhead jh = new jhead();
                        int   ret = ljpeg_start(jh, 0, ms);
                        int   jrow, jcol;
                        if (ret > 0 && jh != null)
                        {
                            int jwide = jh.wide;
                            jwide *= jh.clrs;


                            unsafe
                            {
                                if (jh.algo == 0xc3) //lossless JPEG
                                {
                                    for (jrow = 0; jrow < jh.high; jrow++)
                                    {
                                        fixed(ushort *ptr = jh.row)
                                        {
                                            jh.rowPtr = ptr;
                                            ushort *rp = ljpeg_row(jrow, jh, ms);

                                            for (jcol = 0; jcol < jwide; jcol++)
                                            {
                                                if (jcol < mWidth && jrow + (strip * rowsPerStrip) < mHeight)
                                                {
                                                    int black = blackLevelH[jcol];
                                                    black        += blackLevelV[(strip * rowsPerStrip) + jrow];
                                                    maxBlackLevel = Math.Max(maxBlackLevel, black);
                                                    if (mLinearizationTable != null)
                                                    {
                                                        mRawImage[(strip * rowsPerStrip) + jrow, jcol] = (ushort)Math.Max(0, (int)((mLinearizationTable.Value[rp[jcol] < mLinearizationTable.Value.Length ? rp[jcol] : mLinearizationTable.Value.Length - 1]) - black));
                                                    }
                                                    else
                                                    {
                                                        mRawImage[(strip * rowsPerStrip) + jrow, jcol] = (ushort)Math.Max(0, (int)(rp[jcol] - black));
                                                    }
                                                }
                                            }
                                            jh.rowPtr = null;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else if (rawIFD.GetEntry <IFDCompression>().Value == IFDCompression.Compression.NoCompression)
                {
                    mRawImage = new ushort[mHeight, mWidth];

                    if (mBitDepth == 16)
                    {
                        for (int strip = 0; strip < offsets.Length; strip++)
                        {
                            byte[] data;
                            Seek(offsets[strip], SeekOrigin.Begin);
                            data = mFileReader.ReadBytes((int)byteCounts[strip]);

                            unsafe
                            {
                                fixed(byte *ptr = data)
                                {
                                    ushort *usptr = (ushort *)ptr;

                                    for (int pixel = 0; pixel < data.Length / 2; pixel++)
                                    {
                                        int row = strip * (int)rowsPerStrip;
                                        int col = pixel;
                                        if (col >= mWidth)
                                        {
                                            row += pixel / mWidth;
                                            col  = pixel % mWidth;
                                        }

                                        int black = blackLevelH[col];
                                        black        += blackLevelV[row];
                                        maxBlackLevel = Math.Max(maxBlackLevel, black);
                                        if (mLinearizationTable != null)
                                        {
                                            mRawImage[row, col] = (ushort)Math.Max(0, (int)(mLinearizationTable.Value[usptr[pixel] < mLinearizationTable.Value.Length ? usptr[pixel] : mLinearizationTable.Value.Length - 1]) - black);
                                        }
                                        else
                                        {
                                            mRawImage[row, col] = (ushort)Math.Max(0, (int)(usptr[pixel]) - black);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else if (mBitDepth < 16)
                    {
                        for (int strip = 0; strip < offsets.Length; strip++)
                        {
                            byte[] data;
                            Seek(offsets[strip], SeekOrigin.Begin);
                            data = mFileReader.ReadBytes((int)byteCounts[strip]);

                            uint pos    = 0;
                            int  offset = 0;

                            for (int line = 0; line < rowsPerStrip; line++)
                            {
                                for (int pixel = 0; pixel < mWidth; pixel++)
                                {
                                    int row = strip * (int)rowsPerStrip + line;
                                    int col = pixel;

                                    uint val = data[pos];

                                    while (offset < mBitDepth)
                                    {
                                        val     = data[pos];
                                        bitbuf  = (bitbuf << 8) + val;
                                        offset += 8;
                                        pos++;
                                    }

                                    val     = bitbuf << (32 - offset) >> (32 - mBitDepth);
                                    offset -= mBitDepth;

                                    int black = blackLevelH[col];
                                    black        += blackLevelV[row];
                                    maxBlackLevel = Math.Max(maxBlackLevel, black);

                                    if (mLinearizationTable != null)
                                    {
                                        mRawImage[row, col] = (ushort)Math.Max(0, (int)(mLinearizationTable.Value[val < mLinearizationTable.Value.Length ? (ushort)(val) : mLinearizationTable.Value.Length - 1]) - black);
                                    }
                                    else
                                    {
                                        mRawImage[row, col] = (ushort)Math.Max(0, (int)(val) - black);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    throw new ArgumentException("I don't know how to read that file :(");
                }
            }
            //close the file
            Close();

            WhiteLevel[0] -= maxBlackLevel;
            WhiteLevel[1] -= maxBlackLevel;
            WhiteLevel[2] -= maxBlackLevel;
        }