lossless compresson help please

Posted on 2011-10-14
Last Modified: 2012-06-27
Hi all, I need help please I need to make this bmpConvert process at lossless compression.... I am not sure how to go about that  you will see my MESS of code below any ideas any thoughts?
using System;
using System.Collections.Generic;
using System.Text;

namespace PARK_Enroll_Adj_DMS_v1_07_28_2011
    class BmpConverter
          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>
        /// Copies a bitmap into a 1bpp/8bpp bitmap of the same dimensions, fast
        /// </summary>
        /// <param name="b">original bitmap</param>
        /// <param name="bpp">1 or 8, target bpp</param>
        /// <returns>a 1bpp copy of the bitmap</returns>
        public static System.Drawing.Bitmap CopyToBpp(System.Drawing.Bitmap b, int bpp)
        { if (bpp!=1 && bpp!=8) throw new System.ArgumentException("1 or 8","bpp");

          // Plan: built into Windows GDI is the ability to convert
          // bitmaps from one format to another. Most of the time, this
          // job is actually done by the graphics hardware accelerator card
          // and so is extremely fast. The rest of the time, the job is done by
          // very fast native code.
          // We will call into this GDI functionality from C#. Our plan:
          // (1) Convert our Bitmap into a GDI hbitmap (ie. copy unmanaged->managed)
          // (2) Create a GDI monochrome hbitmap
          // (3) Use GDI "BitBlt" function to copy from hbitmap into monochrome (as above)
          // (4) Convert the monochrone hbitmap into a Bitmap (ie. copy unmanaged->managed)

          int w=b.Width, h=b.Height;
          IntPtr hbm = b.GetHbitmap(); // this is step (1)
          // Step (2): create the monochrome bitmap.
          // "BITMAPINFO" is an interop-struct which we define below.
          // In GDI terms, it's a BITMAPHEADERINFO followed by an array of two RGBQUADs
          BITMAPINFO bmi = new BITMAPINFO();
          bmi.biSize=40;  // the size of the BITMAPHEADERINFO struct
          bmi.biPlanes=1; // "planes" are confusing. We always use just 1. Read MSDN for more info.
          bmi.biBitCount=(short)bpp; // ie. 1bpp or 8bpp
          bmi.biCompression=BI_RGB; // ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes
          bmi.biSizeImage = (uint)(((w+7)&0xFFFFFFF8)*h/8);
          bmi.biXPelsPerMeter=1000000; // not really important
          bmi.biYPelsPerMeter=1000000; // not really important
          // Now for the colour table.
          uint ncols = (uint)1<<bpp; // 2 colours for 1bpp; 256 colours for 8bpp
          bmi.cols=new uint[256]; // The structure always has fixed size 256, even if we end up using fewer colours
          if (bpp==1) {bmi.cols[0]=MAKERGB(0,0,0); bmi.cols[1]=MAKERGB(255,255,255);}
          else {for (int i=0; i<ncols; i++) bmi.cols[i]=MAKERGB(i,i,i);}
          // For 8bpp we've created an palette with just greyscale colours.
          // You can set up any palette you want here. Here are some possibilities:
          // greyscale: for (int i=0; i<256; i++) bmi.cols[i]=MAKERGB(i,i,i);
          // rainbow: bmi.biClrUsed=216; bmi.biClrImportant=216; int[] colv=new int[6]{0,51,102,153,204,255};
          //          for (int i=0; i<216; i++) bmi.cols[i]=MAKERGB(colv[i/36],colv[(i/6)%6],colv[i%6]);
          // optimal: a difficult topic:
          // Now create the indexed bitmap "hbm0"
          IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
          IntPtr hbm0 = CreateDIBSection(IntPtr.Zero,ref bmi,DIB_RGB_COLORS,out bits0,IntPtr.Zero,0);
          // Step (3): use GDI's BitBlt function to copy from original hbitmap into monocrhome bitmap
          // GDI programming is kind of confusing... nb. The GDI equivalent of "Graphics" is called a "DC".
          IntPtr sdc = GetDC(IntPtr.Zero);       // First we obtain the DC for the screen
           // Next, create a DC for the original hbitmap
          IntPtr hdc = CreateCompatibleDC(sdc); SelectObject(hdc,hbm); 
          // and create a DC for the monochrome hbitmap
          IntPtr hdc0 = CreateCompatibleDC(sdc); SelectObject(hdc0,hbm0);
          // Now we can do the BitBlt:
          // Step (4): convert this monochrome hbitmap back into a Bitmap:
          System.Drawing.Bitmap b0 = System.Drawing.Bitmap.FromHbitmap(hbm0);
          // Finally some cleanup.
          return b0;

Open in new window

Question by:HawaiiDragon
    LVL 6

    Accepted Solution

    The following .NET code can be used for compressing a bitmap

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    class Example_SetTIFFCompression
        public static void Main()
            Bitmap myBitmap;
            ImageCodecInfo myImageCodecInfo;
            Encoder myEncoder;
            EncoderParameter myEncoderParameter;
            EncoderParameters myEncoderParameters;
            // Create a Bitmap object based on a BMP file.
            myBitmap = new Bitmap("Shapes.bmp");
            // Get an ImageCodecInfo object that represents the TIFF codec.
            myImageCodecInfo = GetEncoderInfo("image/tiff");
            // Create an Encoder object based on the GUID
            // for the Compression parameter category.
            myEncoder = Encoder.Compression;
            // Create an EncoderParameters object.
            // An EncoderParameters object has an array of EncoderParameter
            // objects. In this case, there is only one
            // EncoderParameter object in the array.
            myEncoderParameters = new EncoderParameters(1);
            // Save the bitmap as a TIFF file with LZW compression.
            myEncoderParameter = new EncoderParameter(
            myEncoderParameters.Param[0] = myEncoderParameter;
            myBitmap.Save("ShapesLZW.tif", myImageCodecInfo, myEncoderParameters);
        private static ImageCodecInfo GetEncoderInfo(String mimeType)
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for(j = 0; j < encoders.Length; ++j)
                if(encoders[j].MimeType == mimeType)
                    return encoders[j];
            return null;

    Open in new window

    Answer is based on MSDN forum discussion -

    Author Comment

    So how would you say I incorperate it into this code?
    static void funWriteTiff(string strFileName, string strActualText)
                //  Change bitmap values to match your file size
                Bitmap imgThumb = new Bitmap(1024, 1024);
                //Image imgThumb = new Bitmap(4000, 1500);
                MemoryStream ms = new MemoryStream();
                Graphics objGraphics = Graphics.FromImage(imgThumb);
                //System.Drawing.Bitmap b = new System.Drawing.Bitmap(imgThumb);
                //  Font objFont = new Font("Arial", 12, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel);
                Font objFont = new Font("Courier New", 12, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel);
                objGraphics = Graphics.FromImage(imgThumb);
                // Set Background color
                //objGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
                //Color.FromArgb (0,0,0) = black; change values to change text color
                objGraphics.DrawString(strActualText, objFont, new SolidBrush(Color.FromArgb(0, 0, 0)), 0, 0);
                //Convert to 1bpp
                imgThumb = BmpConverter.CopyToBpp(imgThumb, 1);
                imgThumb.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
                byte[] be = ms.ToArray();
                using (var fileStream = File.OpenWrite(strFileName))

    Open in new window


    Author Closing Comment

    thank you sir

    Featured Post

    How to improve team productivity

    Quip adds documents, spreadsheets, and tasklists to your Slack experience
    - Elevate ideas to Quip docs
    - Share Quip docs in Slack
    - Get notified of changes to your docs
    - Available on iOS/Android/Desktop/Web
    - Online/Offline

    Join & Write a Comment

    Suggested Solutions

    Article by: Najam
    Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
    This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
    Need more eyes on your posted question? Go ahead and follow the quick steps in this video to learn how to Request Attention to your question. *Log into your Experts Exchange account *Find the question you want to Request Attention for *Go to the e…
    Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

    734 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now