3

twaindotnetを使用して、デバイスに接続して画像を取得できます。Imageしかし、私は画像をクラスとして扱いたいです。私がこのようなことをしようとすると:

    ...
  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;                          
       }                    
    ...

行に「Error:Generic Error Occured in GDI+」というエラーが表示されます。

Image r = Image.FromHbitmap(img, this.Handle);

どこが間違っているのですか?画像を画像として取得するにはどうすればよいですか?

4

2 に答える 2

5

私も、電話をかけるImage.FromHbitmapだけでは十分ではないことがわかりました。

あなたが言及したTwainDotNetライブラリを調べたところ、BitmapRendererクラスが見つかりました。

関連するビットだけを引き出すと、それを使用して単純な静的メソッドを作成し、IntPtrTWAIN から取得したもの (この場合は img 変数) に渡してBitmapに変換するのは簡単です。したがって、次のように呼び出します。

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, 
                    0, 0, rectangle.Width, rectangle.Height, 0, 0, 0, 
                    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);
    }
}
于 2012-10-24T11:46:56.647 に答える
1

tw.TransferPictures()がビットマップ ハンドルの配列を返すと仮定すると、次のように変更Image r = ...します。

      Image r = Image.FromHbitmap(img);

FromHbitmap の 2 番目の引数は、GDI パレットへのハンドルです。

于 2011-05-25T21:28:41.063 に答える