Hi everyone,
I've been struggeling with this problem for some time now.
I'm starting from 4 image objects of 24bpp with a resolution of 300dpi. Then I have to save these object into 1 Tiff-file with the following specifications:
- Multi-page Tiff
-
Black&white
-
Group4 compression
-
1bpp
-
Must maintain the dpi-settings of the original Image object (300dpi)
I found a sub, that converts an Image object to a black&white 1bpp image object, but there are two problems:
- It's too slow (1.5sec/image on a fast computer)
- It changes the dpi-settings to 96dpi
At the moment, I just reset the resolution to 300dpi and save the file to disk. This works fine, but the image-quality isn't good enough to do ICR (Intelligent Character Recognition).
So I really have to get a Black&White image of 300dpi.
Here is the sub I am using at the moment, but I have no idea how to modify the code so I can maintain the original 300dpi in stead of the 96dpi.
I hope someone can help me with this, or show me a better way to do this!
The code:
#region "Converting 32bpp to 1bpp image"
[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;
public byte blue0, green0, red0, reserved0;
public byte blue1, green1, red1, reserved1;
}
public static System.Drawing.Bitmap CopyTo1bb(System.Drawing.Bitmap b)
{
// 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 = 1; // ie. 1bpp
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); // number of bytes. each scanline is padded to a multiple of 4
//bmi.biXPelsPerMeter = 11811; // not really important
//bmi.biYPelsPerMeter = 11811; // not really important
bmi.biClrUsed = 2; // our mono bitmap uses both colours in the RGBQUAD table
bmi.biClrImportant = 2; // and both are important
// Now for the RGBQUAD table. Its first entry is "black". Its second entry is "white".
bmi.red0 = 0; bmi.green0 = 0; bmi.blue0 = 0; bmi.reserved0 = 0;
bmi.red1 = 255; bmi.green1 = 255; bmi.blue1 = 255; bmi.reserved1 = 255;
// Now create the monochrome 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 monochrome bitmap
// GDI programming is kind of confusing...
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 GDI cleanup tasks
DeleteDC(hdc);
DeleteDC(hdc0);
ReleaseDC(IntPtr.Zero, sdc);
DeleteObject(hbm);
DeleteObject(hbm0);
//I Added the following rule to do ICR on the images (the program only accepts 300dpi images)
b0.SetResolution(300, 300);
return b0;
}
#endregion

Save Image object as Group4 B&W Tiff with 300dpi
rcook349
You'll need a smarter algorithm than the one BitBlt uses to convert colors to monochrome if you want better results. That's really going to slow down the code. Don't try to do this yourself, purchase a commercial image processing library like Lead Tools.
globemast
LeadTools is using the GDI+ methods behind the screens, so this won't improve the image-conversion.
I also tried Victor Imaging, which was even slower than the procedure I'm using at the moment. I guess I'll stick with the procedure above. I just can't figure out how I can get a 300 dpi image.
The "pixels per meter" setting doesn't change anything. Does anyone have an idea
Thanks again...
raj.ramesh
First of all, thank you for the reply
Secondly: yes, I'm using a Digital Pen (Maxell's) to create an image of A3 page.
This image has a resolution of 3508x4961 with 300dpi.
So I guess you could say "very large images"
I tried to modify the "pixels per meter" setting, but still I get an image of 96dpi.
I'm considering to buy a library, but is Lead Tools a good choice Are there some alternatives