libcamera  v0.5.0+38-2f62701e
Supporting cameras in Linux since 2019
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
interpolator.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /*
3  * Copyright (C) 2024, Paul Elder <paul.elder@ideasonboard.com>
4  *
5  * Helper class for interpolating maps of objects
6  */
7 
8 #pragma once
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <map>
13 #include <string>
14 #include <tuple>
15 
16 #include <libcamera/base/log.h>
17 
19 
20 namespace libcamera {
21 
22 LOG_DECLARE_CATEGORY(Interpolator)
23 
24 namespace ipa {
25 
26 template<typename T>
28 {
29 public:
30  Interpolator() = default;
31  Interpolator(const std::map<unsigned int, T> &data)
32  : data_(data)
33  {
34  }
35  Interpolator(std::map<unsigned int, T> &&data)
36  : data_(std::move(data))
37  {
38  }
39 
40  ~Interpolator() = default;
41 
43  const std::string &key_name,
44  const std::string &value_name)
45  {
46  data_.clear();
47  lastInterpolatedKey_.reset();
48 
49  if (!yaml.isList()) {
50  LOG(Interpolator, Error) << "yaml object must be a list";
51  return -EINVAL;
52  }
53 
54  for (const auto &value : yaml.asList()) {
55  unsigned int ct = std::stoul(value[key_name].get<std::string>(""));
56  std::optional<T> data =
57  value[value_name].get<T>();
58  if (!data) {
59  return -EINVAL;
60  }
61 
62  data_[ct] = *data;
63  }
64 
65  if (data_.size() < 1) {
66  LOG(Interpolator, Error) << "Need at least one element";
67  return -EINVAL;
68  }
69 
70  return 0;
71  }
72 
73  void setQuantization(const unsigned int q)
74  {
75  quantization_ = q;
76  }
77 
78  void setData(std::map<unsigned int, T> &&data)
79  {
80  data_ = std::move(data);
81  lastInterpolatedKey_.reset();
82  }
83 
84  const std::map<unsigned int, T> &data() const
85  {
86  return data_;
87  }
88 
89  const T &getInterpolated(unsigned int key, unsigned int *quantizedKey = nullptr)
90  {
91  ASSERT(data_.size() > 0);
92 
93  if (quantization_ > 0)
94  key = std::lround(key / static_cast<double>(quantization_)) * quantization_;
95 
96  if (quantizedKey)
97  *quantizedKey = key;
98 
99  if (lastInterpolatedKey_.has_value() &&
100  *lastInterpolatedKey_ == key)
101  return lastInterpolatedValue_;
102 
103  auto it = data_.lower_bound(key);
104 
105  if (it == data_.begin())
106  return it->second;
107 
108  if (it == data_.end())
109  return std::prev(it)->second;
110 
111  if (it->first == key)
112  return it->second;
113 
114  auto it2 = std::prev(it);
115  double lambda = (key - it2->first) / static_cast<double>(it->first - it2->first);
116  interpolate(it2->second, it->second, lastInterpolatedValue_, lambda);
117  lastInterpolatedKey_ = key;
118 
119  return lastInterpolatedValue_;
120  }
121 
122  void interpolate(const T &a, const T &b, T &dest, double lambda)
123  {
124  dest = a * (1.0 - lambda) + b * lambda;
125  }
126 
127 private:
128  std::map<unsigned int, T> data_;
129  T lastInterpolatedValue_;
130  std::optional<unsigned int> lastInterpolatedKey_;
131  unsigned int quantization_ = 0;
132 };
133 
134 } /* namespace ipa */
135 
136 } /* namespace libcamera */
#define LOG(category, severity)
Log a message.
Interpolator()=default
Construct an empty interpolator.
Top-level libcamera namespace.
Definition: backtrace.h:17
Class for storing, retrieving, and interpolating objects.
Definition: interpolator.h:27
Definition: v4l2_pixelformat.h:62
ListAdapter asList() const
Wrap a list YamlObject in an adapter that exposes iterators.
Definition: yaml_parser.h:206
const T & getInterpolated(unsigned int key, unsigned int *quantizedKey=nullptr)
Retrieve an interpolated value for the given key.
Definition: interpolator.h:89
#define ASSERT(condition)
Abort program execution if assertion fails.
Interpolator(std::map< unsigned int, T > &&data)
Construct an interpolator from a map of objects.
Definition: interpolator.h:35
bool isList() const
Return whether the YamlObject is a list.
Definition: yaml_parser.h:155
Interpolator(const std::map< unsigned int, T > &data)
Construct an interpolator from a map of objects.
Definition: interpolator.h:31
#define LOG_DECLARE_CATEGORY(name)
Declare a category of log messages.
void setQuantization(const unsigned int q)
Set the quantization value.
Definition: interpolator.h:73
void interpolate(const T &a, const T &b, T &dest, double lambda)
Interpolate between two instances of T.
Definition: interpolator.h:122
A class representing the tree structure of the YAML content.
Definition: yaml_parser.h:27
void setData(std::map< unsigned int, T > &&data)
Set the internal map.
Definition: interpolator.h:78
int readYaml(const libcamera::YamlObject &yaml, const std::string &key_name, const std::string &value_name)
Initialize an Interpolator instance from yaml.
Definition: interpolator.h:42
const std::map< unsigned int, T > & data() const
Access the internal map.
Definition: interpolator.h:84
Logging infrastructure.
A YAML parser helper.