public void DecompressNikon(TIFFBinaryReader metadata, UInt32 w, UInt32 h, UInt32 bitsPS, UInt32 offset, UInt32 size)
        {
            metadata.Position = 0;
            UInt32 v0         = metadata.ReadByte();
            UInt32 v1         = metadata.ReadByte();
            UInt32 huffSelect = 0;
            UInt32 split      = 0;

            int[] pUp1 = new int[2];
            int[] pUp2 = new int[2];
            mUseBigtable = true;

            //_RPT2(0, "Nef version v0:%u, v1:%u\n", v0, v1);

            if (v0 == 73 || v1 == 88)
            {
                metadata.ReadBytes(2110);
            }

            if (v0 == 70)
            {
                huffSelect = 2;
            }
            if (bitsPS == 14)
            {
                huffSelect += 3;
            }

            pUp1[0] = metadata.ReadInt16();
            pUp1[1] = metadata.ReadInt16();
            pUp2[0] = metadata.ReadInt16();
            pUp2[1] = metadata.ReadInt16();

            int    _max  = 1 << (int)bitsPS & 0x7fff;
            UInt32 step  = 0;
            UInt32 csize = metadata.ReadUInt16();

            if (csize > 1)
            {
                step = (uint)_max / (csize - 1);
            }
            if (v0 == 68 && v1 == 32 && step > 0)
            {
                for (UInt32 i = 0; i < csize; i++)
                {
                    curve[i * step] = (ushort)metadata.ReadInt16();
                }
                for (int i = 0; i < _max; i++)
                {
                    curve[i] = (ushort)((curve[i - i % step] * (step - i % step) + curve[i - i % step + step] * (i % step)) / step);
                }
                metadata.Position = (562);
                split             = metadata.ReadUInt16();
            }
            else if (v0 != 70 && csize <= 0x4001)
            {
                for (UInt32 i = 0; i < csize; i++)
                {
                    curve[i] = metadata.ReadUInt16();
                }
                _max = (int)csize;
            }
            initTable(huffSelect);

            mRaw.whitePoint = curve[_max - 1];
            mRaw.blackLevel = curve[0];
            if (!uncorrectedRawValues)
            {
                mRaw.setTable(curve, _max, true);
            }

            UInt32     x, y;
            BitPumpMSB bits  = new BitPumpMSB(ref input, offset, size);
            UInt32     pitch = w;

            int    pLeft1 = 0;
            int    pLeft2 = 0;
            UInt32 cw     = w / 2;
            UInt32 random = bits.peekBits(24);

            for (y = 0; y < h; y++)
            {
                if (split != 0 && (y == split))
                {
                    initTable(huffSelect + 1);
                }
                pUp1[y & 1] += HuffDecodeNikon(bits);
                pUp2[y & 1] += HuffDecodeNikon(bits);
                pLeft1       = pUp1[y & 1];
                pLeft2       = pUp2[y & 1];
                uint dest = y * pitch;
                mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random);
                mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random);
                for (x = 1; x < cw; x++)
                {
                    bits.checkPos();
                    pLeft1 += HuffDecodeNikon(bits);
                    pLeft2 += HuffDecodeNikon(bits);
                    mRaw.setWithLookUp((ushort)Common.clampbits(pLeft1, 15), ref mRaw.rawData, dest++, ref random);
                    mRaw.setWithLookUp((ushort)Common.clampbits(pLeft2, 15), ref mRaw.rawData, dest++, ref random);
                }
            }

            if (uncorrectedRawValues)
            {
                mRaw.setTable(curve, _max, false);
            }
            else
            {
                mRaw.table = (null);
            }
        }
