Difference between Cvb.SharedImg and Cvb.Image.IMG

Ok, here is the promised example:

const int NumDriverBuffers = 100;

static void Main()
{	
  var driverPath = Path.Combine(Environment.GetEnvironmentVariable("CVB"), "Drivers", "GenICam.vin");
  using (var camera = DriverExtensions.TryOpenWithBufferCount(driverPath, NumDriverBuffers))
  {
    if (camera == null)
    {
      Console.WriteLine("Error loading driver: " + driverPath);
      return;
    }
		
    camera.SetLockModeToOn();

    camera.StartAcquisition();
    try
    {
      for (int i = 0; i < 2 * NumDriverBuffers; i++)
      {
        var image = camera.WaitForNextImage();
				
        // for a real application the tasks should be stored for proper app-exit handling
        Task.Run(() =>
        {
          Parallel.For(0, image.Height, line =>
          {
            // do something
          });
          image.Unlock(); // and thus dispose...
        });
      }
    }
    finally
    {
      camera.AbortAcquisition();
    }
  }
}

And for this you need these helper classes (and the references to iCVCImg.dll and iCVCDriver.dll):

class RingBufferImage : IDisposable
{
  private Cvb.Image.IMG _driverImage;
  private Cvb.SharedImg _bufferImage;
  private int _bufferIndex;

  public static RingBufferImage FromCurrent(Cvb.SharedImg driver)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));

    return new RingBufferImage(driver, driver.GetCurrentBufferIndex());
  }

  private RingBufferImage(Cvb.SharedImg driverImage, int bufferIndex)
  {
    _driverImage = driverImage;
    _bufferImage = driverImage.GetBufferImage(bufferIndex);
    _bufferIndex = bufferIndex;
  }
	
  ~RingBufferImage()
  {
    Dispose(disposing: false);
  }
	
  // Simply a readable alias for dispose.
  public void Unlock()
  {
    Dispose();
  }
	
  public void Dispose()
  {
    Dispose(disposing: true);
    GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
      _bufferImage?.Dispose();
      Cvb.Driver.IRingBuffer.RBUnlock(_driverImage, _bufferIndex);
    }
  }
	
  public static implicit operator Cvb.Image.IMG(RingBufferImage image)
  {
    return image._bufferImage;
  }

  public int Width
  {
    get { return Cvb.Image.ImageWidth(this); }
  }

  public int Height
  {
    get { return Cvb.Image.ImageHeight(this); }
  }
}
static class DriverExtensions
{
  // Opens a driver with a given number of buffers; null on error.
  public static Cvb.SharedImg TryOpenWithBufferCount(string path, int numBuffers)
  {
    var driver = TryOpen(path);
    if (driver == null)
      return null;

    if (driver.GetBufferCount() == numBuffers)
      return driver;

    try
    {
      return driver.CreateWithNewNumberOfBuffers(numBuffers);
    }
    finally
    {
      driver.Dispose();
    }
  }

  // Opens a driver; null on error.
  public static Cvb.SharedImg TryOpen(string path)
  {
    Cvb.SharedImg driver;
    Cvb.Image.LoadImageFile(path, out driver);
    return driver;
  }

  public static int GetBufferCount(this Cvb.SharedImg driver)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));
    if (!Cvb.Driver.IRingBuffer.CanRingBuffer(driver))
      throw new InvalidOperationException("Driver image does not support the IRingBuffer interface");

    int numBuffers = 0;
    Cvb.Image.IMG dummy;
    int result = Cvb.Driver.IRingBuffer.RBNumBuffer(driver, Cvb.Driver.IRingBuffer.TRingbufferNumbufferCMD.RINGBUFFER_NUMBUFFER_CMD_GET, ref numBuffers, out dummy);
    if (result < 0)
      throw new ExternalException("Error getting number of buffers", result);

    return numBuffers;
  }

  public static Cvb.SharedImg CreateWithNewNumberOfBuffers(this Cvb.SharedImg driver, int numBuffers)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));
    if (!Cvb.Driver.IRingBuffer.CanRingBuffer(driver))
      throw new InvalidOperationException("Driver image does not support the IRingBuffer interface");

    Cvb.SharedImg newDriver;
    int result = Cvb.Driver.IRingBuffer.RBNumBuffer(driver, Cvb.Driver.IRingBuffer.TRingbufferNumbufferCMD.RINGBUFFER_NUMBUFFER_CMD_SET, ref numBuffers, out newDriver);
    if (result < 0)
      throw new ExternalException("Error creating new buffer driver image", result);

    return newDriver;
  }

  public static void SetLockModeToOn(this Cvb.SharedImg driver)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));
    if (!Cvb.Driver.IRingBuffer.CanRingBuffer(driver))
      throw new InvalidOperationException("Driver image does not support the IRingBuffer interface");

    var lockModeOn = Cvb.Driver.IRingBuffer.TRingbufferLockmode.RINGBUFFER_LOCKMODE_ON;
    int result = Cvb.Driver.IRingBuffer.RBLockMode(driver, Cvb.Driver.IRingBuffer.TRingbufferLockmodeCMD.RINGBUFFER_LOCKMODE_CMD_SET, ref lockModeOn);
    if (result < 0)
      throw new ExternalException("Error setting lock-mode to: on", result);
  }

  public static int GetCurrentBufferIndex(this Cvb.SharedImg driver)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));
    if (!Cvb.Driver.IRingBuffer.CanRingBuffer(driver))
      throw new InvalidOperationException("Driver image does not support the IRingBuffer interface");

    int bufferIndex;
    int result = Cvb.Driver.IRingBuffer.RBBufferSeq(driver, 0, out bufferIndex);
    if (result < 0)
      throw new ExternalException("Error getting current buffer index", result);

    return bufferIndex;
  }

  public static Cvb.SharedImg GetBufferImage(this Cvb.SharedImg driver, int bufferIndex)
  {
    if (driver == null)
      throw new NullReferenceException(nameof(driver));
    if (!Cvb.Driver.IRingBuffer.CanRingBuffer(driver))
      throw new InvalidOperationException("Driver image does not support the IRingBuffer interface");

    Cvb.SharedImg bufferImage;
    int result = Cvb.Driver.IRingBuffer.RBGetBufferImage(driver, bufferIndex, out bufferImage);
    if (result < 0)
      throw new ExternalException("Error getting image at buffer index", result);

    return bufferImage;
  }

  public static void StartAcquisition(this Cvb.SharedImg driver)
  {
    int result = Cvb.Driver.IGrab2.G2Grab(driver);
    if (result < 0)
      throw new ExternalException("Error starting acquisition", result);
  }
	
  public static void AbortAcquisition(this Cvb.SharedImg driver)
  {
    int result = Cvb.Driver.IGrab2.G2Freeze(driver, kill: true);
    if (result < 0)
      throw new ExternalException("Error stopping acquisition", result);
  }
	
  public static RingBufferImage WaitForNextImage(this Cvb.SharedImg driver)
  {
    int result = Cvb.Driver.IGrab2.G2Wait(driver);
    if (result < 0)
      throw new ExternalException("Error waiting for next image", result);

    return RingBufferImage.FromCurrent(driver);
  }
}
3 Likes