private static ICollection <MetadataEntry> ConvertIFDEntriesToMetadataEntries(EndianBinaryReader reader, List <ParserIFDEntry> entries) { List <MetadataEntry> metadataEntries = new List <MetadataEntry>(entries.Count); bool swapNumberByteOrder = reader.Endianess == Endianess.Big; for (int i = 0; i < entries.Count; i++) { ParserIFDEntry entry = entries[i]; byte[] propertyData; if (entry.OffsetFieldContainsValue) { propertyData = entry.GetValueBytesFromOffset(); if (propertyData is null) { continue; } } else { long bytesToRead = entry.Count * TagDataTypeUtil.GetSizeInBytes(entry.Type); // Skip any tags that are empty or larger than 2 GB. if (bytesToRead == 0 || bytesToRead > int.MaxValue) { continue; } uint offset = entry.Offset; if ((offset + bytesToRead) > reader.Length) { continue; } reader.Position = offset; propertyData = reader.ReadBytes((int)bytesToRead); if (swapNumberByteOrder) { // Paint.NET converts all multi-byte numbers to little-endian. switch (entry.Type) { case TagDataType.Short: case TagDataType.SShort: propertyData = SwapShortArrayToLittleEndian(propertyData, entry.Count); break; case TagDataType.Long: case TagDataType.SLong: case TagDataType.Float: propertyData = SwapLongArrayToLittleEndian(propertyData, entry.Count); break; case TagDataType.Rational: case TagDataType.SRational: propertyData = SwapRationalArrayToLittleEndian(propertyData, entry.Count); break; case TagDataType.Double: propertyData = SwapDoubleArrayToLittleEndian(propertyData, entry.Count); break; case TagDataType.Byte: case TagDataType.Ascii: case TagDataType.Undefined: case TagDataType.SByte: default: break; } } } metadataEntries.Add(new MetadataEntry(entry.Section, entry.Tag, entry.Type, propertyData)); } return(metadataEntries); }
private string GetValueStringFromOffset() { string valueString; TagDataType type = this.entry.Type; uint count = this.entry.Count; uint offset = this.entry.Offset; if (count == 0) { return(string.Empty); } int typeSizeInBytes = TagDataTypeUtil.GetSizeInBytes(type); if (typeSizeInBytes == 1) { byte[] bytes = new byte[count]; if (this.offsetIsBigEndian) { switch (count) { case 1: bytes[0] = (byte)((offset >> 24) & 0x000000ff); break; case 2: bytes[0] = (byte)((offset >> 24) & 0x000000ff); bytes[1] = (byte)((offset >> 16) & 0x000000ff); break; case 3: bytes[0] = (byte)((offset >> 24) & 0x000000ff); bytes[1] = (byte)((offset >> 16) & 0x000000ff); bytes[2] = (byte)((offset >> 8) & 0x000000ff); break; case 4: bytes[0] = (byte)((offset >> 24) & 0x000000ff); bytes[1] = (byte)((offset >> 16) & 0x000000ff); bytes[2] = (byte)((offset >> 8) & 0x000000ff); bytes[3] = (byte)(offset & 0x000000ff); break; } } else { switch (count) { case 1: bytes[0] = (byte)(offset & 0x000000ff); break; case 2: bytes[0] = (byte)(offset & 0x000000ff); bytes[1] = (byte)((offset >> 8) & 0x000000ff); break; case 3: bytes[0] = (byte)(offset & 0x000000ff); bytes[1] = (byte)((offset >> 8) & 0x000000ff); bytes[2] = (byte)((offset >> 16) & 0x000000ff); break; case 4: bytes[0] = (byte)(offset & 0x000000ff); bytes[1] = (byte)((offset >> 8) & 0x000000ff); bytes[2] = (byte)((offset >> 16) & 0x000000ff); bytes[3] = (byte)((offset >> 24) & 0x000000ff); break; } } if (type == TagDataType.Ascii) { valueString = Encoding.ASCII.GetString(bytes).TrimEnd('\0'); } else if (count == 1) { valueString = bytes[0].ToString(CultureInfo.InvariantCulture); } else { StringBuilder builder = new StringBuilder(); uint lastItemIndex = count - 1; for (int i = 0; i < count; i++) { builder.Append(bytes[i].ToString(CultureInfo.InvariantCulture)); if (i < lastItemIndex) { builder.Append(","); } } valueString = builder.ToString(); } } else if (typeSizeInBytes == 2) { ushort[] values = new ushort[count]; if (this.offsetIsBigEndian) { switch (count) { case 1: values[0] = (ushort)((offset >> 16) & 0x0000ffff); break; case 2: values[0] = (ushort)((offset >> 16) & 0x0000ffff); values[1] = (ushort)(offset & 0x0000ffff); break; } } else { switch (count) { case 1: values[0] = (ushort)(offset & 0x0000ffff); break; case 2: values[0] = (ushort)(offset & 0x0000ffff); values[1] = (ushort)((offset >> 16) & 0x0000ffff); break; } } if (count == 1) { switch (type) { case TagDataType.SShort: valueString = ((short)values[0]).ToString(CultureInfo.InvariantCulture); break; case TagDataType.Short: default: valueString = values[0].ToString(CultureInfo.InvariantCulture); break; } } else { switch (type) { case TagDataType.SShort: valueString = ((short)values[0]).ToString(CultureInfo.InvariantCulture) + "," + ((short)values[1]).ToString(CultureInfo.InvariantCulture); break; case TagDataType.Short: default: valueString = values[0].ToString(CultureInfo.InvariantCulture) + "," + values[1].ToString(CultureInfo.InvariantCulture); break; } } } else { valueString = offset.ToString(CultureInfo.InvariantCulture); } return(valueString); }