在c#中使用twain获取图像作为图像类

问题描述

| 我可以使用twaindotnet连接并从设备中获取图像。但我想将图像作为“ 0”类处理。当我尝试这样的事情:
    ...
  ArrayList pics = tw.TransferPictures();
  EndingScan();
  tw.CloseSrc();

  if(pics.Count > 0)  {                     
  IntPtr img = (IntPtr) pics[ 0 ];
  PicForm newpic = new PicForm( img );
  Image r = Image.FromHbitmap(img,this.Handle);
  pictureBox.Image = r;                          
       }                    
    ...
我在行中收到\“错误:GDI +中发生一般错误”的错误
Image r = Image.FromHbitmap(img,this.Handle);
那我在哪里错了?如何获得图像图像?     

解决方法

我也发现只叫
Image.FromHbitmap
是不够的。 我在您提到的TwainDotNet库中进行了查看,然后找到了BitmapRenderer类。 仅提取相关位,就很容易使用它来创建一个简单的静态方法,您可以传入从TWAIN(在您的情况下为img变量)中获取的ѭ4并将其转换为位图。因此,您可以这样称呼它:
Image r = TwainBitmapConvertor.ToBitmap(img);
这是代码(它仅适用于x86,需要整理,但可以完成工作):
public static class TwainBitmapConvertor
{
    [StructLayout(LayoutKind.Sequential,Pack = 2)]
    private class BitmapInfoHeader
    {
        public int Size;
        public int Width;
        public int Height;
        public short Planes;
        public short BitCount;
        public int Compression;
        public int SizeImage;
        public int XPelsPerMeter;
        public int YPelsPerMeter;
        public int ClrUsed;
        public int ClrImportant;
    }

    [DllImport(\"gdi32.dll\",ExactSpelling = true)]
    private static extern int SetDIBitsToDevice(IntPtr hdc,int xdst,int ydst,int width,int height,int xsrc,int ysrc,int start,int lines,IntPtr bitsptr,IntPtr bmiptr,int color);

    [DllImport(\"kernel32.dll\",ExactSpelling = true)]
    private static extern IntPtr GlobalLock(IntPtr handle);

    [DllImport(\"kernel32.dll\",ExactSpelling = true)]
    private static extern bool GlobalUnlock(IntPtr handle);

    [DllImport(\"kernel32.dll\",ExactSpelling = true)]
    private static extern IntPtr GlobalFree(IntPtr handle);

    public static Bitmap ToBitmap(IntPtr dibHandle)
    {
        var bitmapPointer = GlobalLock(dibHandle);

        var bitmapInfo = new BitmapInfoHeader();
        Marshal.PtrToStructure(bitmapPointer,bitmapInfo);

        var rectangle = new Rectangle();
        rectangle.X = rectangle.Y = 0;
        rectangle.Width = bitmapInfo.Width;
        rectangle.Height = bitmapInfo.Height;

        if (bitmapInfo.SizeImage == 0)
        {
            bitmapInfo.SizeImage = 
                ((((bitmapInfo.Width * bitmapInfo.BitCount) + 31) & ~31) >> 3) 
                * bitmapInfo.Height;
        }

        // The following code only works on x86
        Debug.Assert(Marshal.SizeOf(typeof(IntPtr)) == 4);

        int pixelInfoPointer = bitmapInfo.ClrUsed;
        if ((pixelInfoPointer == 0) && (bitmapInfo.BitCount <= 8))
        {
            pixelInfoPointer = 1 << bitmapInfo.BitCount;
        }

        pixelInfoPointer = (pixelInfoPointer * 4) + bitmapInfo.Size 
            + bitmapPointer.ToInt32();

        IntPtr pixelInfoIntPointer = new IntPtr(pixelInfoPointer);

        Bitmap bitmap = new Bitmap(rectangle.Width,rectangle.Height);

        using (Graphics graphics = Graphics.FromImage(bitmap))
        {
            IntPtr hdc = graphics.GetHdc();

            try
            {
                SetDIBitsToDevice(hdc,rectangle.Width,rectangle.Height,pixelInfoIntPointer,bitmapPointer,0);
            }
            finally
            {
                graphics.ReleaseHdc(hdc);
            }
        }

        bitmap.SetResolution(PpmToDpi(bitmapInfo.XPelsPerMeter),PpmToDpi(bitmapInfo.YPelsPerMeter));

        GlobalUnlock(dibHandle);
        GlobalFree(dibHandle);

        return bitmap;
    }

    private static float PpmToDpi(double pixelsPerMeter)
    {
        double pixelsPerMillimeter = (double)pixelsPerMeter / 1000.0;
        double dotsPerInch = pixelsPerMillimeter * 25.4;
        return (float)Math.Round(dotsPerInch,2);
    }
}
    ,假设
tw.TransferPictures()
返回一个位图句柄数组,然后将
Image r = ...
更改为:
      Image r = Image.FromHbitmap(img);
FromHbitmap的第二个参数是GDI调色板的句柄,我怀疑您有。