Exemple #1
0
        /// <summary>
        /// データの型式が何バイトのデータ長かを返す
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private int GetSizeOf(IFDType type)
        {
            switch (type)
            {
            case IFDType.Byte:
            case IFDType.SByte:
            case IFDType.Ascii:
            case IFDType.Undefined:
                return(1);

            case IFDType.Short:
            case IFDType.SShort:
                return(2);

            case IFDType.Long:
            case IFDType.SLong:
            case IFDType.Float:
                return(4);

            case IFDType.Rational:
            case IFDType.SRational:
            case IFDType.DFloat:
                return(8);

            default:
                throw new Exception();
            }
        }
Exemple #2
0
 public IFD GetIFDWithType(IFDType t)
 {
     if (type == t)
     {
         return(this);
     }
     foreach (IFD i in subIFD)
     {
         var l = i.GetIFDWithType(t);
         if (l != null)
         {
             return(l);
         }
     }
     return(null);
 }
Exemple #3
0
        public IFD(IFDType type, ImageBinaryReader fileStream, uint offset, Endianness endian, int depth, int relativeOffset) : this(endian, depth)
        {
            this.type = type;

            if (relativeOffset > 0)
            {
                fileStream.Position = offset + relativeOffset;
            }
            else
            {
                fileStream.Position = offset;
            }

            Offset         = offset;
            RelativeOffset = relativeOffset;
            if (depth > MaxRecursion)
            {
                throw new IndexOutOfRangeException();
            }

            Parse(fileStream);
        }
Exemple #4
0
        private static ExifData ProcessExifTag(byte[] data, int position, Endianess endianess, IFDType ifdType)
        {
            var result = new ExifData
            {
                IFDType = ifdType
            };

            if (ifdType == IFDType.IFD_GPS)
            {
                result.GPSTag = data.ReadGPSType(position, endianess);
            }
            else
            {
                result.ExifTag = data.ReadExifType(position, endianess);
            }

            var dataType = data.ReadUShort(position + 2, endianess);

            result.ValueType = (ExifValueType)dataType;
            var componentCount = data.ReadUInt(position + 4, endianess);
            int offset;

            switch (result.ValueType)
            {
            case ExifValueType.UnsignedByte:        // unsigned byte, 1 byte / component
                if (componentCount > 4)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <byte>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadByte(offset + i));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.ASCIIString:         // ascii strings, 1 byte / component
                if (componentCount > 4)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                result.Value = data.ReadString(offset, componentCount);
                break;

            case ExifValueType.UnsignedShort:       // unsigned short, 2 bytes / component
                if (componentCount > 2)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <ushort>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadUShort(offset + (i * 2), endianess));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.UnsignedLong:        // unsigned long, 4 bytes / component
                if (componentCount > 1)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <uint>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadUInt(offset + (i * 4), endianess));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.UnsignedRational:        // unsigned rational, 8 bytes / component
                offset = (int)data.ReadUInt(position + 8, endianess);
                {
                    var lst = new List <string>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        var numerator   = data.ReadUInt(offset + (i * 8), endianess);
                        var denominator = data.ReadUInt(offset + (i * 8) + 4, endianess);
                        lst.Add(String.Format("{0}/{1}", numerator, denominator));
                    }
                    result.Value = String.Join(", ", lst);
                }
                break;

            case ExifValueType.SignedByte:          // signed byte, 1 byte / component
                if (componentCount > 4)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <sbyte>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadSByte(offset + i));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.Undefined:         // undefined
                switch (result.ExifTag)
                {
                case ExifTag.ComponentConfiguration:
                    result.Value = String.Format("{0}, {1}, {2}, {3}",
                                                 data.ReadByte(position + 8),
                                                 data.ReadByte(position + 9),
                                                 data.ReadByte(position + 10),
                                                 data.ReadByte(position + 11));
                    break;

                case ExifTag.ExifVersion:
                    result.Value = data.ReadString(position + 8, 4);
                    break;

                default:
                {
                    if (componentCount > 4)
                    {
                        offset = (int)data.ReadUInt(position + 8, endianess);
                    }
                    else
                    {
                        offset = position + 8;
                    }
                    var lst = new List <byte>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadByte(offset + i));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;
                }
                break;

            case ExifValueType.SignedShort:         // signed short, 2 bytes / component
                if (componentCount > 2)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <short>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadShort(offset + (i * 2), endianess));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.SignedLong:         // signed long, 4 bytes / component
                if (componentCount > 1)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <int>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadInt(offset + (i * 4), endianess));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.SignedRational:        // signed rational, 8 bytes / component
                offset = (int)data.ReadUInt(position + 8, endianess);
                {
                    var lst = new List <string>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        var numerator   = data.ReadInt(offset + (i * 8), endianess);
                        var denominator = data.ReadInt(offset + (i * 8) + 4, endianess);
                        lst.Add(String.Format("{0}/{1}", numerator, denominator));
                    }
                    result.Value = String.Join(", ", lst);
                }
                break;

            case ExifValueType.Single:        // single float, 4 bytes / component
                if (componentCount > 1)
                {
                    offset = (int)data.ReadUInt(position + 8, endianess);
                }
                else
                {
                    offset = position + 8;
                }
                {
                    var lst = new List <float>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadSingle(offset + (i * 4), endianess));
                    }
                    result.Value = String.Join(", ", lst.Select(x => x.ToString(CultureInfo.InvariantCulture)));
                }
                break;

            case ExifValueType.Double:        // double float, 8 bytes / component
                offset = (int)data.ReadUInt(position + 8, endianess);
                {
                    var lst = new List <double>();
                    for (var i = 0; i < componentCount; i++)
                    {
                        lst.Add(data.ReadDouble(offset + (i * 4), endianess));
                    }
                    result.Value = String.Join(", ", lst);
                }
                break;
            }

            return(result);
        }
