Skip to content

baderouaich/BitmapPlusPlus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bitmap Plus Plus

Simple and Fast header only Bitmap (BMP) library

Bitmap Type Supported

  • 24 Bits Per Pixel (RGB)

Integration

You can either download the header file and use it your project directly, or you can leverage CMake for this. The library can be easily integrated with FetchContent or through CPM.
An example of CPM integration can be found here.
An example of FetchContent integration can be found here.

Examples

Random Pixel Colors

#include "BitmapPlusPlus.hpp" #include <random> #include <iostream> static bmp::Pixel random_color() { static std::random_device seed{}; static std::default_random_engine engine{seed()}; std::uniform_int_distribution<std::int32_t> dist(0, 255); bmp::Pixel color{}; color.r = dist(engine); color.g = dist(engine); color.b = dist(engine); return color; } int main(void) { try { // Create a 512x512 bitmap bmp::Bitmap image(512, 512); // Assign a random color to each pixel in the image for (bmp::Pixel &pixel: image) { pixel = random_color(); } // Save bitmap to new file image.bmp image.save("image.bmp"); // And Voila! return EXIT_SUCCESS; } catch (const bmp::Exception &e) { std::cerr << "[BMP ERROR]: " << e.what() << std::endl; return EXIT_FAILURE; } }

random

Draw Primitives

#include <iostream> #include "BitmapPlusPlus.hpp" using namespace bmp; int main() { // Create a 512x240 blank image Bitmap image(512, 240); image.clear(Pixel(0x25292e)); /** Line **/ // Draw a yellow line from position (250, 50) to position (500, 50) image.draw_line(250, 50, 500, 50, Yellow); /** Rectangle **/ // Draw a red rectangle in position (10, 10) with size 100x100 image.draw_rect(10, 10, 100, 100, Red); // Draw a white filled rectangle in position (120, 10) with size 100x100 image.fill_rect(120, 10, 100, 100, White); /** Triangle **/ image.draw_triangle(60, 120, 10, 220, 120, 220, Cyan); image.fill_triangle(180, 120, 130, 220, 245, 220, Magenta); /** Circle **/ // Draw a non-filled Gray circle in position (300, 170) with 50 pixels radius image.draw_circle(300, 170, 50, Gray); // Draw a filled Lime circle in position (300, 170) with 50 pixels radius image.fill_circle(420, 170, 50, Lime); // Save bitmap image.save("primitives.bmp"); return EXIT_SUCCESS; }

primitives



Mandelbrot Fractal Set

#include "BitmapPlusPlus.hpp" #include "color_maps.inl" #include <cmath> int main(void) { bmp::Bitmap image(1280, 960); double cr, ci; double nextr, nexti; double prevr, previ; constexpr const std::uint16_t max_iterations = 3000; for (std::int32_t y = 0; y < image.height(); ++y) { for (std::int32_t x = 0; x < image.width(); ++x) { cr = 1.5 * (2.0 * x / image.width() - 1.0) - 0.5; ci = (2.0 * y / image.height() - 1.0); nextr = nexti = 0; prevr = previ = 0; for (std::uint16_t i = 0; i < max_iterations; ++i) { prevr = nextr; previ = nexti; nextr = prevr * prevr - previ * previ + cr; nexti = 2 * prevr * previ + ci; if (((nextr * nextr) + (nexti * nexti)) > 4) { const double z = sqrt(nextr * nextr + nexti * nexti); // https://en.wikipedia.org/wiki/Mandelbrot_set#Continuous_.28smooth.29_coloring const std::uint32_t index = static_cast<std::uint32_t>(1000.0 * log2(1.75 + i - log2(log2(z))) / log2(max_iterations)); image.set(x, y, jet_colormap[index]); break; } } } } image.save("mandelbrot.bmp"); return EXIT_SUCCESS; }

mandelbrot



Julia Fractal Set

#include "BitmapPlusPlus.hpp" #include "color_maps.inl" int main(void) { bmp::Bitmap image(1280, 960); constexpr const std::uint16_t max_iterations = 300; constexpr const double cr = -0.70000; constexpr const double ci = 0.27015; double prevr, previ; for (std::int32_t y = 0; y < image.height(); ++y) { for (std::int32_t x = 0; x < image.width(); ++x) { double nextr = 1.5 * (2.0 * x / image.width() - 1.0); double nexti = (2.0 * y / image.height() - 1.0); for (std::uint16_t i = 0; i < max_iterations; ++i) { prevr = nextr; previ = nexti; nextr = prevr * prevr - previ * previ + cr; nexti = 2 * prevr * previ + ci; if (((nextr * nextr) + (nexti * nexti)) > 4) { const bmp::Pixel color = hsv_colormap[static_cast<std::size_t>((1000.0 * i) / max_iterations)]; image.set(x, y, color); break; } } } } image.save("julia.bmp"); return EXIT_SUCCESS; }

julia



Modify The Penguin

