“Connect, Set, Decode!”
In the following section, we present a small sample program (“Connect, Set, Decode!”). This sample demonstrates how the CameraSDK and the ImageSDK can be utilized in relation to each other, when connecting to a camera, setting properties, capturing an image and decoding the image.
The application code takes the following actions:
Connects through USB to a camera (to utilize the CameraSDK, at least one camera must be connected to the Host computer). 1. If multiple cameras are connected, the application picks any of the connected cameras, if none are specified.
Set-up of 3 properties: “ISO”, “Aperture” and “Shutter-time” (see Getting / Setting Properties).
Enable image receiving (see Receive Captured Images).
Capture an image (see Triggering a Capture).
Receive the images in-memory (RAM) on the Host computer.
Use the ImageSDK’s Decode pipeline to decode the image into uncompressed Bayer sensor data (see Decode Pipeline).
Use the ImageSDK’s Convert pipeline to scale the image to a width of 1024px, and convert it into an RGB image (see Convert Pipeline).
Save the converted image to a file.
Full Source code
#include <iostream> // Print out messages to the console
#include <fstream> // Save to file
#include <P1Camera.hpp> // CameraSDK
#include <P1Image.hpp> // ImageSDK
#include <chrono>
#include <thread>
// This small program demonstrates the CameraSDK and the ImageSDK and how they can be
// utilized in conjunction with each other.
// !! On IQ4, this code will work only if the exposure program is set to ‘manual’ !!
int main(int argc, const char** argv)
{
// All calls to the CameraSDK and ImageSDK must be wrapped in a try-catch,
// because exceptions are used to report errors, etc.
try
{
std::cout << "Connect to camera" << std::endl;
P1::CameraSdk::Camera camera = P1::CameraSdk::Camera::OpenUsbCamera();
// prepare to set cameras "exposure program" to manual
// this will allow us to set ISO, aperture and shutter time manually.
P1::CameraSdk::PropertyValue exposureProgram;
exposureProgram.mType = P1::CameraSdk::kPropertyTypeEnum;
exposureProgram.mInt = 0;
uint32_t exposureProgramId = 1000;
// Only change exposure program - if not already 0
if (camera.Property(1000).mInt != 0)
{
camera.SetProperty(exposureProgramId, exposureProgram);
}
// Setup ISO, Aperture and Shutter-time
P1::CameraSdk::PropertyValue isoValue;
isoValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
isoValue.mDouble = 200;
P1::CameraSdk::PropertyValue apertureValue;
apertureValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
apertureValue.mDouble = 5.0;
P1::CameraSdk::PropertyValue shutterTimeValue;
shutterTimeValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
shutterTimeValue.mDouble = 0.125;
// PropertyIDs:
uint32_t isoId = 120;
uint32_t apertureId = 1003;
uint32_t shutterTimeId = 1002;
camera.SetProperty(isoId, isoValue);
camera.SetProperty(apertureId, apertureValue);
camera.SetProperty(shutterTimeId, shutterTimeValue);
// Set-up so images will be sent to this computer and trig the capture
std::cout << "Start capture" << std::endl;
P1::CameraSdk::Listener imgListener;
imgListener.EnableNotification(camera, P1::CameraSdk::EventType::CameraImageReady);
camera.Subscriptions()->FullImages()->Subscribe();
// Necessary to sleep, otherwise TriggerCapture will start before EnableImageReceiving is done
std::this_thread::sleep_for(std::chrono::milliseconds(200));
camera.TriggerCapture();
// Wait for image
P1::CameraSdk::NotificationEventPtr event = imgListener.WaitForNotification(10000);
std::cout << "Image received" << std::endl;
//------
// We are done with the CameraSDK, and now use our ImageSDK for the rest
//------
auto iiqImage = event->FullImage();
// Parse IIQ file
P1::ImageSdk::RawImage image(iiqImage->Data(), iiqImage->DataSizeBytes());
// Decode image data with default values
P1::ImageSdk::DecodeConfig decodeConfig = P1::ImageSdk::DecodeConfig::Defaults;
P1::ImageSdk::SensorBayerOutput decodedImage = image.Decode(decodeConfig);
std::cout << "Decoded image size: " << decodedImage.ByteSize()
<< " Height=" << decodedImage.FullHeight()
<< " Width=" << decodedImage.FullWidth() << std::endl;
// Write decoded bitmap to file
std::fstream rawFile("bitmapRAW.bin", std::ios::binary | std::ios::trunc |
std::ios::out);
rawFile.write((char*)decodedImage.Data().get(), decodedImage.ByteSize());
rawFile.close();
// Convert image data to RGB
P1::ImageSdk::ConvertConfig config;
config.SetOutputWidth(1024);
P1::ImageSdk::BitmapImage bitmap = config.ApplyTo(image);
std::cout << "Output bitmap.bin " << " Height=" << bitmap.Width() << " Width= "
<< bitmap.Height() << std::endl;
// Write RGB bitmap to file
std::fstream rgbFile("bitmapRGB.bin", std::ios::binary | std::ios::trunc |
std::ios::out);
rgbFile.write((char*)bitmap.Data().get(), bitmap.ByteSize());
rgbFile.close();
std::cout << "Program successfully completed" << std::endl;
return 0;
}
catch (P1::ImageSdk::SdkException exception)
{
// Exception from ImageSDK
std::cout << "ImageSDK Exception: " << exception.what() << " Code:" << exception.mCode <<
std::endl;
return -1;
}
catch (P1::CameraSdk::SdkException exception)
{
// Exception from CameraSDK
std::cout << "CameraSDK Exception: " << exception.what() << " Code:"
<< exception.mErrorCode <<
std::endl;
return -1;
}
catch (...)
{
// Any other exception - just in case
std::cout << "Argh - we got an exception" << std::endl;
return -1;
}
}
using System;
using P1.CameraSdk;
using P1.ImageSdk;
namespace TestDocumentation1Cs
{
class Program
{
// This small program demonstrates the CameraSDK and the ImageSDK and how they can be
// utilized in conjunction with each other.
// !! On IQ4, this code will only work if the exposure program is set to ‘manual’ !!
static int Main(string[] args)
{
Camera camera = null;
try
{
// All calls to the CameraSDK and ImageSDK must be wrapped in a try-catch,
// because exceptions are used to report errors, etc.
Console.WriteLine("Connect to camera");
camera = Camera.OpenUsbCamera();
PropertyValue exposureProgram = new PropertyValue(PropertyType.Enum);
exposureProgram.IntValue = 0; // M
uint exposureProgramId = 1000;
camera.SetProperty(exposureProgramId, exposureProgram);
// Setup ISO, Aperture and Shutter-time
PropertyValue isoValue = 200.0;
PropertyValue apertureValue = 5.0;
PropertyValue shutterTimeValue = 0.125;
// Property IDs
uint isoId = 120;
uint apertureId = 1003;
uint shutterTimeId = 1002;
camera.SetProperty(isoId, isoValue);
camera.SetProperty(apertureId, apertureValue);
camera.SetProperty(shutterTimeId, shutterTimeValue);
// Set-up so images will be sent to this computer and trig the capture
Console.WriteLine("Start capture");
camera.EnableImageReceiving(true);
System.Threading.Thread.Sleep(100); // sleep for 100 ms
camera.TriggerCapture();
// Wait for image
IIQImageFile imageFile = camera.WaitForImage(10000);
Console.WriteLine("Image received");
camera.Close();
//------
// We are done with the CameraSDK, and now use our ImageSDK for the rest
//------
// Parse IIQ file
RawImage image = new RawImage(imageFile.Data.Pointer, (int)imageFile.Data.Length);
// Decode image data with default values
DecodeConfig decodeConfig = DecodeConfig.Defaults();
SensorBayerOutput decodedImage = decodeConfig.ApplyTo(image);
Console.WriteLine("Decoded image size: {0}, Dimension: {1} x {2}",
decodedImage.ByteSize, decodedImage.FullWidth, decodedImage.FullHeight);
// Write decoded bitmap to file
System.IO.File.WriteAllBytes("bitmapBayer.bin", decodedImage.Data);
// Convert image data to RGB
ConvertConfig config = new ConvertConfig();
config.SetOutputWidth(1024);
BitmapImage bitmap = config.ApplyTo(image);
Console.WriteLine("Output bitmap.bin: {0} x {1}", bitmap.Width, bitmap.Height);
// Write RGB bitmap to file
System.IO.File.WriteAllBytes("bitmapRGB.bin", bitmap.Data);
return 0;
}
catch (P1.CameraSdk.SdkException e)
{
Console.WriteLine("Camera Sdk error {0} : {1}", e.ErrorCode, e.Message);
return 1;
}
catch (P1.ImageSdk.SdkException e)
{
Console.WriteLine("Image Sdk error {0} : {1}", e.Code, e.Message);
return 1;
}
// Added extra catch exception
catch (Exception e)
{
Console.WriteLine("Output: Any other error: {0}", e.Message);
return 1;
}
} // Main func
} // Program class
} // namespace
Setting Properties Explanation
When setting properties, both the type and value of the property should be assigned (see Getting / Setting Properties).
// Setup ISO, Aperture and Shutter-time
P1::CameraSdk::PropertyValue isoValue;
isoValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
isoValue.mDouble = 200;
P1::CameraSdk::PropertyValue apertureValue;
apertureValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
apertureValue.mDouble = 5.0;
P1::CameraSdk::PropertyValue shutterTimeValue;
shutterTimeValue.mType = P1::CameraSdk::kPropertyTypeFloat64;
shutterTimeValue.mDouble = 0.125;
// Setup ISO, Aperture and Shutter-time
PropertyValue isoValue = 200.0;
PropertyValue apertureValue = 5.0;
PropertyValue shutterTimeValue = 0.125;
Alternatively, use the conversion operators to assign the properties. This can be seen in the following example, where the type is assigned:
// Setup ISO, Aperture and Shutter-time
P1::CameraSdk::PropertyValue isoValue = (double)200;
P1::CameraSdk::PropertyValue apertureValue = (double)5.0;
P1::CameraSdk::PropertyValue shutterTimeValue = (double)0.125;
// Setup ISO, Aperture and Shutter-time
PropertyValue isoValue1 = (double)200;
PropertyValue apertureValue1 = (double)5.0;
PropertyValue shutterTimeValue1 = (double)0.125;
In C#, typecasting for aperture and shutter time is not strictly necessary in the above example, as 5.0 and 0.125 are already doubles. However, 200 need it, because it will be interpreted as an integer.