Передаем в параметр (Bitmap, глубину цвета, серое или цветное)
| Код | #region gdi32 [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)); } #endregion
public static Bitmap CopyToBpp(Bitmap b, int bpp, bool grayscale) { // (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)
if (bpp != 1 && bpp != 8) throw new System.ArgumentException("1 or 8", "bpp");
int w = b.Width, h = b.Height; IntPtr hbm = b.GetHbitmap(); // this is step (1) // Step (2): create the monochrome bitmap. BITMAPINFO bmi = new BITMAPINFO(); bmi.biSize = 40; // the size of the BITMAPHEADERINFO struct bmi.biWidth = w; bmi.biHeight = h; bmi.biPlanes = 1; bmi.biBitCount = (short)bpp; // ie. 1bpp or 8bpp bmi.biCompression = BI_RGB; 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 { if (grayscale) { for (int i = 0; i < ncols; i++) bmi.cols[i] = MAKERGB(i, i, i); } else { 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]); } } IntPtr bits0; 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 IntPtr sdc = GetDC(IntPtr.Zero); IntPtr hdc = CreateCompatibleDC(sdc); SelectObject(hdc, hbm); IntPtr hdc0 = CreateCompatibleDC(sdc); SelectObject(hdc0, hbm0); 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); // DeleteDC(hdc); DeleteDC(hdc0); ReleaseDC(IntPtr.Zero, sdc); DeleteObject(hbm); DeleteObject(hbm0); // return b0; }
|
|