C# Splitting Multi-page Tiff into Single Tiff's on Windows 7 / .Net 4.0
I recently moved to a new development box from Windows XP 32 Bit to Windows 7 64 bit. Both machines are running .Net Framework version 4.0 for development with Visual Studio 2010.

After upgrading to Windows 7 64 Bit, my code to split a multi-page Tiff image into separate images is now broken (worked fine previously on XP 32 Bit, except for the MS fill order bug).  After debugging, the Bitmap Metadata appears to be read correctly by the .Net Framework, however, some component in the stack is incorrectly persisting the some Tiff Tags (273, 278, and 279).  I have tried several methods to accomplish the split, including GDI+, and the FreeImage library, but all fail within .Net.  I was able to successful split the Tiff using Image Magick and another 3rd party tool with valid tag values. 


Specifically, Tiff Tags 273, 278 (should match 257 but does not), and 279 have incorrect values.

Is this a known Microsoft issue? Is there a workaround? Am I doing this task wrong? Very frustrated as this was working on XP 32 just fine and that OS is not a deployment option.


	// Copy bytes into our memory
	using (MemoryStream ms = new MemoryStream())
	{
		using (BinaryWriter bw = new BinaryWriter(ms))
	    {
	        // Get the multi page tiff image's size, and allocate a place to put it.
	        int size = RdmInstance.ImageSize;
	        byte[] imgContents = new byte[size + 1];

			// Create the pointer and assign the Rdm image address to it
			IntPtr pointerToImage = new IntPtr(RdmInstance.ImageData);

			// Copy the bytes from unmanaged memory to managed memory
			Marshal.Copy(pointerToImage, imgContents, 0, size);

			// Now, write that contents into our memory stream
			bw.Write(imgContents);


			// Check for multiple tiff pages, split them out and write them out correctly for the Fed
			TiffBitmapDecoder decoder = new TiffBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

			if (decoder.Frames.Count > 0)
			{

				// check for multi page tiff
				for (int i = 0; i < decoder.Frames.Count; i++)
				{
					log.InfoFormat("Loading Multi Page Tiff Frame [{0}]... to bitmap", i);

					// First is front, second is back 
					// TODO - it would be better to get this out of tiff tag RDM sets with the page info
					string fileName = (i == 0) ? frontFileName : backFileName;
					BitmapSource bmSrc = decoder.Frames[i];
					TiffBitmapEncoder encoder = new TiffBitmapEncoder();

					encoder.Compression = TiffCompressOption.Ccitt4;
					encoder.Frames.Add(BitmapFrame.Create(bmSrc));

					log.InfoFormat("Saving Multi Page Tiff Frame [{0}]... to file {1}.", i, fileName);
					using (var fs = new FileStream(fileName, FileMode.Create))
					{
						encoder.Save(fs);
					}

					/*
					 * jknipp - 6/4/2010 
					 * Microsoft has a bug in their TiffBitmapEncoder where
					 * they incorrectly set tag 266 (Fill Order) to 0, where the TIFF
					 * spec says it should be 1 or 2. We fix this here.
					 * Reopen the stupid file and fix the fill order
					 */
					using (var file = new FileStream(fileName, FileMode.Open))
					{
						TiffBitmapDecoder output = new TiffBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
						InPlaceBitmapMetadataWriter metadata = output.Frames[0].CreateInPlaceBitmapMetadataWriter();

						var fillOrder = metadata.GetQuery("/ifd/{ushort=266}");
						log.DebugFormat("Read Fill Order Metadata tag as {0}", fillOrder);

						// If .Net added a bogus fill order, correct it
						if (fillOrder != null && (ushort)fillOrder == 0)
						{
							log.InfoFormat("Correcting FILL ORDER in file {0}", fileName);
							metadata.SetQuery("/ifd/{ushort=266}", (ushort)1);

							// Try to save new metadata
							if (metadata.TrySave())
							{
								fillOrder = metadata.GetQuery("/ifd/{ushort=266}");
								log.Info("Fill order correction successful!");
								log.DebugFormat("Read New Fill Order Metadata tag as {0}", fillOrder);
							}
						}
					}
				}
			}
		}
	}

