private void Realloc(int width, int height) { if (_gcHandle.IsAllocated) { _gcHandle.Free(); } Width = width; Height = height; _pArray = new int[Width * Height]; _gcHandle = GCHandle.Alloc(_pArray, GCHandleType.Pinned); _bi = new Bitmapinfo { biHeader = { bihBitCount = 32, bihPlanes = 1, bihSize = 40, bihWidth = Width, bihHeight = -Height, bihSizeImage = (Width * Height) << 2 } }; }
static extern IntPtr CreateDIBSection( IntPtr hdc, ref Bitmapinfo bmi, uint usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref Bitmapinfo lParam);
private static extern int SetDIBitsToDevice(HandleRef hDc, int xDest, int yDest, int dwWidth, int dwHeight, int xSrc, int ySrc, int uStartScan, int cScanLines, ref int lpvBits, ref Bitmapinfo lpbmi, uint fuColorUse);
/// <summary> /// Converts a bitmap into a 1 bpp bitmap of the same dimensions, fast. /// Original source from: http://www.wischik.com/lu/programmer/1bpp.html /// </summary> /// <param name="source">The bitmap, which will be converted.</param> /// <returns>A 1 or 8 bpp copy of the source bitmap.</returns> public static Bitmap To1Bpp(Bitmap source) { // 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 = source.Width, h = source.Height; IntPtr hbm = source.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 = 1; 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. const uint ncols = (uint)1 << 1; 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 bmi.cols[0] = MAKERGB(0, 0, 0); bmi.cols[1] = MAKERGB(255, 255, 255); // 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: Bitmap b0 = Image.FromHbitmap(hbm0); // // Finally some cleanup. DeleteDC(hdc); DeleteDC(hdc0); ReleaseDC(IntPtr.Zero, sdc); DeleteObject(hbm); DeleteObject(hbm0); // return b0; }
/// <summary> /// Converts a bitmap into a 1 bpp bitmap of the same dimensions, fast. /// Original source from: http://www.wischik.com/lu/programmer/1bpp.html /// </summary> /// <param name="source">The bitmap, which will be converted.</param> /// <returns>A 1 or 8 bpp copy of the source bitmap.</returns> public static Bitmap To1Bpp(Bitmap source) { // 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 = source.Width, h = source.Height; IntPtr hbm = source.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 = 1; 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. const uint ncols = (uint)1 << 1; 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 bmi.cols[0] = MAKERGB(0, 0, 0); bmi.cols[1] = MAKERGB(255, 255, 255); // 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: Bitmap b0 = Image.FromHbitmap(hbm0); // // Finally some cleanup. DeleteDC(hdc); DeleteDC(hdc0); ReleaseDC(IntPtr.Zero, sdc); DeleteObject(hbm); DeleteObject(hbm0); // return(b0); }