If you want to convert a bitmap into a TIFF, than then you can use the code:

using (System.Drawing.Bitmap sourceBitmap = new System.Drawing.Bitmap(@"C:\Temp\Source.bmp"))
    string outputFileName = @"C:\Temp\Destination.tiff";
    if (System.IO.File.Exists(outputFileName))
    sourceBitmap.Save(outputFileName, System.Drawing.Imaging.ImageFormat.Tiff);

If you want to convert a bitmap to a 1bpp monochrome TIFF in C#, I found 4 options:

1. http://www.bobpowell.net/onebit.htm ( no P-Invoke required, but not as fast as other methods )

2. http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/9757dc94-11f3-4b30-a85c-cb9145eba12d (only when you are using WPF)

3. http://www.news2news.com/vfp/?example=493&ver=vcs&PHPSESSID=35494364de9987dfd2a9f3fe18f17565 (less code then option 4, but did not have time to investigate)

4. http://www.wischik.com/lu/programmer/1bpp.html


For the last options I cleanup some code:

using (System.Drawing.Bitmap sourceBitmap = new System.Drawing.Bitmap(@"C:\Temp\Source.bmp"))
    using (Bitmap destinationBitmap = sourceBitmap.ConvertToMonochromeTiff())
        string outputFileName = @"C:\Temp\Destination.tiff";
        if (System.IO.File.Exists(outputFileName))

Where the ConvertToMonochromeTiff is an extension method to the System.Drawing.Bitmap type:


using System;
using System.Drawing;

namespace Rli.Extensions
    /// <summary>
    /// Contains extensions methods to the System.Drawing.Bitmap type.
    /// </summary>
    public static class BitmapExtensions
        #region P-Invoke
        public static extern bool DeleteObject(IntPtr hObject);

        public static extern IntPtr GetDC(IntPtr hwnd);

        public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

        public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        public static extern int DeleteDC(IntPtr hdc);

        public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

        public static extern int BitBlt(IntPtr hdcDst, int xDst, int yDst, int w, int h, IntPtr hdcSrc, int xSrc, int ySrc, int rop);
        static int SRCCOPY = 0x00CC0020;

        static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
        static uint BI_RGB = 0;
        static uint DIB_RGB_COLORS = 0;
        public struct BITMAPINFO
            public uint biSize;
            public int biWidth, biHeight;
            public short biPlanes, biBitCount;
            public uint biCompression, biSizeImage;
            public int biXPelsPerMeter, biYPelsPerMeter;
            public uint biClrUsed, biClrImportant;
            [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 256)]
            public uint[] cols;

        static uint MAKERGB(int r, int g, int b)
            return ((uint)(b & 255)) | ((uint)((r & 255) << 8)) | ((uint)((g & 255) << 16));

        /// <summary>
        /// Converts the given bitmap to a monochrome tiff bitmap.
        /// </summary>
        /// <param name="sourceBitmap">The source bitmap.</param>
        /// <returns></returns>
        public static Bitmap ConvertToMonochromeTiff(this Bitmap sourceBitmap)
            Bitmap destination = null;
            int bpp = 1;                                                            // Amount of bits to use in pallet, for monochrome use 1 bit (0 = black, 1 = white).
            uint ncols = (uint)1 << bpp;                                            // Use 2 colours (black and white) for monochrome tiff.
            int width = sourceBitmap.Width;
            int height = sourceBitmap.Height;
            uint size = (uint)(((width + 7) & 0xFFFFFFF8) * height / 8);
            uint[] pallet = new uint[256];                                          // Pallet has a fixed size 256, even when we are using fewer colours.
            pallet[0] = MAKERGB(0, 0, 0);                                           // Create black pixel.
            pallet[1] = MAKERGB(255, 255, 255);                                     // Create white pixel.
            BITMAPINFO bmi = new BITMAPINFO()                                       // Create unmanaged monochrome bitmapinfo.
                biSize = 40,                                                        // The size of the BITMAPHEADERINFO struct.
                biWidth = width,
                biHeight = height,
                biPlanes = 1,
                biBitCount = (short)bpp,                                            // Amount of bits per pixel (1 for monochrome).
                biCompression = BI_RGB,
                biSizeImage = size,
                biXPelsPerMeter = 1000000,
                biYPelsPerMeter = 1000000,
                biClrUsed = ncols,
                biClrImportant = ncols,
                cols = pallet

            IntPtr sourceHbitmap = sourceBitmap.GetHbitmap();                       // Convert bitmap to unmanaged HBitmap.
            IntPtr bits0;                                                           // Pointer to the raw bits that make up the bitmap.
            IntPtr destinationHbitmap = CreateDIBSection
                ref bmi,
                out bits0,
            );                                                                      // Create the indexed bitmap.
            IntPtr screenDC = GetDC(IntPtr.Zero);                                   // Obtain the DC (= GDI equivalent of "Graphics" in GDI+) for the screen.
            IntPtr sourceDC = CreateCompatibleDC(screenDC);                         // Create a DC for the original hbitmap.
            SelectObject(sourceDC, sourceHbitmap);
            IntPtr destinationDC = CreateCompatibleDC(screenDC);                    // Create a DC for the monochrome hbitmap.
            SelectObject(destinationDC, destinationHbitmap);
            BitBlt(destinationDC, 0, 0, width, height, sourceDC, 0, 0, SRCCOPY);    // Use GDI's BitBlt function to copy from original hbitmap into monocrhome bitmap.
            destination = System.Drawing.Bitmap.FromHbitmap(destinationHbitmap);    // Convert this monochrome hbitmap back into a Bitmap.

            // Cleanup.
            ReleaseDC(IntPtr.Zero, screenDC);

            return destination;


  1. Hi,

    Very good article. i learnt lot of things. I am using .Net Compact Framework 2.0/3.0 and getting error at fallowing line as OutOfMemoryException.
    destination = System.Drawing.Bitmap.FromHbitmap(destinationHbitmap); // Convert this monochrome hbitmap back into a Bitmap.

    Can you please help me to solve this ?

    Siddeswara GM

    Siddeswara GM
  2. Nice post! I did find that #2 above CAN be used within a C# console application if you include the WPF libraries (PresentationCore.dll and System.Xaml.dll I think). Then code like this can be used to generate pretty decent 1bpp TIF files:

    TiffBitmapEncoder encoder = new TiffBitmapEncoder();
    encoder.Compression = TiffCompressOption.Ccitt4;



    Mark Quigg

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.