Exemple #1
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();
        }
Exemple #2
0
        IFD parseDngPrivateData(Tag t)
        {
            /*
             * 1. Six bytes containing the zero-terminated string "Adobe". (The DNG specification calls for the DNGPrivateData tag to start with an ASCII string identifying the creator/format).
             * 2. 4 bytes: an ASCII string ("MakN" for a Makernote),  indicating what sort of data is being stored here. Note that this is not zero-terminated.
             * 3. A four-byte count (number of data bytes following); this is the length of the original MakerNote data. (This is always in "most significant byte first" format).
             * 4. 2 bytes: the byte-order indicator from the original file (the usual 'MM'/4D4D or 'II'/4949).
             * 5. 4 bytes: the original file offset for the MakerNote tag data (stored according to the byte order given above).
             * 6. The contents of the MakerNote tag. This is a simple byte-for-byte copy, with no modification.
             */
            uint size = t.dataCount;

            Common.ConvertArray(ref t.data, out byte[] data);
            Common.ByteToChar(ref data, out char[] dataAsChar);
            string id = new String(dataAsChar);

            if (!id.StartsWith("Adobe"))
            {
                Debug.WriteLine("Not Adobe Private data");
                return(null);
            }

            if (!(data[6] == 'M' && data[7] == 'a' && data[8] == 'k' && data[9] == 'N'))
            {
                Debug.WriteLine("Not Makernote");
                return(null);
            }

            data = data.Skip(10).ToArray();
            uint count;

            count = (uint)data[0] << 24 | (uint)data[1] << 16 | (uint)data[2] << 8 | data[3];

            data = data.Skip(4).ToArray();
            if (count > size)
            {
                Debug.WriteLine("Error reading TIFF structure (invalid size). File Corrupt");
                return(null);
            }
            Endianness makernote_endian = Endianness.unknown;

            if (data[0] == 0x49 && data[1] == 0x49)
            {
                makernote_endian = Endianness.little;
            }
            else if (data[0] == 0x4D && data[1] == 0x4D)
            {
                makernote_endian = Endianness.big;
            }
            else
            {
                Debug.WriteLine("Cannot determine endianess of DNG makernote");
                return(null);
            }
            data = data.Skip(2).ToArray();
            uint org_offset;


            org_offset = (uint)data[0] << 24 | (uint)data[1] << 16 | (uint)data[2] << 8 | data[3];

            data = data.Skip(4).ToArray();
            /* We don't parse original makernotes that are placed after 300MB mark in the original file */
            if (org_offset + count > 300 * 1024 * 1024)
            {
                Debug.WriteLine("Adobe Private data: original offset of makernote is past 300MB offset");
                return(null);
            }
            /* Create fake tiff with original offsets */
            //byte[] maker_data = new byte[count];
            // Common.memcopy(ref maker_data, ref data, count, 0, 0);
            TIFFBinaryReader maker_map = new TIFFBinaryReader(TIFFBinaryReader.streamFromArray(data));

            IFD maker_ifd;

            try
            {
                maker_ifd = parseMakerNote(maker_map, 0, makernote_endian);
            }
            catch (TiffParserException e)
            {
                Debug.WriteLine(e.Message);
                return(null);
            }
            return(maker_ifd);
        }