38 #ifndef WIN32_LEAN_AND_MEAN
39 #define WIN32_LEAN_AND_MEAN 1
46 #include <arpa/inet.h>
55 #include <opencv2/imgcodecs.hpp>
64 bool write_binary_image(
const Image &image,
const std::filesystem::path &path)
66 std::ofstream output(path, std::ios::binary | std::ios::out);
70 std::cerr <<
"Failed to open: " << path << std::endl;
80 << image.width <<
" " << image.height <<
"\n"
83 output.write(
reinterpret_cast<const char*
>(image.raw_data->data()) + image.image_data_offset,
84 image.image_data_length);
90 << image.width <<
" " << image.height <<
"\n"
96 const uint16_t* raw_data =
reinterpret_cast<const uint16_t*
>(image.raw_data->data() + image.image_data_offset);
97 for (
int i = 0 ; i < (image.width * image.height) ; ++i)
99 const uint16_t o = htons(raw_data[i]);
100 output.write(
reinterpret_cast<const char*
>(&o),
sizeof(uint16_t));
108 << image.width <<
" " << image.height <<
"\n"
114 for (
int i = 0 ; i < (image.width * image.height) ; ++i)
116 const auto bgr =
reinterpret_cast<const std::array<uint8_t, 3>*
>(image.raw_data->data() + image.image_data_offset + (i * 3));
117 const std::array<uint8_t, 3> rgb{bgr->at(2), bgr->at(1), bgr->at(0)};
118 output.write(
reinterpret_cast<const char*
>(rgb.data()),
sizeof(rgb));
125 std::cerr <<
"Unhandled image format. Cannot write to disk" << std::endl;
157 cv::Mat Image::cv_mat()
const
166 default: {
throw std::runtime_error(
"invalid pixel format");}
179 return cv::imwrite(path.string(), image.cv_mat());
181 const auto extension = path.extension();
182 if (extension ==
".pgm" || extension ==
".PGM" || extension ==
".ppm" || extension ==
".PPM")
184 return write_binary_image(image, path);
186 throw std::runtime_error(
"Unsupported path extension: " + extension.string() +
". Try compiling with OpenCV");
201 const auto disparity = frame.
get_image(disparity_source);
204 disparity.width < 0 ||
205 disparity.height < 0)
213 size_t bytes_per_pixel = 0;
214 switch (depth_format)
218 bytes_per_pixel =
sizeof(uint16_t);
223 bytes_per_pixel =
sizeof(
float);
228 std::cerr <<
"Unsupported depth pixel format" << std::endl;
233 auto data = std::make_shared<std::vector<uint8_t>>(disparity.width * disparity.height * bytes_per_pixel,
234 static_cast<uint8_t
>(0));
239 constexpr
double scale = 1.0 / 16.0;
241 for (
size_t i = 0 ; i < static_cast<size_t>(disparity.width * disparity.height) ; ++i)
243 const size_t index = disparity.image_data_offset + (i *
sizeof(uint16_t));
246 static_cast<double>(*
reinterpret_cast<const uint16_t*
>(disparity.raw_data->data() + index)) * scale;
248 switch (depth_format)
255 const uint16_t depth = (
d == 0.0) ?
static_cast<uint16_t
>(invalid_value) :
256 static_cast<uint16_t
>(1000 * fx * -tx /
d);
258 auto data_pointer =
reinterpret_cast<uint16_t*
>(data->data() + (
sizeof(uint16_t) * i));
259 *data_pointer = depth;
264 const float depth = (
d == 0.0) ? invalid_value :
265 static_cast<float>(fx * -tx /
d);
267 auto data_pointer =
reinterpret_cast<float*
>(data->data() + (
sizeof(
float) * i));
268 *data_pointer = depth;
273 std::cerr <<
"Unsupported depth pixel format" << std::endl;
285 disparity.camera_timestamp,
286 disparity.ptp_timestamp,
288 disparity.calibration};
301 std::vector<uint8_t> raw_data(color_length,
static_cast<uint8_t
>(0));
303 for (
int h = 0 ; h < luma.
height ; ++h)
305 const size_t row_offset = h * luma.
width * 3;
307 for (
int w = 0 ; w < luma.
width ; ++w)
309 const size_t luma_offset = (h * luma.
width) + w;
310 const size_t chroma_offset = 2 * (((h / 2) * (luma.
width / 2)) + (w / 2));
314 const float px_cr =
static_cast<float>(*(chroma.
raw_data->data() + chroma.
image_data_offset + chroma_offset + 1)) - 128.0f;
316 const float px_r = std::clamp(px_y + 1.13983
f * px_cr, 0.0
f, 255.0
f);
317 const float px_g = std::clamp(px_y - 0.39465
f * px_cb - 0.58060
f * px_cr, 0.0
f, 255.0
f);
318 const float px_b = std::clamp(px_y + 2.03211
f * px_cb, 0.0
f, 255.0
f);
320 auto bgr_pixel_ptr =
reinterpret_cast<uint8_t*
>(raw_data.data() + row_offset + (3 * w));
322 bgr_pixel_ptr[0] =
static_cast<uint8_t
>(px_b);
323 bgr_pixel_ptr[1] =
static_cast<uint8_t
>(px_g);
324 bgr_pixel_ptr[2] =
static_cast<uint8_t
>(px_r);
328 return Image{std::make_shared<std::vector<uint8_t>>(std::move(raw_data)),
346 switch (output_source)
360 default: {
return std::nullopt;}
377 return create_color_pointcloud<void>(frame, max_range,
DataSource::UNKNOWN, disparity_source);