Original

You are currently reviewing an older revision of this page.
Go to current version
 public static void ChangeImageToBlackAndWhite(string fileName)
        {
            Bitmap bitmap = new Bitmap(fileName);

            string FileExtension = fileName.Substring(fileName.LastIndexOf("."));
            string tempfileName = Guid.NewGuid().ToString() + FileExtension;

            try
            {
                Image img = Image.FromFile(fileName);

                short resolution = (short)img.HorizontalResolution;
                PixelFormat convertToPixelFormat = img.PixelFormat;

                img.Dispose();

                if (IsColor(bitmap)) //colour image can be transform in gray or black/white
                {
                    if (convertToPixelFormat == PixelFormat.Format1bppIndexed)
                        ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
                    else if (convertToPixelFormat == PixelFormat.Format8bppIndexed)
                        ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
                    else
                        ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
                }
                else //gray image can be transform in black/white
                {
                    if (convertToPixelFormat == PixelFormat.Format1bppIndexed)
                        ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
                    else
                        ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
                }
            }
            catch (Exception ex)
            {
                bitmap.Dispose();
                throw ex;
            }
            finally
            {
                bitmap.Dispose();

            }
        }

        private static System.Drawing.Imaging.ImageCodecInfo GetCodecType()
        {

            System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();

            foreach (System.Drawing.Imaging.ImageCodecInfo cod in codecs)
            {

                if (cod.MimeType == "image/tiff")
                    return cod;
            }
            return null;
        }

        private static void ConvertToBpp(string fileName, int bpp, Bitmap newBitmap, string tempfileName, int resolution)
        {
            Bitmap convertedBitmap = null;

            if (bpp == 1 || bpp == 8)
            {
                convertedBitmap = ConvertToBpp(newBitmap, bpp, resolution);
                newBitmap.Dispose();
            }
            else
            {
                newBitmap.SetResolution(resolution, resolution);
                convertedBitmap = newBitmap;
            }

            long NewColorDepth = 1;

            System.Drawing.Imaging.EncoderParameters encoder = new System.Drawing.Imaging.EncoderParameters(2);
            encoder.Param[0] = new System.Drawing.Imaging.EncoderParameter(new System.Drawing.Imaging.Encoder(System.Drawing.Imaging.Encoder.ColorDepth.Guid), NewColorDepth);
            encoder.Param[1] = new System.Drawing.Imaging.EncoderParameter(new System.Drawing.Imaging.Encoder(System.Drawing.Imaging.Encoder.Compression.Guid),
                (long)System.Drawing.Imaging.EncoderValue.CompressionCCITT4);

            convertedBitmap.Save(tempfileName, GetCodecType(), encoder);

            if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                File.SetAttributes(fileName, FileAttributes.Normal); convertedBitmap.Dispose();

            File.Delete(fileName);
            File.Move(tempfileName, fileName);
        }

        public static Bitmap ConvertToBpp(Bitmap b, int bpp, int resolution)
        {
            if (bpp != 1 && bpp != 8) throw new ArgumentException("1 or 8", "bpp");

            int w = b.Width, h = b.Height;
            IntPtr hbm = b.GetHbitmap();

            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

            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); }

            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);

            IntPtr sdc = GetDC(IntPtr.Zero);       // First we obtain the DC for the screen

            IntPtr hdc = CreateCompatibleDC(sdc); SelectObject(hdc, hbm);

            IntPtr hdc0 = CreateCompatibleDC(sdc); SelectObject(hdc0, hbm0);

            BitBlt(hdc0, 0, 0, w, h, hdc, 0, 0, SRCCOPY);

            Bitmap b0 = Bitmap.FromHbitmap(hbm0);

            b0.SetResolution(resolution, resolution);

            DeleteDC(hdc);
            DeleteDC(hdc0);
            ReleaseDC(IntPtr.Zero, sdc);
            DeleteObject(hbm);
            DeleteObject(hbm0);

            return b0;
        }

        [DllImport("gdi32.dll")]
        private static extern bool DeleteObject(IntPtr hObject);

        [DllImport("user32.dll")]
        private static extern int InvalidateRect(IntPtr hwnd, IntPtr rect, int bErase);

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateCompatibleDC(IntPtr hdc);

        [DllImport("user32.dll")]
        private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

        [DllImport("gdi32.dll")]
        private static extern int DeleteDC(IntPtr hdc);

        [DllImport("gdi32.dll")]
        private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

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

        [DllImport("gdi32.dll")]
        private static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
        private static uint BI_RGB = 0;
        private static uint DIB_RGB_COLORS = 0;

        [StructLayout(LayoutKind.Sequential)]
        private 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;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public uint[] cols;
        }

        private static uint MAKERGB(int r, int g, int b)
        {
            return ((uint)(b & 255)) | ((uint)((r & 255) << 8)) | ((uint)((g & 255) << 16));
        }
        #endregion

        #region Properties
        BitmapData bitmapData = null;
        Byte* pBase = null;

        public bool IsWhitePixel(int X, int Y)
        {
            try
            {
                return PixelAt(X, Y);
            }
            catch (AccessViolationException ave)
            {
                throw (ave);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private bool PixelAt(int x, int y)
        {
            pBase = (Byte*)bitmapData.Scan0.ToPointer();

            int index = y * bitmapData.Stride + (x >> 3);
            byte mask = (byte)(0x80 >> (x & 0x7));

            int n = pBase[index] & mask;

            //branco ou preto
            return (n > 0);
        }