Ejemplo n.º 1
0
        /// <exception cref="System.IO.IOException"/>
        private void Set4ByteString(Com.Drew.Metadata.Directory directory, int tagType, RandomAccessReader reader)
        {
            int i = reader.GetInt32(tagType);

            if (i != 0)
            {
                directory.SetString(tagType, GetStringFromInt32(i));
            }
        }
Ejemplo n.º 2
0
        /// <exception cref="System.IO.IOException"/>
        private void SetInt32(Com.Drew.Metadata.Directory directory, int tagType, RandomAccessReader reader)
        {
            int i = reader.GetInt32(tagType);

            if (i != 0)
            {
                directory.SetInt(tagType, i);
            }
        }
Ejemplo n.º 3
0
        /// <exception cref="System.IO.IOException"/>
        private void SetInt64(Com.Drew.Metadata.Directory directory, int tagType, RandomAccessReader reader)
        {
            long l = reader.GetInt64(tagType);

            if (l != 0)
            {
                directory.SetLong(tagType, l);
            }
        }
Ejemplo n.º 4
0
 protected internal virtual void PushDirectory([NotNull] Type directoryClass)
 {
     _directoryStack.Push(_currentDirectory);
     try
     {
         _currentDirectory = (Directory)System.Activator.CreateInstance(directoryClass);
     }
     catch (InstantiationException e)
     {
         throw new RuntimeException(e);
     }
     catch (MemberAccessException e)
     {
         throw new RuntimeException(e);
     }
     _metadata.AddDirectory(_currentDirectory);
 }
Ejemplo n.º 5
0
 protected internal DirectoryTiffHandler(Com.Drew.Metadata.Metadata metadata, Type initialDirectoryClass)
 {
     _metadata = metadata;
     try
     {
         _currentDirectory = (Directory)System.Activator.CreateInstance(initialDirectoryClass);
     }
     catch (InstantiationException e)
     {
         throw new RuntimeException(e);
     }
     catch (MemberAccessException e)
     {
         throw new RuntimeException(e);
     }
     _metadata.AddDirectory(_currentDirectory);
 }
Ejemplo n.º 6
0
 protected internal DirectoryTiffHandler(Com.Drew.Metadata.Metadata metadata, Type initialDirectoryClass)
 {
     _metadata = metadata;
     try
     {
         _currentDirectory = (Directory)System.Activator.CreateInstance(initialDirectoryClass);
     }
     catch (InstantiationException e)
     {
         throw new RuntimeException(e);
     }
     catch (MemberAccessException e)
     {
         throw new RuntimeException(e);
     }
     _metadata.AddDirectory(_currentDirectory);
 }
 public virtual void Extract(SequentialReader reader, Com.Drew.Metadata.Metadata metadata)
 {
     Com.Drew.Metadata.Directory directory = metadata.GetOrCreateDirectory <AdobeJpegDirectory>();
     try
     {
         reader.SetMotorolaByteOrder(false);
         if (!reader.GetString(5).Equals("Adobe"))
         {
             directory.AddError("Invalid Adobe JPEG data header.");
             return;
         }
         directory.SetInt(AdobeJpegDirectory.TagDctEncodeVersion, reader.GetUInt16());
         directory.SetInt(AdobeJpegDirectory.TagApp14Flags0, reader.GetUInt16());
         directory.SetInt(AdobeJpegDirectory.TagApp14Flags1, reader.GetUInt16());
         directory.SetInt(AdobeJpegDirectory.TagColorTransform, reader.GetInt8());
     }
     catch (IOException ex)
     {
         directory.AddError("IO exception processing data: " + ex.Message);
     }
 }
Ejemplo n.º 8
0
 protected internal virtual void PushDirectory <T>() where T : Com.Drew.Metadata.Directory
 {
     System.Diagnostics.Debug.Assert((typeof(T) != _currentDirectory.GetType()));
     _directoryStack.Push(_currentDirectory);
     _currentDirectory = _metadata.GetOrCreateDirectory <T>();
 }
 public virtual void Setup()
 {
     _directory = new MockDirectory();
 }
Ejemplo n.º 10
0
 public Tag(int tagType, Com.Drew.Metadata.Directory directory)
 {
     _tagType   = tagType;
     _directory = directory;
 }
Ejemplo n.º 11
0
 private void Validate(Com.Drew.Metadata.Metadata metadata)
 {
     Com.Drew.Metadata.Directory directory = metadata.GetDirectory <ExifSubIFDDirectory>();
     NUnit.Framework.Assert.IsNotNull(directory);
     Sharpen.Tests.AreEqual("80", directory.GetString(ExifSubIFDDirectory.TagIsoEquivalent));
 }
