#pragma once #include #include #include #include "../architecture/Render_Lease.h" #include "../base/Color.h" #include "../base/Geometry.h" #include "../plottable/Interpolation_p.h" #include "../render/Canvas.h" #include "../render/Image.h" #include "Color_Map.h" #include "Raster_Image.h" namespace renderive { class Raster_Image_Buffer { public: [[nodiscard]] int width() const { return image_data.width(); } [[nodiscard]] int height() const { return image_data.height(); } [[nodiscard]] bool is_null() const { return image_data.empty(); } [[nodiscard]] const Image& image() const { return image_data; } Image& image() { return image_data; } void set_image(Image image) { image_data = std::move(image); } void resize(int width, int height) { image_data.resize(width, height); } void fill(Color color) { image_data.fill(color); } Pixel* row(int row) { return image_data.row(row); } void write_color_mapped_row(int row_index, const double* values, int first_col, int last_col, double value_start_coord, double rate, const Color_Map& color_map, Color background_color) { Pixel* line = row(row_index); Pixel bg = premultiply(background_color); std::fill(line, line + image_data.width(), bg); for (int col = first_col; col <= last_col; ++col) { int color_offset = static_cast((values[col] - value_start_coord) * rate); line[col] = color_map.at_offset(color_offset); } } void write_normalized_grid(const double* values, int width, int height, const Color_Map& color_map) { for (int row_index = 0; row_index < height; ++row_index) { Pixel* line = row(row_index); const double* source = values + row_index * width; for (int col = 0; col < width; ++col) { line[col] = color_map.at_normalized(source[col]); } } } void draw(Canvas& canvas, const RectF& target_rect, Image_Interpolation_Mode mode = Image_Interpolation_Mode::Nearest) const { draw(canvas, target_rect, RectF{0.0, 0.0, static_cast(image_data.width()), static_cast(image_data.height())}, mode); } void draw(Canvas& canvas, const RectF& target_rect, const RectF& source_rect, Image_Interpolation_Mode mode) const { if (image_data.empty()) return; canvas.save(); if (mode == Image_Interpolation_Mode::Bicubic) { Size target_size{std::max(1, static_cast(std::ceil(std::abs(target_rect.width)))), std::max(1, static_cast(std::ceil(std::abs(target_rect.height))))}; Image scaled_image = bicubic_scale(image_data, source_rect, target_size); canvas.draw_image(target_rect, scaled_image); } else { canvas.set_image_interpolation(mode); canvas.draw_image(target_rect, image_data, source_rect); } canvas.restore(); } private: Image image_data; }; } // namespace renderive