How to update driver memory after changing camera parameters

Hey, wrote a little C# program to demonstrate how to update the image data if the changed parameter concerns the memory of an image. We need to update the memory allocated by the driver to be able to interpret the new image data.

I posted this in the general topic because I will submit the code translated into Python and C++ later.


using System;
using Stemmer.Cvb;
using Stemmer.Cvb.Driver;
using Stemmer.Cvb.GenApi;

namespace PixelFormat
{
  class Program
  {
    static void Main(string[] args)
    {
      Device device = DeviceFactory.Open("GenICam.vin");
      NodeMap deviceNodeMap = device.NodeMaps[NodeMapNames.Device];

      // Stream need to be stopped when setting image width or similar
      // as this values are not accessible while grabbing. Thus we are using GetSnapshot rather than 
      // manually start the stream, get an image and then stop the stream to be able to make further changes on the image
      WriteImageData(device.Stream.GetSnapshot());

      Console.WriteLine("Now changing width in nodemap and updating image rect");

      var oldWidth = device.DeviceImage.Width;
      SetIntegerNodeMapValue(deviceNodeMap["Width"] as IntegerNode, 2000);

      // As we changed parameters that directly concerns the memory for an image we have to update 
      // the memory allocated by the driver to be able to correctly interprete the new image data
      device.ImageRect.Update(DeviceUpdateMode.UpdateDeviceImage);

      WriteImageData(device.Stream.GetSnapshot());

      // Set the width back to the old value
      SetIntegerNodeMapValue(deviceNodeMap["Width"] as IntegerNode, oldWidth);

      // keep console alive
      Console.ReadKey();
    }

    private static void WriteImageData(Image toWriteDataFrom)
    {
      Console.WriteLine("Width of image: " + toWriteDataFrom.Width);
    }

    private static void SetIntegerNodeMapValue(IntegerNode fromNode, int toValue)
    {
      fromNode.Value = toValue;
      Console.WriteLine("Set " + fromNode.Name + " to value: " + fromNode.Value);
    }
  }
}

4 Likes

Good job @silas!

However there is one thing worth mentioning: In case of image size changing (as in your example), the UpdateDeviceImage method can be avoided if the ChangeSize method of the IImageRect Interface is used :nerd_face:

3 Likes

Thank you!

I wanted to show a way that works with bitdepth and colorformat and I wasn’t sure if this would work. But thanks for the mention. :smiley:

2 Likes

Hey, here is my code snippet rewritten in python. The C++ version is coming as soon as possible.

import cvb
import os
import cvb.foundation

def WriteImageData(toWriteDataFrom):
        print("Width of image:", toWriteDataFrom.width)

def SetIntegerNodeMap(fromNode, toValue):
        fromNode.value = toValue
        print("Set", fromNode.name, " to value:", fromNode.value)

device = cvb.DeviceFactory.open(os.path.join(cvb.install_path(), "drivers", "GenICam.vin"))
deviceNodeMap = device.node_maps["Device"]

WriteImageData(device.device_image)

print("Now changing width in nodemap and updating image rect")

oldWidth =  deviceNodeMap["Width"].value
SetIntegerNodeMap(deviceNodeMap["Width"], 2000)

# As we changed parameters that directly concerns the memory for an image we have to update
# the memory allocated by the driver to be able to correctly interprete the new image data
device.image_rect.update(0)

WriteImageData(device.device_image)

# Set the width back to the old value
SetIntegerNodeMap(deviceNodeMap["Width"], oldWidth)
2 Likes

After some delay, here is my code snipped translated into C++.

#include <iostream>
#include <cvb/device_factory.hpp>
#include <cvb/utilities/system_info.hpp>
#include <cvb/driver/stream.hpp>
#include <cvb/driver/image_rect.hpp>

using namespace std;
using namespace Cvb;

void WriteImageData(DeviceImagePtr toWriteDataFrom) {
	cout << "Width of image: " << toWriteDataFrom->Width() << endl;
}

void SetIntegerNodeMapValue(shared_ptr<IntegerNode> fromNode, int toValue) {
	fromNode->SetValue(toValue);
	cout << "Set " << fromNode->Name() << " to value: " << fromNode->Value() << endl;
}

int main() {
	auto device = DeviceFactory::Open(ExpandPath(InstallPath() + CVB_LIT("drivers/GenICam.vin")), AcquisitionStack::Vin);
	auto deviceNodeMap = device->NodeMap(CVB_LIT("Device"));

	WriteImageData(device->DeviceImage());

	cout << "Now changing width in nodemap and updating image rect" << endl;

	auto oldWidth = device->DeviceImage()->Width();
	SetIntegerNodeMapValue(deviceNodeMap->Node<IntegerNode>("Width"), 2000);

	// As we changed parameters that directly concerns the memory for an image we have to update 
	// the memory allocated by the driver to be able to correctly interprete the new image data
	device->ImageRect()->Update(DeviceUpdateMode::UpdateDeviceImage);

	WriteImageData(device->DeviceImage());

	SetIntegerNodeMapValue(deviceNodeMap->Node<IntegerNode>("Width"), oldWidth);
}
2 Likes