Ejemplo n.º 12
0
        /// <exception cref="System.IO.IOException"/>
        private void ProcessTag([NotNull] SequentialReader reader, [NotNull] Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount)
        {
            int tagIdentifier = tagType | (directoryType << 8);

            // Some images have been seen that specify a zero byte tag, which cannot be of much use.
            // We elect here to completely ignore the tag. The IPTC specification doesn't mention
            // anything about the interpretation of this situation.
            // https://raw.githubusercontent.com/wiki/drewnoakes/metadata-extractor/docs/IPTC-IIMV4.2.pdf
            if (tagByteCount == 0)
            {
                directory.SetString(tagIdentifier, string.Empty);
                return;
            }
            string @string = null;

            switch (tagIdentifier)
            {
            case IptcDirectory.TagCodedCharacterSet:
            {
                sbyte[] bytes   = reader.GetBytes(tagByteCount);
                string  charset = Iso2022Converter.ConvertISO2022CharsetToJavaCharset(bytes);
                if (charset == null)
                {
                    // Unable to determine the charset, so fall through and treat tag as a regular string
                    @string = Sharpen.Runtime.GetStringForBytes(bytes);
                    break;
                }
                directory.SetString(tagIdentifier, charset);
                return;
            }

            case IptcDirectory.TagEnvelopeRecordVersion:
            case IptcDirectory.TagApplicationRecordVersion:
            case IptcDirectory.TagFileVersion:
            case IptcDirectory.TagArmVersion:
            case IptcDirectory.TagProgramVersion:
            {
                // short
                if (tagByteCount >= 2)
                {
                    int shortValue = reader.GetUInt16();
                    reader.Skip(tagByteCount - 2);
                    directory.SetInt(tagIdentifier, shortValue);
                    return;
                }
                break;
            }

            case IptcDirectory.TagUrgency:
            {
                // byte
                directory.SetInt(tagIdentifier, reader.GetUInt8());
                reader.Skip(tagByteCount - 1);
                return;
            }

            case IptcDirectory.TagReleaseDate:
            case IptcDirectory.TagDateCreated:
            {
                // Date object
                if (tagByteCount >= 8)
                {
                    @string = reader.GetString(tagByteCount);
                    try
                    {
                        int      year  = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4));
                        int      month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1;
                        int      day   = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8));
                        DateTime date  = new Sharpen.GregorianCalendar(year, month, day).GetTime();
                        directory.SetDate(tagIdentifier, date);
                        return;
                    }
                    catch (FormatException)
                    {
                    }
                }
                else
                {
                    // fall through and we'll process the 'string' value below
                    reader.Skip(tagByteCount);
                }
                goto case IptcDirectory.TagReleaseTime;
            }

            case IptcDirectory.TagReleaseTime:
            case IptcDirectory.TagTimeCreated:
            default:
            {
                break;
            }
            }
            // time...
            // fall through
            // If we haven't returned yet, treat it as a string
            // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value
            if (@string == null)
            {
                string encoding = directory.GetString(IptcDirectory.TagCodedCharacterSet);
                if (encoding != null)
                {
                    @string = reader.GetString(tagByteCount, encoding);
                }
                else
                {
                    sbyte[] bytes_1 = reader.GetBytes(tagByteCount);
                    encoding = Iso2022Converter.GuessEncoding(bytes_1);
                    @string  = encoding != null?Sharpen.Runtime.GetStringForBytes(bytes_1, encoding) : Sharpen.Runtime.GetStringForBytes(bytes_1);
                }
            }
            if (directory.ContainsTag(tagIdentifier))
            {
                // this fancy string[] business avoids using an ArrayList for performance reasons
                string[] oldStrings = directory.GetStringArray(tagIdentifier);
                string[] newStrings;
                if (oldStrings == null)
                {
                    newStrings = new string[1];
                }
                else
                {
                    newStrings = new string[oldStrings.Length + 1];
                    System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length);
                }
                newStrings[newStrings.Length - 1] = @string;
                directory.SetStringArray(tagIdentifier, newStrings);
            }
            else
            {
                directory.SetString(tagIdentifier, @string);
            }
        }
