2011-05-25 2 views
3

Я могу подключать и получать изображения с моего устройства с помощью twaindotnet. Но я хочу обрабатывать изображения как класс Image. Когда я пытаюсь что-то вроде этого:Получить изображение как изображение класса с twain в C#

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

я получаю сообщение об ошибке, как «Ошибка: Generic ошибка в GDI +» на линии,

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

Итак, где я не прав? Как я могу получить изображение как изображение?

ответ

1

Предполагая, что tw.TransferPictures() возвращает массив растровых ручек, а затем изменить Image r = ... на:

 Image r = Image.FromHbitmap(img); 

Второй аргумент FromHbitmap является дескриптор палитры GDI, который я сомневаюсь, у вас есть.

+0

Но есть метод перегрузки, что принимает только один параметр. Что я могу использовать в качестве палитры GDI? извините, я так любитель на этом титуле. – ocanal

+0

Попробуйте использовать метод с одним аргументом! У вас нет палитры GDI, поэтому не беспокойтесь об этом. –

+0

Я пробовал эту, ту же ошибку. – ocanal

4

Я тоже узнал, что звонка Image.FromHbitmap не достаточно.

Я нашел в библиотеке TwainDotNet, которую вы упомянули, и там я нашел класс BitmapRenderer.

Вытащив только соответствующий бит это достаточно легко использовать, чтобы создать простой статический метод, который можно передать в IntPtr вы получаете от TWAIN (в вашем случае вашего 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); 
    } 
} 
+0

В настоящее время я использую это решение, но у меня есть ошибка с genrated Bitmap. Некоторые из них перевернуты. Есть идеи ? – Gnial0id

Смежные вопросы