C# Splitting Multi-page Tiff into Single Tiff's on Windows 7 / .Net 4.0
===

I recently moved to a new development box from Windows XP 32 Bit to Windows 7 64 bit. Both machines are running .Net Framework version 4.0 for development with Visual Studio 2010.

After upgrading to Windows 7 64 Bit, my code to split a multi-page Tiff image into separate images is now broken (worked fine previously on XP 32 Bit, except for the MS fill order bug).  After debugging, the Bitmap Metadata appears to be read correctly by the .Net Framework, however, some component in the stack is incorrectly persisting the some Tiff Tags (273, 278, and 279).  I have tried several methods to accomplish the split, including GDI+, and the FreeImage library, but all fail within .Net.  I was able to successful split the Tiff using Image Magick and another 3rd party tool with valid tag values. 


Specifically, Tiff Tags 273, 278 (should match 257 but does not), and 279 have incorrect values.

Is this a known Microsoft issue? Is there a workaround? Am I doing this task wrong? Very frustrated as this was working on XP 32 just fine and that OS is not a deployment option.


	// Copy bytes into our memory
	using (MemoryStream ms = new MemoryStream())
	{
		using (BinaryWriter bw = new BinaryWriter(ms))
	    {
	        // Get the multi page tiff image's size, and allocate a place to put it.
	        int size = RdmInstance.ImageSize;
	        byte[] imgContents = new byte[size + 1];

			// Create the pointer and assign the Rdm image address to it
			IntPtr pointerToImage = new IntPtr(RdmInstance.ImageData);

			// Copy the bytes from unmanaged memory to managed memory
			Marshal.Copy(pointerToImage, imgContents, 0, size);

			// Now, write that contents into our memory stream
			bw.Write(imgContents);


			// Check for multiple tiff pages, split them out and write them out correctly for the Fed
			TiffBitmapDecoder decoder = new TiffBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

			if (decoder.Frames.Count > 0)
			{

				// check for multi page tiff
				for (int i = 0; i < decoder.Frames.Count; i++)
				{
					log.InfoFormat("Loading Multi Page Tiff Frame [{0}]... to bitmap", i);

					// First is front, second is back 
					// TODO - it would be better to get this out of tiff tag RDM sets with the page info
					string fileName = (i == 0) ? frontFileName : backFileName;
					BitmapSource bmSrc = decoder.Frames[i];
					TiffBitmapEncoder encoder = new TiffBitmapEncoder();

					encoder.Compression = TiffCompressOption.Ccitt4;
					encoder.Frames.Add(BitmapFrame.Create(bmSrc));

					log.InfoFormat("Saving Multi Page Tiff Frame [{0}]... to file {1}.", i, fileName);
					using (var fs = new FileStream(fileName, FileMode.Create))
					{
						encoder.Save(fs);
					}

					/*
					 * jknipp - 6/4/2010 
					 * Microsoft has a bug in their TiffBitmapEncoder where
					 * they incorrectly set tag 266 (Fill Order) to 0, where the TIFF
					 * spec says it should be 1 or 2. We fix this here.
					 * Reopen the stupid file and fix the fill order
					 */
					using (var file = new FileStream(fileName, FileMode.Open))
					{
						TiffBitmapDecoder output = new TiffBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
						InPlaceBitmapMetadataWriter metadata = output.Frames[0].CreateInPlaceBitmapMetadataWriter();

						var fillOrder = metadata.GetQuery("/ifd/{ushort=266}");
						log.DebugFormat("Read Fill Order Metadata tag as {0}", fillOrder);

						// If .Net added a bogus fill order, correct it
						if (fillOrder != null && (ushort)fillOrder == 0)
						{
							log.InfoFormat("Correcting FILL ORDER in file {0}", fileName);
							metadata.SetQuery("/ifd/{ushort=266}", (ushort)1);

							// Try to save new metadata
							if (metadata.TrySave())
							{
								fillOrder = metadata.GetQuery("/ifd/{ushort=266}");
								log.Info("Fill order correction successful!");
								log.DebugFormat("Read New Fill Order Metadata tag as {0}", fillOrder);
							}
						}
					}
				}
			}
		}
	}