Example #2
0
        /* This will attempt to parse makernotes and return it as an IFD */
        IFD parseMakerNote(TIFFBinaryReader reader, uint off, Endianness parent_end)
        {
            IFD              maker_ifd = null;
            uint             offset    = 0;
            TIFFBinaryReader mFile     = null;

            reader.Position = off;
            byte[] data = reader.ReadBytes(100);
            // Pentax makernote starts with AOC\0 - If it's there, skip it
            if (data[0] == 0x41 && data[1] == 0x4f && data[2] == 0x43 && data[3] == 0)
            {
                //data = data.Skip(4).ToArray();
                offset += 4;
            }

            // Pentax also has "PENTAX" at the start, makernote starts at 8
            if (data[0 + offset] == 0x50 && data[1 + offset] == 0x45 &&
                data[2 + offset] == 0x4e && data[3 + offset] == 0x54 && data[4 + offset] == 0x41 && data[5 + offset] == 0x58)
            {
                mFile      = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length);
                parent_end = getTiffEndianness(data.Skip(8).ToArray());
                if (parent_end == Endianness.unknown)
                {
                    throw new TiffParserException("Cannot determine Pentax makernote endianness");
                }
                //data = data.Skip(10).ToArray();
                offset += 10;
                // Check for fuji signature in else block so we don't accidentally leak FileMap
            }
            else if (Common.memcmp(ref fuji_signature, ref data))
            {
                offset = 12;
                mFile  = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length);
            }
            else if (Common.memcmp(ref nikon_v3_signature, ref data))
            {
                //offset = 10;
                offset = 10;
                // Read endianness
                if (data[0 + offset] == 0x49 && data[1 + offset] == 0x49)
                {
                    parent_end = Endianness.little;
                    mFile      = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length);
                    offset     = 8;
                }
                else if (data[0 + offset] == 0x4D && data[1 + offset] == 0x4D)
                {
                    parent_end = Endianness.big;
                    mFile      = new TIFFBinaryReaderRE(reader.BaseStream, offset + off, (uint)data.Length);
                    offset     = 8;
                }
            }

            // Panasonic has the word Exif at byte 6, a complete Tiff header starts at byte 12
            // This TIFF is 0 offset based
            if (data[6] == 0x45 && data[7] == 0x78 && data[8] == 0x69 && data[9] == 0x66)
            {
                parent_end = getTiffEndianness(data.Skip(12).ToArray());
                if (parent_end == Endianness.unknown)
                {
                    throw new TiffParserException("Cannot determine Panasonic makernote endianness");
                }
                offset = 20;
            }

            // Some have MM or II to indicate endianness - read that
            if (data[0] == 0x49 && data[1] == 0x49)
            {
                offset    += 2;
                parent_end = Endianness.little;
            }
            else if (data[0] == 0x4D && data[1] == 0x4D)
            {
                parent_end = Endianness.big;
                offset    += 2;
            }

            // Olympus starts the makernote with their own name, sometimes truncated
            if (Common.strncmp(data, "OLYMP", 5))
            {
                offset += 8;
                if (Common.strncmp(data, "OLYMPUS", 7))
                {
                    offset += 4;
                }
            }

            // Epson starts the makernote with its own name
            if (Common.strncmp(data, "EPSON", 5))
            {
                offset += 8;
            }

            // Attempt to parse the rest as an IFD
            try
            {
                if (mFile == null)
                {
                    if (parent_end == Endianness.little)
                    {
                        mFile = new TIFFBinaryReader(reader.BaseStream, offset + off, (uint)data.Length);
                    }
                    else if (parent_end == Endianness.big)
                    {
                        mFile = new TIFFBinaryReaderRE(reader.BaseStream, offset + off, (uint)data.Length);
                    }
                }

                /* if (parent_end == getHostEndianness())
                 *   maker_ifd = new IFD(mFile, offset, depth);
                 * else
                 *   maker_ifd = new IFDBE(mFile, offset, depth);*/
                maker_ifd = new IFD(mFile, offset, endian, depth);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                return(null);
            }
            // If the structure cannot be read, a TiffParserException will be thrown.

            return(maker_ifd);
        }
