using Itala;
using Itala.GenApi;
/// <summary>
/// "GrabChunks" is an extension of the simple Grab example which introduces
/// the chunk data functionality. Along with the image data itself, images can
/// be shipped along with additional information. This additional data is arranged in
/// "chunks". For instance, an image can contain two chunks: its timestamp and the
/// temperature of the device at the moment of the acquisition. Chunks can be read
/// as GenICam features returned by the IImage interface.
/// </summary>
internal class Program
{
const int ACQUIRE_COUNT = 10;
private static void GrabChunks_Sample()
{
Console.WriteLine("######## GrabChunks ########");
ISystem system = SystemFactory.Create();
List<DeviceInfo> deviceInfos = system.EnumerateDevices();
if (deviceInfos.Count == 0)
throw new ItalaRuntimeException("No devices found. Example canceled.");
if (deviceInfos[0].AccessStatus != DeviceAccessStatus.AvailableReadWrite)
throw new ItalaRuntimeException("Target device is unaccessible in RW mode. Example canceled.");
IDevice device = system.CreateDevice(deviceInfos[0]);
Console.WriteLine("First device initialized.");
Console.WriteLine("Enabling chunk data...");
// Enable the auto exposure time functionality to cause changes in the exposure
// time value when the scene changes or the camera itself is moved.
IEnumeration exposureAuto = device.GetNodeMap().GetNode<IEnumeration>("ExposureAuto");
if (!exposureAuto.IsWritable)
throw new ItalaRuntimeException("Unable to activate auto exposure time mode. Aborting.");
Int64 originalExposureAuto = exposureAuto.IntValue;
exposureAuto.FromString("Continuous");
// The chunk data functionality is enabled via the "ChunkModeActive" feature.
IBoolean chunkModeActive = device.GetNodeMap().GetNode<IBoolean>("ChunkModeActive");
if (!chunkModeActive.IsWritable)
throw new ItalaRuntimeException("Unable to activate chunk mode. Aborting.");
bool originalChunkModeActive = chunkModeActive.Value;
chunkModeActive.Value = true;
// Each chunk data available can be enabled individually. In this case, exposure
// time, pixel format and frame timestamp chunks are activated.
// First select the exposure time chunk via the selector and enable it via the
// "ChunkEnable" feature.
IEnumeration chunkSelector = device.GetNodeMap().GetNode<IEnumeration>("ChunkSelector");
if (!chunkSelector.IsWritable)
throw new ItalaRuntimeException("Unable to retrieve chunk selector. Aborting.");
chunkSelector.FromString("ExposureTime");
IBoolean chunkEnable = device.GetNodeMap().GetNode<IBoolean>("ChunkEnable");
bool originalExposureTimeChunkEnabled = chunkEnable.Value;
chunkEnable.Value = true;
// Do the same for frame ID chunk.
chunkSelector.FromString("FrameID");
bool originalFrameIDChunkEnabled = chunkEnable.Value;
chunkEnable.Value = true;
// And again for timestamp chunk.
chunkSelector.FromString("Timestamp");
bool originalTimestampChunkEnabled = chunkEnable.Value;
chunkEnable.Value = true;
Console.WriteLine();
device.StartAcquisition();
Console.WriteLine("Acquisition started with chunk functionality enabled.\n");
List<IImage> images = new List<IImage>();
for(int i = 0; i < ACQUIRE_COUNT; i++)
{
IImage image = device.GetNextImage(1000);
if(image.IsIncomplete)
{
// Report some info if the image is partially filled.
Console.WriteLine("Icomplete image.");
Console.WriteLine("\tBytes filled: "+ image.BytesFilled+"/"+image.PayloadSize);
}
else
{
Console.WriteLine("Image grabbed.");
}
// Add the image to the acquired frames list so that image chunks can be
// retrieved and displayed after che grab.
images.Add(image);
// The image IS NOT disposed here since it's needed afterwards to get and
// display the attached chunk data.
}
Console.WriteLine();
// The chunks embedded in the available images are ready to be read.
foreach(var (img, i) in images.Select((value, index)=>(value, index)))
{
Console.WriteLine("Retrieving chunks for image " + i + "...");
// Check if the acquired image has embedded chunk data.
if(img.HasChunckData)
{
// Chunk data is exposed as a set GenICam features which names ar
// regulated by the SFNC specification. In general, the names of
// chunk features are defined by prepending the "Chunk" prefix
// (e.g. ChunkExposureTime) to the equivalent standard feature
// (e.g. ExposureTime).
IFloat chunkExposureTime = img.GetChunkNode<IFloat>("ChunkExposureTime");
IInteger chunkFrameId = img.GetChunkNode<IInteger>("ChunkFrameID");
IInteger chunkTimestamp = img.GetChunkNode<IInteger>("ChunkTimestamp");
Console.WriteLine("\tChunkExposureTime: " + chunkExposureTime.Value);
Console.WriteLine("\tChunkFrameID: " + chunkFrameId.Value);
Console.WriteLine("\tChunkTimestamp: " + chunkTimestamp.Value);
}
else
{
Console.WriteLine("\tNo chunk data attached.");
}
// The image can now be disposed: it's not required anymore.
img.Dispose();
Console.WriteLine();
}
// The acquisition must be stopped AFTER the acquired images have been used
// (to display chunk data, in this case). If the acquisition was stopped
// prematurely, errors may have occurred when accessing the image data (released
// by the library).
device.StopAcquisition();
// Restore the original features state.
exposureAuto.IntValue = originalExposureAuto;
chunkSelector.FromString("ExposureTime");
chunkEnable.Value = originalExposureTimeChunkEnabled;
chunkSelector.FromString("FrameID");
chunkEnable.Value = originalFrameIDChunkEnabled;
chunkSelector.FromString("Timestamp");
chunkEnable.Value = originalTimestampChunkEnabled;
chunkModeActive.Value = originalChunkModeActive;
device.Dispose();
Console.WriteLine("Device instance disposed.");
system.Dispose();
Console.WriteLine("System instance disposed.");
}
private static void Main(string[] args)
{
try
{
GrabChunks_Sample();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}