blob: abde78b93c8d30bb3d585485473ca0cf0f916a5e [file] [log] [blame]
James Kuszmaul0c593962023-01-28 16:04:20 -08001#include "frc971/vision/foxglove_image_converter.h"
2#include <opencv2/imgcodecs.hpp>
3#include <opencv2/imgproc.hpp>
4
5namespace frc971::vision {
James Kuszmaul0c593962023-01-28 16:04:20 -08006std::string_view ExtensionForCompression(ImageCompression compression) {
7 switch (compression) {
8 case ImageCompression::kJpeg:
9 return "jpeg";
10 case ImageCompression::kPng:
11 return "png";
12 }
13}
James Kuszmaul59a308f2023-01-28 19:14:07 -080014
James Kuszmaul0c593962023-01-28 16:04:20 -080015flatbuffers::Offset<foxglove::CompressedImage> CompressImage(
James Kuszmaul59a308f2023-01-28 19:14:07 -080016 const cv::Mat image, const aos::monotonic_clock::time_point eof,
17 flatbuffers::FlatBufferBuilder *fbb, ImageCompression compression) {
James Kuszmaul0c593962023-01-28 16:04:20 -080018 std::string_view format = ExtensionForCompression(compression);
19 // imencode doesn't let us pass in anything other than an std::vector, and
20 // performance isn't yet a big enough issue to try to avoid the copy.
21 std::vector<uint8_t> buffer;
James Kuszmaul59a308f2023-01-28 19:14:07 -080022 CHECK(cv::imencode(absl::StrCat(".", format), image, buffer));
James Kuszmaul0c593962023-01-28 16:04:20 -080023 const flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data_offset =
24 fbb->CreateVector(buffer);
James Kuszmaul59a308f2023-01-28 19:14:07 -080025 const struct timespec timestamp_t = aos::time::to_timespec(eof);
James Kuszmaul0c593962023-01-28 16:04:20 -080026 const foxglove::Time time{static_cast<uint32_t>(timestamp_t.tv_sec),
27 static_cast<uint32_t>(timestamp_t.tv_nsec)};
28 const flatbuffers::Offset<flatbuffers::String> format_offset =
29 fbb->CreateString(format);
30 foxglove::CompressedImage::Builder builder(*fbb);
31 builder.add_timestamp(&time);
32 builder.add_data(data_offset);
33 builder.add_format(format_offset);
34 return builder.Finish();
35}
36
37FoxgloveImageConverter::FoxgloveImageConverter(aos::EventLoop *event_loop,
38 std::string_view input_channel,
39 std::string_view output_channel,
40 ImageCompression compression)
41 : event_loop_(event_loop),
James Kuszmaul59a308f2023-01-28 19:14:07 -080042 image_callback_(
43 event_loop_, input_channel,
44 [this, compression](const cv::Mat image,
45 const aos::monotonic_clock::time_point eof) {
46 auto builder = sender_.MakeBuilder();
47 builder.CheckOk(builder.Send(
48 CompressImage(image, eof, builder.fbb(), compression)));
49 }),
James Kuszmaul0c593962023-01-28 16:04:20 -080050 sender_(
James Kuszmaul59a308f2023-01-28 19:14:07 -080051 event_loop_->MakeSender<foxglove::CompressedImage>(output_channel)) {}
James Kuszmaul0c593962023-01-28 16:04:20 -080052} // namespace frc971::vision