ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
bitmap.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <ios>
13 #include <limits>
14 #include <memory>
15 #include <string>
16 #include <vector>
17 
18 #ifdef _WIN32
19 #define NOMINMAX
20 #include <Windows.h>
21 #endif
22 #include <FreeImage.h>
23 
24 #include "util/string.h"
25 
26 namespace colmap {
27 
28 // Templated bitmap color class.
29 template <typename T>
30 struct BitmapColor {
31  BitmapColor();
32  BitmapColor(const T gray);
33  BitmapColor(const T r, const T g, const T b);
34 
35  template <typename D>
36  BitmapColor<D> Cast() const;
37 
38  bool operator==(const BitmapColor<T>& rhs) const;
39  bool operator!=(const BitmapColor<T>& rhs) const;
40 
41  template <typename D>
42  friend std::ostream& operator<<(std::ostream& output,
43  const BitmapColor<D>& color);
44 
45  T r;
46  T g;
47  T b;
48 };
49 
50 // Wrapper class around FreeImage bitmaps.
51 class Bitmap {
52 public:
53  Bitmap();
54 
55  // Copy constructor.
56  Bitmap(const Bitmap& other);
57  // Move constructor.
58  Bitmap(Bitmap&& other);
59 
60  // Create bitmap object from existing FreeImage bitmap object. Note that
61  // this class takes ownership of the object.
62  explicit Bitmap(FIBITMAP* data);
63 
64  // Copy assignment.
65  Bitmap& operator=(const Bitmap& other);
66  // Move assignment.
67  Bitmap& operator=(Bitmap&& other);
68 
69  // Allocate bitmap by overwriting the existing data.
70  bool Allocate(const int width, const int height, const bool as_rgb);
71 
72  // Deallocate the bitmap by releasing the existing data.
73  void Deallocate();
74 
75  // Get pointer to underlying FreeImage object.
76  inline const FIBITMAP* Data() const;
77  inline FIBITMAP* Data();
78 
79  // Dimensions of bitmap.
80  inline int Width() const;
81  inline int Height() const;
82  inline int Channels() const;
83 
84  // Number of bits per pixel. This is 8 for grey and 24 for RGB image.
85  inline unsigned int BitsPerPixel() const;
86 
87  // Scan width of bitmap which differs from the actual image width to achieve
88  // 32 bit aligned memory. Also known as pitch or stride.
89  inline unsigned int ScanWidth() const;
90 
91  // Check whether image is grey- or colorscale.
92  inline bool IsRGB() const;
93  inline bool IsGrey() const;
94 
95  // Number of bytes required to store image.
96  size_t NumBytes() const;
97 
98  // Copy raw image data to array.
99  std::vector<uint8_t> ConvertToRawBits() const;
100  std::vector<uint8_t> ConvertToRowMajorArray() const;
101  std::vector<uint8_t> ConvertToColMajorArray() const;
102 
103  // Manipulate individual pixels. For grayscale images, only the red element
104  // of the RGB color is used.
105  bool GetPixel(const int x, const int y, BitmapColor<uint8_t>* color) const;
106  bool SetPixel(const int x, const int y, const BitmapColor<uint8_t>& color);
107 
108  // Get pointer to y-th scanline, where the 0-th scanline is at the top.
109  const uint8_t* GetScanline(const int y) const;
110 
111  // Fill entire bitmap with uniform color. For grayscale images, the first
112  // element of the vector is used.
113  void Fill(const BitmapColor<uint8_t>& color);
114 
115  // Interpolate color at given floating point position.
116  bool InterpolateNearestNeighbor(const double x,
117  const double y,
118  BitmapColor<uint8_t>* color) const;
119  bool InterpolateBilinear(const double x,
120  const double y,
121  BitmapColor<float>* color) const;
122 
123  // Extract EXIF information from bitmap. Returns false if no EXIF
124  // information is embedded in the bitmap.
125  bool ExifCameraModel(std::string* camera_model) const;
126  bool ExifFocalLength(double* focal_length) const;
127  bool ExifLatitude(double* latitude) const;
128  bool ExifLongitude(double* longitude) const;
129  bool ExifAltitude(double* altitude) const;
130 
131  // Read bitmap at given path and convert to grey- or colorscale.
132  bool Read(const std::string& path, const bool as_rgb = true);
133 
134  // Write image to file. Flags can be used to set e.g. the JPEG quality.
135  // Consult the FreeImage documentation for all available flags.
136  bool Write(const std::string& path,
137  const FREE_IMAGE_FORMAT format = FIF_UNKNOWN,
138  const int flags = 0) const;
139 
140  // Smooth the image using a Gaussian kernel.
141  void Smooth(const float sigma_x, const float sigma_y);
142 
143  // Rescale image to the new dimensions.
144  void Rescale(const int new_width,
145  const int new_height,
146  const FREE_IMAGE_FILTER filter = FILTER_BILINEAR);
147 
148  // Clone the image to a new bitmap object.
149  Bitmap Clone() const;
150  Bitmap CloneAsGrey() const;
151  Bitmap CloneAsRGB() const;
152 
153  // Clone metadata from this bitmap object to another target bitmap object.
154  void CloneMetadata(Bitmap* target) const;
155 
156  // Read specific EXIF tag.
157  bool ReadExifTag(const FREE_IMAGE_MDMODEL model,
158  const std::string& tag_name,
159  std::string* result) const;
160 
161 private:
162  typedef std::unique_ptr<FIBITMAP, decltype(&FreeImage_Unload)> FIBitmapPtr;
163 
164  void SetPtr(FIBITMAP* data);
165 
166  static bool IsPtrGrey(FIBITMAP* data);
167  static bool IsPtrRGB(FIBITMAP* data);
168  static bool IsPtrSupported(FIBITMAP* data);
169 
170  FIBitmapPtr data_;
171  int width_;
172  int height_;
173  int channels_;
174 };
175 
176 // Jet colormap inspired by Matlab. Grayvalues are expected in the range [0, 1]
177 // and are converted to RGB values in the same range.
178 class JetColormap {
179 public:
180  static float Red(const float gray);
181  static float Green(const float gray);
182  static float Blue(const float gray);
183 
184 private:
185  static float Interpolate(const float val,
186  const float y0,
187  const float x0,
188  const float y1,
189  const float x1);
190  static float Base(const float val);
191 };
192 
194 // Implementation
196 
197 namespace internal {
198 
199 template <typename T1, typename T2>
200 T2 BitmapColorCast(const T1 value) {
201  return std::min(static_cast<T1>(std::numeric_limits<T2>::max()),
202  std::max(static_cast<T1>(std::numeric_limits<T2>::min()),
203  std::round(value)));
204 }
205 
206 } // namespace internal
207 
208 template <typename T>
209 BitmapColor<T>::BitmapColor() : r(0), g(0), b(0) {}
210 
211 template <typename T>
212 BitmapColor<T>::BitmapColor(const T gray) : r(gray), g(gray), b(gray) {}
213 
214 template <typename T>
215 BitmapColor<T>::BitmapColor(const T r, const T g, const T b)
216  : r(r), g(g), b(b) {}
217 
218 template <typename T>
219 template <typename D>
222  color.r = internal::BitmapColorCast<T, D>(r);
223  color.g = internal::BitmapColorCast<T, D>(g);
224  color.b = internal::BitmapColorCast<T, D>(b);
225  return color;
226 }
227 
228 template <typename T>
230  return r == rhs.r && g == rhs.g && b == rhs.b;
231 }
232 
233 template <typename T>
235  return r != rhs.r || g != rhs.g || b != rhs.b;
236 }
237 
238 template <typename T>
239 std::ostream& operator<<(std::ostream& output, const BitmapColor<T>& color) {
240  output << StringPrintf("RGB(%f, %f, %f)", static_cast<double>(color.r),
241  static_cast<double>(color.g),
242  static_cast<double>(color.b));
243  return output;
244 }
245 
246 FIBITMAP* Bitmap::Data() { return data_.get(); }
247 const FIBITMAP* Bitmap::Data() const { return data_.get(); }
248 
249 int Bitmap::Width() const { return width_; }
250 int Bitmap::Height() const { return height_; }
251 int Bitmap::Channels() const { return channels_; }
252 
253 unsigned int Bitmap::BitsPerPixel() const {
254  return FreeImage_GetBPP(data_.get());
255 }
256 
257 unsigned int Bitmap::ScanWidth() const {
258  return FreeImage_GetPitch(data_.get());
259 }
260 
261 bool Bitmap::IsRGB() const { return channels_ == 3; }
262 
263 bool Bitmap::IsGrey() const { return channels_ == 1; }
264 
265 } // namespace colmap
filament::Texture::InternalFormat format
int width
int height
math::float4 color
core::Tensor result
Definition: VtkUtils.cpp:76
bool SetPixel(const int x, const int y, const BitmapColor< uint8_t > &color)
Definition: bitmap.cc:199
std::vector< uint8_t > ConvertToRowMajorArray() const
Definition: bitmap.cc:147
bool GetPixel(const int x, const int y, BitmapColor< uint8_t > *color) const
Definition: bitmap.cc:178
bool ExifCameraModel(std::string *camera_model) const
Definition: bitmap.cc:306
bool IsRGB() const
Definition: bitmap.h:261
void Fill(const BitmapColor< uint8_t > &color)
Definition: bitmap.cc:226
bool Read(const std::string &path, const bool as_rgb=true)
Definition: bitmap.cc:485
Bitmap Clone() const
Definition: bitmap.cc:586
std::vector< uint8_t > ConvertToRawBits() const
Definition: bitmap.cc:136
const uint8_t * GetScanline(const int y) const
Definition: bitmap.cc:220
bool Allocate(const int width, const int height, const bool as_rgb)
Definition: bitmap.cc:104
void Rescale(const int new_width, const int new_height, const FREE_IMAGE_FILTER filter=FILTER_BILINEAR)
Definition: bitmap.cc:581
void Smooth(const float sigma_x, const float sigma_y)
Definition: bitmap.cc:553
bool InterpolateBilinear(const double x, const double y, BitmapColor< float > *color) const
Definition: bitmap.cc:248
void CloneMetadata(Bitmap *target) const
Definition: bitmap.cc:604
unsigned int ScanWidth() const
Definition: bitmap.h:257
std::vector< uint8_t > ConvertToColMajorArray() const
Definition: bitmap.cc:162
int Width() const
Definition: bitmap.h:249
bool InterpolateNearestNeighbor(const double x, const double y, BitmapColor< uint8_t > *color) const
Definition: bitmap.cc:241
bool IsGrey() const
Definition: bitmap.h:263
bool ExifAltitude(double *altitude) const
Definition: bitmap.cc:472
void Deallocate()
Definition: bitmap.cc:121
const FIBITMAP * Data() const
Definition: bitmap.h:247
bool ExifFocalLength(double *focal_length) const
Definition: bitmap.cc:336
bool ReadExifTag(const FREE_IMAGE_MDMODEL model, const std::string &tag_name, std::string *result) const
Definition: bitmap.cc:610
int Channels() const
Definition: bitmap.h:251
int Height() const
Definition: bitmap.h:250
bool ExifLongitude(double *longitude) const
Definition: bitmap.cc:444
size_t NumBytes() const
Definition: bitmap.cc:128
bool ExifLatitude(double *latitude) const
Definition: bitmap.cc:416
Bitmap CloneAsGrey() const
Definition: bitmap.cc:588
Bitmap & operator=(const Bitmap &other)
Definition: bitmap.cc:87
Bitmap CloneAsRGB() const
Definition: bitmap.cc:596
unsigned int BitsPerPixel() const
Definition: bitmap.h:253
bool Write(const std::string &path, const FREE_IMAGE_FORMAT format=FIF_UNKNOWN, const int flags=0) const
Definition: bitmap.cc:523
static float Red(const float gray)
Definition: bitmap.cc:655
static float Blue(const float gray)
Definition: bitmap.cc:659
static float Green(const float gray)
Definition: bitmap.cc:657
GraphType data
Definition: graph_cut.cc:138
normal_z y
normal_z x
static const std::string path
Definition: PointCloud.cpp:59
T2 BitmapColorCast(const T1 value)
Definition: bitmap.h:200
std::ostream & operator<<(std::ostream &output, const BitmapColor< T > &color)
Definition: bitmap.h:239
std::string StringPrintf(const char *format,...)
Definition: string.cc:131
friend std::ostream & operator<<(std::ostream &output, const BitmapColor< D > &color)
BitmapColor< D > Cast() const
Definition: bitmap.h:220
bool operator!=(const BitmapColor< T > &rhs) const
Definition: bitmap.h:234
bool operator==(const BitmapColor< T > &rhs) const
Definition: bitmap.h:229