Manipulating TIFF images in .Net without 3rd party libraries

If you need to do basic TIFF file manipulation you don’t need to reach for a 3rd party library. The Windows.Media.Imaging namespace provides tools you can use to:

  • Create Multi-Page TIFF files
  • Extract Pages
  • Remove Pages
  • Get page count
  • Work with other encoder/decoders like gif, png, jpeg, bmp, etc.

Download a brief sample GitHub project here that demonstrates some common TIFF file operations.
The VS2013 solution contains a working console application with some sample images. For a quick code reference, the entire source is shown below.

You will need to reference the following namespaces. Note that you do not need to be doing a XAML/WPF project to utilize these classes:

Capture
The code below demonstrates merging several images into one multi-page TIFF file and then splitting those pages back out into separate files. One file is an image created in memory to illustrate that an image source can be any valid Image instance.

using System;
using System.Drawing;
using System.IO;
using System.Windows.Media.Imaging;

namespace TiffsAintTough
{
    class Program
    {
        private static Random rnd = new Random();

        static void Main(string[] args)
        {
            MakeATiff();
            SplitATiff();
        }

        ///
        /// Combines four images into one multi-page .tif
        ///
        public static void MakeATiff()
        {
            TiffBitmapEncoder tiffEncoder = new TiffBitmapEncoder();

            //The new .tif file that will be the combination of several image sources
            FileStream endResult = new FileStream(@"./images/NewTif.tif", FileMode.OpenOrCreate);

            //add three existing image files as pages (frames) to the new .tif file
            Stream imageStream = new FileStream(@"./images/codereview.png", FileMode.Open);
            BitmapFrame frame = BitmapFrame.Create(imageStream);
            tiffEncoder.Frames.Add(frame);

            imageStream = new FileStream(@"./images/happydog.jpg", FileMode.Open);
            frame = BitmapFrame.Create(imageStream);
            tiffEncoder.Frames.Add(frame);

            imageStream = new FileStream(@"./images/lobester.jpg", FileMode.Open);
            frame = BitmapFrame.Create(imageStream);
            tiffEncoder.Frames.Add(frame);

            //Demonstrate that a Frame can be created from any image source, not just existing file
            tiffEncoder.Frames.Add(MakeRandomImage());

            //saves the changes to the encoder
            tiffEncoder.Save(endResult);

            imageStream.Dispose();
            endResult.Dispose();
        }

        /// Creates a separate image from from each page of the new tiff we just created
        public static void SplitATiff()
        {
            using (FileStream fs = File.OpenRead(@"./images/NewTif.tif"))
            {
                TiffBitmapDecoder decoder = new TiffBitmapDecoder(fs, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);

                for (int i = 0; i < decoder.Frames.Count; i++)
                {
                    TiffBitmapEncoder encoder = new TiffBitmapEncoder();
                    encoder.Frames.Add(decoder.Frames[i]);
                    using (FileStream stream = new FileStream("./images/frame" + i.ToString() + ".tif", FileMode.Create))
                    {
                        encoder.Save(stream);
                    }
                }
            }
        }

        /// Helper function that creates a random image
        private static BitmapFrame MakeRandomImage()
        {
            System.Drawing.Image img = new System.Drawing.Bitmap(400, 400, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

            using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(img))
            {
                g.Clear(Color.White);
                for (int i = 0; i < 42; i++)
                {
                    Pen p = GetRandomPen();
                    Point start = GetRandomPoint();
                    Point end = GetRandomPoint();
                    g.DrawLine(p, start, end);
                    g.Save();
                }
            }
            var imgStream = new MemoryStream();
            img.Save(imgStream, System.Drawing.Imaging.ImageFormat.Png);
            imgStream.Position = 0;
            return BitmapFrame.Create(imgStream);
        }

        /// Generates a random Pen
        private static System.Drawing.Pen GetRandomPen()
        {
            Int32 LineWidth = rnd.Next(3, 25);
            Color rndColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
            return new Pen(rndColor, LineWidth);
        }

        /// Gets a random point
        private static Point GetRandomPoint()
        {
            int start = rnd.Next(0, 390);
            int end = rnd.Next(0, 390);
            return new Point(start, end);
        }
    }
}

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s