#include "BitmapPlusPlus.hpp" int main(void) { try { bmp::Bitmap image; // Load penguin.bmp bitmap image.load("penguin.bmp"); // Modify loaded image (makes half of the image black) for (std::int32_t y = 0; y < image.height(); ++y) { for (std::int32_t x = 0; x < image.width() / 2; ++x) { image.set(x, y, bmp::Black); } } // Save image.save("modified-penguin.bmp"); return EXIT_SUCCESS; } catch (const bmp::Exception &e) { return EXIT_FAILURE; } }

penguin modified-penguin



Rotate, Flip The Penguin

#include "BitmapPlusPlus.hpp" #include <iostream> int main(void) { try { bmp::Bitmap image; // Load the original bitmap image.load(std::filesystem::path(ROOT_DIR) / "images" / "penguin.bmp"); // Test vertical flip bmp::Bitmap flipped_v = image.flip_v(); flipped_v.save(std::filesystem::path(ROOT_DIR) / "images" / "rotated" / "penguin_flipped_v.bmp"); std::cout << "Vertical flip saved as penguin_flipped_v.bmp" << std::endl; // Test horizontal flip bmp::Bitmap flipped_h = image.flip_h(); flipped_h.save(std::filesystem::path(ROOT_DIR) / "images" / "rotated" / "penguin_flipped_h.bmp"); std::cout << "Horizontal flip saved as penguin_flipped_h.bmp" << std::endl; // Test rotate 90 degrees to the right bmp::Bitmap rotated_right = image.rotate_90_right(); rotated_right.save(std::filesystem::path(ROOT_DIR) / "images" / "rotated" / "penguin_rotated_right.bmp"); std::cout << "Rotated 90 degrees right saved as penguin_rotated_right.bmp" << std::endl; // Test rotate 90 degrees to the left bmp::Bitmap rotated_left = image.rotate_90_left(); rotated_left.save(std::filesystem::path(ROOT_DIR) / "images" / "rotated" / "penguin_rotated_left.bmp"); std::cout << "Rotated 90 degrees left saved as penguin_rotated_left.bmp" << std::endl; return EXIT_SUCCESS; } catch (const bmp::Exception& e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } } 

penguin penguin_flipped_v penguin_flipped_h penguin_rotated_right penguin_rotated_left



Chess Board

#include <iostream> #include "BitmapPlusPlus.hpp" int main() { try { // 8x8 chess board bmp::Bitmap image(640, 640); const std::size_t board_dims = 8; const std::size_t rect_w = image.width() / board_dims; const std::size_t rect_h = image.height() / board_dims; // Iterate over rects bool is_white = true; for (std::size_t x = 0; x < image.width(); x += rect_w) { for (std::size_t y = 0; y < image.height(); y += rect_h) { bmp::Pixel color = is_white ? bmp::White : bmp::Black; // Fill rect image.fill_rect(x, y, rect_w, rect_h, color); // Next rect in will be the opposite color is_white = !is_white; } is_white = !is_white; } // Save bitmap to file image.save("chess_board.bmp"); return EXIT_SUCCESS; } catch (const bmp::Exception &e) { std::cerr << "[BMP ERROR]: " << e.what() << '\n'; return EXIT_FAILURE; } }

chess_board



Draw multiple shapes using Polymorphism

#include <iostream> #include "BitmapPlusPlus.hpp" struct Shape { int x, y; bmp::Pixel color; Shape(int x, int y, bmp::Pixel color) : x(x), y(y), color(color) {} virtual void draw(bmp::Bitmap &image) = 0; }; struct Rectangle : Shape { int width, height; Rectangle(int x, int y, int w, int h, bmp::Pixel color) : width(w), height(h), Shape(x, y, color) {} void draw(bmp::Bitmap &image) override { image.fill_rect(x, y, width, height, color); } }; struct Triangle : Shape { int x2, y2, x3, y3; Triangle(int x1, int y1, int x2, int y2, int x3, int y3, bmp::Pixel color) : x2(x2), y2(y2), x3(x3), y3(y3), Shape(x1, y1, color) {} void draw(bmp::Bitmap &image) override { image.fill_triangle(x, y, x2, y2, x3, y3, color); } }; struct Circle : Shape { int radius; Circle(int x, int y, int radius, bmp::Pixel color) : radius(radius), Shape(x, y, color) {} void draw(bmp::Bitmap &image) override { image.fill_circle(x, y, radius, color); } }; int main() { try { bmp::Bitmap image(640, 256); bmp::Pixel background_color{bmp::Silver}; image.clear(background_color); std::vector<Shape *> shapes { new Rectangle(20, 20, 180, 180, bmp::Pixel(0xa31d3a)), new Triangle(310, 20, 230, 200, 400, 200, bmp::Pixel(0x1a5096)), new Circle(500, 110, 90, bmp::Pixel(0x228035)) }; for (Shape *shape: shapes) { shape->draw(image); delete shape; } image.save("shapes.bmp"); return EXIT_SUCCESS; } catch (const bmp::Exception &e) { std::cerr << "[BMP ERROR]: " << e.what() << '\n'; return EXIT_FAILURE; } }

shapes

Features and bugs

If you face any problems feel free to open an issue at the issue tracker. If you feel the library is missing a feature, please raise a ticket on Github. Pull request are also welcome.