locked
Can't get 1-bit dept image via c# RRS feed

  • Question

  • thank you in advance for your help!!

    We are trying to generate 1-bit images via c#.  The properties on the image say it is 1-bit, but when we try to print it on a laser that only print 1-bit images, we get an error indicating it's an 8-bit image.  Also, we be bring it up in Adobe or Photoshop, it says it is an 8-bit image.  thank you!!!!

            public CurvedTextImageGenerator(string serialNumber)
            {
                int serial = Convert.ToInt32(serialNumber);
                int counter = 1;
    
                for (int i = serial; i <= serial + 400; i++)
                {
                    Bitmap b = CreateBitmapImage(i.ToString());
    
                    Bitmap b2 = Util.CopyToBpp(b, 1);
     
                    b2.Save(@"C:\Greenlaser\" + counter.ToString() + ".png");
    
                    counter++;
                }
            }
            private Bitmap CreateBitmapImage(string sImageText)
            {
                // create Image Object using rear image byte[]
    
                Bitmap objBmpImage = new Bitmap(264, 100);
    
                int intWidth = 264;
                int intHeight = 100;
    
                string firstLine = sImageText.Substring(0, 2) + "-" + sImageText.Substring(2, 2);
                string secondLine = sImageText.Substring(4);
    
                // Create the Font object for the image text drawing.
                System.Drawing.Font objFont = new System.Drawing.Font("Arial", 40, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Pixel);
    
                // Create a graphics object to measure the text's width and height.
                Graphics objGraphics = Graphics.FromImage(objBmpImage);
    
    
                // Create the bmpImage again with the correct size for the text and font.
                objBmpImage = new Bitmap(objBmpImage, new Size(intWidth, intHeight));
    
                // Add the colors to the new bitmap.
                objGraphics = Graphics.FromImage(objBmpImage);
    
                // Set Background color
    
                objGraphics.Clear(System.Drawing.Color.White);
                objGraphics.SmoothingMode = SmoothingMode.HighQuality;
                
                objGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; //  <-- This is the correct value to use. ClearTypeGridFit is better yet!
                objGraphics.DrawString(firstLine, objFont, new SolidBrush(System.Drawing.Color.Black), 0, 0, StringFormat.GenericDefault);
                objGraphics.DrawString(secondLine, objFont, new SolidBrush(System.Drawing.Color.Black), 0, intHeight/2, StringFormat.GenericDefault);
    
                objGraphics.Flush();
    
                return (objBmpImage);
            }
    
        internal static class Util
        {
    
            /// <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;
            }
    
            [System.Runtime.InteropServices.DllImport("gdi32.dll")]
            public static extern bool DeleteObject(IntPtr hObject);
    
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            public static extern int InvalidateRect(IntPtr hwnd, IntPtr rect, int bErase);
    
            [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 bitmap of the same dimensions, slowly, using code from Bob Powell's GDI+ faq http://www.bobpowell.net/onebit.htm
            /// </summary>
            /// <param name="b">original bitmap</param>
            /// <returns>a 1bpp copy of the bitmap</returns>
            static System.Drawing.Bitmap FaqCopyTo1bpp(System.Drawing.Bitmap b)
            {
                int w = b.Width, h = b.Height; System.Drawing.Rectangle r = new System.Drawing.Rectangle(0, 0, w, h);
                if (b.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
                {
                    System.Drawing.Bitmap temp = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
                    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(temp);
                    g.DrawImage(b, r, 0, 0, w, h, System.Drawing.GraphicsUnit.Pixel);
                    g.Dispose(); b = temp;
                }
                System.Drawing.Imaging.BitmapData bdat = b.LockBits(r, System.Drawing.Imaging.ImageLockMode.ReadOnly, b.PixelFormat);
                System.Drawing.Bitmap b0 = new System.Drawing.Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
                System.Drawing.Imaging.BitmapData b0dat = b0.LockBits(r, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        int index = y * bdat.Stride + (x * 4);
                        if (System.Drawing.Color.FromArgb(System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index + 2), System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index + 1), System.Runtime.InteropServices.Marshal.ReadByte(bdat.Scan0, index)).GetBrightness() > 0.5f)
                        {
                            int index0 = y * b0dat.Stride + (x >> 3);
                            byte p = System.Runtime.InteropServices.Marshal.ReadByte(b0dat.Scan0, index0);
                            byte mask = (byte)(0x80 >> (x & 0x7));
                            System.Runtime.InteropServices.Marshal.WriteByte(b0dat.Scan0, index0, (byte)(p | mask));
                        }
                    }
                }
                b0.UnlockBits(b0dat);
                b.UnlockBits(bdat);
                return b0;
            }
    
        }
    




    closl

    Monday, January 27, 2014 6:33 PM

Answers

  • Save it in an ImageFormat that supports 1 bit images; BMP and TIFF are 2 choices.
    • Marked as answer by closl Friday, March 17, 2017 5:34 PM
    Tuesday, January 28, 2014 3:36 AM

All replies

  • Save it in an ImageFormat that supports 1 bit images; BMP and TIFF are 2 choices.
    • Marked as answer by closl Friday, March 17, 2017 5:34 PM
    Tuesday, January 28, 2014 3:36 AM
  • we are saving it in an image format that supports 1 bit images...png

    closl

    Tuesday, January 28, 2014 12:47 PM