Example #1
0
        /// <summary>
        ///    Try to parse the given IFD entry, used to discover format-specific entries.
        /// </summary>
        /// <param name="tag">
        ///    A <see cref="System.UInt16"/> with the tag of the entry.
        /// </param>
        /// <param name="type">
        ///    A <see cref="System.UInt16"/> with the type of the entry.
        /// </param>
        /// <param name="count">
        ///    A <see cref="System.UInt32"/> with the data count of the entry.
        /// </param>
        /// <param name="base_offset">
        ///    A <see cref="System.Int64"/> with the base offset which every offsets in the
        ///    IFD are relative to.
        /// </param>
        /// <param name="offset">
        ///    A <see cref="System.UInt32"/> with the offset of the entry.
        /// </param>
        /// <returns>
        ///    A <see cref="IFDEntry"/> with the given parameters, or null if none was parsed, after
        ///    which the normal TIFF parsing is used.
        /// </returns>
        protected override IFDEntry ParseIFDEntry(ushort tag, ushort type, uint count, long base_offset, uint offset)
        {
            if (tag == (ushort)Nikon3MakerNoteEntryTag.Preview)
            {
                // SubIFD with Preview Image
                // The entry itself is usually a long
                // 2TODO: handle JPEGInterchangeFormat and JPEGInterchangeFormatLength correctly

                // The preview field contains a long with an offset to an IFD
                // that contains the preview image. We need to be careful
                // though: this IFD does not contain a valid next-offset
                // pointer. For this reason, we only read the first IFD and
                // ignore the rest (which is preview image data, directly
                // starting after the IFD entries).

                type = (ushort)IFDEntryType.IFD;

                IFDStructure ifd_structure = new IFDStructure();
                IFDReader    reader        = CreateSubIFDReader(file, is_bigendian, ifd_structure, base_offset, offset, max_offset);

                reader.Read(1);
                return(new SubIFDEntry(tag, type, (uint)ifd_structure.Directories.Length, ifd_structure));
            }
            return(base.ParseIFDEntry(tag, type, count, base_offset, offset));
        }
Example #2
0
 protected override IFDEntry ParseIFDEntry(ushort tag, ushort type, uint count, long base_offset, uint offset)
 {
     if (tag == (ushort)Nikon3MakerNoteEntryTag.Preview)
     {
         type = (ushort)IFDEntryType.IFD;
         IFDStructure ifd_structure = new IFDStructure();
         IFDReader    reader        = CreateSubIFDReader(file, is_bigendian, ifd_structure, base_offset, offset, max_offset);
         reader.Read(1);
         return(new SubIFDEntry(tag, type, (uint)ifd_structure.Directories.Length, ifd_structure));
     }
     return(base.ParseIFDEntry(tag, type, count, base_offset, offset));
 }
Example #3
0
        private void ReadAPP1Segment(ushort length)
        {
            long       position           = Tell;
            ByteVector data               = null;
            int        exif_header_length = 14;

            if ((ImageTag.TagTypes & TagLib.TagTypes.TiffIFD) == 0x00 && length >= exif_header_length)
            {
                data = ReadBlock(exif_header_length);
                if (data.Count == exif_header_length && data.Mid(0, 6).ToString().Equals(EXIF_IDENTIFIER))
                {
                    bool   is_bigendian = data.Mid(6, 2).ToString().Equals("MM");
                    ushort magic        = data.Mid(8, 2).ToUShort(is_bigendian);
                    if (magic != 42)
                    {
                        throw new Exception(String.Format("Invalid TIFF magic: {0}", magic));
                    }
                    uint ifd_offset = data.Mid(10, 4).ToUInt(is_bigendian);
                    var  exif       = new IFDTag();
                    var  reader     = new IFDReader(this, is_bigendian, exif.Structure, position + 6, ifd_offset, (uint)(length - 6));
                    reader.Read();
                    ImageTag.AddTag(exif);
                    AddMetadataBlock(position - 4, length + 4);
                    return;
                }
            }
            int xmp_header_length = XmpTag.XAP_NS.Length + 1;

            if ((ImageTag.TagTypes & TagLib.TagTypes.XMP) == 0x00 && length >= xmp_header_length)
            {
                if (data == null)
                {
                    data = ReadBlock(xmp_header_length);
                }
                else
                {
                    data.Add(ReadBlock(xmp_header_length - exif_header_length));
                }
                if (data.ToString().Equals(XmpTag.XAP_NS + "\0"))
                {
                    ByteVector xmp_data = ReadBlock(length - xmp_header_length);
                    ImageTag.AddTag(new XmpTag(xmp_data.ToString(), this));
                    AddMetadataBlock(position - 4, length + 4);
                }
            }
        }
Example #4
0
        /// <summary>
        ///    Reads an APP1 segment to find EXIF or XMP metadata.
        /// </summary>
        /// <param name="length">
        ///    The length of the segment that will be read.
        /// </param>
        private void ReadAPP1Segment(ushort length)
        {
            long       position = Tell;
            ByteVector data     = null;

            // for an Exif segment, the data block consists of 14 bytes of:
            //    * 6 bytes Exif identifier string
            //    * 2 bytes bigendian indication MM (or II)
            //    * 2 bytes Tiff magic number (42)
            //    * 4 bytes offset of the first IFD in this segment
            //
            //    the last two points are alreay encoded according to
            //    big- or littleendian
            int exif_header_length = 14;

            // could be an Exif segment
            if ((ImageTag.TagTypes & TagLib.TagTypes.TiffIFD) == 0x00 && length >= exif_header_length)
            {
                data = ReadBlock(exif_header_length);

                if (data.Count == exif_header_length &&
                    data.Mid(0, 6).ToString().Equals(EXIF_IDENTIFIER))
                {
                    bool is_bigendian = data.Mid(6, 2).ToString().Equals("MM");

                    ushort magic = data.Mid(8, 2).ToUShort(is_bigendian);
                    if (magic != 42)
                    {
                        throw new Exception(String.Format("Invalid TIFF magic: {0}", magic));
                    }

                    uint ifd_offset = data.Mid(10, 4).ToUInt(is_bigendian);

                    var exif   = new IFDTag();
                    var reader = new IFDReader(this, is_bigendian, exif.Structure, position + 6, ifd_offset, (uint)(length - 6));
                    reader.Read();
                    ImageTag.AddTag(exif);

                    AddMetadataBlock(position - 4, length + 4);

                    return;
                }
            }

            int xmp_header_length = XmpTag.XAP_NS.Length + 1;

            // could be an Xmp segment
            if ((ImageTag.TagTypes & TagLib.TagTypes.XMP) == 0x00 && length >= xmp_header_length)
            {
                // if already data is read for determining the Exif segment,
                // just read the remaining bytes.
                // NOTE: that (exif_header_length < xmp_header_length) holds
                if (data == null)
                {
                    data = ReadBlock(xmp_header_length);
                }
                else
                {
                    data.Add(ReadBlock(xmp_header_length - exif_header_length));
                }

                if (data.ToString().Equals(XmpTag.XAP_NS + "\0"))
                {
                    ByteVector xmp_data = ReadBlock(length - xmp_header_length);

                    ImageTag.AddTag(new XmpTag(xmp_data.ToString(), this));

                    AddMetadataBlock(position - 4, length + 4);
                }
            }
        }