/// <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(); } }
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); }
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); }
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); }
public IFD(IFDType type, ImageBinaryReader fileStream, uint offset, Endianness endian, int depth) : this(type, fileStream, offset, endian, depth, 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); }
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); }
/// <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(); } }