Ejemplo n.º 13
0
        /// <exception cref="System.IO.IOException"/>
        private void ProcessTag(SequentialReader reader, Com.Drew.Metadata.Directory directory, int directoryType, int tagType, int tagByteCount)
        {
            int    tagIdentifier = tagType | (directoryType << 8);
            string @string       = null;

            switch (tagIdentifier)
            {
            case IptcDirectory.TagApplicationRecordVersion:
            {
                // short
                int shortValue = reader.GetUInt16();
                reader.Skip(tagByteCount - 2);
                directory.SetInt(tagIdentifier, shortValue);
                return;
            }

            case IptcDirectory.TagUrgency:
            {
                // byte
                directory.SetInt(tagIdentifier, reader.GetUInt8());
                reader.Skip(tagByteCount - 1);
                return;
            }

            case IptcDirectory.TagReleaseDate:
            case IptcDirectory.TagDateCreated:
            {
                // Date object
                if (tagByteCount >= 8)
                {
                    @string = reader.GetString(tagByteCount);
                    try
                    {
                        int      year  = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 0, 4));
                        int      month = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 4, 6)) - 1;
                        int      day   = System.Convert.ToInt32(Sharpen.Runtime.Substring(@string, 6, 8));
                        DateTime date  = new Sharpen.GregorianCalendar(year, month, day).GetTime();
                        directory.SetDate(tagIdentifier, date);
                        return;
                    }
                    catch (FormatException)
                    {
                    }
                }
                else
                {
                    // fall through and we'll process the 'string' value below
                    reader.Skip(tagByteCount);
                }
                goto case IptcDirectory.TagReleaseTime;
            }

            case IptcDirectory.TagReleaseTime:
            case IptcDirectory.TagTimeCreated:
            default:
            {
                break;
            }
            }
            // time...
            // fall through
            // If we haven't returned yet, treat it as a string
            // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value
            if (@string == null)
            {
                @string = reader.GetString(tagByteCount, Runtime.GetProperty("file.encoding"));
            }
            // "ISO-8859-1"
            if (directory.ContainsTag(tagIdentifier))
            {
                // this fancy string[] business avoids using an ArrayList for performance reasons
                string[] oldStrings = directory.GetStringArray(tagIdentifier);
                string[] newStrings;
                if (oldStrings == null)
                {
                    newStrings = new string[1];
                }
                else
                {
                    newStrings = new string[oldStrings.Length + 1];
                    System.Array.Copy(oldStrings, 0, newStrings, 0, oldStrings.Length);
                }
                newStrings[newStrings.Length - 1] = @string;
                directory.SetStringArray(tagIdentifier, newStrings);
            }
            else
            {
                directory.SetString(tagIdentifier, @string);
            }
        }
Ejemplo n.º 14
0
 public virtual void Setup()
 {
     _directory = new MockDirectory();
 }
