2013-10-27 6 views
2

Я пытаюсь использовать ISampleGrabberCB::BufferCB для преобразования текущего кадра в растровом используя следующий код: Однако это не кажетсяКак преобразовать буфер ISampleGrabber :: BufferCB к растровым

int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr buffer, int bufferLength) 
    { 
     try 
     { 

      Form1 form1 = new Form1("", "", ""); 
      if (pictureReady == null) 
      { 
       Debug.Assert(bufferLength == Math.Abs(pitch) * videoHeight, "Wrong Buffer Length"); 
      } 

      Debug.Assert(imageBuffer != IntPtr.Zero, "Remove Buffer"); 

      Bitmap bitmapOfCurrentFrame = new Bitmap(width, height, capturePitch, PixelFormat.Format24bppRgb, buffer); 
      MessageBox.Show("Works"); 
      form1.changepicturebox3(bitmapOfCurrentFrame); 

      pictureReady.Set(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 

     return 0; 
    } 

это работает.

Кроме того, кажется, вызвать эту функцию, когда я нажимаю кнопку, которая запускает следующий код:

public IntPtr getFrame() 
    { 
     int hr; 
     try 
     { 
      pictureReady.Reset(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 
     imageBuffer = Marshal.AllocCoTaskMem(Math.Abs(pitch) * videoHeight); 

     try 
     { 
      gotFrame = true; 

      if (videoControl != null) 
      { 
       hr = videoControl.SetMode(stillPin, VideoControlFlags.Trigger); 
       DsError.ThrowExceptionForHR(hr); 
      } 

      if (!pictureReady.WaitOne(9000, false)) 
      { 
       throw new Exception("Timeout waiting to get picture"); 
      } 

     } 
     catch 
     { 
      Marshal.FreeCoTaskMem(imageBuffer); 
      imageBuffer = IntPtr.Zero; 
     } 

     return imageBuffer; 

    } 

После того, как этот код выбежал я получаю окно сообщения, которое показывает «работает», таким образом, что означает мое BufferCB сусло но не обновляет картинку с текущим изображением.

Является ли BufferCB не вызывается после каждого нового кадра? Если да, почему я не получаю сообщение «Работы»?

Наконец, можно преобразовать каждый новый кадр в растровое изображение (это используется для последующей обработки) с использованием BufferCB, и если да, то как?

Edited код:

int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr buffer, int bufferLength) 
    {   

      Debug.Assert(bufferLength == Math.Abs(pitch) * videoHeight, "Wrong Buffer Length"); 
      Debug.Assert(imageBuffer != IntPtr.Zero, "Remove Buffer"); 
      CopyMemory(imageBuffer, buffer, bufferLength); 
      Decode(buffer); 


     return 0; 
    } 

public Image Decode(IntPtr imageData) 
    { 
     var bitmap = new Bitmap(width, height, pitch, PixelFormat.Format24bppRgb, imageBuffer); 
     bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); 
     Form1 form1 = new Form1("", "", ""); 
     form1.changepicturebox3(bitmap); 
     bitmap.Save("C:\\Users\\...\\Desktop\\A2 Project\\barcode.jpg"); 
     return bitmap; 
    } 

Код кнопки:

public void getFrameFromWebcam() 
{ 
    if (iPtr != IntPtr.Zero) 
    { 
     Marshal.FreeCoTaskMem(iPtr); 
     iPtr = IntPtr.Zero; 
    } 

     //Get Image 
     iPtr = sampleGrabberCallBack.getFrame(); 
     Bitmap bitmapOfFrame = new Bitmap(sampleGrabberCallBack.width, sampleGrabberCallBack.height, sampleGrabberCallBack.capturePitch, PixelFormat.Format24bppRgb, iPtr); 
     bitmapOfFrame.RotateFlip(RotateFlipType.RotateNoneFlipY); 
     barcodeReader(bitmapOfFrame); 
} 

public IntPtr getFrame() 
    { 
     int hr; 

     try 
     { 
      pictureReady.Reset(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show(ex.ToString()); 
     } 
     imageBuffer = Marshal.AllocCoTaskMem(Math.Abs(pitch) * videoHeight); 

     try 
     { 
      gotFrame = true; 

      if (videoControl != null) 
      { 
       hr = videoControl.SetMode(stillPin, VideoControlFlags.Trigger); 
       DsError.ThrowExceptionForHR(hr); 
      } 

      if (!pictureReady.WaitOne(9000, false)) 
      { 
       throw new Exception("Timeout waiting to get picture"); 
      } 

     } 
     catch 
     { 
      Marshal.FreeCoTaskMem(imageBuffer); 
      imageBuffer = IntPtr.Zero; 
     } 

     return imageBuffer; 

    } 

мне еще нужно нажать на кнопку, чтобы запустить BufferCB

Спасибо за чтение.

+0

Первое, что вы пропустили 'CopyMemory «Шаг, который я предложил. На самом деле вы вообще не используете переданный 'buffer'. Вы используете' imageBuffer'. Во-вторых, как я уже упоминал, вы не можете получить доступ к нити ui из пробоотборной нити. – Matthias

+0

Итак, в 'Decode' я должен использовать буферную переменную из' BufferCB'? И да, извините, понял, что после того, как я отправил код, теперь я получаю изображение в сохраненном файле, однако pictureBox3 не обновляется? Также, как я должен повторно запускать метод BufferCB тогда (я знаю, что это происходит после каждого кадра, но это не приводит к тому, что я получаю, когда нажимаю кнопку). – legohead

+0

Я уже разместил ссылку на операции с поперечными потоками. Когда люди пытаются помочь вам, вы должны прочитать все, что они скажут вам. Не обижайтесь, но вы не можете ожидать, что кто-то решает все ваши проблемы только в одном вопросе. Пожалуйста, постарайтесь, чтобы ваши предстоящие вопросы были короче. – Matthias

ответ

1

BufferCB предназначен для каждого нового кадра, который был захвачен камерой. Вы не видите окно сообщения, потому что метод вызывается из другого потока (а не из потока ui). См. this question.

В моем коде я использовал AutoResetEvent для захвата кадра:

#region samplegrabber 
/// <summary> 
/// buffer callback, COULD BE FROM FOREIGN THREAD. 
/// </summary> 
int ISampleGrabberCB.BufferCB (double sampleTime, 
           IntPtr pBuffer, 
           int bufferLen) 
{ 
    if (_sampleRequest) 
    { 
    _sampleRequest = false; 

    if (bufferLen > _bufferSize) 
     throw new Exception ("buffer is wrong size"); 

    Win32.CopyMemory (_buffer, pBuffer, _bufferSize); 

    // Picture is ready. 
    _resetEvent.Set(); 
    } 
    else 
    _dropped++; 
    return 0; 
} 

Изображение может быть расшифровано из IntPtr с другой функцией:

public Image Decode (IntPtr data) 
{ 
    var bitmap = new Bitmap (_width, _height, _stride, PixelFormat.Format24bppRgb, data); 

    bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY); 

    return bitmap; 
} 
+0

В моем коде я использую 'ManualResetEvent', который является частью pictureReady.set() первого раздела кода. Как вы думаете, потребуется ли изменить это на 'AutoResetEvent'? Также, где вы используете функцию декодирования изображения, откуда будет получен этот массив байтов данных? – legohead

+0

'_buffer' - это массив байтов, который должен быть передан методу' Decode'. Не важно, используете ли вы события ручного или автоматического сброса. Важно то, что ваш метод GetFrame сигнализирует, что вы хотите создать фрейм ('_sampleRequest'), а затем дождаться появления данных (' _resetEvent'). – Matthias

+0

О да, я вижу это сейчас. Поэтому, когда я использую 'gotFrame' вместо ваших' _sampleRequest' и 'pictureReady' вместо вашего' _resetEvent', я уже говорю буферу, что мне нужен фрейм, однако я в настоящее время не использую ' if (gotFrame) 'в моем' BufferCB'. Именно поэтому я получаю сообщение о работе, когда я нажимаю кнопку, чтобы запустить код? – legohead