Example #1
0
        private bool ProcessApp1Data(byte[] data, out DateTime dateTaken)
        {
            dateTaken = DateTime.MinValue;

            if (CheckTiffHeader(data, out bool isLittleEndian, out int ifdOffset) == false || ifdOffset <= 0)
            {
                return(false);
            }

            int workOffset = ifdOffset;

            bool     isSubstituteFound   = false;
            DateTime substituteDateTaken = DateTime.MinValue;

            while (workOffset > 0)
            {
                workOffset += 6; // 6 is exif header size
                                 // exif spec says all offsets start from tiff header, but current buffer starts from exif header

                int directoryCount;

                if (isLittleEndian)
                {
                    directoryCount = BitConverter.ToInt16(data, workOffset);
                }
                else
                {
                    directoryCount = BitConverterBE.ToInt16(data, workOffset);
                }

                workOffset += 2;

                bool subIFDFound = false;

                for (int i = 0; i < directoryCount; i++)
                {
                    var ifd = ImageFileDirectory.Read(isLittleEndian, data, workOffset);

                    if (ifd.Tag == SUBIFD)
                    {
                        if (isLittleEndian)
                        {
                            workOffset = BitConverter.ToInt32(ifd.Value.Array, ifd.Value.Offset);
                        }
                        else
                        {
                            workOffset = BitConverterBE.ToInt32(ifd.Value.Array, ifd.Value.Offset);
                        }

                        subIFDFound = true;
                        break;
                    }

                    if (ifd.Tag == 306)
                    {
                        if (ifd.Type != 2 || ifd.Value.Count != 20)
                        {
                            continue;
                        }

                        isSubstituteFound = TryParseDateTime(ifd.Value.Array, ifd.Value.Offset, ifd.Value.Count, out substituteDateTaken);
                    }
                    else if (ifd.Tag == 0x9003 || ifd.Tag == 0x9004)
                    {
                        if (ifd.Type != 2 || ifd.Value.Count != 20)
                        {
                            return(false);
                        }

                        if (TryParseDateTime(ifd.Value.Array, ifd.Value.Offset, ifd.Value.Count, out dateTaken))
                        {
                            return(true);
                        }
                    }

                    workOffset += 12;
                }

                if (subIFDFound)
                {
                    continue;
                }

                if (isLittleEndian)
                {
                    workOffset = BitConverter.ToInt32(data, workOffset);
                }
                else
                {
                    workOffset = BitConverterBE.ToInt32(data, workOffset);
                }
            }

            if (isSubstituteFound)
            {
                dateTaken = substituteDateTaken;
                return(true);
            }

            return(false);
        }
Example #2
0
        internal static ImageFileDirectory Read(bool isLittleEndian, byte[] data, int offset)
        {
            var ifd = new ImageFileDirectory();

            if (isLittleEndian)
            {
                ifd.Tag = BitConverter.ToUInt16(data, offset);
            }
            else
            {
                ifd.Tag = BitConverterBE.ToUInt16(data, offset);
            }

            if (isLittleEndian)
            {
                ifd.Type = BitConverter.ToUInt16(data, offset + 2);
            }
            else
            {
                ifd.Type = BitConverterBE.ToUInt16(data, offset + 2);
            }

            uint components;
            uint dataOffset;

            if (isLittleEndian)
            {
                components = BitConverter.ToUInt32(data, offset + 4);
            }
            else
            {
                components = BitConverterBE.ToUInt32(data, offset + 4);
            }

            if (isLittleEndian)
            {
                dataOffset = BitConverter.ToUInt32(data, offset + 8) + 6;
            }
            else
            {
                dataOffset = BitConverterBE.ToUInt32(data, offset + 8) + 6;
            }

            uint componentSize = 1;

            if (ifd.Type == 3 || ifd.Type == 8)
            {
                componentSize = 2;
            }
            else if (ifd.Type == 4 || ifd.Type == 9 || ifd.Type == 11)
            {
                componentSize = 4;
            }
            else if (ifd.Type == 5 || ifd.Type == 10 || ifd.Type == 12)
            {
                componentSize = 8;
            }

            uint totalByteLength = componentSize * components;

            if (totalByteLength <= 4)
            {
                ifd.Value = new ArraySegment <byte>(data, offset + 8, (int)totalByteLength);
            }
            else
            {
                ifd.Value = new ArraySegment <byte>(data, (int)dataOffset, (int)totalByteLength);
            }

            return(ifd);
        }