Ejemplo n.º 15
0
        private static void ProcessIFD(Com.Drew.Metadata.Directory directory, ICollection <int> processedIfdOffsets, int ifdOffset, int tiffHeaderOffset, Com.Drew.Metadata.Metadata metadata, RandomAccessReader reader)
        {
            // check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist
            if (processedIfdOffsets.Contains(Sharpen.Extensions.ValueOf(ifdOffset)))
            {
                return;
            }
            // remember that we've visited this directory so that we don't visit it again later
            processedIfdOffsets.Add(ifdOffset);
            if (ifdOffset >= reader.GetLength() || ifdOffset < 0)
            {
                directory.AddError("Ignored IFD marked to start outside data segment");
                return;
            }
            // First two bytes in the IFD are the number of tags in this directory
            int dirTagCount = reader.GetUInt16(ifdOffset);
            int dirLength   = (2 + (12 * dirTagCount) + 4);

            if (dirLength + ifdOffset > reader.GetLength())
            {
                directory.AddError("Illegally sized IFD");
                return;
            }
            // Handle each tag in this directory
            for (int tagNumber = 0; tagNumber < dirTagCount; tagNumber++)
            {
                int tagOffset = CalculateTagOffset(ifdOffset, tagNumber);
                // 2 bytes for the tag type
                int tagType = reader.GetUInt16(tagOffset);
                // 2 bytes for the format code
                int formatCode = reader.GetUInt16(tagOffset + 2);
                if (formatCode < 1 || formatCode > MaxFormatCode)
                {
                    // This error suggests that we are processing at an incorrect index and will generate
                    // rubbish until we go out of bounds (which may be a while).  Exit now.
                    directory.AddError("Invalid TIFF tag format code: " + formatCode);
                    return;
                }
                // 4 bytes dictate the number of components in this tag's data
                int componentCount = reader.GetInt32(tagOffset + 4);
                if (componentCount < 0)
                {
                    directory.AddError("Negative TIFF tag component count");
                    continue;
                }
                // each component may have more than one byte... calculate the total number of bytes
                int byteCount = componentCount * BytesPerFormat[formatCode];
                int tagValueOffset;
                if (byteCount > 4)
                {
                    // If it's bigger than 4 bytes, the dir entry contains an offset.
                    // dirEntryOffset must be passed, as some makernote implementations (e.g. Fujifilm) incorrectly use an
                    // offset relative to the start of the makernote itself, not the TIFF segment.
                    int offsetVal = reader.GetInt32(tagOffset + 8);
                    if (offsetVal + byteCount > reader.GetLength())
                    {
                        // Bogus pointer offset and / or byteCount value
                        directory.AddError("Illegal TIFF tag pointer offset");
                        continue;
                    }
                    tagValueOffset = tiffHeaderOffset + offsetVal;
                }
                else
                {
                    // 4 bytes or less and value is in the dir entry itself
                    tagValueOffset = tagOffset + 8;
                }
                if (tagValueOffset < 0 || tagValueOffset > reader.GetLength())
                {
                    directory.AddError("Illegal TIFF tag pointer offset");
                    continue;
                }
                // Check that this tag isn't going to allocate outside the bounds of the data array.
                // This addresses an uncommon OutOfMemoryError.
                if (byteCount < 0 || tagValueOffset + byteCount > reader.GetLength())
                {
                    directory.AddError("Illegal number of bytes for TIFF tag data: " + byteCount);
                    continue;
                }
                //
                // Special handling for certain known tags that point to or contain other chunks of data to be processed
                //
                if (tagType == ExifIFD0Directory.TagExifSubIfdOffset && directory is ExifIFD0Directory)
                {
                    if (byteCount != 4)
                    {
                        directory.AddError("Exif SubIFD Offset tag should have a component count of four (bytes) for the offset.");
                    }
                    else
                    {
                        int subDirOffset = tiffHeaderOffset + reader.GetInt32(tagValueOffset);
                        ProcessIFD(metadata.GetOrCreateDirectory <ExifSubIFDDirectory>(), processedIfdOffsets, subDirOffset, tiffHeaderOffset, metadata, reader);
                    }
                }
                else
                {
                    if (tagType == ExifSubIFDDirectory.TagInteropOffset && directory is ExifSubIFDDirectory)
                    {
                        if (byteCount != 4)
                        {
                            directory.AddError("Exif Interop Offset tag should have a component count of four (bytes) for the offset.");
                        }
                        else
                        {
                            int subDirOffset = tiffHeaderOffset + reader.GetInt32(tagValueOffset);
                            ProcessIFD(metadata.GetOrCreateDirectory <ExifInteropDirectory>(), processedIfdOffsets, subDirOffset, tiffHeaderOffset, metadata, reader);
                        }
                    }
                    else
                    {
                        if (tagType == ExifIFD0Directory.TagGpsInfoOffset && directory is ExifIFD0Directory)
                        {
                            if (byteCount != 4)
                            {
                                directory.AddError("Exif GPS Info Offset tag should have a component count of four (bytes) for the offset.");
                            }
                            else
                            {
                                int subDirOffset = tiffHeaderOffset + reader.GetInt32(tagValueOffset);
                                ProcessIFD(metadata.GetOrCreateDirectory <GpsDirectory>(), processedIfdOffsets, subDirOffset, tiffHeaderOffset, metadata, reader);
                            }
                        }
                        else
                        {
                            if (tagType == ExifSubIFDDirectory.TagMakernote && directory is ExifSubIFDDirectory)
                            {
                                // The makernote tag contains the encoded makernote data directly.
                                // Pass the offset to this tag's value. Manufacturer/Model-specific logic will be used to
                                // determine the correct offset for further processing.
                                ProcessMakernote(tagValueOffset, processedIfdOffsets, tiffHeaderOffset, metadata, reader);
                            }
                            else
                            {
                                ProcessTag(directory, tagType, tagValueOffset, componentCount, formatCode, reader);
                            }
                        }
                    }
                }
            }
            // at the end of each IFD is an optional link to the next IFD
            int finalTagOffset      = CalculateTagOffset(ifdOffset, dirTagCount);
            int nextDirectoryOffset = reader.GetInt32(finalTagOffset);

            if (nextDirectoryOffset != 0)
            {
                nextDirectoryOffset += tiffHeaderOffset;
                if (nextDirectoryOffset >= reader.GetLength())
                {
                    // Last 4 bytes of IFD reference another IFD with an address that is out of bounds
                    // Note this could have been caused by jhead 1.3 cropping too much
                    return;
                }
                else
                {
                    if (nextDirectoryOffset < ifdOffset)
                    {
                        // Last 4 bytes of IFD reference another IFD with an address that is before the start of this directory
                        return;
                    }
                }
                // TODO in Exif, the only known 'follower' IFD is the thumbnail one, however this may not be the case
                ExifThumbnailDirectory nextDirectory = metadata.GetOrCreateDirectory <ExifThumbnailDirectory>();
                ProcessIFD(nextDirectory, processedIfdOffsets, nextDirectoryOffset, tiffHeaderOffset, metadata, reader);
            }
        }
