| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "util/bitmap.h" |
| |
|
| | #include <regex> |
| | #include <unordered_map> |
| |
|
| | #include "VLFeat/imopv.h" |
| | #include "base/camera_database.h" |
| | #include "util/logging.h" |
| | #include "util/math.h" |
| | #include "util/misc.h" |
| |
|
| | namespace colmap { |
| | namespace { |
| |
|
| | #ifdef FREEIMAGE_LIB |
| |
|
| | struct FreeImageInitializer { |
| | FreeImageInitializer() { FreeImage_Initialise(); } |
| | ~FreeImageInitializer() { FreeImage_DeInitialise(); } |
| | }; |
| |
|
| | const static auto initializer = FreeImageInitializer(); |
| |
|
| | #endif |
| |
|
| | } |
| |
|
| | Bitmap::Bitmap() |
| | : data_(nullptr, &FreeImage_Unload), width_(0), height_(0), channels_(0) {} |
| |
|
| | Bitmap::Bitmap(const Bitmap& other) : Bitmap() { |
| | if (other.data_) { |
| | SetPtr(FreeImage_Clone(other.data_.get())); |
| | } |
| | } |
| |
|
| | Bitmap::Bitmap(Bitmap&& other) : Bitmap() { |
| | data_ = std::move(other.data_); |
| | width_ = other.width_; |
| | height_ = other.height_; |
| | channels_ = other.channels_; |
| | } |
| |
|
| | Bitmap::Bitmap(FIBITMAP* data) : Bitmap() { SetPtr(data); } |
| |
|
| | Bitmap& Bitmap::operator=(const Bitmap& other) { |
| | if (other.data_) { |
| | SetPtr(FreeImage_Clone(other.data_.get())); |
| | } |
| | return *this; |
| | } |
| |
|
| | Bitmap& Bitmap::operator=(Bitmap&& other) { |
| | if (this != &other) { |
| | data_ = std::move(other.data_); |
| | width_ = other.width_; |
| | height_ = other.height_; |
| | channels_ = other.channels_; |
| | } |
| | return *this; |
| | } |
| |
|
| | bool Bitmap::Allocate(const int width, const int height, const bool as_rgb) { |
| | FIBITMAP* data = nullptr; |
| | width_ = width; |
| | height_ = height; |
| | if (as_rgb) { |
| | const int kNumBitsPerPixel = 24; |
| | data = FreeImage_Allocate(width, height, kNumBitsPerPixel); |
| | channels_ = 3; |
| | } else { |
| | const int kNumBitsPerPixel = 8; |
| | data = FreeImage_Allocate(width, height, kNumBitsPerPixel); |
| | channels_ = 1; |
| | } |
| | data_ = FIBitmapPtr(data, &FreeImage_Unload); |
| | return data != nullptr; |
| | } |
| |
|
| | void Bitmap::Deallocate() { |
| | data_.reset(); |
| | width_ = 0; |
| | height_ = 0; |
| | channels_ = 0; |
| | } |
| |
|
| | size_t Bitmap::NumBytes() const { |
| | if (data_) { |
| | return ScanWidth() * height_; |
| | } else { |
| | return 0; |
| | } |
| | } |
| |
|
| | std::vector<uint8_t> Bitmap::ConvertToRawBits() const { |
| | const unsigned int scan_width = ScanWidth(); |
| | const unsigned int bpp = BitsPerPixel(); |
| | const bool kTopDown = true; |
| | std::vector<uint8_t> raw_bits(scan_width * height_, 0); |
| | FreeImage_ConvertToRawBits(raw_bits.data(), data_.get(), scan_width, bpp, |
| | FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, |
| | FI_RGBA_BLUE_MASK, kTopDown); |
| | return raw_bits; |
| | } |
| |
|
| | std::vector<uint8_t> Bitmap::ConvertToRowMajorArray() const { |
| | std::vector<uint8_t> array(width_ * height_ * channels_); |
| | size_t i = 0; |
| | for (int y = 0; y < height_; ++y) { |
| | const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | for (int x = 0; x < width_; ++x) { |
| | for (int d = 0; d < channels_; ++d) { |
| | array[i] = line[x * channels_ + d]; |
| | i += 1; |
| | } |
| | } |
| | } |
| | return array; |
| | } |
| |
|
| | std::vector<uint8_t> Bitmap::ConvertToColMajorArray() const { |
| | std::vector<uint8_t> array(width_ * height_ * channels_); |
| | size_t i = 0; |
| | for (int d = 0; d < channels_; ++d) { |
| | for (int x = 0; x < width_; ++x) { |
| | for (int y = 0; y < height_; ++y) { |
| | const uint8_t* line = |
| | FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | array[i] = line[x * channels_ + d]; |
| | i += 1; |
| | } |
| | } |
| | } |
| | return array; |
| | } |
| |
|
| | bool Bitmap::GetPixel(const int x, const int y, |
| | BitmapColor<uint8_t>* color) const { |
| | if (x < 0 || x >= width_ || y < 0 || y >= height_) { |
| | return false; |
| | } |
| |
|
| | const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| |
|
| | if (IsGrey()) { |
| | color->r = line[x]; |
| | return true; |
| | } else if (IsRGB()) { |
| | color->r = line[3 * x + FI_RGBA_RED]; |
| | color->g = line[3 * x + FI_RGBA_GREEN]; |
| | color->b = line[3 * x + FI_RGBA_BLUE]; |
| | return true; |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool Bitmap::SetPixel(const int x, const int y, |
| | const BitmapColor<uint8_t>& color) { |
| | if (x < 0 || x >= width_ || y < 0 || y >= height_) { |
| | return false; |
| | } |
| |
|
| | uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| |
|
| | if (IsGrey()) { |
| | line[x] = color.r; |
| | return true; |
| | } else if (IsRGB()) { |
| | line[3 * x + FI_RGBA_RED] = color.r; |
| | line[3 * x + FI_RGBA_GREEN] = color.g; |
| | line[3 * x + FI_RGBA_BLUE] = color.b; |
| | return true; |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | const uint8_t* Bitmap::GetScanline(const int y) const { |
| | CHECK_GE(y, 0); |
| | CHECK_LT(y, height_); |
| | return FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | } |
| |
|
| | void Bitmap::Fill(const BitmapColor<uint8_t>& color) { |
| | for (int y = 0; y < height_; ++y) { |
| | uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | for (int x = 0; x < width_; ++x) { |
| | if (IsGrey()) { |
| | line[x] = color.r; |
| | } else if (IsRGB()) { |
| | line[3 * x + FI_RGBA_RED] = color.r; |
| | line[3 * x + FI_RGBA_GREEN] = color.g; |
| | line[3 * x + FI_RGBA_BLUE] = color.b; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | bool Bitmap::InterpolateNearestNeighbor(const double x, const double y, |
| | BitmapColor<uint8_t>* color) const { |
| | const int xx = static_cast<int>(std::round(x)); |
| | const int yy = static_cast<int>(std::round(y)); |
| | return GetPixel(xx, yy, color); |
| | } |
| |
|
| | bool Bitmap::InterpolateBilinear(const double x, const double y, |
| | BitmapColor<float>* color) const { |
| | |
| | const double inv_y = height_ - 1 - y; |
| |
|
| | const int x0 = static_cast<int>(std::floor(x)); |
| | const int x1 = x0 + 1; |
| | const int y0 = static_cast<int>(std::floor(inv_y)); |
| | const int y1 = y0 + 1; |
| |
|
| | if (x0 < 0 || x1 >= width_ || y0 < 0 || y1 >= height_) { |
| | return false; |
| | } |
| |
|
| | const double dx = x - x0; |
| | const double dy = inv_y - y0; |
| | const double dx_1 = 1 - dx; |
| | const double dy_1 = 1 - dy; |
| |
|
| | const uint8_t* line0 = FreeImage_GetScanLine(data_.get(), y0); |
| | const uint8_t* line1 = FreeImage_GetScanLine(data_.get(), y1); |
| |
|
| | if (IsGrey()) { |
| | |
| | const double v0 = dx_1 * line0[x0] + dx * line0[x1]; |
| |
|
| | |
| | const double v1 = dx_1 * line1[x0] + dx * line1[x1]; |
| |
|
| | |
| | color->r = dy_1 * v0 + dy * v1; |
| | return true; |
| | } else if (IsRGB()) { |
| | const uint8_t* p00 = &line0[3 * x0]; |
| | const uint8_t* p01 = &line0[3 * x1]; |
| | const uint8_t* p10 = &line1[3 * x0]; |
| | const uint8_t* p11 = &line1[3 * x1]; |
| |
|
| | |
| | const double v0_r = dx_1 * p00[FI_RGBA_RED] + dx * p01[FI_RGBA_RED]; |
| | const double v0_g = dx_1 * p00[FI_RGBA_GREEN] + dx * p01[FI_RGBA_GREEN]; |
| | const double v0_b = dx_1 * p00[FI_RGBA_BLUE] + dx * p01[FI_RGBA_BLUE]; |
| |
|
| | |
| | const double v1_r = dx_1 * p10[FI_RGBA_RED] + dx * p11[FI_RGBA_RED]; |
| | const double v1_g = dx_1 * p10[FI_RGBA_GREEN] + dx * p11[FI_RGBA_GREEN]; |
| | const double v1_b = dx_1 * p10[FI_RGBA_BLUE] + dx * p11[FI_RGBA_BLUE]; |
| |
|
| | |
| | color->r = dy_1 * v0_r + dy * v1_r; |
| | color->g = dy_1 * v0_g + dy * v1_g; |
| | color->b = dy_1 * v0_b + dy * v1_b; |
| | return true; |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool Bitmap::ExifCameraModel(std::string* camera_model) const { |
| | |
| | std::string make_str; |
| | std::string model_str; |
| | std::string focal_length; |
| | *camera_model = ""; |
| | if (ReadExifTag(FIMD_EXIF_MAIN, "Make", &make_str)) { |
| | *camera_model += (make_str + "-"); |
| | } else { |
| | *camera_model = ""; |
| | return false; |
| | } |
| | if (ReadExifTag(FIMD_EXIF_MAIN, "Model", &model_str)) { |
| | *camera_model += (model_str + "-"); |
| | } else { |
| | *camera_model = ""; |
| | return false; |
| | } |
| | if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLengthIn35mmFilm", &focal_length)) { |
| | *camera_model += (focal_length + "-"); |
| | } else if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLength", &focal_length)) { |
| | *camera_model += (focal_length + "-"); |
| | } else { |
| | *camera_model = ""; |
| | return false; |
| | } |
| | *camera_model += (std::to_string(width_) + "x" + std::to_string(height_)); |
| | return true; |
| | } |
| |
|
| | bool Bitmap::ExifFocalLength(double* focal_length) const { |
| | const double max_size = std::max(width_, height_); |
| |
|
| | |
| | |
| | |
| |
|
| | std::string focal_length_35mm_str; |
| | if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLengthIn35mmFilm", |
| | &focal_length_35mm_str)) { |
| | const std::regex regex(".*?([0-9.]+).*?mm.*?"); |
| | std::cmatch result; |
| | if (std::regex_search(focal_length_35mm_str.c_str(), result, regex)) { |
| | const double focal_length_35 = std::stold(result[1]); |
| | if (focal_length_35 > 0) { |
| | *focal_length = focal_length_35 / 35.0 * max_size; |
| | return true; |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | std::string focal_length_str; |
| | if (ReadExifTag(FIMD_EXIF_EXIF, "FocalLength", &focal_length_str)) { |
| | std::regex regex(".*?([0-9.]+).*?mm"); |
| | std::cmatch result; |
| | if (std::regex_search(focal_length_str.c_str(), result, regex)) { |
| | const double focal_length_mm = std::stold(result[1]); |
| |
|
| | |
| | std::string make_str; |
| | std::string model_str; |
| | if (ReadExifTag(FIMD_EXIF_MAIN, "Make", &make_str) && |
| | ReadExifTag(FIMD_EXIF_MAIN, "Model", &model_str)) { |
| | CameraDatabase database; |
| | double sensor_width; |
| | if (database.QuerySensorWidth(make_str, model_str, &sensor_width)) { |
| | *focal_length = focal_length_mm / sensor_width * max_size; |
| | return true; |
| | } |
| | } |
| |
|
| | |
| | std::string pixel_x_dim_str; |
| | std::string x_res_str; |
| | std::string res_unit_str; |
| | if (ReadExifTag(FIMD_EXIF_EXIF, "PixelXDimension", &pixel_x_dim_str) && |
| | ReadExifTag(FIMD_EXIF_EXIF, "FocalPlaneXResolution", &x_res_str) && |
| | ReadExifTag(FIMD_EXIF_EXIF, "FocalPlaneResolutionUnit", |
| | &res_unit_str)) { |
| | regex = std::regex(".*?([0-9.]+).*?"); |
| | if (std::regex_search(pixel_x_dim_str.c_str(), result, regex)) { |
| | const double pixel_x_dim = std::stold(result[1]); |
| | regex = std::regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?"); |
| | if (std::regex_search(x_res_str.c_str(), result, regex)) { |
| | const double x_res = std::stold(result[2]) / std::stold(result[1]); |
| | |
| | |
| | const double ccd_width = x_res * pixel_x_dim; |
| | if (ccd_width > 0 && focal_length_mm > 0) { |
| | if (res_unit_str == "cm") { |
| | *focal_length = focal_length_mm / (ccd_width * 10.0) * max_size; |
| | return true; |
| | } else if (res_unit_str == "inches") { |
| | *focal_length = focal_length_mm / (ccd_width * 25.4) * max_size; |
| | return true; |
| | } |
| | } |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | return false; |
| | } |
| |
|
| | bool Bitmap::ExifLatitude(double* latitude) const { |
| | std::string str; |
| | double sign = 1.0; |
| | if (ReadExifTag(FIMD_EXIF_GPS, "GPSLatitudeRef", &str)) { |
| | StringTrim(&str); |
| | StringToLower(&str); |
| | if (!str.empty() && str[0] == 's') { |
| | sign = -1.0; |
| | } |
| | } |
| | if (ReadExifTag(FIMD_EXIF_GPS, "GPSLatitude", &str)) { |
| | const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?"); |
| | std::cmatch result; |
| | if (std::regex_search(str.c_str(), result, regex)) { |
| | const double hours = std::stold(result[1]); |
| | const double minutes = std::stold(result[2]); |
| | const double seconds = std::stold(result[3]); |
| | double value = hours + minutes / 60.0 + seconds / 3600.0; |
| | if (value > 0 && sign < 0) { |
| | value *= sign; |
| | } |
| | *latitude = value; |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | bool Bitmap::ExifLongitude(double* longitude) const { |
| | std::string str; |
| | double sign = 1.0; |
| | if (ReadExifTag(FIMD_EXIF_GPS, "GPSLongitudeRef", &str)) { |
| | StringTrim(&str); |
| | StringToLower(&str); |
| | if (!str.empty() && str[0] == 'w') { |
| | sign = -1.0; |
| | } |
| | } |
| | if (ReadExifTag(FIMD_EXIF_GPS, "GPSLongitude", &str)) { |
| | const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?"); |
| | std::cmatch result; |
| | if (std::regex_search(str.c_str(), result, regex)) { |
| | const double hours = std::stold(result[1]); |
| | const double minutes = std::stold(result[2]); |
| | const double seconds = std::stold(result[3]); |
| | double value = hours + minutes / 60.0 + seconds / 3600.0; |
| | if (value > 0 && sign < 0) { |
| | value *= sign; |
| | } |
| | *longitude = value; |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | bool Bitmap::ExifAltitude(double* altitude) const { |
| | std::string str; |
| | if (ReadExifTag(FIMD_EXIF_GPS, "GPSAltitude", &str)) { |
| | const std::regex regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?"); |
| | std::cmatch result; |
| | if (std::regex_search(str.c_str(), result, regex)) { |
| | *altitude = std::stold(result[1]) / std::stold(result[2]); |
| | return true; |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | bool Bitmap::Read(const std::string& path, const bool as_rgb) { |
| | if (!ExistsFile(path)) { |
| | return false; |
| | } |
| |
|
| | const FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path.c_str(), 0); |
| |
|
| | if (format == FIF_UNKNOWN) { |
| | return false; |
| | } |
| |
|
| | FIBITMAP* fi_bitmap = FreeImage_Load(format, path.c_str()); |
| | if (fi_bitmap == nullptr) { |
| | return false; |
| | } |
| |
|
| | data_ = FIBitmapPtr(fi_bitmap, &FreeImage_Unload); |
| |
|
| | if (!IsPtrRGB(data_.get()) && as_rgb) { |
| | FIBITMAP* converted_bitmap = FreeImage_ConvertTo24Bits(fi_bitmap); |
| | data_ = FIBitmapPtr(converted_bitmap, &FreeImage_Unload); |
| | } else if (!IsPtrGrey(data_.get()) && !as_rgb) { |
| | FIBITMAP* converted_bitmap = FreeImage_ConvertToGreyscale(fi_bitmap); |
| | data_ = FIBitmapPtr(converted_bitmap, &FreeImage_Unload); |
| | } |
| |
|
| | if (!IsPtrSupported(data_.get())) { |
| | data_.reset(); |
| | return false; |
| | } |
| |
|
| | width_ = FreeImage_GetWidth(data_.get()); |
| | height_ = FreeImage_GetHeight(data_.get()); |
| | channels_ = as_rgb ? 3 : 1; |
| |
|
| | return true; |
| | } |
| |
|
| | bool Bitmap::Write(const std::string& path, const FREE_IMAGE_FORMAT format, |
| | const int flags) const { |
| | FREE_IMAGE_FORMAT save_format; |
| | if (format == FIF_UNKNOWN) { |
| | save_format = FreeImage_GetFIFFromFilename(path.c_str()); |
| | if (save_format == FIF_UNKNOWN) { |
| | |
| | save_format = FIF_PNG; |
| | } |
| | } else { |
| | save_format = format; |
| | } |
| |
|
| | int save_flags = flags; |
| | if (save_format == FIF_JPEG && flags == 0) { |
| | |
| | save_flags = JPEG_QUALITYSUPERB; |
| | } |
| |
|
| | bool success = false; |
| | if (save_flags == 0) { |
| | success = FreeImage_Save(save_format, data_.get(), path.c_str()); |
| | } else { |
| | success = |
| | FreeImage_Save(save_format, data_.get(), path.c_str(), save_flags); |
| | } |
| |
|
| | return success; |
| | } |
| |
|
| | void Bitmap::Smooth(const float sigma_x, const float sigma_y) { |
| | std::vector<float> array(width_ * height_); |
| | std::vector<float> array_smoothed(width_ * height_); |
| | for (int d = 0; d < channels_; ++d) { |
| | size_t i = 0; |
| | for (int y = 0; y < height_; ++y) { |
| | const uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | for (int x = 0; x < width_; ++x) { |
| | array[i] = line[x * channels_ + d]; |
| | i += 1; |
| | } |
| | } |
| |
|
| | vl_imsmooth_f(array_smoothed.data(), width_, array.data(), width_, height_, |
| | width_, sigma_x, sigma_y); |
| |
|
| | i = 0; |
| | for (int y = 0; y < height_; ++y) { |
| | uint8_t* line = FreeImage_GetScanLine(data_.get(), height_ - 1 - y); |
| | for (int x = 0; x < width_; ++x) { |
| | line[x * channels_ + d] = |
| | TruncateCast<float, uint8_t>(array_smoothed[i]); |
| | i += 1; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | void Bitmap::Rescale(const int new_width, const int new_height, |
| | const FREE_IMAGE_FILTER filter) { |
| | SetPtr(FreeImage_Rescale(data_.get(), new_width, new_height, filter)); |
| | } |
| |
|
| | Bitmap Bitmap::Clone() const { return Bitmap(FreeImage_Clone(data_.get())); } |
| |
|
| | Bitmap Bitmap::CloneAsGrey() const { |
| | if (IsGrey()) { |
| | return Clone(); |
| | } else { |
| | return Bitmap(FreeImage_ConvertToGreyscale(data_.get())); |
| | } |
| | } |
| |
|
| | Bitmap Bitmap::CloneAsRGB() const { |
| | if (IsRGB()) { |
| | return Clone(); |
| | } else { |
| | return Bitmap(FreeImage_ConvertTo24Bits(data_.get())); |
| | } |
| | } |
| |
|
| | void Bitmap::CloneMetadata(Bitmap* target) const { |
| | CHECK_NOTNULL(target); |
| | CHECK_NOTNULL(target->Data()); |
| | FreeImage_CloneMetadata(data_.get(), target->Data()); |
| | } |
| |
|
| | bool Bitmap::ReadExifTag(const FREE_IMAGE_MDMODEL model, |
| | const std::string& tag_name, |
| | std::string* result) const { |
| | FITAG* tag = nullptr; |
| | FreeImage_GetMetadata(model, data_.get(), tag_name.c_str(), &tag); |
| | if (tag == nullptr) { |
| | *result = ""; |
| | return false; |
| | } else { |
| | if (tag_name == "FocalPlaneXResolution") { |
| | |
| | *result = std::string(FreeImage_TagToString(FIMD_EXIF_INTEROP, tag)); |
| | } else { |
| | *result = FreeImage_TagToString(model, tag); |
| | } |
| | return true; |
| | } |
| | } |
| |
|
| | void Bitmap::SetPtr(FIBITMAP* data) { |
| | if (!IsPtrSupported(data)) { |
| | FIBITMAP* temp_data = data; |
| | data = FreeImage_ConvertTo24Bits(temp_data); |
| | FreeImage_Unload(temp_data); |
| | } |
| |
|
| | data_ = FIBitmapPtr(data, &FreeImage_Unload); |
| | width_ = FreeImage_GetWidth(data); |
| | height_ = FreeImage_GetHeight(data); |
| | channels_ = IsPtrRGB(data) ? 3 : 1; |
| | } |
| |
|
| | bool Bitmap::IsPtrGrey(FIBITMAP* data) { |
| | return FreeImage_GetColorType(data) == FIC_MINISBLACK && |
| | FreeImage_GetBPP(data) == 8; |
| | } |
| |
|
| | bool Bitmap::IsPtrRGB(FIBITMAP* data) { |
| | return FreeImage_GetColorType(data) == FIC_RGB && |
| | FreeImage_GetBPP(data) == 24; |
| | } |
| |
|
| | bool Bitmap::IsPtrSupported(FIBITMAP* data) { |
| | return IsPtrGrey(data) || IsPtrRGB(data); |
| | } |
| |
|
| | float JetColormap::Red(const float gray) { return Base(gray - 0.25f); } |
| |
|
| | float JetColormap::Green(const float gray) { return Base(gray); } |
| |
|
| | float JetColormap::Blue(const float gray) { return Base(gray + 0.25f); } |
| |
|
| | float JetColormap::Base(const float val) { |
| | if (val <= 0.125f) { |
| | return 0.0f; |
| | } else if (val <= 0.375f) { |
| | return Interpolate(2.0f * val - 1.0f, 0.0f, -0.75f, 1.0f, -0.25f); |
| | } else if (val <= 0.625f) { |
| | return 1.0f; |
| | } else if (val <= 0.87f) { |
| | return Interpolate(2.0f * val - 1.0f, 1.0f, 0.25f, 0.0f, 0.75f); |
| | } else { |
| | return 0.0f; |
| | } |
| | } |
| |
|
| | float JetColormap::Interpolate(const float val, const float y0, const float x0, |
| | const float y1, const float x1) { |
| | return (val - x0) * (y1 - y0) / (x1 - x0) + y0; |
| | } |
| |
|
| | } |
| |
|