Exemple #5
0
 public IFD(IFDType type, ImageBinaryReader fileStream, uint offset, Endianness endian, int depth) : this(type, fileStream, offset, endian, depth, 0)
 {
 }
Exemple #6
0
        private bool ParseOneIFD(BinaryReader br, IFDType ifdt)
        {
            mNumIFDEntries = ReadUInt16(br);
            Console.WriteLine("NumIfdEntries={0:X4}", mNumIFDEntries);

            Console.WriteLine("Offs     tag  type count    data/offs");

            for (int i = 0; i < mNumIFDEntries; ++i)
            {
                IFDEntry ifdEntry;
                if (!ReadIFDEntry(br, ifdt, out ifdEntry))
                {
                    // 全て終わり。
                    Console.WriteLine("End Tag reached");
                    return(false);
                }

                ShowData(ifdEntry);
                mIFDList.Add(ifdEntry);

                // 特殊なタグの処理。
                switch (ifdEntry.tag)
                {
                case IFDEntry.Tag.ExifIFD:
                    if (ifdEntry.fieldType != IFDEntry.FieldType.SHORT &&
                        ifdEntry.fieldType != IFDEntry.FieldType.LONG)
                    {
                        throw new FormatException();
                    }
                    mExifIFDPos = ifdEntry.dataOffset;
                    break;

                case IFDEntry.Tag.GPSInfo:
                    if (ifdEntry.fieldType != IFDEntry.FieldType.SHORT &&
                        ifdEntry.fieldType != IFDEntry.FieldType.LONG)
                    {
                        throw new FormatException();
                    }
                    mGpsIFDPos = ifdEntry.dataOffset;
                    break;

                case IFDEntry.Tag.SubIFDs:
                    switch (ifdEntry.fieldType)
                    {
                    case IFDEntry.FieldType.LONG:
                        var ia = ifdEntry.GetDataAsUIntArray();
                        foreach (var a in ia)
                        {
                            mSubIFDs.Add(a);
                        }
                        break;

                    case IFDEntry.FieldType.SHORT:
                        var sa = ifdEntry.GetDataAsUShortArray();
                        foreach (var a in sa)
                        {
                            mSubIFDs.Add(a);
                        }
                        break;

                    default:
                        Console.WriteLine("Error: SubIFDs unexpected tag type {0}", ifdEntry.fieldType);
                        break;
                    }
                    break;

                default:
                    break;
                }
            }
            // Next IFD offset
            var endPos = br.BaseStream.Position;

            mNextIFDPos = ReadUInt32(br);
            Console.WriteLine("{0:X8} Next IFD Offset=={1:X8}", endPos, mNextIFDPos);
            Console.WriteLine("End.");

            return(true);
        }
Exemple #7
0
        private bool ReadIFDEntry(BinaryReader br, IFDType ifdt, out IFDEntry ifdEntry)
        {
            long pos = br.BaseStream.Position;

            uint originalTag = ReadUInt16(br);

            int t = (int)originalTag;

            if (ifdt == IFDType.Gps)
            {
                t += 0x10000;
            }
            else
            {
                mAppearedTags.Add(t);
            }

            int f     = ReadUInt16(br);
            int count = ReadInt32(br);

            uint dataOffset = ReadUInt32(br);

            var tag = IFDEntry.Tag.Unknown;

            if (Enum.IsDefined(typeof(IFDEntry.Tag), t))
            {
                tag = (IFDEntry.Tag)t;
            }

            var ft = IFDEntry.FieldType.Unknown;

            if (Enum.IsDefined(typeof(IFDEntry.FieldType), f))
            {
                ft = (IFDEntry.FieldType)f;
            }

            int dataBytes = IFDEntry.DataBytes(ft, count);

            if (4 < dataBytes)
            {
                // dataOffset==データが置いてある位置。

                long cur = br.BaseStream.Position;

                br.BaseStream.Seek(dataOffset, SeekOrigin.Begin);

                ifdEntry            = CreateIFDEntry(br, tag, ft, count);
                ifdEntry.dataOffset = dataOffset;

                br.BaseStream.Seek(cur, SeekOrigin.Begin);
            }
            else
            {
                // dataPosをもう一度データとして読む。

                long cur = br.BaseStream.Position;

                br.BaseStream.Seek(pos + 8, SeekOrigin.Begin);

                ifdEntry = CreateIFDEntry(br, tag, ft, count);

                br.BaseStream.Seek(cur, SeekOrigin.Begin);
            }

            ifdEntry.originalTag  = originalTag;
            ifdEntry.filePosition = pos;

            return(true);
        }
Exemple #8
0
 /// <summary>
 /// データの型式が何バイトのデータ長かを返す
 /// </summary>
 /// <param name="type"></param>
 /// <returns></returns>
 private int GetSizeOf(IFDType type)
 {
     switch (type)
     {
         case IFDType.Byte:
         case IFDType.SByte:
         case IFDType.Ascii:
         case IFDType.Undefined:
             return 1;
         case IFDType.Short:
         case IFDType.SShort:
             return 2;
         case IFDType.Long:
         case IFDType.SLong:
         case IFDType.Float:
             return 4;
         case IFDType.Rational:
         case IFDType.SRational:
         case IFDType.DFloat:
             return 8;
         default:
             throw new Exception();
     }
 }