Ejemplo n.º 16
0
        private static void ExtractTiff(RandomAccessReader reader, Com.Drew.Metadata.Metadata metadata, Com.Drew.Metadata.Directory firstDirectory, int tiffHeaderOffset)
        {
            // this should be either "MM" or "II"
            string byteOrderIdentifier = reader.GetString(tiffHeaderOffset, 2);

            if ("MM".Equals(byteOrderIdentifier))
            {
                reader.SetMotorolaByteOrder(true);
            }
            else
            {
                if ("II".Equals(byteOrderIdentifier))
                {
                    reader.SetMotorolaByteOrder(false);
                }
                else
                {
                    firstDirectory.AddError("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier);
                    return;
                }
            }
            // Check the next two values for correctness.
            int tiffMarker           = reader.GetUInt16(2 + tiffHeaderOffset);
            int standardTiffMarker   = unchecked ((int)(0x002A));
            int olympusRawTiffMarker = unchecked ((int)(0x4F52));
            // for ORF files
            int panasonicRawTiffMarker = unchecked ((int)(0x0055));

            // for RW2 files
            if (tiffMarker != standardTiffMarker && tiffMarker != olympusRawTiffMarker && tiffMarker != panasonicRawTiffMarker)
            {
                firstDirectory.AddError("Unexpected TIFF marker after byte order identifier: 0x" + Sharpen.Extensions.ToHexString(tiffMarker));
                return;
            }
            int firstIfdOffset = reader.GetInt32(4 + tiffHeaderOffset) + tiffHeaderOffset;

            // David Ekholm sent a digital camera image that has this problem
            // TODO getLength should be avoided as it causes RandomAccessStreamReader to read to the end of the stream
            if (firstIfdOffset >= reader.GetLength() - 1)
            {
                firstDirectory.AddError("First Exif directory offset is beyond end of Exif data segment");
                // First directory normally starts 14 bytes in -- try it here and catch another error in the worst case
                firstIfdOffset = 14;
            }
            ICollection <int> processedIfdOffsets = new HashSet <int>();

            ProcessIFD(firstDirectory, processedIfdOffsets, firstIfdOffset, tiffHeaderOffset, metadata, reader);
            // after the extraction process, if we have the correct tags, we may be able to store thumbnail information
            ExifThumbnailDirectory thumbnailDirectory = metadata.GetDirectory <ExifThumbnailDirectory>();

            if (thumbnailDirectory != null && thumbnailDirectory.ContainsTag(ExifThumbnailDirectory.TagThumbnailCompression))
            {
                int?offset = thumbnailDirectory.GetInteger(ExifThumbnailDirectory.TagThumbnailOffset);
                int?length = thumbnailDirectory.GetInteger(ExifThumbnailDirectory.TagThumbnailLength);
                if (offset != null && length != null)
                {
                    try
                    {
                        sbyte[] thumbnailData = reader.GetBytes(tiffHeaderOffset + offset.Value, length.Value);
                        thumbnailDirectory.SetThumbnailData(thumbnailData);
                    }
                    catch (IOException ex)
                    {
                        firstDirectory.AddError("Invalid thumbnail data specification: " + ex.Message);
                    }
                }
            }
        }
Ejemplo n.º 17
0
        /// <exception cref="System.IO.IOException"/>
        private bool ProcessMakernote(int makernoteOffset, ICollection <int> processedIfdOffsets, int tiffHeaderOffset, RandomAccessReader reader, int byteCount)
        {
            // Determine the camera model and makernote format.
            Com.Drew.Metadata.Directory ifd0Directory = _metadata.GetDirectory <ExifIFD0Directory>();
            if (ifd0Directory == null)
            {
                return(false);
            }
            string cameraMake       = ifd0Directory.GetString(ExifIFD0Directory.TagMake);
            string firstTwoChars    = reader.GetString(makernoteOffset, 2);
            string firstThreeChars  = reader.GetString(makernoteOffset, 3);
            string firstFourChars   = reader.GetString(makernoteOffset, 4);
            string firstFiveChars   = reader.GetString(makernoteOffset, 5);
            string firstSixChars    = reader.GetString(makernoteOffset, 6);
            string firstSevenChars  = reader.GetString(makernoteOffset, 7);
            string firstEightChars  = reader.GetString(makernoteOffset, 8);
            string firstTwelveChars = reader.GetString(makernoteOffset, 12);
            bool   byteOrderBefore  = reader.IsMotorolaByteOrder();

            if ("OLYMP".Equals(firstFiveChars) || "EPSON".Equals(firstFiveChars) || "AGFA".Equals(firstFourChars))
            {
                // Olympus Makernote
                // Epson and Agfa use Olympus makernote standard: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
                PushDirectory <OlympusMakernoteDirectory>();
                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
            }
            else
            {
                if (cameraMake != null && cameraMake.ToUpper().StartsWith("MINOLTA"))
                {
                    // Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote
                    // area that commences immediately.
                    PushDirectory <OlympusMakernoteDirectory>();
                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
                }
                else
                {
                    if (cameraMake != null && Sharpen.Extensions.Trim(cameraMake).ToUpper().StartsWith("NIKON"))
                    {
                        if ("Nikon".Equals(firstFiveChars))
                        {
                            switch (reader.GetUInt8(makernoteOffset + 6))
                            {
                            case 1:
                            {
                                /* There are two scenarios here:
                                 * Type 1:                  **
                                 * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
                                 * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
                                 * Type 3:                  **
                                 * :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
                                 * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
                                 */
                                PushDirectory <NikonType1MakernoteDirectory>();
                                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
                                break;
                            }

                            case 2:
                            {
                                PushDirectory <NikonType2MakernoteDirectory>();
                                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 18, makernoteOffset + 10);
                                break;
                            }

                            default:
                            {
                                ifd0Directory.AddError("Unsupported Nikon makernote data ignored.");
                                break;
                            }
                            }
                        }
                        else
                        {
                            // The IFD begins with the first Makernote byte (no ASCII name).  This occurs with CoolPix 775, E990 and D1 models.
                            PushDirectory <NikonType2MakernoteDirectory>();
                            TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
                        }
                    }
                    else
                    {
                        if ("SONY CAM".Equals(firstEightChars) || "SONY DSC".Equals(firstEightChars))
                        {
                            PushDirectory <SonyType1MakernoteDirectory>();
                            TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, tiffHeaderOffset);
                        }
                        else
                        {
                            if ("SEMC MS\u0000\u0000\u0000\u0000\u0000".Equals(firstTwelveChars))
                            {
                                // force MM for this directory
                                reader.SetMotorolaByteOrder(true);
                                // skip 12 byte header + 2 for "MM" + 6
                                PushDirectory <SonyType6MakernoteDirectory>();
                                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 20, tiffHeaderOffset);
                            }
                            else
                            {
                                if ("SIGMA\u0000\u0000\u0000".Equals(firstEightChars) || "FOVEON\u0000\u0000".Equals(firstEightChars))
                                {
                                    PushDirectory <SigmaMakernoteDirectory>();
                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 10, tiffHeaderOffset);
                                }
                                else
                                {
                                    if ("KDK".Equals(firstThreeChars))
                                    {
                                        reader.SetMotorolaByteOrder(firstSevenChars.Equals("KDK INFO"));
                                        ProcessKodakMakernote(_metadata.GetOrCreateDirectory <KodakMakernoteDirectory>(), makernoteOffset, reader);
                                    }
                                    else
                                    {
                                        if (Sharpen.Runtime.EqualsIgnoreCase("Canon", cameraMake))
                                        {
                                            PushDirectory <CanonMakernoteDirectory>();
                                            TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
                                        }
                                        else
                                        {
                                            if (cameraMake != null && cameraMake.ToUpper().StartsWith("CASIO"))
                                            {
                                                if ("QVC\u0000\u0000\u0000".Equals(firstSixChars))
                                                {
                                                    PushDirectory <CasioType2MakernoteDirectory>();
                                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 6, tiffHeaderOffset);
                                                }
                                                else
                                                {
                                                    PushDirectory <CasioType1MakernoteDirectory>();
                                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
                                                }
                                            }
                                            else
                                            {
                                                if ("FUJIFILM".Equals(firstEightChars) || Sharpen.Runtime.EqualsIgnoreCase("Fujifilm", cameraMake))
                                                {
                                                    // Note that this also applies to certain Leica cameras, such as the Digilux-4.3
                                                    reader.SetMotorolaByteOrder(false);
                                                    // the 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote
                                                    // IFD, though the offset is relative to the start of the makernote, not the TIFF
                                                    // header (like everywhere else)
                                                    int ifdStart = makernoteOffset + reader.GetInt32(makernoteOffset + 8);
                                                    PushDirectory <FujifilmMakernoteDirectory>();
                                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, ifdStart, makernoteOffset);
                                                }
                                                else
                                                {
                                                    if ("KYOCERA".Equals(firstSevenChars))
                                                    {
                                                        // http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html
                                                        PushDirectory <KyoceraMakernoteDirectory>();
                                                        TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 22, tiffHeaderOffset);
                                                    }
                                                    else
                                                    {
                                                        if ("LEICA".Equals(firstFiveChars))
                                                        {
                                                            reader.SetMotorolaByteOrder(false);
                                                            if ("Leica Camera AG".Equals(cameraMake))
                                                            {
                                                                PushDirectory <LeicaMakernoteDirectory>();
                                                                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
                                                            }
                                                            else
                                                            {
                                                                if ("LEICA".Equals(cameraMake))
                                                                {
                                                                    // Some Leica cameras use Panasonic makernote tags
                                                                    PushDirectory <PanasonicMakernoteDirectory>();
                                                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
                                                                }
                                                                else
                                                                {
                                                                    return(false);
                                                                }
                                                            }
                                                        }
                                                        else
                                                        {
                                                            if ("Panasonic\u0000\u0000\u0000".Equals(reader.GetString(makernoteOffset, 12)))
                                                            {
                                                                // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD
                                                                // Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment
                                                                // more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html
                                                                PushDirectory <PanasonicMakernoteDirectory>();
                                                                TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, tiffHeaderOffset);
                                                            }
                                                            else
                                                            {
                                                                if ("AOC\u0000".Equals(firstFourChars))
                                                                {
                                                                    // NON-Standard TIFF IFD Data using Casio Type 2 Tags
                                                                    // IFD has no Next-IFD pointer at end of IFD, and
                                                                    // Offsets are relative to the start of the current IFD tag, not the TIFF header
                                                                    // Observed for:
                                                                    // - Pentax ist D
                                                                    PushDirectory <CasioType2MakernoteDirectory>();
                                                                    TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 6, makernoteOffset);
                                                                }
                                                                else
                                                                {
                                                                    if (cameraMake != null && (cameraMake.ToUpper().StartsWith("PENTAX") || cameraMake.ToUpper().StartsWith("ASAHI")))
                                                                    {
                                                                        // NON-Standard TIFF IFD Data using Pentax Tags
                                                                        // IFD has no Next-IFD pointer at end of IFD, and
                                                                        // Offsets are relative to the start of the current IFD tag, not the TIFF header
                                                                        // Observed for:
                                                                        // - PENTAX Optio 330
                                                                        // - PENTAX Optio 430
                                                                        PushDirectory <PentaxMakernoteDirectory>();
                                                                        TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset, makernoteOffset);
                                                                    }
                                                                    else
                                                                    {
                                                                        //        } else if ("KC".equals(firstTwoChars) || "MINOL".equals(firstFiveChars) || "MLY".equals(firstThreeChars) || "+M+M+M+M".equals(firstEightChars)) {
                                                                        //            // This Konica data is not understood.  Header identified in accordance with information at this site:
                                                                        //            // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html
                                                                        //            // TODO add support for minolta/konica cameras
                                                                        //            exifDirectory.addError("Unsupported Konica/Minolta data ignored.");
                                                                        if ("SANYO\x0\x1\x0".Equals(firstEightChars))
                                                                        {
                                                                            PushDirectory <SanyoMakernoteDirectory>();
                                                                            TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset);
                                                                        }
                                                                        else
                                                                        {
                                                                            if (cameraMake != null && cameraMake.ToLower().StartsWith("ricoh"))
                                                                            {
                                                                                if (firstTwoChars.Equals("Rv") || firstThreeChars.Equals("Rev"))
                                                                                {
                                                                                    // This is a textual format, where the makernote bytes look like:
                                                                                    //   Rv0103;Rg1C;Bg18;Ll0;Ld0;Aj0000;Bn0473800;Fp2E00:пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
                                                                                    //   Rv0103;Rg1C;Bg18;Ll0;Ld0;Aj0000;Bn0473800;Fp2D05:пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
                                                                                    //   Rv0207;Sf6C84;Rg76;Bg60;Gg42;Ll0;Ld0;Aj0004;Bn0B02900;Fp10B8;Md6700;Ln116900086D27;Sv263:0000000000000000000000пїЅпїЅ
                                                                                    // This format is currently unsupported
                                                                                    return(false);
                                                                                }
                                                                                else
                                                                                {
                                                                                    if (Sharpen.Runtime.EqualsIgnoreCase(firstFiveChars, "Ricoh"))
                                                                                    {
                                                                                        // Always in Motorola byte order
                                                                                        reader.SetMotorolaByteOrder(true);
                                                                                        PushDirectory <RicohMakernoteDirectory>();
                                                                                        TiffReader.ProcessIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset);
                                                                                    }
                                                                                }
                                                                            }
                                                                            else
                                                                            {
                                                                                // The makernote is not comprehended by this library.
                                                                                // If you are reading this and believe a particular camera's image should be processed, get in touch.
                                                                                return(false);
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            reader.SetMotorolaByteOrder(byteOrderBefore);
            return(true);
        }
Ejemplo n.º 18
0
        private static void ProcessTag(Com.Drew.Metadata.Directory directory, int tagType, int tagValueOffset, int componentCount, int formatCode, RandomAccessReader reader)
        {
            switch (formatCode)
            {
            case FmtUndefined:
            {
                // Directory simply stores raw values
                // The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions
                // this includes exif user comments
                directory.SetByteArray(tagType, reader.GetBytes(tagValueOffset, componentCount));
                break;
            }

            case FmtString:
            {
                string @string = reader.GetNullTerminatedString(tagValueOffset, componentCount);
                directory.SetString(tagType, @string);
                break;
            }

            case FmtSrational:
            {
                if (componentCount == 1)
                {
                    directory.SetRational(tagType, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] rationals = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            rationals[i] = new Rational(reader.GetInt32(tagValueOffset + (8 * i)), reader.GetInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        directory.SetRationalArray(tagType, rationals);
                    }
                }
                break;
            }

            case FmtUrational:
            {
                if (componentCount == 1)
                {
                    directory.SetRational(tagType, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4)));
                }
                else
                {
                    if (componentCount > 1)
                    {
                        Rational[] rationals = new Rational[componentCount];
                        for (int i = 0; i < componentCount; i++)
                        {
                            rationals[i] = new Rational(reader.GetUInt32(tagValueOffset + (8 * i)), reader.GetUInt32(tagValueOffset + 4 + (8 * i)));
                        }
                        directory.SetRationalArray(tagType, rationals);
                    }
                }
                break;
            }

            case FmtSingle:
            {
                if (componentCount == 1)
                {
                    directory.SetFloat(tagType, reader.GetFloat32(tagValueOffset));
                }
                else
                {
                    float[] floats = new float[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        floats[i] = reader.GetFloat32(tagValueOffset + (i * 4));
                    }
                    directory.SetFloatArray(tagType, floats);
                }
                break;
            }

            case FmtDouble:
            {
                if (componentCount == 1)
                {
                    directory.SetDouble(tagType, reader.GetDouble64(tagValueOffset));
                }
                else
                {
                    double[] doubles = new double[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        doubles[i] = reader.GetDouble64(tagValueOffset + (i * 4));
                    }
                    directory.SetDoubleArray(tagType, doubles);
                }
                break;
            }

            case FmtSbyte:
            {
                //
                // Note that all integral types are stored as int32 internally (the largest supported by TIFF)
                //
                if (componentCount == 1)
                {
                    directory.SetInt(tagType, reader.GetInt8(tagValueOffset));
                }
                else
                {
                    int[] bytes = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        bytes[i] = reader.GetInt8(tagValueOffset + i);
                    }
                    directory.SetIntArray(tagType, bytes);
                }
                break;
            }

            case FmtByte:
            {
                if (componentCount == 1)
                {
                    directory.SetInt(tagType, reader.GetUInt8(tagValueOffset));
                }
                else
                {
                    int[] bytes = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        bytes[i] = reader.GetUInt8(tagValueOffset + i);
                    }
                    directory.SetIntArray(tagType, bytes);
                }
                break;
            }

            case FmtUshort:
            {
                if (componentCount == 1)
                {
                    int i = reader.GetUInt16(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetUInt16(tagValueOffset + (i * 2));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            case FmtSshort:
            {
                if (componentCount == 1)
                {
                    int i = reader.GetInt16(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetInt16(tagValueOffset + (i * 2));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            case FmtSlong:
            case FmtUlong:
            {
                // NOTE 'long' in this case means 32 bit, not 64
                if (componentCount == 1)
                {
                    int i = reader.GetInt32(tagValueOffset);
                    directory.SetInt(tagType, i);
                }
                else
                {
                    int[] ints = new int[componentCount];
                    for (int i = 0; i < componentCount; i++)
                    {
                        ints[i] = reader.GetInt32(tagValueOffset + (i * 4));
                    }
                    directory.SetIntArray(tagType, ints);
                }
                break;
            }

            default:
            {
                directory.AddError("Unknown format code " + formatCode + " for tag " + tagType);
                break;
            }
            }
        }
Ejemplo n.º 19
0
 protected internal virtual void PushDirectory([NotNull] Type directoryClass)
 {
     _directoryStack.Push(_currentDirectory);
     try
     {
         _currentDirectory = (Directory)System.Activator.CreateInstance(directoryClass);
     }
     catch (InstantiationException e)
     {
         throw new RuntimeException(e);
     }
     catch (MemberAccessException e)
     {
         throw new RuntimeException(e);
     }
     _metadata.AddDirectory(_currentDirectory);
 }
Ejemplo n.º 20
0
 public virtual void EndingIFD()
 {
     _currentDirectory = _directoryStack.IsEmpty() ? null : _directoryStack.Pop();
 }
Ejemplo n.º 21
0
 protected internal DirectoryTiffHandler(Com.Drew.Metadata.Metadata metadata, Type initialDirectory)
 {
     _metadata         = metadata;
     _currentDirectory = _metadata.GetOrCreateDirectory(initialDirectory);
 }
Ejemplo n.º 22
0
 public Tag(int tagType, [NotNull] Com.Drew.Metadata.Directory directory)
 {
     _tagType = tagType;
     _directory = directory;
 }
Ejemplo n.º 23
0
 public virtual void EndingIFD()
 {
     _currentDirectory = _directoryStack.IsEmpty() ? null : _directoryStack.Pop();
 }