• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 229
  • Last Modified:

lossless compresson help please

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: http://en.wikipedia.org/wiki/Color_quantization
          // 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

  • 2
1 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 - http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/5e755b7b-c0f3-46e3-b4cd-5881bf654d7f
HawaiiDragonAuthor Commented:
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

HawaiiDragonAuthor Commented:
thank you sir

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now