• 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
    {
          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          public static extern bool DeleteObject(IntPtr hObject);

          [System.Runtime.InteropServices.DllImport("user32.dll")]
          public static extern IntPtr GetDC(IntPtr hwnd);

          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

          [System.Runtime.InteropServices.DllImport("user32.dll")]
          public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          public static extern int DeleteDC(IntPtr hdc);

          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          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;

          [System.Runtime.InteropServices.DllImport("gdi32.dll")]
          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;
          [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] 


          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.biWidth=w;
          bmi.biHeight=h;
          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.biClrUsed=ncols;
          bmi.biClrImportant=ncols;
          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:
          BitBlt(hdc0,0,0,w,h,hdc,0,0,SRCCOPY);
          // Step (4): convert this monochrome hbitmap back into a Bitmap:
          System.Drawing.Bitmap b0 = System.Drawing.Bitmap.FromHbitmap(hbm0);
          //
          // Finally some cleanup.
          DeleteDC(hdc);
          DeleteDC(hdc0);
          ReleaseDC(IntPtr.Zero,sdc);
          DeleteObject(hbm);
          DeleteObject(hbm0);
          //
          return b0;
        }
	}
}

Open in new window

0
HawaiiDragon
Asked:
HawaiiDragon
  • 2
1 Solution
 
regevhaCommented:
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(
            myEncoder,
            (long)EncoderValue.CompressionLZW);
        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
0
 
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.Clear(Color.White);

            //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))
            {
                ms.WriteTo(fileStream);
            }
        }

Open in new window

0
 
HawaiiDragonAuthor Commented:
thank you sir
0

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