public static Bitmap <short> LoadTiff16(string inputFilename) { using (var tiffReader = new TiffReader(File.OpenRead(inputFilename))) { return(tiffReader.ReadImageFile <short>().ToBitmap()); } }
private static byte[] ExtractXMPPacket(BitmapMetadata xmp) { BitmapMetadata tiffMetaData = new BitmapMetadata("tiff"); tiffMetaData.SetQuery("/ifd/xmp", new BitmapMetadata("xmp")); foreach (string tag in xmp) { object value = xmp.GetQuery(tag); if (value is BitmapMetadata xmpSub) { CopySubIFDRecursive(ref tiffMetaData, xmpSub, "/ifd/xmp" + tag); } else { tiffMetaData.SetQuery("/ifd/xmp" + tag, value); } } byte[] xmpBytes = null; using (MemoryStream stream = new MemoryStream()) { // Create a dummy tiff to extract the XMP packet from. BitmapSource source = BitmapSource.Create(1, 1, 96.0, 96.0, PixelFormats.Gray8, null, new byte[] { 255 }, 1); TiffBitmapEncoder encoder = new TiffBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(source, null, tiffMetaData, null)); encoder.Save(stream); xmpBytes = TiffReader.ExtractXMP(stream); } return(xmpBytes); }
public async Task ReadSubIfdReferencesAsync_ReadsCorrectly(ByteOrder byteOrder, TiffType type) { var stream = new StreamBuilder(byteOrder) .WritePadding(20) .WriteUInt32(10) .WriteUInt32(42) .WriteUInt32(30) .ToStream(); var tiffIfd = new TiffIfd { Entries = new[] { new TiffIfdEntry { Tag = 10, Type = TiffType.Ascii, Count = 10 }, new TiffIfdEntry { Tag = TiffTags.SubIFDs, Type = type, Count = 3, Value = ByteArrayHelper.ToBytes(20u, byteOrder) }, new TiffIfdEntry { Tag = 20, Type = TiffType.Ascii, Count = 10 } } }; var subIfdReferences = await TiffReader.ReadSubIfdReferencesAsync(tiffIfd, stream, byteOrder); Assert.Equal(new[] { new TiffIfdReference(10), new TiffIfdReference(42), new TiffIfdReference(30) }, subIfdReferences); }
protected override IBitmap <short> LoadMapGranulate(int lat, int lon) { string bitmapPath = string.Format(InputPath, MapGranulateName(lat, lon)); var bitmapEntry = _zipArchive.GetEntry(bitmapPath); if (bitmapEntry == null) { return(_oceanBitmap); } Console.WriteLine($"Found: {bitmapPath}"); var memoryStream = new MemoryStream(); using (var tiffStream = bitmapEntry.Open()) tiffStream.CopyTo(memoryStream); memoryStream.Position = 0; var tiffReader = new TiffReader(memoryStream); var bitmap = tiffReader.ReadImageFile <short>(); _tiffReaders.Add(tiffReader); return(bitmap); }
public void Create() { var sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Charon\Charon_NewHorizons_Global_DEM_300m_Jul2017_16bit.tif"))) { var elevationTextureLarge = tiffReader.ReadImageFile <short>(); _elevationTexture = Resampler.Resample(elevationTextureLarge, 1200, 600).ToBitmap(); Console.WriteLine($"Resampling used {sw.Elapsed}"); } BitmapHelper.SaveRaw16($@"Generated\Planets\Charon\Charon{_elevationTexture.Width}x{_elevationTexture.Height}.raw", _elevationTexture); BitmapHelper.SaveTiff8($@"Generated\Planets\Charon\Charon{_elevationTexture.Width}x{_elevationTexture.Height}.tif", _elevationTexture); var blurFilter = new BlurFilter(PlanetProjection); sw = Stopwatch.StartNew(); _elevationTextureBlur = blurFilter.Blur2(_elevationTexture, MathHelper.ToRadians(10), (h) => { return(h != -32640 ? (short?)h : null); }); Console.WriteLine($"Blur used {sw.Elapsed}"); BitmapHelper.SaveRaw16($@"Generated\Planets\Charon\CharonBlur{_elevationTextureBlur.Width}x{_elevationTextureBlur.Height}.raw", _elevationTextureBlur); BitmapHelper.SaveTiff8($@"Generated\Planets\Charon\CharonBlur{_elevationTextureBlur.Width}x{_elevationTextureBlur.Height}.tif", _elevationTextureBlur); sw = Stopwatch.StartNew(); CreatePlanetVertexes(RecursionLevel); Console.WriteLine($"Time used to create planet vertexes: {sw.Elapsed}"); SaveStl($@"Generated\Planets\Charon\Charon{RecursionLevel}.stl"); }
public void Create() { Stopwatch sw; sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Phobos\Phobos_ME_HRSC_DEM_Global_2ppd.tif"))) { _elevationTexture = tiffReader.ReadImageFile <short>().ToBitmap(); Console.WriteLine($"Loading texture used {sw.Elapsed}"); } BitmapHelper.SaveTiff8($@"Generated\Planets\Phobos\Phobos{_elevationTexture.Width}x{_elevationTexture.Height}.tif", _elevationTexture); sw = Stopwatch.StartNew(); var blurFilter = new BlurFilter(PlanetProjection); _elevationTexture = blurFilter.Blur3(_elevationTexture, MathHelper.ToRadians(2)); Console.WriteLine($"Blur used {sw.Elapsed}"); sw = Stopwatch.StartNew(); CreatePlanetVertexes(RecursionLevel); Console.WriteLine($"Time used to create planet vertexes: {sw.Elapsed}"); SaveStl($@"Generated\Planets\Phobos\Phobos{RecursionLevel}.stl"); }
public void Create() { var sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Ceres\Ceres_Dawn_FC_HAMO_DTM_DLR_Global_60ppd_Oct2016.tif"))) { var elevationTextureLarge = tiffReader.ReadImageFile <short>(); _elevationTexture = Resampler.Resample(elevationTextureLarge, 1200, 600).ToBitmap(); Console.WriteLine($"Resampling used {sw.Elapsed}"); } BitmapHelper.SaveRaw16($@"Generated\Planets\Ceres\Ceres{_elevationTexture.Width}x{_elevationTexture.Height}.raw", _elevationTexture); BitmapHelper.SaveTiff8($@"Generated\Planets\Ceres\Ceres{_elevationTexture.Width}x{_elevationTexture.Height}.tif", _elevationTexture); var blurFilter = new BlurFilter(PlanetProjection); sw = Stopwatch.StartNew(); _elevationTextureBlur = blurFilter.Blur3(_elevationTexture, MathHelper.ToRadians(10)); Console.WriteLine($"Blur used {sw.Elapsed}"); BitmapHelper.SaveRaw16($@"Generated\Planets\Ceres\CeresBlur{_elevationTextureBlur.Width}x{_elevationTextureBlur.Height}.raw", _elevationTextureBlur); BitmapHelper.SaveTiff8($@"Generated\Planets\Ceres\CeresBlur{_elevationTextureBlur.Width}x{_elevationTextureBlur.Height}.tif", _elevationTextureBlur); sw = Stopwatch.StartNew(); CreatePlanetVertexes(RecursionLevel); Console.WriteLine($"Time used to create planet vertexes: {sw.Elapsed}"); SaveStl($@"Generated\Planets\Ceres\Ceres{RecursionLevel}.stl"); }
public async Task ReadIfdAsync_ReadsCorrectlyWithReference(ByteOrder byteOrder) { var stream = new StreamBuilder(byteOrder) .WritePadding(20) .WriteInt16(3) .WriteTiffIfdEntry(2, TiffType.Ascii, 20, new byte[] { 1, 2, 3, 4 }) .WriteTiffIfdEntry(4, TiffType.Short, 40, new byte[] { 2, 3, 4, 5 }) .WriteTiffIfdEntry(6, TiffType.Double, 60, new byte[] { 3, 4, 5, 6 }) .WriteUInt32(123456) .ToStream(); var ifdReference = new TiffIfdReference(20); var ifd = await TiffReader.ReadIfdAsync(ifdReference, stream, byteOrder); Assert.Equal(3, ifd.Entries.Length); AssertTiff.Equal(new TiffIfdEntry { Tag = 2, Type = TiffType.Ascii, Count = 20, Value = new byte[] { 1, 2, 3, 4 } }, ifd.Entries[0]); AssertTiff.Equal(new TiffIfdEntry { Tag = 4, Type = TiffType.Short, Count = 40, Value = new byte[] { 2, 3, 4, 5 } }, ifd.Entries[1]); AssertTiff.Equal(new TiffIfdEntry { Tag = 6, Type = TiffType.Double, Count = 60, Value = new byte[] { 3, 4, 5, 6 } }, ifd.Entries[2]); Assert.Equal(new TiffIfdReference(123456), ifd.NextIfdReference); }
public void SizeOfHeader_AlwaysReturnsEightBytes() { var header = new TiffHeader(); var size = TiffReader.SizeOfHeader(header); Assert.Equal(8, size); }
/// <summary> /// Reads first frame of image in TIFF format using memory-friendly Pipeline API /// </summary> private static void ReadTiffMemoryFriendly() { using (var reader = new TiffReader("../../../../_Output/WriteMultiframeTiffMemoryFriendly.tif")) using (var writer = new JpegWriter("../../../../_Output/ReadTiffMemoryFriendly.jpg")) { Pipeline.Run(reader + writer); } }
public void SizeOfIfdEntry_AlwaysReturnsTwelveBytes() { var ifdEntry = new TiffIfdEntry(); var size = TiffReader.SizeOfIfdEntry(ifdEntry); Assert.Equal(12, size); }
/// <summary> /// Reads and saves extra channel /// </summary> private static void ReadExtraChannel() { using (var reader = new TiffReader("../../../../_Output/BusinessCard.tif")) { var bitmap = reader.Frames[0].ExtraChannels[0].GetBitmap(); bitmap.Save("../../../../_Output/BusinessCard_ReadExtra.tif"); } }
public void Create() { Stopwatch sw; sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Mars\Mars_HRSC_MOLA_BlendDEM_Global_200mp.tif"))) { var ifd = tiffReader.ImageFileDirectories[0]; _topSectorOffsetY = (int)(ifd.ImageHeight * (Math.PI / 2 - LatT0) / Math.PI); _topSectorOffsetX = (int)(ifd.ImageWidth * (Math.PI + LonT0) / (Math.PI * 2)); _topSectorWidth = (int)Math.Ceiling(ifd.ImageHeight * (LatT0 - LatT1) / Math.PI); _topSectorHeight = (int)Math.Ceiling(ifd.ImageWidth * (LonT1 - LonT0) / (Math.PI * 2)); var topElevationBitmap = tiffReader.ReadImageFile <short>(ifd, _topSectorOffsetX, _topSectorOffsetY, _topSectorWidth, _topSectorHeight); _topElevationBitmap = topElevationBitmap /*Resampler.Resample(topElevationBitmap, 1024, 1024)*/.ToBitmap(); Console.WriteLine($"Loading image top {_topElevationBitmap.Width}x{_topElevationBitmap.Height} sector used {sw.Elapsed}"); using (var tiffWriter = new TiffWriter(File.Create($@"Generated\Planets\MarsDouble2\MarsTop.tif"))) { var bitmap = _topElevationBitmap.Convert((p) => { return((ushort)(p - short.MinValue)); }); tiffWriter.WriteImageFile(bitmap); } //-- _bottomSectorOffsetY = (int)(ifd.ImageHeight * (Math.PI / 2 - LatB0) / Math.PI); _bottomSectorOffsetX = (int)(ifd.ImageWidth * (Math.PI + LonB0) / (Math.PI * 2)); _bottomSectorWidth = (int)Math.Ceiling(ifd.ImageHeight * (LatB0 - LatB1) / Math.PI); _bottomSectorHeight = (int)Math.Ceiling(ifd.ImageWidth * (LonB1 - LonB0) / (Math.PI * 2)); var bottomElevationBitmap = tiffReader.ReadImageFile <short>(ifd, _bottomSectorOffsetX, _bottomSectorOffsetY, _bottomSectorWidth, _bottomSectorHeight); _bottomElevationBitmap = bottomElevationBitmap /*Resampler.Resample(bottomElevationBitmap, 1024, 1024)*/.ToBitmap(); Console.WriteLine($"Loading image bottom {_bottomElevationBitmap.Width}x{_bottomElevationBitmap.Height} sector used {sw.Elapsed}"); using (var tiffWriter = new TiffWriter(File.Create($@"Generated\Planets\MarsDouble2\MarsBottom.tif"))) { var bitmap = _bottomElevationBitmap.Convert((p) => { return((ushort)(p - short.MinValue)); }); tiffWriter.WriteImageFile(bitmap); } } Init(); sw = Stopwatch.StartNew(); Split(); Console.WriteLine($"Time used to split planet geometry: {sw.Elapsed}"); PrintSummary(); sw = Stopwatch.StartNew(); Merge(); Console.WriteLine($"Time used to merge planet geometry: {sw.Elapsed}"); PrintSummary(); SaveStl("Generated/Planets/MarsDouble2/MarsDouble2.stl"); }
public void SizeOfIfd_ReturnsCorrectSize(int entryCount, int expectedSize) { var ifd = new TiffIfd { Entries = new TiffIfdEntry[entryCount] }; var size = TiffReader.SizeOfIfd(ifd); Assert.Equal(expectedSize, size); }
public void Create() { var targetPath = $@"Generated\Planets\Mars\{Name}"; Directory.CreateDirectory(targetPath); Stopwatch sw; int width = 2880; int height = 1440; string elevationTextureFilename = $@"Generated\Planets\Mars\{Name}\Mars{width}x{height}.tif"; if (!File.Exists(elevationTextureFilename)) { sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Mars\Mars_HRSC_MOLA_BlendDEM_Global_200mp.tif"))) { // Right-most pixel column in the Mars dataset is broken. This trick will skip it. var ifd = tiffReader.ImageFileDirectories[0]; var elevationTextureLarge = tiffReader.ReadImageFile <short>(0, 0, ifd.ImageWidth - 1, ifd.ImageHeight); _elevationTexture = Resampler.Resample(elevationTextureLarge, width, height).ToBitmap(); Console.WriteLine($"Resampling used {sw.Elapsed}"); } BitmapHelper.SaveTiff16(elevationTextureFilename, _elevationTexture); } else { _elevationTexture = BitmapHelper.LoadTiff16(elevationTextureFilename); } string elevationTextureBlurFilename = $@"Generated\Planets\Mars\{Name}\MarsBlur{width}x{height}.raw"; if (!File.Exists(elevationTextureBlurFilename)) { sw = Stopwatch.StartNew(); var blurFilter = new BlurFilter(PlanetProjection); _elevationTextureBlur = blurFilter.Blur3(_elevationTexture, MathHelper.ToRadians(10)); Console.WriteLine($"Blur used {sw.Elapsed}"); BitmapHelper.SaveTiff16(elevationTextureBlurFilename, _elevationTextureBlur); } else { _elevationTextureBlur = BitmapHelper.LoadRaw16(elevationTextureBlurFilename, width, height); } sw = Stopwatch.StartNew(); CreatePlanetVertexes(RecursionLevel); Console.WriteLine($"Time used to create planet vertexes: {sw.Elapsed}"); SaveStl($@"Generated\Planets\Mars\{Name}\Mars{RecursionLevel}_{(int)ElevationScale}x.stl"); }
public async Task ReadHeaderAsync_ThrowsException_MagicNumberIsIncorrect() { var stream = new StreamBuilder(ByteOrder.BigEndian) .WriteBytes(0x4D, 0x4D) .WriteInt16(123) .WriteUInt32(123456) .ToStream(); var e = await Assert.ThrowsAsync <ImageFormatException>(() => TiffReader.ReadHeaderAsync(stream)); Assert.Equal("The TIFF header does not contain the expected magic number.", e.Message); }
public async Task ReadHeaderAsync_ThrowsException_IfSecondByteOrderMarkerIsUnknown() { var stream = new StreamBuilder(ByteOrder.BigEndian) .WriteBytes(0x4D, 0xAB) .WriteInt16(42) .WriteUInt32(123456) .ToStream(); var e = await Assert.ThrowsAsync <ImageFormatException>(() => TiffReader.ReadHeaderAsync(stream)); Assert.Equal("The TIFF byte order markers are invalid.", e.Message); }
public void TestReadRgbChunky() { using (var tiffReader = new TiffReader(File.OpenRead(Path.Combine("TestData", "rgb_chunky.tif")))) { var ifd = tiffReader.ImageFileDirectories[0]; Assert.Equal(64, ifd.ImageWidth); Assert.Equal(64, ifd.ImageHeight); Assert.Equal(8, ifd.BitsPerSample); Assert.Equal(3, ifd.SamplesPerPixel); Assert.Equal(Compression.NoCompression, ifd.Compression); var bitmap = tiffReader.ReadImageFile <byte>(ifd).ToBitmap(); } }
/// <summary> /// Reads multiframe image in TIFF format using memory-friendly Pipeline API /// </summary> private static void ReadMultiframeTiffMemoryFriendly() { using (var reader = new TiffReader("../../../../_Output/WriteMultiframeTiff.tif")) { for (int i = 0; i < reader.Frames.Count; i++) { using (var writer = new JpegWriter("../../../../_Output/ReadMultiframeTiffMemoryFriendly_" + i + ".jpg")) { Pipeline.Run(reader.Frames[i] + writer); } } } }
/// <summary> /// Reads multiframe image in TIFF format /// </summary> private static void ReadMultiframeTiff() { using (var reader = new TiffReader("../../../../_Output/WriteMultiframeTiff.tif")) { for (int i = 0; i < reader.Frames.Count; i++) { using (var bitmap = reader.Frames[i].GetBitmap()) { bitmap.Save("../../../../_Output/ReadMultiframeTiff_" + i + ".jpg"); } } } }
public async Task ReadHeaderAsync_ReadsCorrectly_BigEndian() { var stream = new StreamBuilder(ByteOrder.BigEndian) .WriteBytes(0x4D, 0x4D) .WriteInt16(42) .WriteUInt32(123456) .ToStream(); var header = await TiffReader.ReadHeaderAsync(stream); Assert.Equal(ByteOrder.BigEndian, header.ByteOrder); Assert.Equal(new TiffIfdReference(123456), header.FirstIfdReference); }
public void TestReadGray32() { using (var tiffReader = new TiffReader(File.OpenRead(Path.Combine("TestData", "gray32.tif")))) { var ifd = tiffReader.ImageFileDirectories[0]; Assert.Equal(64, ifd.ImageWidth); Assert.Equal(64, ifd.ImageHeight); Assert.Equal(32, ifd.BitsPerSample); Assert.Equal(1, ifd.SamplesPerPixel); Assert.Equal(Compression.NoCompression, ifd.Compression); var bitmap = tiffReader.ReadImageFile <float>(ifd).ToBitmap(); } }
public static TiffIfdReference?GetExifIfdReference(TiffIfd ifd, ByteOrder byteOrder) { var exifEntry = TiffReader.GetTiffIfdEntry(ifd, TiffTags.ExifIFD); if (exifEntry == null) { return(null); } else { return(exifEntry.Value.GetIfdReference(byteOrder)); } }
/// <summary> /// Loads multiframe image /// </summary> private static void LoadMultiframeImage() { using (var reader = new TiffReader("../../../../_Output/SaveMultiframe.tif")) { for (int i = 0; i < reader.Frames.Count; i++) { using (var bitmap = reader.Frames[i].GetBitmap()) { bitmap.Save("../../../../_Output/LoadMultiframe_" + i + ".jpg"); } } } }
public void Create() { Stopwatch sw; int width = 2880; int height = 1440; string elevationTextureSmallFilename = $@"Generated\Planets\Moon\Moon{width}x{height}.tif"; if (!File.Exists(elevationTextureSmallFilename)) { sw = Stopwatch.StartNew(); using (var tiffReader = new TiffReader(File.OpenRead(@"Datasets\Planets\Moon\Lunar_LRO_LOLA_Global_LDEM_118m_Mar2014.tif"))) { var elevationTextureLarge = tiffReader.ReadImageFile <short>(); _elevationTexture = Resampler.Resample(elevationTextureLarge, width, height).ToBitmap(); Console.WriteLine($"Resampling used {sw.Elapsed}"); } BitmapHelper.SaveTiff16(elevationTextureSmallFilename, _elevationTexture); BitmapHelper.SaveTiff8($@"Generated\Planets\Moon\Moon{_elevationTexture.Width}x{_elevationTexture.Height}.tif", _elevationTexture); } else { _elevationTexture = BitmapHelper.LoadTiff16(elevationTextureSmallFilename); } string elevationTextureBlurFilename = $@"Generated\Planets\Moon\MoonBlur{width}x{height}.tif"; if (!File.Exists(elevationTextureBlurFilename)) { sw = Stopwatch.StartNew(); var blurFilter = new BlurFilter(PlanetProjection); _elevationTextureBlur = blurFilter.Blur3(_elevationTexture, MathHelper.ToRadians(10)); Console.WriteLine($"Blur used {sw.Elapsed}"); BitmapHelper.SaveTiff16(elevationTextureBlurFilename, _elevationTextureBlur); } else { _elevationTextureBlur = BitmapHelper.LoadTiff16(elevationTextureBlurFilename); } //BitmapHelper.SaveTiff8($@"Generated\Planets\Moon\MoonBlur{_elevationTextureBlur.Width}x{_elevationTextureBlur.Height}.tif", _elevationTextureBlur); sw = Stopwatch.StartNew(); CreatePlanetVertexes(RecursionLevel); Console.WriteLine($"Time used to create planet vertexes: {sw.Elapsed}"); SaveStl($@"Generated\Planets\Moon\Moon{RecursionLevel}.stl"); }
public void ParseIfdEntry_CanCompareToTiffTagEnumeration(ByteOrder byteOrder) { var bytes = new StreamBuilder(byteOrder) .WritePadding(20) .WriteInt16(274) .WriteInt16(5) .WriteUInt32(123456) .WriteBytes(new byte[] { 3, 4, 5, 6 }) .ToBytes(); var ifdEntry = TiffReader.ParseIfdEntry(bytes, 20, byteOrder); Assert.True(ifdEntry.Tag == TiffTags.Orientation); }
protected override IBitmap <short> LoadMapGranulate(int lat, int lon) { string bitmapPath = LocateMapGranulate(lat, lon); if (bitmapPath == null) { return(_oceanBitmap); } var tiffReader = new TiffReader(File.OpenRead(bitmapPath)); var bitmap = tiffReader.ReadImageFile <short>(); _tiffReaders.Add(tiffReader); return(bitmap); }
/// <summary> /// Creates business card 3.5"x2.0" size with extra channel /// </summary> private static void WriteExtraChannel() { using (var reader = new TiffReader("../../../../_Output/BusinessCard_Base.tif")) using (var writer = new TiffWriter("../../../../_Output/BusinessCard.tif")) { // Load bitmap for the extra channel. // Note: image for extra channel must be grayscale and have the same dimensions and DPI as the source one. using (var extraBitmap = new Bitmap("../../../../_Output/BusinessCard_Extra.tif")) { // Create extra channel options based on extraBitmap. var extraChannel = new TiffExtraChannelEntry(extraBitmap, TiffChannelType.Alpha); writer.ExtraChannels.Add(extraChannel); Pipeline.Run(reader + writer); } } }
/// <summary> /// Combines image channels from multiple sources /// </summary> private static void CombineChannels() { using (var writer = ImageWriter.Create("../../../../_Output/Copenhagen_CMYK_Combined.jpg")) using (var combiner = new CmykChannelCombiner()) using (var readerC = new TiffReader("../../../../_Output/Copenhagen_C.tif")) using (var readerM = new TiffReader("../../../../_Output/Copenhagen_M.tif")) using (var readerY = new TiffReader("../../../../_Output/Copenhagen_Y.tif")) using (var readerK = new TiffReader("../../../../_Output/Copenhagen_K.tif")) { combiner.C = readerC; combiner.M = readerM; combiner.Y = readerY; combiner.K = readerK; Pipeline.Run(combiner + writer); } }
public DirectoryList Extract([NotNull] IndexedReader reader) { var directories = new List <Directory>(); var exifTiffHandler = new ExifTiffHandler(directories); try { // Read the TIFF-formatted Exif data TiffReader.ProcessTiff(reader, exifTiffHandler); } catch (Exception e) { exifTiffHandler.Error("Exception processing TIFF data: " + e.Message); } return(directories); }