Home › Forums › TWAIN Classic › .Net Bitmap 1bpp problem?
- This topic has 0 replies, 1 voice, and was last updated 13 years, 11 months ago by polo.
- AuthorPosts
Hi guys,
Iam trying to get scanned image from IntPtr in memory to .net Bitmap format.Firstly i used peace of code i found on internet. Basicly it does
MethodInfo mi = typeof(Bitmap).GetMethod(“FromGDIplus”, BindingFlags.Static | BindingFlags.NonPublic);
GdiPlusLib.Gdip.GdipCreateBitmapFromGdiDib(bmPtr, _pixptr, ref gdiBMP);
new Bitmap((Bitmap)mi.Invoke(null, new object[] { gdiBMP }));this works fine, except that it always produces 32bitARGB bitmap which takes a lot of memory.
so i start to dig again and created this class, so i will have controll over when the memory allocated by twain is released.
the code is very simple and works fine, except one case.
➡ when i scan 1bpp image i got Attempted to read or write protected memory.
this is probably caused by the fact that iam trying to work with unalocated memory, but where? And why it only happens when 1bpp picture is scanned?
💡 code follows:
namespace csq_twain
{
public class TwImage : IDisposable
{
private IntPtr lockedImagePtr;
private IntPtr imagePtr;
private BITMAPINFOHEADER imageHeader;public TwImage(IntPtr p)
{
imageHeader = new BITMAPINFOHEADER();
imagePtr = p;
lockedImagePtr = Twain.GlobalLock(imagePtr); //zamknout pamet
Marshal.PtrToStructure(lockedImagePtr, imageHeader); //nahrat hlavicku bmp
}private Bitmap GetImage()
{
IntPtr pixelDataHandle = IntPtr.Zero;
PixelFormat pixelFormat = PixelFormat.Format32bppArgb;
Bitmap b;
int stride = 0;
ColorPalette pal;pixelDataHandle = (IntPtr)((int)lockedImagePtr + imageHeader.biSize + imageHeader.biClrUsed * 4); //zacatek dat = velikost hlavicky + paleta * 4 (RGBP)
switch (imageHeader.biBitCount)
{
case 1: //BW
pixelFormat = PixelFormat.Format1bppIndexed;
break;
case 8: //Gray
pixelFormat = PixelFormat.Format8bppIndexed;
break;
case 16:
pixelFormat = PixelFormat.Format16bppRgb565;
break;
case 24:
pixelFormat = PixelFormat.Format24bppRgb;
break;
case 32:
pixelFormat = PixelFormat.Format32bppArgb;
break;
}// stride urcuje kolik pixelu ma kazdy radek. Musi byt delitelny 4, takze si tu musime pomoct.
if (imageHeader.biBitCount == 1)
stride = imageHeader.biWidth * imageHeader.biBitCount;
else
stride = imageHeader.biWidth * (imageHeader.biBitCount >> 3);if (stride % 4 != 0)
{
int tmp = stride / 4;
stride = ++tmp * 4;
}b = new Bitmap(imageHeader.biWidth, imageHeader.biHeight, stride, pixelFormat, pixelDataHandle);
// pokud je > 0 znamena to ze se nejedna o obrazek s indexovanou paletou.
if (imageHeader.biClrUsed > 0)
{
// vytvoreni genericke palety pro grayscale
pal = b.Palette;//for (int i = 0; i < bmpHeader.biClrUsed; i++)
for (int i = 0; i < pal.Entries.GetLength(0); i++)
{
pal.Entries = Color.FromArgb(i, i, i);
}
b.Palette = pal;
}Image tb = (Image)b;
tb.RotateFlip(RotateFlipType.RotateNoneFlipY);
return tb as Bitmap;
}public Bitmap Image
{
get { return this.GetImage(); }
}#region IDisposable Members
void IDisposable.Dispose()
{
Twain.GlobalUnlock(lockedImagePtr);
Twain.GlobalFree(imagePtr);
}#endregion
}
}- AuthorPosts