https://github.com/baderouaich/BitmapPlusPlus
Simple and Fast single header Bitmap (BMP) C++ library
https://github.com/baderouaich/BitmapPlusPlus
bitmap bitmap-graphics bitmap-image bitmap-images bitmaps blazingly-fast bmp cpp cpp-header cpp-library cpp17 cpp20 header-only header-only-library image-manipulation single-header
Last synced: 3 months ago
JSON representation
Simple and Fast single header Bitmap (BMP) C++ library
- Host: GitHub
- URL: https://github.com/baderouaich/BitmapPlusPlus
- Owner: baderouaich
- License: mit
- Created: 2020-08-19T17:01:07.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2025-07-03T19:55:28.000Z (3 months ago)
- Last Synced: 2025-07-03T20:36:38.218Z (3 months ago)
- Topics: bitmap, bitmap-graphics, bitmap-image, bitmap-images, bitmaps, blazingly-fast, bmp, cpp, cpp-header, cpp-library, cpp17, cpp20, header-only, header-only-library, image-manipulation, single-header
- Language: CMake
- Homepage:
- Size: 1.1 MB
- Stars: 44
- Watchers: 1
- Forks: 12
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# 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](integration_tests/cpm).
An example of FetchContent integration can be found [here](integration_tests/fetchcontent).## Examples
Random Pixel Colors
```cpp
#include "BitmapPlusPlus.hpp"
#include
#includestatic bmp::Pixel random_color() {
static std::random_device seed{};
static std::default_random_engine engine{seed()};
std::uniform_int_distribution 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;
}
}
```
Draw Primitives
```cpp
#include
#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;
}
```

Mandelbrot Fractal Set
```cpp
#include "BitmapPlusPlus.hpp"
#include "color_maps.inl"
#includeint 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(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;
}
```

Julia Fractal Set
```cpp
#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((1000.0 * i) / max_iterations)];
image.set(x, y, color);
break;
}
}
}
}image.save("julia.bmp");
return EXIT_SUCCESS;
}
```

Modify The Penguin
```cpp
#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;
}
}
```


Rotate, Flip The Penguin```cpp
#include "BitmapPlusPlus.hpp"
#includeint 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;
}
}```





Chess Board
```cpp
#include
#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;
}
}
```

Draw multiple shapes using Polymorphism
```cpp
#include
#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 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;
}
}
```
## Features and bugs
If you face any problems feel free to open an issue at the [issue tracker][tracker]. If you feel the library is missing a feature, please raise a ticket on Github. Pull request are also welcome.[tracker]: https://github.com/baderouaich/BitmapPlusPlus/issues