Refactor & test foxglove image converter

Add a simple test to confirm that it actually produces useful images.

Trying to get a start on better testing for the infrastructure
associated with various calibration stuff, and figured I'd actually add
tests for the code that I added...

Change-Id: I4ac485b1c199f5412c9c6f41a9dd93639ce8f1a1
Signed-off-by: James Kuszmaul <jabukuszmaul@gmail.com>
diff --git a/frc971/vision/foxglove_image_converter.cc b/frc971/vision/foxglove_image_converter.cc
index 0c5c736..abde78b 100644
--- a/frc971/vision/foxglove_image_converter.cc
+++ b/frc971/vision/foxglove_image_converter.cc
@@ -3,7 +3,6 @@
 #include <opencv2/imgproc.hpp>
 
 namespace frc971::vision {
-namespace {
 std::string_view ExtensionForCompression(ImageCompression compression) {
   switch (compression) {
     case ImageCompression::kJpeg:
@@ -12,25 +11,18 @@
       return "png";
   }
 }
-}  // namespace
+
 flatbuffers::Offset<foxglove::CompressedImage> CompressImage(
-    const CameraImage *raw_image, flatbuffers::FlatBufferBuilder *fbb,
-    ImageCompression compression) {
+    const cv::Mat image, const aos::monotonic_clock::time_point eof,
+    flatbuffers::FlatBufferBuilder *fbb, ImageCompression compression) {
   std::string_view format = ExtensionForCompression(compression);
   // imencode doesn't let us pass in anything other than an std::vector, and
   // performance isn't yet a big enough issue to try to avoid the copy.
   std::vector<uint8_t> buffer;
-  CHECK(raw_image->has_data());
-  cv::Mat image_color_mat(cv::Size(raw_image->cols(), raw_image->rows()),
-                          CV_8UC2, (void *)raw_image->data()->data());
-  cv::Mat bgr_image(cv::Size(raw_image->cols(), raw_image->rows()), CV_8UC3);
-  cv::cvtColor(image_color_mat, bgr_image, cv::COLOR_YUV2BGR_YUYV);
-  CHECK(cv::imencode(absl::StrCat(".", format), bgr_image, buffer));
+  CHECK(cv::imencode(absl::StrCat(".", format), image, buffer));
   const flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data_offset =
       fbb->CreateVector(buffer);
-  const struct timespec timestamp_t =
-      aos::time::to_timespec(aos::monotonic_clock::time_point(
-          std::chrono::nanoseconds(raw_image->monotonic_timestamp_ns())));
+  const struct timespec timestamp_t = aos::time::to_timespec(eof);
   const foxglove::Time time{static_cast<uint32_t>(timestamp_t.tv_sec),
                             static_cast<uint32_t>(timestamp_t.tv_nsec)};
   const flatbuffers::Offset<flatbuffers::String> format_offset =
@@ -47,13 +39,14 @@
                                                std::string_view output_channel,
                                                ImageCompression compression)
     : event_loop_(event_loop),
+      image_callback_(
+          event_loop_, input_channel,
+          [this, compression](const cv::Mat image,
+                              const aos::monotonic_clock::time_point eof) {
+            auto builder = sender_.MakeBuilder();
+            builder.CheckOk(builder.Send(
+                CompressImage(image, eof, builder.fbb(), compression)));
+          }),
       sender_(
-          event_loop_->MakeSender<foxglove::CompressedImage>(output_channel)) {
-  event_loop_->MakeWatcher(input_channel, [this, compression](
-                                              const CameraImage &image) {
-    auto builder = sender_.MakeBuilder();
-    builder.CheckOk(
-        builder.Send(CompressImage(&image, builder.fbb(), compression)));
-  });
-}
+          event_loop_->MakeSender<foxglove::CompressedImage>(output_channel)) {}
 }  // namespace frc971::vision