Hi,
just a small code example to compare different file saving times with CVB.
Code is in the attachments. (it makes some assumptions about pixelformats, which may not be true in your case.
Results are in std::chrono::microseconds (taken with a pinch of doubt about accuracy)
CMakeList.txt (may not work without changes on Linux):
cmake_minimum_required(VERSION 3.5)
project(saveTest)
set (CMAKE_CXX_STANDARD 17)
#find CVB
file(TO_CMAKE_PATH "$ENV{CVB}/cmake" CVB_MODULE_PATH)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CVB_MODULE_PATH}")
find_package(CVB REQUIRED)
add_executable(saveTest main.cpp ${SOURCES} ${HEADERS})
target_link_libraries(saveTest CVB::CVCDriver CVB::CVCUtilities)
if(UNIX)
target_link_libraries(saveTest pthread)
endif()
main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <cvb/device_factory.hpp>
#include <cvb/utilities/system_info.hpp>
#include <cvb/driver/stream.hpp>
void dumpRawImage(Cvb::Image& image, const std::string& filename)
{
// warning these tests are not complete
if (image.PlanesCount() != 1)
throw std::runtime_error("single plane images only");
const auto linAccess = image.Plane(0).LinearAccess();
if (linAccess.XInc() < 1 || linAccess.YInc() < 1)
throw std::runtime_error("weird increments found");
const auto size = image.Height() * linAccess.YInc();
const auto basePtr = reinterpret_cast<char*>(linAccess.BasePtr());
const auto flags = std::ios::out | std::ios::binary;
auto file = std::fstream(filename, flags);
if (!file.good())
throw std::runtime_error("failed to open file");
file.write(basePtr, size);
file.close();
}
template<typename Callable>
long long measureTime(Callable c)
{
// warning: high_resolution does not mean high_accuracy!
auto before = std::chrono::high_resolution_clock::now();
c();
auto after = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(after - before).count();
}
void saveImage(Cvb::Image& image)
{
static int index = 0;
auto prefix = "C:\\temp\\" + std::to_string(index++);
// raw
auto msRaw = measureTime([&image, &prefix] {dumpRawImage(image, prefix + ".raw"); });
// the usual suspects
auto msJpg = measureTime([&image, &prefix] {image.Save(prefix + ".jpg"); });
auto msTif = measureTime([&image, &prefix] {image.Save(prefix + ".tiff"); });
auto msPng = measureTime([&image, &prefix] {image.Save(prefix + ".png"); });
auto msBmp = measureTime([&image, &prefix] {image.Save(prefix + ".bmp"); });
std::cout << "jpg: " << msJpg << " | tif: " << msTif << " | png: " << msPng << " | bmp: " << msBmp << " | raw: " << msRaw << "\n";
}
int main(int argc, char* argv[])
{
const int NUM_IMAGES = 20;
auto flags = Cvb::DiscoverFlags::IgnoreVins;
#ifdef WIN32
flags = flags | Cvb::DiscoverFlags::IgnoreGevSD;
#endif
const auto timeout = std::chrono::seconds(10);
try
{
// find all cams
auto tokens = Cvb::DeviceFactory::Discover(flags);
// open/test all cams serially
for (auto& token : tokens)
{
token.SetParameter("NumBuffer", std::to_string(NUM_IMAGES + 1)); // (too) large Ringbuffer, we only care about image saving time.
token.SetParameter("PixelFormat", "1"); // Enforce MONO8
auto device = Cvb::DeviceFactory::Open(token.AccessToken());
auto stream = device->Stream();
stream->Start();
for (int i = 0; i < NUM_IMAGES; ++i)
{
auto waitResult = stream->WaitFor(timeout);
if (waitResult.Status == Cvb::WaitStatus::Timeout)
throw std::runtime_error("acquisition timeout");
saveImage(*waitResult.Image);
}
stream->Stop();
}
}
catch (const std::exception& error)
{
std::cout << "something went wrong: " << error.what() << std::endl;
}
}