ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
bitmap.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #include "util/bitmap.h"
33 
34 #include <regex>
35 #include <string>
36 #include <unordered_map>
37 
38 #include "VLFeat/imopv.h"
39 #include "base/camera_database.h"
40 #include "util/logging.h"
41 #include "util/math.h"
42 #include "util/misc.h"
43 
44 namespace colmap {
45 namespace {
46 #ifdef FREEIMAGE_LIB // Only needed for static FreeImage.
47 
48 void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
49  std::string error_info = "FreeImage error";
50  if(fif != FIF_UNKNOWN) {
51  error_info += " (" + std::string(FreeImage_GetFormatFromFIF(fif)) + ")";
52  }
53  LOG(ERROR) << error_info << ": " << message;
54 }
55 
56 struct FreeImageInitializer {
57  FreeImageInitializer() {
58  FreeImage_SetOutputMessage(FreeImageErrorHandler);
59  FreeImage_Initialise();
60  }
61  ~FreeImageInitializer() { FreeImage_DeInitialise(); }
62 };
63 
64 const static auto initializer = FreeImageInitializer();
65 
66 #endif // FREEIMAGE_LIB
67 }
68 
70  : data_(nullptr, &FreeImage_Unload), width_(0), height_(0), channels_(0) {}
71 
72 Bitmap::Bitmap(const Bitmap& other) : Bitmap() {
73  if (other.data_) {
74  SetPtr(FreeImage_Clone(other.data_.get()));
75  }
76 }
77 
79  data_ = std::move(other.data_);
80  width_ = other.width_;
81  height_ = other.height_;
82  channels_ = other.channels_;
83 }
84 
85 Bitmap::Bitmap(FIBITMAP* data) : Bitmap() { SetPtr(data); }
86 
88  if (other.data_) {
89  SetPtr(FreeImage_Clone(other.data_.get()));
90  }
91  return *this;
92 }
93 
95  if (this != &other) {
96  data_ = std::move(other.data_);
97  width_ = other.width_;
98  height_ = other.height_;
99  channels_ = other.channels_;
100  }
101  return *this;
102 }
103 
104 bool Bitmap::Allocate(const int width, const int height, const bool as_rgb) {
105  FIBITMAP* data = nullptr;
106  width_ = width;
107  height_ = height;
108  if (as_rgb) {
109  const int kNumBitsPerPixel = 24;
110  data = FreeImage_Allocate(width, height, kNumBitsPerPixel);
111  channels_ = 3;
112  } else {
113  const int kNumBitsPerPixel = 8;
114  data = FreeImage_Allocate(width, height, kNumBitsPerPixel);
115  channels_ = 1;
116  }
117  data_ = FIBitmapPtr(data, &FreeImage_Unload);
118  return data != nullptr;
119 }
120 
122  data_.reset();
123  width_ = 0;
124  height_ = 0;
125  channels_ = 0;
126 }
127 
128 size_t Bitmap::NumBytes() const {
129  if (data_) {
130  return ScanWidth() * height_;
131  } else {
132  return 0;
133  }
134 }
135 
136 std::vector<uint8_t> Bitmap::ConvertToRawBits() const {
137  const unsigned int scan_width = ScanWidth();
138  const unsigned int bpp = BitsPerPixel();
139  const bool kTopDown = true;
140  std::vector<uint8_t> raw_bits(scan_width * height_, 0);
141  FreeImage_ConvertToRawBits(raw_bits.data(), data_.get(), scan_width, bpp,
142  FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK,
143  FI_RGBA_BLUE_MASK, kTopDown);
144  return raw_bits;
145 }
146 
147 std::vector<uint8_t> Bitmap::ConvertToRowMajorArray() const {
148  std::vector<uint8_t> array(width_ * height_ * channels_);
149  size_t i = 0;
150  for (int y = 0; y < height_; ++y) {
151  const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
152  for (int x = 0; x < width_; ++x) {
153  for (int d = 0; d < channels_; ++d) {
154  array[i] = line[x * channels_ + d];
155  i += 1;
156  }
157  }
158  }
159  return array;
160 }
161 
162 std::vector<uint8_t> Bitmap::ConvertToColMajorArray() const {
163  std::vector<uint8_t> array(width_ * height_ * channels_);
164  size_t i = 0;
165  for (int d = 0; d < channels_; ++d) {
166  for (int x = 0; x < width_; ++x) {
167  for (int y = 0; y < height_; ++y) {
168  const uint8_t* line =
169  FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
170  array[i] = line[x * channels_ + d];
171  i += 1;
172  }
173  }
174  }
175  return array;
176 }
177 
178 bool Bitmap::GetPixel(const int x, const int y,
179  BitmapColor<uint8_t>* color) const {
180  if (x < 0 || x >= width_ || y < 0 || y >= height_) {
181  return false;
182  }
183 
184  const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
185 
186  if (IsGrey()) {
187  color->r = line[x];
188  return true;
189  } else if (IsRGB()) {
190  color->r = line[3 * x + FI_RGBA_RED];
191  color->g = line[3 * x + FI_RGBA_GREEN];
192  color->b = line[3 * x + FI_RGBA_BLUE];
193  return true;
194  }
195 
196  return false;
197 }
198 
199 bool Bitmap::SetPixel(const int x, const int y,
200  const BitmapColor<uint8_t>& color) {
201  if (x < 0 || x >= width_ || y < 0 || y >= height_) {
202  return false;
203  }
204 
205  uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
206 
207  if (IsGrey()) {
208  line[x] = color.r;
209  return true;
210  } else if (IsRGB()) {
211  line[3 * x + FI_RGBA_RED] = color.r;
212  line[3 * x + FI_RGBA_GREEN] = color.g;
213  line[3 * x + FI_RGBA_BLUE] = color.b;
214  return true;
215  }
216 
217  return false;
218 }
219 
220 const uint8_t* Bitmap::GetScanline(const int y) const {
221  CHECK_GE(y, 0);
222  CHECK_LT(y, height_);
223  return FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
224 }
225 
227  for (int y = 0; y < height_; ++y) {
228  uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
229  for (int x = 0; x < width_; ++x) {
230  if (IsGrey()) {
231  line[x] = color.r;
232  } else if (IsRGB()) {
233  line[3 * x + FI_RGBA_RED] = color.r;
234  line[3 * x + FI_RGBA_GREEN] = color.g;
235  line[3 * x + FI_RGBA_BLUE] = color.b;
236  }
237  }
238  }
239 }
240 
241 bool Bitmap::InterpolateNearestNeighbor(const double x, const double y,
242  BitmapColor<uint8_t>* color) const {
243  const int xx = static_cast<int>(std::round(x));
244  const int yy = static_cast<int>(std::round(y));
245  return GetPixel(xx, yy, color);
246 }
247 
248 bool Bitmap::InterpolateBilinear(const double x, const double y,
249  BitmapColor<float>* color) const {
250  // FreeImage's coordinate system origin is in the lower left of the image.
251  const double inv_y = height_ - 1 - y;
252 
253  const int x0 = static_cast<int>(std::floor(x));
254  const int x1 = x0 + 1;
255  const int y0 = static_cast<int>(std::floor(inv_y));
256  const int y1 = y0 + 1;
257 
258  if (x0 < 0 || x1 >= width_ || y0 < 0 || y1 >= height_) {
259  return false;
260  }
261 
262  const double dx = x - x0;
263  const double dy = inv_y - y0;
264  const double dx_1 = 1 - dx;
265  const double dy_1 = 1 - dy;
266 
267  const uint8_t* line0 = FreeImage_GetScanLine(data_.get(), y0);
268  const uint8_t* line1 = FreeImage_GetScanLine(data_.get(), y1);
269 
270  if (IsGrey()) {
271  // Top row, column-wise linear interpolation.
272  const double v0 = dx_1 * line0[x0] + dx * line0[x1];
273 
274  // Bottom row, column-wise linear interpolation.
275  const double v1 = dx_1 * line1[x0] + dx * line1[x1];
276 
277  // Row-wise linear interpolation.
278  color->r = dy_1 * v0 + dy * v1;
279  return true;
280  } else if (IsRGB()) {
281  const uint8_t* p00 = &line0[3 * x0];
282  const uint8_t* p01 = &line0[3 * x1];
283  const uint8_t* p10 = &line1[3 * x0];
284  const uint8_t* p11 = &line1[3 * x1];
285 
286  // Top row, column-wise linear interpolation.
287  const double v0_r = dx_1 * p00[FI_RGBA_RED] + dx * p01[FI_RGBA_RED];
288  const double v0_g = dx_1 * p00[FI_RGBA_GREEN] + dx * p01[FI_RGBA_GREEN];
289  const double v0_b = dx_1 * p00[FI_RGBA_BLUE] + dx * p01[FI_RGBA_BLUE];
290 
291  // Bottom row, column-wise linear interpolation.
292  const double v1_r = dx_1 * p10[FI_RGBA_RED] + dx * p11[FI_RGBA_RED];
293  const double v1_g = dx_1 * p10[FI_RGBA_GREEN] + dx * p11[FI_RGBA_GREEN];
294  const double v1_b = dx_1 * p10[FI_RGBA_BLUE] + dx * p11[FI_RGBA_BLUE];
295 
296  // Row-wise linear interpolation.
297  color->r = dy_1 * v0_r + dy * v1_r;
298  color->g = dy_1 * v0_g + dy * v1_g;
299  color->b = dy_1 * v0_b + dy * v1_b;
300  return true;
301  }
302 
303  return false;
304 }
305 
306 bool Bitmap::ExifCameraModel(std::string* camera_model) const {
307  // Read camera make and model
308  std::string make_str;
309  std::string model_str;
310  std::string focal_length;
311  *camera_model = "";
312  if (ReadExifTag(FIMD_EXIF_MAIN, "Make", &make_str)) {
313  *camera_model += (make_str + "-");
314  } else {
315  *camera_model = "";
316  return false;
317  }
318  if (ReadExifTag(FIMD_EXIF_MAIN, "Model", &model_str)) {
319  *camera_model += (model_str + "-");
320  } else {
321  *camera_model = "";
322  return false;
323  }
324  if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLengthIn35mmFilm", &focal_length)) {
325  *camera_model += (focal_length + "-");
326  } else if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLength", &focal_length)) {
327  *camera_model += (focal_length + "-");
328  } else {
329  *camera_model = "";
330  return false;
331  }
332  *camera_model += (std::to_string(width_) + "x" + std::to_string(height_));
333  return true;
334 }
335 
336 bool Bitmap::ExifFocalLength(double* focal_length) const {
337  const double max_size = std::max(width_, height_);
338 
340  // Focal length in 35mm equivalent
342 
343  std::string focal_length_35mm_str;
344  if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLengthIn35mmFilm",
345  &focal_length_35mm_str)) {
346  const std::regex regex(".*?([0-9.]+).*?mm.*?");
347  std::cmatch result;
348  if (std::regex_search(focal_length_35mm_str.c_str(), result, regex)) {
349  const double focal_length_35 = std::stold(result[1]);
350  if (focal_length_35 > 0) {
351  *focal_length = focal_length_35 / 35.0 * max_size;
352  return true;
353  }
354  }
355  }
356 
358  // Focal length in mm
360 
361  std::string focal_length_str;
362  if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLength", &focal_length_str)) {
363  std::regex regex(".*?([0-9.]+).*?mm");
364  std::cmatch result;
365  if (std::regex_search(focal_length_str.c_str(), result, regex)) {
366  const double focal_length_mm = std::stold(result[1]);
367 
368  // Lookup sensor width in database.
369  std::string make_str;
370  std::string model_str;
371  if (ReadExifTag(FIMD_EXIF_MAIN, "Make", &make_str) &&
372  ReadExifTag(FIMD_EXIF_MAIN, "Model", &model_str)) {
373  CameraDatabase database;
374  double sensor_width;
375  if (database.QuerySensorWidth(make_str, model_str, &sensor_width)) {
376  *focal_length = focal_length_mm / sensor_width * max_size;
377  return true;
378  }
379  }
380 
381  // Extract sensor width from EXIF.
382  std::string pixel_x_dim_str;
383  std::string x_res_str;
384  std::string res_unit_str;
385  if (ReadExifTag(FIMD_EXIF_EXIF, "PixelXDimension", &pixel_x_dim_str) &&
386  ReadExifTag(FIMD_EXIF_EXIF, "FocalPlaneXResolution", &x_res_str) &&
387  ReadExifTag(FIMD_EXIF_EXIF, "FocalPlaneResolutionUnit",
388  &res_unit_str)) {
389  regex = std::regex(".*?([0-9.]+).*?");
390  if (std::regex_search(pixel_x_dim_str.c_str(), result, regex)) {
391  const double pixel_x_dim = std::stold(result[1]);
392  regex = std::regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?");
393  if (std::regex_search(x_res_str.c_str(), result, regex)) {
394  const double x_res = std::stold(result[2]) / std::stold(result[1]);
395  // Use PixelXDimension instead of actual width of image, since
396  // the image might have been resized, but the EXIF data preserved.
397  const double ccd_width = x_res * pixel_x_dim;
398  if (ccd_width > 0 && focal_length_mm > 0) {
399  if (res_unit_str == "cm") {
400  *focal_length = focal_length_mm / (ccd_width * 10.0) * max_size;
401  return true;
402  } else if (res_unit_str == "inches") {
403  *focal_length = focal_length_mm / (ccd_width * 25.4) * max_size;
404  return true;
405  }
406  }
407  }
408  }
409  }
410  }
411  }
412 
413  return false;
414 }
415 
416 bool Bitmap::ExifLatitude(double* latitude) const {
417  std::string str;
418  double sign = 1.0;
419  if (ReadExifTag(FIMD_EXIF_GPS, "GPSLatitudeRef", &str)) {
420  StringTrim(&str);
421  StringToLower(&str);
422  if (!str.empty() && str[0] == 's') {
423  sign = -1.0;
424  }
425  }
426  if (ReadExifTag(FIMD_EXIF_GPS, "GPSLatitude", &str)) {
427  const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?");
428  std::cmatch result;
429  if (std::regex_search(str.c_str(), result, regex)) {
430  const double hours = std::stold(result[1]);
431  const double minutes = std::stold(result[2]);
432  const double seconds = std::stold(result[3]);
433  double value = hours + minutes / 60.0 + seconds / 3600.0;
434  if (value > 0 && sign < 0) {
435  value *= sign;
436  }
437  *latitude = value;
438  return true;
439  }
440  }
441  return false;
442 }
443 
444 bool Bitmap::ExifLongitude(double* longitude) const {
445  std::string str;
446  double sign = 1.0;
447  if (ReadExifTag(FIMD_EXIF_GPS, "GPSLongitudeRef", &str)) {
448  StringTrim(&str);
449  StringToLower(&str);
450  if (!str.empty() && str[0] == 'w') {
451  sign = -1.0;
452  }
453  }
454  if (ReadExifTag(FIMD_EXIF_GPS, "GPSLongitude", &str)) {
455  const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?");
456  std::cmatch result;
457  if (std::regex_search(str.c_str(), result, regex)) {
458  const double hours = std::stold(result[1]);
459  const double minutes = std::stold(result[2]);
460  const double seconds = std::stold(result[3]);
461  double value = hours + minutes / 60.0 + seconds / 3600.0;
462  if (value > 0 && sign < 0) {
463  value *= sign;
464  }
465  *longitude = value;
466  return true;
467  }
468  }
469  return false;
470 }
471 
472 bool Bitmap::ExifAltitude(double* altitude) const {
473  std::string str;
474  if (ReadExifTag(FIMD_EXIF_GPS, "GPSAltitude", &str)) {
475  const std::regex regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?");
476  std::cmatch result;
477  if (std::regex_search(str.c_str(), result, regex)) {
478  *altitude = std::stold(result[1]) / std::stold(result[2]);
479  return true;
480  }
481  }
482  return false;
483 }
484 
485 bool Bitmap::Read(const std::string& path, const bool as_rgb) {
486  if (!ExistsFile(path)) {
487  return false;
488  }
489 
490  const FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path.c_str(), 0);
491 
492  if (format == FIF_UNKNOWN) {
493  return false;
494  }
495 
496  FIBITMAP* fi_bitmap = FreeImage_Load(format, path.c_str(), JPEG_EXIFROTATE);
497  if (fi_bitmap == nullptr) {
498  return false;
499  }
500 
501  data_ = FIBitmapPtr(fi_bitmap, &FreeImage_Unload);
502 
503  if (!IsPtrRGB(data_.get()) && as_rgb) {
504  FIBITMAP* converted_bitmap = FreeImage_ConvertTo24Bits(fi_bitmap);
505  data_ = FIBitmapPtr(converted_bitmap, &FreeImage_Unload);
506  } else if (!IsPtrGrey(data_.get()) && !as_rgb) {
507  FIBITMAP* converted_bitmap = FreeImage_ConvertToGreyscale(fi_bitmap);
508  data_ = FIBitmapPtr(converted_bitmap, &FreeImage_Unload);
509  }
510 
511  if (!IsPtrSupported(data_.get())) {
512  data_.reset();
513  return false;
514  }
515 
516  width_ = FreeImage_GetWidth(data_.get());
517  height_ = FreeImage_GetHeight(data_.get());
518  channels_ = as_rgb ? 3 : 1;
519 
520  return true;
521 }
522 
523 bool Bitmap::Write(const std::string& path, const FREE_IMAGE_FORMAT format,
524  const int flags) const {
525  FREE_IMAGE_FORMAT save_format;
526  if (format == FIF_UNKNOWN) {
527  save_format = FreeImage_GetFIFFromFilename(path.c_str());
528  if (save_format == FIF_UNKNOWN) {
529  // If format could not be deduced, save as PNG by default.
530  save_format = FIF_PNG;
531  }
532  } else {
533  save_format = format;
534  }
535 
536  int save_flags = flags;
537  if (save_format == FIF_JPEG && flags == 0) {
538  // Use superb JPEG quality by default to avoid artifacts.
539  save_flags = JPEG_QUALITYSUPERB;
540  }
541 
542  bool success = false;
543  if (save_flags == 0) {
544  success = FreeImage_Save(save_format, data_.get(), path.c_str());
545  } else {
546  success =
547  FreeImage_Save(save_format, data_.get(), path.c_str(), save_flags);
548  }
549 
550  return success;
551 }
552 
553 void Bitmap::Smooth(const float sigma_x, const float sigma_y) {
554  std::vector<float> array(width_ * height_);
555  std::vector<float> array_smoothed(width_ * height_);
556  for (int d = 0; d < channels_; ++d) {
557  size_t i = 0;
558  for (int y = 0; y < height_; ++y) {
559  const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
560  for (int x = 0; x < width_; ++x) {
561  array[i] = line[x * channels_ + d];
562  i += 1;
563  }
564  }
565 
566  vl_imsmooth_f(array_smoothed.data(), width_, array.data(), width_, height_,
567  width_, sigma_x, sigma_y);
568 
569  i = 0;
570  for (int y = 0; y < height_; ++y) {
571  uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y);
572  for (int x = 0; x < width_; ++x) {
573  line[x * channels_ + d] =
574  TruncateCast<float, uint8_t>(array_smoothed[i]);
575  i += 1;
576  }
577  }
578  }
579 }
580 
581 void Bitmap::Rescale(const int new_width, const int new_height,
582  const FREE_IMAGE_FILTER filter) {
583  SetPtr(FreeImage_Rescale(data_.get(), new_width, new_height, filter));
584 }
585 
586 Bitmap Bitmap::Clone() const { return Bitmap(FreeImage_Clone(data_.get())); }
587 
589  if (IsGrey()) {
590  return Clone();
591  } else {
592  return Bitmap(FreeImage_ConvertToGreyscale(data_.get()));
593  }
594 }
595 
597  if (IsRGB()) {
598  return Clone();
599  } else {
600  return Bitmap(FreeImage_ConvertTo24Bits(data_.get()));
601  }
602 }
603 
604 void Bitmap::CloneMetadata(Bitmap* target) const {
605  CHECK_NOTNULL(target);
606  CHECK_NOTNULL(target->Data());
607  FreeImage_CloneMetadata(data_.get(), target->Data());
608 }
609 
610 bool Bitmap::ReadExifTag(const FREE_IMAGE_MDMODEL model,
611  const std::string& tag_name,
612  std::string* result) const {
613  FITAG* tag = nullptr;
614  FreeImage_GetMetadata(model, data_.get(), tag_name.c_str(), &tag);
615  if (tag == nullptr) {
616  *result = "";
617  return false;
618  } else {
619  if (tag_name == "FocalPlaneXResolution") {
620  // This tag seems to be in the wrong category.
621  *result = std::string(FreeImage_TagToString(FIMD_EXIF_INTEROP, tag));
622  } else {
623  *result = FreeImage_TagToString(model, tag);
624  }
625  return true;
626  }
627 }
628 
629 void Bitmap::SetPtr(FIBITMAP* data) {
630  if (!IsPtrSupported(data)) {
631  FreeImage_Unload(data);
632  data = FreeImage_ConvertTo24Bits(data);
633  }
634 
635  data_ = FIBitmapPtr(data, &FreeImage_Unload);
636  width_ = FreeImage_GetWidth(data);
637  height_ = FreeImage_GetHeight(data);
638  channels_ = IsPtrRGB(data) ? 3 : 1;
639 }
640 
641 bool Bitmap::IsPtrGrey(FIBITMAP* data) {
642  return FreeImage_GetColorType(data) == FIC_MINISBLACK &&
643  FreeImage_GetBPP(data) == 8;
644 }
645 
646 bool Bitmap::IsPtrRGB(FIBITMAP* data) {
647  return FreeImage_GetColorType(data) == FIC_RGB &&
648  FreeImage_GetBPP(data) == 24;
649 }
650 
651 bool Bitmap::IsPtrSupported(FIBITMAP* data) {
652  return IsPtrGrey(data) || IsPtrRGB(data);
653 }
654 
655 float JetColormap::Red(const float gray) { return Base(gray - 0.25f); }
656 
657 float JetColormap::Green(const float gray) { return Base(gray); }
658 
659 float JetColormap::Blue(const float gray) { return Base(gray + 0.25f); }
660 
661 float JetColormap::Base(const float val) {
662  if (val <= 0.125f) {
663  return 0.0f;
664  } else if (val <= 0.375f) {
665  return Interpolate(2.0f * val - 1.0f, 0.0f, -0.75f, 1.0f, -0.25f);
666  } else if (val <= 0.625f) {
667  return 1.0f;
668  } else if (val <= 0.87f) {
669  return Interpolate(2.0f * val - 1.0f, 1.0f, 0.25f, 0.0f, 0.75f);
670  } else {
671  return 0.0f;
672  }
673 }
674 
675 float JetColormap::Interpolate(const float val, const float y0, const float x0,
676  const float y1, const float x1) {
677  return (val - x0) * (y1 - y0) / (x1 - x0) + y0;
678 }
679 
680 } // 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
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
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
bool QuerySensorWidth(const std::string &make, const std::string &model, double *sensor_width)
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
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Definition: MiniVec.h:75
void StringTrim(std::string *str)
Definition: string.cc:188
void StringToLower(std::string *str)
Definition: string.cc:193
bool ExistsFile(const std::string &path)
Definition: misc.cc:100
std::string to_string(const T &n)
Definition: Common.h:20