private ExifValue CreateValue() { if (this.RemainingLength < 12) { return(null); } ExifTag tag = this.ToEnum(this.GetShort(), ExifTag.Unknown); ExifDataType dataType = this.ToEnum(this.GetShort(), ExifDataType.Unknown); object value; if (dataType == ExifDataType.Unknown) { return(new ExifValue(tag, dataType, null, false)); } uint numberOfComponents = this.GetLong(); // Issue #132: ExifDataType == Undefined is treated like a byte array. // If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes) if (dataType == ExifDataType.Undefined && numberOfComponents == 0) { numberOfComponents = 4; } uint size = numberOfComponents * ExifValue.GetSize(dataType); byte[] data = this.GetBytes(4); if (size > 4) { uint oldIndex = this.currentIndex; this.currentIndex = this.ToLong(data) + this.startIndex; if (this.RemainingLength < size) { this.invalidTags.Add(tag); this.currentIndex = oldIndex; return(null); } value = this.ConvertValue(dataType, this.GetBytes(size), numberOfComponents); this.currentIndex = oldIndex; } else { value = this.ConvertValue(dataType, data, numberOfComponents); } bool isArray = value != null && numberOfComponents > 1; return(new ExifValue(tag, dataType, value, isArray)); }
private static TDataType[] ToArray <TDataType>(ExifDataType dataType, ReadOnlySpan <byte> data, ConverterMethod <TDataType> converter) { int dataTypeSize = (int)ExifValue.GetSize(dataType); int length = data.Length / dataTypeSize; var result = new TDataType[length]; for (int i = 0; i < length; i++) { ReadOnlySpan <byte> buffer = data.Slice(i * dataTypeSize, dataTypeSize); result.SetValue(converter(buffer), i); } return(result); }
private static TDataType[] ToArray <TDataType>(ExifDataType dataType, byte[] data, ConverterMethod <TDataType> converter) { int dataTypeSize = (int)ExifValue.GetSize(dataType); int length = data.Length / dataTypeSize; TDataType[] result = new TDataType[length]; byte[] buffer = new byte[dataTypeSize]; for (int i = 0; i < length; i++) { Array.Copy(data, i * dataTypeSize, buffer, 0, dataTypeSize); result.SetValue(converter(buffer), i); } return(result); }
private bool TryReadValue(out ExifValue exifValue) { // 2 | 2 | 4 | 4 // tag | type | count | value offset if (this.RemainingLength < 12) { exifValue = default; return(false); } ExifTag tag = this.ToEnum(this.ReadUInt16(), ExifTag.Unknown); uint type = this.ReadUInt16(); // Ensure that the data type is valid if (type == 0 || type > 12) { exifValue = new ExifValue(tag, ExifDataType.Unknown, null, false); return(true); } var dataType = (ExifDataType)type; object value; uint numberOfComponents = this.ReadUInt32(); // Issue #132: ExifDataType == Undefined is treated like a byte array. // If numberOfComponents == 0 this value can only be handled as an inline value and must fallback to 4 (bytes) if (dataType == ExifDataType.Undefined && numberOfComponents == 0) { numberOfComponents = 4; } uint size = numberOfComponents * ExifValue.GetSize(dataType); this.TryReadSpan(4, out ReadOnlySpan <byte> offsetBuffer); if (size > 4) { int oldIndex = this.position; uint newIndex = this.ConvertToUInt32(offsetBuffer) + (uint)this.startIndex; // Ensure that the new index does not overrun the data if (newIndex > int.MaxValue) { this.invalidTags.Add(tag); exifValue = default; return(false); } this.position = (int)newIndex; if (this.RemainingLength < size) { this.invalidTags.Add(tag); this.position = oldIndex; exifValue = default; return(false); } this.TryReadSpan((int)size, out ReadOnlySpan <byte> dataBuffer); value = this.ConvertValue(dataType, dataBuffer, numberOfComponents); this.position = oldIndex; } else { value = this.ConvertValue(dataType, offsetBuffer, numberOfComponents); } exifValue = new ExifValue(tag, dataType, value, isArray: value != null && numberOfComponents != 1); return(true); }