Example #3
0
        public IFD(TIFFBinaryReader fileStream, uint offset, Endianness endian)
        {
            this.endian         = endian;
            fileStream.Position = offset;
            tagNumber           = fileStream.ReadUInt16();
            tags = new Dictionary <TagType, Tag>();

            for (int i = 0; i < tagNumber; i++)
            {
                Tag temp = new Tag();
                temp.tagId = (TagType)fileStream.ReadUInt16();
                //add the displayname
                temp.displayName = null;

                temp.dataType  = (TiffDataType)fileStream.ReadUInt16();
                temp.dataCount = fileStream.ReadUInt32();

                //IF makernote, do not parse data
                //if (temp.tagId == TagType.MAKERNOTE || temp.tagId == TagType.MAKERNOTE_ALT) temp.dataCount = 0;

                temp.dataOffset = 0;
                if (((temp.dataCount * temp.getTypeSize(temp.dataType) > 4)))
                {
                    temp.dataOffset = fileStream.ReadUInt32();
                }

                //Get the tag data
                temp.data = new Object[temp.dataCount];
                long firstPosition = fileStream.Position;
                if (temp.dataOffset > 1)
                {
                    fileStream.Position = temp.dataOffset;
                    //todo check if correct
                }

                if (temp.tagId != TagType.MAKERNOTE && temp.tagId != TagType.MAKERNOTE_ALT)
                {
                    for (int j = 0; j < temp.dataCount; j++)
                    {
                        switch (temp.dataType)
                        {
                        case TiffDataType.BYTE:
                        case TiffDataType.UNDEFINED:
                        case TiffDataType.ASCII:
                        case TiffDataType.OFFSET:
                            temp.data[j] = fileStream.ReadByte();
                            break;

                        case TiffDataType.SHORT:
                            temp.data[j] = fileStream.ReadUInt16();
                            break;

                        case TiffDataType.LONG:
                            temp.data[j] = fileStream.ReadUInt32();
                            break;

                        case TiffDataType.RATIONAL:
                            temp.data[j] = fileStream.ReadDouble();
                            break;

                        case TiffDataType.SBYTE:
                            temp.data[j] = fileStream.ReadSByte();
                            break;

                        case TiffDataType.SSHORT:
                            temp.data[j] = fileStream.ReadInt16();
                            //if (temp.dataOffset == 0 && temp.dataCount == 1) fileStream.ReadInt16();
                            break;

                        case TiffDataType.SLONG:
                            temp.data[j] = fileStream.ReadInt32();
                            break;

                        case TiffDataType.SRATIONAL:
                            //Because the nikonmakernote is broken with the tag 0x19 wich is double but offset of zero.
                            //TODO remove this Fix
                            if (temp.dataOffset == 0)
                            {
                                temp.data[j] = .0;
                            }
                            else
                            {
                                temp.data[j] = fileStream.ReadDouble();
                            }
                            break;

                        case TiffDataType.FLOAT:
                            temp.data[j] = fileStream.ReadSingle();
                            break;

                        case TiffDataType.DOUBLE:
                            temp.data[j] = fileStream.ReadDouble();
                            break;
                        }
                    }
                }//Special tag
                switch (temp.tagId)
                {
                case TagType.DNGPRIVATEDATA:
                {
                    try
                    {
                        IFD maker_ifd = parseDngPrivateData(temp);
                        if (maker_ifd != null)
                        {
                            subIFD.Add(maker_ifd);
                        }
                        temp.data = null;
                    }
                    catch (TiffParserException)
                    {         // Unparsable private data are added as entries
                    }
                    catch (IOException)
                    {         // Unparsable private data are added as entries
                    }
                }
                break;

                case TagType.MAKERNOTE:
                case TagType.MAKERNOTE_ALT:
                {
                    try
                    {
                        //save current position
                        long pos       = fileStream.Position;
                        IFD  makernote = parseMakerNote(fileStream, temp.dataOffset, endian);
                        if (makernote != null)
                        {
                            subIFD.Add(makernote);
                        }

                        //correct here
                        fileStream.BaseStream.Position = pos;
                        //return to current position
                    }
                    catch (TiffParserException)
                    {         // Unparsable makernotes are added as entries
                    }
                    catch (IOException)
                    {         // Unparsable makernotes are added as entries
                    }
                }
                break;

                case TagType.FUJI_RAW_IFD:
                    if (temp.dataType == TiffDataType.OFFSET)     // FUJI - correct type
                    {
                        temp.dataType = TiffDataType.LONG;
                    }
                    goto case TagType.SUBIFDS;

                case TagType.SUBIFDS:
                case TagType.EXIFIFDPOINTER:
                case TagType.NIKONTHUMB:
                    long p = fileStream.Position;
                    try
                    {
                        for (Int32 k = 0; k < temp.dataCount; k++)
                        {
                            subIFD.Add(new IFD(fileStream, Convert.ToUInt32(temp.data[k]), endian, depth));
                        }
                    }
                    catch (TiffParserException)
                    {     // Unparsable subifds are added as entries
                    }
                    catch (IOException)
                    {     // Unparsable subifds are added as entries
                    }
                    fileStream.BaseStream.Position = p;
                    break;
                }
                //transform data ToString
                if (temp.dataType == TiffDataType.ASCII)
                {
                    //remove \0 if any
                    if ((byte)temp.data[temp.dataCount - 1] == 0)
                    {
                        temp.data[temp.dataCount - 1] = (byte)' ';
                    }
                    string t = Encoding.ASCII.GetString(temp.data.Cast <byte>().ToArray());
                    temp.data    = new Object[1];
                    temp.data[0] = t;
                }

                if (temp.dataOffset > 1)
                {
                    fileStream.BaseStream.Position = firstPosition;
                }
                else if (temp.dataOffset == 0)
                {
                    int k = (int)temp.dataCount * temp.getTypeSize(temp.dataType);
                    if (k < 4)
                    {
                        fileStream.ReadBytes(4 - k);
                    }
                }

                /*else
                 * {
                 *  temp.dataCount = 0;
                 *  temp.data = null;
                 * }*/
                if (!tags.ContainsKey(temp.tagId))
                {
                    tags.Add(temp.tagId, temp);
                }
                else
                {
                    Debug.WriteLine("tags already exist");
                }
            }
            nextOffset = fileStream.ReadUInt16();
        }
        public void parseSOS()
        {
            if (!frame.initialized)
            {
                throw new Exception("parseSOS: Frame not yet initialized (SOF Marker not parsed)");
            }

            UInt32 headerLength = (uint)input.ReadInt16();
            UInt32 soscps       = input.ReadByte();

            if (frame.cps != soscps)
            {
                throw new Exception("parseSOS: Component number mismatch.");
            }

            for (UInt32 i = 0; i < frame.cps; i++)
            {
                UInt32 cs = input.ReadByte();

                UInt32 count = 0;  // Find the correct component
                while (frame.compInfo[count].componentId != cs)
                {
                    if (count >= frame.cps)
                    {
                        throw new Exception("parseSOS: Invalid Component Selector");
                    }
                    count++;
                }

                UInt32 b1 = input.ReadByte();
                UInt32 td = b1 >> 4;
                if (td > 3)
                {
                    throw new Exception("parseSOS: Invalid Huffman table selection");
                }
                if (!huff[td].initialized)
                {
                    throw new Exception("parseSOS: Invalid Huffman table selection, not defined.");
                }

                if (count > 3)
                {
                    throw new Exception("parseSOS: Component count out of range");
                }

                frame.compInfo[count].dcTblNo = td;
            }

            // Get predictor
            pred = input.ReadByte();
            if (pred > 7)
            {
                throw new Exception("parseSOS: Invalid predictor mode.");
            }

            input.ReadBytes(1);                    // Se + Ah Not used in LJPEG
            UInt32 b = input.ReadByte();

            Pt = b & 0xf;        // Point Transform

            UInt32 cheadersize = 3 + frame.cps * 2 + 3;

            //_ASSERTE(cheadersize == headerLength);

            bits = new BitPumpJPEG(input);
            decodeScan();
            input.ReadBytes((int)bits.getOffset());
        }