MapLibre Native Core
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
image.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 #include <mbgl/util/geometry.hpp>
5 #include <mbgl/util/size.hpp>
6 
7 #include <string>
8 #include <cstring>
9 #include <memory>
10 #include <algorithm>
11 
12 namespace mbgl {
13 
14 enum class ImageAlphaMode {
17  Exclusive,
18 };
19 
20 template <ImageAlphaMode Mode>
21 class Image : private util::noncopyable {
22 public:
23  Image() = default;
24 
25  Image(Size size_) : size(size_), data(std::make_unique<uint8_t[]>(bytes())) {}
26 
27  Image(Size size_, const uint8_t* srcData, std::size_t srcLength) : size(size_) {
28  if (srcLength != bytes()) {
29  throw std::invalid_argument("mismatched image size");
30  }
31  data = std::make_unique<uint8_t[]>(bytes());
32  std::copy(srcData, srcData + srcLength, data.get());
33  }
34 
35  Image(Size size_, std::unique_ptr<uint8_t[]> data_) : size(size_), data(std::move(data_)) {}
36 
37  Image(Image&& o) noexcept : size(o.size), data(std::move(o.data)) { o.size.width = o.size.height = 0; }
38 
39  Image& operator=(Image&& o) noexcept {
40  size = o.size;
41  data = std::move(o.data);
42  o.size.width = o.size.height = 0;
43  return *this;
44  }
45 
46  friend bool operator==(const Image& lhs, const Image& rhs) {
47  return std::equal(lhs.data.get(), lhs.data.get() + lhs.bytes(),
48  rhs.data.get(), rhs.data.get() + rhs.bytes());
49  }
50 
51  friend bool operator!=(const Image& lhs, const Image& rhs) {
52  return !(lhs == rhs);
53  }
54 
55  bool valid() const { return !size.isEmpty() && data != nullptr; }
56 
57  template <typename T = Image>
58  T clone() const {
59  T copy_(size);
60  std::copy(data.get(), data.get() + bytes(), copy_.data.get());
61  return copy_;
62  }
63 
64  size_t stride() const { return channels * size.width; }
65  size_t bytes() const { return stride() * size.height; }
66 
67  void fill(uint8_t value) {
68  std::fill(data.get(), data.get() + bytes(), value);
69  }
70 
71  void resize(Size size_) {
72  if (size == size_) {
73  return;
74  }
75  Image newImage(size_);
76  newImage.fill(0);
77  copy(*this, newImage, {0, 0}, {0, 0}, {
78  std::min(size.width, size_.width),
79  std::min(size.height, size_.height)
80  });
81  operator=(std::move(newImage));
82  }
83 
85  static void clear(Image& dstImg, const Point<uint32_t>& pt, const Size& size) {
86  if (size.isEmpty()) {
87  return;
88  }
89 
90  if (!dstImg.valid()) {
91  throw std::invalid_argument("invalid destination for image clear");
92  }
93 
94  if (size.width > dstImg.size.width ||
95  size.height > dstImg.size.height ||
96  pt.x > dstImg.size.width - size.width ||
97  pt.y > dstImg.size.height - size.height) {
98  throw std::out_of_range("out of range destination coordinates for image clear");
99  }
100 
101  uint8_t* dstData = dstImg.data.get();
102 
103  for (uint32_t y = 0; y < size.height; y++) {
104  const std::size_t dstOffset = (pt.y + y) * dstImg.stride() + pt.x * channels;
105  std::memset(dstData + dstOffset, 0, size.width * channels);
106  }
107  }
108 
112  static void copy(const Image& srcImg, Image& dstImg, const Point<uint32_t>& srcPt, const Point<uint32_t>& dstPt, const Size& size) {
113  if (size.isEmpty()) {
114  return;
115  }
116 
117  if (!srcImg.valid()) {
118  throw std::invalid_argument("invalid source for image copy");
119  }
120 
121  if (!dstImg.valid()) {
122  throw std::invalid_argument("invalid destination for image copy");
123  }
124 
125  if (size.width > srcImg.size.width ||
126  size.height > srcImg.size.height ||
127  srcPt.x > srcImg.size.width - size.width ||
128  srcPt.y > srcImg.size.height - size.height) {
129  throw std::out_of_range("out of range source coordinates for image copy");
130  }
131 
132  if (size.width > dstImg.size.width ||
133  size.height > dstImg.size.height ||
134  dstPt.x > dstImg.size.width - size.width ||
135  dstPt.y > dstImg.size.height - size.height) {
136  throw std::out_of_range("out of range destination coordinates for image copy");
137  }
138 
139  const uint8_t* srcData = srcImg.data.get();
140  uint8_t* dstData = dstImg.data.get();
141 
142  assert(srcData != dstData);
143 
144  for (uint32_t y = 0; y < size.height; y++) {
145  const std::size_t srcOffset = (srcPt.y + y) * srcImg.stride() + srcPt.x * channels;
146  const std::size_t dstOffset = (dstPt.y + y) * dstImg.stride() + dstPt.x * channels;
147  std::copy(srcData + srcOffset,
148  srcData + srcOffset + size.width * channels,
149  dstData + dstOffset);
150  }
151  }
152 
154  static constexpr size_t channels = Mode == ImageAlphaMode::Exclusive ? 1 : 4;
155  std::unique_ptr<uint8_t[]> data;
156 };
157 
161 
162 // TODO: don't use std::string for binary data.
165 
166 } // namespace mbgl
Image(Size size_)
Definition: image.hpp:25
void fill(uint8_t value)
Definition: image.hpp:67
static void clear(Image &dstImg, const Point< uint32_t > &pt, const Size &size)
Clears the rect area specified by pt and size from dstImage.
Definition: image.hpp:85
friend bool operator!=(const Image &lhs, const Image &rhs)
Definition: image.hpp:51
Image(Image &&o) noexcept
Definition: image.hpp:37
Size size
Definition: image.hpp:153
Image(Size size_, const uint8_t *srcData, std::size_t srcLength)
Definition: image.hpp:27
friend bool operator==(const Image &lhs, const Image &rhs)
Definition: image.hpp:46
static void copy(const Image &srcImg, Image &dstImg, const Point< uint32_t > &srcPt, const Point< uint32_t > &dstPt, const Size &size)
Definition: image.hpp:112
size_t bytes() const
Definition: image.hpp:65
void resize(Size size_)
Definition: image.hpp:71
std::unique_ptr< uint8_t[]> data
Definition: image.hpp:155
T clone() const
Definition: image.hpp:58
Image()=default
Image & operator=(Image &&o) noexcept
Definition: image.hpp:39
size_t stride() const
Definition: image.hpp:64
static constexpr size_t channels
Definition: image.hpp:154
Image(Size size_, std::unique_ptr< uint8_t[]> data_)
Definition: image.hpp:35
bool valid() const
Definition: image.hpp:55
uint32_t width
Definition: size.hpp:26
uint32_t height
Definition: size.hpp:27
constexpr bool isEmpty() const
Definition: size.hpp:22
std::unique_ptr< Expression > string(std::unique_ptr< Expression >, std::unique_ptr< Expression > def=nullptr)
std::enable_if_t< std::is_integral_v< T >, T > min(T a, T b)
Definition: minmax.hpp:26
Definition: actor.hpp:15
PremultipliedImage decodeImage(const std::string &)
ImageAlphaMode
Definition: image.hpp:14
@ Exclusive
Alpha-channel only.
mapbox::geometry::point< T > Point
Definition: geometry.hpp:21
std::string encodePNG(const PremultipliedImage &)
Definition: tile_id.hpp:256