/// <exception cref="System.IO.IOException"/> private static void ProcessTag(ITiffHandler handler, int tagId, int tagValueOffset, int componentCount, TiffDataFormatCode formatCode, IndexedReader reader) { switch (formatCode) { case TiffDataFormatCode.Undefined: { // this includes exif user comments handler.SetByteArray(tagId, reader.GetBytes(tagValueOffset, componentCount)); break; } case TiffDataFormatCode.String: { handler.SetString(tagId, reader.GetNullTerminatedStringValue(tagValueOffset, componentCount)); break; } case TiffDataFormatCode.RationalS: { if (componentCount == 1) { handler.SetRational(tagId, new Rational(reader.GetInt32(tagValueOffset), reader.GetInt32(tagValueOffset + 4))); } else if (componentCount > 1) { var array = new Rational[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = new Rational(reader.GetInt32(tagValueOffset + 8 * i), reader.GetInt32(tagValueOffset + 4 + 8 * i)); } handler.SetRationalArray(tagId, array); } break; } case TiffDataFormatCode.RationalU: { if (componentCount == 1) { handler.SetRational(tagId, new Rational(reader.GetUInt32(tagValueOffset), reader.GetUInt32(tagValueOffset + 4))); } else if (componentCount > 1) { var array = new Rational[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = new Rational(reader.GetUInt32(tagValueOffset + 8 * i), reader.GetUInt32(tagValueOffset + 4 + 8 * i)); } handler.SetRationalArray(tagId, array); } break; } case TiffDataFormatCode.Single: { if (componentCount == 1) { handler.SetFloat(tagId, reader.GetFloat32(tagValueOffset)); } else { var array = new float[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetFloat32(tagValueOffset + i * 4); } handler.SetFloatArray(tagId, array); } break; } case TiffDataFormatCode.Double: { if (componentCount == 1) { handler.SetDouble(tagId, reader.GetDouble64(tagValueOffset)); } else { var array = new double[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetDouble64(tagValueOffset + i * 4); } handler.SetDoubleArray(tagId, array); } break; } case TiffDataFormatCode.Int8S: { if (componentCount == 1) { handler.SetInt8S(tagId, reader.GetSByte(tagValueOffset)); } else { var array = new sbyte[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetSByte(tagValueOffset + i); } handler.SetInt8SArray(tagId, array); } break; } case TiffDataFormatCode.Int8U: { if (componentCount == 1) { handler.SetInt8U(tagId, reader.GetByte(tagValueOffset)); } else { var array = new byte[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetByte(tagValueOffset + i); } handler.SetInt8UArray(tagId, array); } break; } case TiffDataFormatCode.Int16S: { if (componentCount == 1) { handler.SetInt16S(tagId, reader.GetInt16(tagValueOffset)); } else { var array = new short[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetInt16(tagValueOffset + i * 2); } handler.SetInt16SArray(tagId, array); } break; } case TiffDataFormatCode.Int16U: { if (componentCount == 1) { handler.SetInt16U(tagId, reader.GetUInt16(tagValueOffset)); } else { var array = new ushort[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetUInt16(tagValueOffset + i * 2); } handler.SetInt16UArray(tagId, array); } break; } case TiffDataFormatCode.Int32S: { // NOTE 'long' in this case means 32 bit, not 64 if (componentCount == 1) { handler.SetInt32S(tagId, reader.GetInt32(tagValueOffset)); } else { var array = new int[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetInt32(tagValueOffset + i * 4); } handler.SetInt32SArray(tagId, array); } break; } case TiffDataFormatCode.Int32U: { // NOTE 'long' in this case means 32 bit, not 64 if (componentCount == 1) { handler.SetInt32U(tagId, reader.GetUInt32(tagValueOffset)); } else { var array = new uint[componentCount]; for (var i = 0; i < componentCount; i++) { array[i] = reader.GetUInt32(tagValueOffset + i * 4); } handler.SetInt32UArray(tagId, array); } break; } default: { handler.Error($"Invalid TIFF tag format code {formatCode} for tag 0x{tagId:X4}"); break; } } }
public IEnumerable <Directory> Extract(IndexedReader reader) { var header = reader.GetUInt32(0); if (header != 0x46464600) { var flirHeaderDirectory = new FlirHeaderDirectory(); flirHeaderDirectory.AddError("Unexpected FFF header bytes."); yield return(flirHeaderDirectory); yield break; } var headerDirectory = new FlirHeaderDirectory(); headerDirectory.Set(FlirHeaderDirectory.TagCreatorSoftware, reader.GetNullTerminatedStringValue(4, 16)); yield return(headerDirectory); var baseIndexOffset = reader.GetUInt32(24); var indexCount = reader.GetUInt32(28); var indexOffset = checked ((int)baseIndexOffset); for (int i = 0; i < indexCount; i++) { var mainType = (FlirMainTagType)reader.GetUInt16(indexOffset); var subType = reader.GetUInt16(indexOffset + 2); // 1=BE, 2=LE, 3=PNG; 1 for other record types var version = reader.GetUInt32(indexOffset + 4); var id = reader.GetUInt32(indexOffset + 8); var dataOffset = reader.GetInt32(indexOffset + 12); var dataLength = reader.GetInt32(indexOffset + 16); if (mainType == FlirMainTagType.Pixels) { var reader2 = reader.WithShiftedBaseOffset(dataOffset); // should be 0x0002 if byte order is correct var marker = reader2.GetUInt16(0); if (marker > 0x0100) { reader2 = reader2.WithByteOrder(!reader2.IsMotorolaByteOrder); } var directory = new FlirRawDataDirectory(); directory.Set(FlirRawDataDirectory.TagRawThermalImageWidth, reader2.GetUInt16(FlirRawDataDirectory.TagRawThermalImageWidth)); directory.Set(FlirRawDataDirectory.TagRawThermalImageHeight, reader2.GetUInt16(FlirRawDataDirectory.TagRawThermalImageHeight)); directory.Set(FlirRawDataDirectory.TagRawThermalImageType, reader2.GetUInt16(FlirRawDataDirectory.TagRawThermalImageType)); if (ExtractRawThermalImage) { directory.Set(FlirRawDataDirectory.TagRawThermalImage, reader2.GetBytes(32, dataLength - 32)); } yield return(directory); } else if (mainType == FlirMainTagType.BasicData) { var reader2 = reader.WithShiftedBaseOffset(dataOffset); // should be 0x0002 if byte order is correct var marker = reader2.GetUInt16(0); if (marker > 0x0100) { reader2 = reader2.WithByteOrder(!reader2.IsMotorolaByteOrder); } var directory = new FlirCameraInfoDirectory(); directory.Set(TagEmissivity, reader2.GetFloat32(TagEmissivity)); directory.Set(TagObjectDistance, reader2.GetFloat32(TagObjectDistance)); directory.Set(TagReflectedApparentTemperature, reader2.GetFloat32(TagReflectedApparentTemperature)); directory.Set(TagAtmosphericTemperature, reader2.GetFloat32(TagAtmosphericTemperature)); directory.Set(TagIRWindowTemperature, reader2.GetFloat32(TagIRWindowTemperature)); directory.Set(TagIRWindowTransmission, reader2.GetFloat32(TagIRWindowTransmission)); directory.Set(TagRelativeHumidity, reader2.GetFloat32(TagRelativeHumidity)); directory.Set(TagPlanckR1, reader2.GetFloat32(TagPlanckR1)); directory.Set(TagPlanckB, reader2.GetFloat32(TagPlanckB)); directory.Set(TagPlanckF, reader2.GetFloat32(TagPlanckF)); directory.Set(TagAtmosphericTransAlpha1, reader2.GetFloat32(TagAtmosphericTransAlpha1)); directory.Set(TagAtmosphericTransAlpha2, reader2.GetFloat32(TagAtmosphericTransAlpha2)); directory.Set(TagAtmosphericTransBeta1, reader2.GetFloat32(TagAtmosphericTransBeta1)); directory.Set(TagAtmosphericTransBeta2, reader2.GetFloat32(TagAtmosphericTransBeta2)); directory.Set(TagAtmosphericTransX, reader2.GetFloat32(TagAtmosphericTransX)); directory.Set(TagCameraTemperatureRangeMax, reader2.GetFloat32(TagCameraTemperatureRangeMax)); directory.Set(TagCameraTemperatureRangeMin, reader2.GetFloat32(TagCameraTemperatureRangeMin)); directory.Set(TagCameraTemperatureMaxClip, reader2.GetFloat32(TagCameraTemperatureMaxClip)); directory.Set(TagCameraTemperatureMinClip, reader2.GetFloat32(TagCameraTemperatureMinClip)); directory.Set(TagCameraTemperatureMaxWarn, reader2.GetFloat32(TagCameraTemperatureMaxWarn)); directory.Set(TagCameraTemperatureMinWarn, reader2.GetFloat32(TagCameraTemperatureMinWarn)); directory.Set(TagCameraTemperatureMaxSaturated, reader2.GetFloat32(TagCameraTemperatureMaxSaturated)); directory.Set(TagCameraTemperatureMinSaturated, reader2.GetFloat32(TagCameraTemperatureMinSaturated)); directory.Set(TagCameraModel, reader2.GetNullTerminatedStringValue(TagCameraModel, 32)); directory.Set(TagCameraPartNumber, reader2.GetNullTerminatedStringValue(TagCameraPartNumber, 16)); directory.Set(TagCameraSerialNumber, reader2.GetNullTerminatedStringValue(TagCameraSerialNumber, 16)); directory.Set(TagCameraSoftware, reader2.GetNullTerminatedStringValue(TagCameraSoftware, 16)); directory.Set(TagLensModel, reader2.GetNullTerminatedStringValue(TagLensModel, 32)); directory.Set(TagLensPartNumber, reader2.GetNullTerminatedStringValue(TagLensPartNumber, 16)); directory.Set(TagLensSerialNumber, reader2.GetNullTerminatedStringValue(TagLensSerialNumber, 16)); directory.Set(TagFieldOfView, reader2.GetFloat32(TagFieldOfView)); directory.Set(TagFilterModel, reader2.GetNullTerminatedStringValue(TagFilterModel, 16)); directory.Set(TagFilterPartNumber, reader2.GetNullTerminatedStringValue(TagFilterPartNumber, 32)); directory.Set(TagFilterSerialNumber, reader2.GetNullTerminatedStringValue(TagFilterSerialNumber, 32)); directory.Set(TagPlanckO, reader2.GetInt32(TagPlanckO)); directory.Set(TagPlanckR2, reader2.GetFloat32(TagPlanckR2)); directory.Set(TagRawValueRangeMin, reader2.GetUInt16(TagRawValueRangeMin)); directory.Set(TagRawValueRangeMax, reader2.GetUInt16(TagRawValueRangeMax)); directory.Set(TagRawValueMedian, reader2.GetUInt16(TagRawValueMedian)); directory.Set(TagRawValueRange, reader2.GetUInt16(TagRawValueRange)); var dateTimeBytes = reader2.GetBytes(TagDateTimeOriginal, 10); var dateTimeReader = new SequentialByteArrayReader(dateTimeBytes, isMotorolaByteOrder: false); var tm = dateTimeReader.GetUInt32(); var ss = dateTimeReader.GetUInt32() & 0xffff; var tz = dateTimeReader.GetInt16(); directory.Set(TagDateTimeOriginal, new DateTimeOffset(DateUtil.FromUnixTime(tm - tz * 60).AddSeconds(ss / 1000d), TimeSpan.FromMinutes(tz))); directory.Set(TagFocusStepCount, reader2.GetUInt16(TagFocusStepCount)); directory.Set(TagFocusDistance, reader2.GetFloat32(TagFocusDistance)); directory.Set(TagFrameRate, reader2.GetUInt16(TagFrameRate)); yield return(directory); } indexOffset += 32; } }