{"id":29342863,"url":"https://github.com/baderouaich/BitmapPlusPlus","last_synced_at":"2025-07-08T11:08:06.214Z","repository":{"id":143670198,"uuid":"288789282","full_name":"baderouaich/BitmapPlusPlus","owner":"baderouaich","description":"Simple and Fast single header Bitmap (BMP) C++ library","archived":false,"fork":false,"pushed_at":"2025-07-03T19:55:28.000Z","size":1153,"stargazers_count":44,"open_issues_count":0,"forks_count":12,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-03T20:36:38.218Z","etag":null,"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"],"latest_commit_sha":null,"homepage":"","language":"CMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/baderouaich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-19T17:01:07.000Z","updated_at":"2025-07-01T07:22:50.000Z","dependencies_parsed_at":"2023-12-28T00:57:39.722Z","dependency_job_id":"d4abdd6d-ddcc-475a-ba66-db9dc9735ec9","html_url":"https://github.com/baderouaich/BitmapPlusPlus","commit_stats":null,"previous_names":["badereddineouaich/bitmapplusplus"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/baderouaich/BitmapPlusPlus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2FBitmapPlusPlus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2FBitmapPlusPlus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2FBitmapPlusPlus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2FBitmapPlusPlus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/baderouaich","download_url":"https://codeload.github.com/baderouaich/BitmapPlusPlus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/baderouaich%2FBitmapPlusPlus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264257674,"owners_count":23580469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["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"],"created_at":"2025-07-08T11:08:05.336Z","updated_at":"2025-07-08T11:08:06.203Z","avatar_url":"https://github.com/baderouaich.png","language":"CMake","readme":"# Bitmap Plus Plus\nSimple and Fast header only Bitmap (BMP) library\n\n## Bitmap Type Supported\n- 24 Bits Per Pixel (RGB)\n\n## Integration\n\nYou can either download the header file and use it your project directly, or you can leverage CMake for this.\nThe library can be easily integrated with FetchContent or through CPM.\u003cbr\u003e\nAn example of CPM integration can be found [here](integration_tests/cpm).\u003cbr\u003e\nAn example of FetchContent integration can be found [here](integration_tests/fetchcontent).\n\n\n## Examples\n\u003cstrong\u003eRandom Pixel Colors\u003c/strong\u003e\n\u003cbr\u003e\n```cpp\n#include \"BitmapPlusPlus.hpp\"\n#include \u003crandom\u003e\n#include \u003ciostream\u003e\n\nstatic bmp::Pixel random_color() {\n  static std::random_device seed{};\n  static std::default_random_engine engine{seed()};\n  std::uniform_int_distribution\u003cstd::int32_t\u003e dist(0, 255);\n  bmp::Pixel color{};\n  color.r = dist(engine);\n  color.g = dist(engine);\n  color.b = dist(engine);\n  return color;\n}\n\nint main(void) {\n  try {\n    // Create a 512x512 bitmap\n    bmp::Bitmap image(512, 512);\n\n    // Assign a random color to each pixel in the image\n    for (bmp::Pixel \u0026pixel: image) {\n      pixel = random_color();\n    }\n\n    // Save bitmap to new file image.bmp\n    image.save(\"image.bmp\");\n\n    // And Voila!\n    return EXIT_SUCCESS;\n  }\n  catch (const bmp::Exception \u0026e) {\n    std::cerr \u003c\u003c \"[BMP ERROR]: \" \u003c\u003c e.what() \u003c\u003c std::endl;\n    return EXIT_FAILURE;\n  }\n}\n```\n![random](images/random.bmp)\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cstrong\u003eDraw Primitives\u003c/strong\u003e\n\n```cpp\n#include \u003ciostream\u003e\n#include \"BitmapPlusPlus.hpp\"\n\nusing namespace bmp;\n\nint main() {\n  // Create a 512x240 blank image\n  Bitmap image(512, 240);\n  image.clear(Pixel(0x25292e));\n\n  /** Line **/\n  // Draw a yellow line from position (250, 50) to position (500, 50)\n  image.draw_line(250, 50, 500, 50, Yellow);\n\n  /** Rectangle **/\n  // Draw a red rectangle in position (10, 10) with size 100x100\n  image.draw_rect(10, 10, 100, 100, Red);\n  // Draw a white filled rectangle in position (120, 10) with size 100x100\n  image.fill_rect(120, 10, 100, 100, White);\n\n  /** Triangle **/\n  image.draw_triangle(60, 120, 10, 220, 120, 220, Cyan);\n  image.fill_triangle(180, 120, 130, 220, 245, 220, Magenta);\n\n  /** Circle **/\n  // Draw a non-filled Gray circle in position (300, 170) with 50 pixels radius\n  image.draw_circle(300, 170, 50, Gray);\n  // Draw a filled Lime circle in position (300, 170) with 50 pixels radius\n  image.fill_circle(420, 170, 50, Lime);\n\n  // Save bitmap\n  image.save(\"primitives.bmp\");\n\n  return EXIT_SUCCESS;\n}\n```\n![primitives](images/primitives.bmp)\n\n\u003cbr\u003e\u003cbr\u003e\n\n\n\u003cstrong\u003eMandelbrot Fractal Set\u003c/strong\u003e\n\u003cbr\u003e\n```cpp\n#include \"BitmapPlusPlus.hpp\"\n#include \"color_maps.inl\"\n#include \u003ccmath\u003e\n\nint main(void) {\n  bmp::Bitmap image(1280, 960);\n\n  double cr, ci;\n  double nextr, nexti;\n  double prevr, previ;\n  constexpr const std::uint16_t max_iterations = 3000;\n\n  for (std::int32_t y = 0; y \u003c image.height(); ++y) {\n    for (std::int32_t x = 0; x \u003c image.width(); ++x) {\n      cr = 1.5 * (2.0 * x / image.width() - 1.0) - 0.5;\n      ci = (2.0 * y / image.height() - 1.0);\n\n      nextr = nexti = 0;\n      prevr = previ = 0;\n\n      for (std::uint16_t i = 0; i \u003c max_iterations; ++i) {\n        prevr = nextr;\n        previ = nexti;\n\n        nextr = prevr * prevr - previ * previ + cr;\n        nexti = 2 * prevr * previ + ci;\n\n        if (((nextr * nextr) + (nexti * nexti)) \u003e 4) {\n          const double z = sqrt(nextr * nextr + nexti * nexti);\n\n          // https://en.wikipedia.org/wiki/Mandelbrot_set#Continuous_.28smooth.29_coloring\n          const std::uint32_t index = static_cast\u003cstd::uint32_t\u003e(1000.0 * log2(1.75 + i - log2(log2(z))) /\n                                                                 log2(max_iterations));\n\n          image.set(x, y, jet_colormap[index]);\n\n          break;\n        }\n      }\n    }\n  }\n\n  image.save(\"mandelbrot.bmp\");\n\n  return EXIT_SUCCESS;\n}\n```\n![mandelbrot](images/mandelbrot.bmp)\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cstrong\u003eJulia Fractal Set\u003c/strong\u003e\n\u003cbr\u003e\n\n```cpp\n#include \"BitmapPlusPlus.hpp\"\n#include \"color_maps.inl\"\n\nint main(void) {\n  bmp::Bitmap image(1280, 960);\n\n  constexpr const std::uint16_t max_iterations = 300;\n\n  constexpr const double cr = -0.70000;\n  constexpr const double ci = 0.27015;\n\n  double prevr, previ;\n\n  for (std::int32_t y = 0; y \u003c image.height(); ++y) {\n    for (std::int32_t x = 0; x \u003c image.width(); ++x) {\n      double nextr = 1.5 * (2.0 * x / image.width() - 1.0);\n      double nexti = (2.0 * y / image.height() - 1.0);\n\n      for (std::uint16_t i = 0; i \u003c max_iterations; ++i) {\n        prevr = nextr;\n        previ = nexti;\n\n        nextr = prevr * prevr - previ * previ + cr;\n        nexti = 2 * prevr * previ + ci;\n\n        if (((nextr * nextr) + (nexti * nexti)) \u003e 4) {\n          const bmp::Pixel color = hsv_colormap[static_cast\u003cstd::size_t\u003e((1000.0 * i) / max_iterations)];\n          image.set(x, y, color);\n          break;\n        }\n      }\n    }\n  }\n\n  image.save(\"julia.bmp\");\n\n  return EXIT_SUCCESS;\n}\n```\n![julia](images/julia.bmp)\n\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cstrong\u003eModify The Penguin\u003c/strong\u003e\n\u003cbr\u003e\n\n```cpp\n#include \"BitmapPlusPlus.hpp\"\n\nint main(void) {\n  try {\n    bmp::Bitmap image;\n\n    // Load penguin.bmp bitmap\n    image.load(\"penguin.bmp\");\n\n    // Modify loaded image (makes half of the image black)\n    for (std::int32_t y = 0; y \u003c image.height(); ++y) {\n      for (std::int32_t x = 0; x \u003c image.width() / 2; ++x) {\n        image.set(x, y, bmp::Black);\n      }\n    }\n\n    // Save\n    image.save(\"modified-penguin.bmp\");\n\n    return EXIT_SUCCESS;\n  }\n  catch (const bmp::Exception \u0026e) {\n    return EXIT_FAILURE;\n  }\n}\n```\n![penguin](images/penguin.bmp)\n![modified-penguin](images/modified-penguin.bmp)\n\n\n\u003cbr\u003e\u003cbr\u003e\n\u003cstrong\u003eRotate, Flip The Penguin\u003c/strong\u003e\n\u003cbr\u003e\n\n```cpp\n#include \"BitmapPlusPlus.hpp\"\n#include \u003ciostream\u003e\n\nint main(void) {\n    try {\n        bmp::Bitmap image;\n\n        // Load the original bitmap\n        image.load(std::filesystem::path(ROOT_DIR) / \"images\" / \"penguin.bmp\");\n\n        // Test vertical flip\n        bmp::Bitmap flipped_v = image.flip_v();\n        flipped_v.save(std::filesystem::path(ROOT_DIR) / \"images\" / \"rotated\" / \"penguin_flipped_v.bmp\");\n        std::cout \u003c\u003c \"Vertical flip saved as penguin_flipped_v.bmp\" \u003c\u003c std::endl;\n\n        // Test horizontal flip\n        bmp::Bitmap flipped_h = image.flip_h();\n        flipped_h.save(std::filesystem::path(ROOT_DIR) / \"images\" / \"rotated\" / \"penguin_flipped_h.bmp\");\n        std::cout \u003c\u003c \"Horizontal flip saved as penguin_flipped_h.bmp\" \u003c\u003c std::endl;\n\n        // Test rotate 90 degrees to the right\n        bmp::Bitmap rotated_right = image.rotate_90_right();\n        rotated_right.save(std::filesystem::path(ROOT_DIR) / \"images\" / \"rotated\" / \"penguin_rotated_right.bmp\");\n        std::cout \u003c\u003c \"Rotated 90 degrees right saved as penguin_rotated_right.bmp\" \u003c\u003c std::endl;\n\n        // Test rotate 90 degrees to the left\n        bmp::Bitmap rotated_left = image.rotate_90_left();\n        rotated_left.save(std::filesystem::path(ROOT_DIR) / \"images\" / \"rotated\" / \"penguin_rotated_left.bmp\");\n        std::cout \u003c\u003c \"Rotated 90 degrees left saved as penguin_rotated_left.bmp\" \u003c\u003c std::endl;\n\n        return EXIT_SUCCESS;\n    }\n    catch (const bmp::Exception\u0026 e) {\n        std::cerr \u003c\u003c \"Error: \" \u003c\u003c e.what() \u003c\u003c std::endl;\n        return EXIT_FAILURE;\n    }\n}\n\n```\n![penguin](images/penguin.bmp)\n![penguin_flipped_v](images/rotated/penguin_flipped_v.bmp)\n![penguin_flipped_h](images/rotated/penguin_flipped_h.bmp)\n![penguin_rotated_right](images/rotated/penguin_rotated_right.bmp)\n![penguin_rotated_left](images/rotated/penguin_rotated_left.bmp)\n\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cstrong\u003eChess Board\u003c/strong\u003e\n\u003cbr\u003e\n\n```cpp\n#include \u003ciostream\u003e\n#include \"BitmapPlusPlus.hpp\"\n\nint main() {\n  try {\n    // 8x8 chess board\n    bmp::Bitmap image(640, 640);\n    const std::size_t board_dims = 8;\n    const std::size_t rect_w = image.width() / board_dims;\n    const std::size_t rect_h = image.height() / board_dims;\n\n    // Iterate over rects\n    bool is_white = true;\n    for (std::size_t x = 0; x \u003c image.width(); x += rect_w) {\n      for (std::size_t y = 0; y \u003c image.height(); y += rect_h) {\n        bmp::Pixel color = is_white ? bmp::White : bmp::Black;\n        // Fill rect\n        image.fill_rect(x, y, rect_w, rect_h, color);\n        // Next rect in will be the opposite color\n        is_white = !is_white;\n      }\n      is_white = !is_white;\n    }\n\n    // Save bitmap to file\n    image.save(\"chess_board.bmp\");\n\n    return EXIT_SUCCESS;\n  }\n  catch (const bmp::Exception \u0026e) {\n    std::cerr \u003c\u003c \"[BMP ERROR]: \" \u003c\u003c e.what() \u003c\u003c '\\n';\n    return EXIT_FAILURE;\n  }\n}\n```\n![chess_board](images/chess_board.bmp)\n\n\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cstrong\u003eDraw multiple shapes using Polymorphism\u003c/strong\u003e\n\u003cbr\u003e\n\n```cpp\n#include \u003ciostream\u003e\n#include \"BitmapPlusPlus.hpp\"\n\nstruct Shape {\n  int x, y;\n  bmp::Pixel color;\n\n  Shape(int x, int y, bmp::Pixel color) : x(x), y(y), color(color) {}\n\n  virtual void draw(bmp::Bitmap \u0026image) = 0;\n};\n\nstruct Rectangle : Shape {\n  int width, height;\n\n  Rectangle(int x, int y, int w, int h, bmp::Pixel color) : width(w), height(h), Shape(x, y, color) {}\n\n  void draw(bmp::Bitmap \u0026image) override {\n    image.fill_rect(x, y, width, height, color);\n  }\n};\n\nstruct Triangle : Shape {\n  int x2, y2, x3, y3;\n\n  Triangle(int x1, int y1, int x2, int y2, int x3, int y3, bmp::Pixel color) : x2(x2), y2(y2), x3(x3), y3(y3),\n                                                                               Shape(x1, y1, color) {}\n\n  void draw(bmp::Bitmap \u0026image) override {\n    image.fill_triangle(x, y, x2, y2, x3, y3, color);\n  }\n};\n\nstruct Circle : Shape {\n  int radius;\n\n  Circle(int x, int y, int radius, bmp::Pixel color) : radius(radius), Shape(x, y, color) {}\n\n  void draw(bmp::Bitmap \u0026image) override {\n    image.fill_circle(x, y, radius, color);\n  }\n};\n\nint main() {\n  try {\n    bmp::Bitmap image(640, 256);\n    bmp::Pixel background_color{bmp::Silver};\n    image.clear(background_color);\n\n    std::vector\u003cShape *\u003e shapes\n      {\n        new Rectangle(20, 20, 180, 180, bmp::Pixel(0xa31d3a)),\n        new Triangle(310, 20, 230, 200, 400, 200, bmp::Pixel(0x1a5096)),\n        new Circle(500, 110, 90, bmp::Pixel(0x228035))\n      };\n\n    for (Shape *shape: shapes) {\n      shape-\u003edraw(image);\n      delete shape;\n    }\n    image.save(\"shapes.bmp\");\n\n    return EXIT_SUCCESS;\n  }\n  catch (const bmp::Exception \u0026e) {\n    std::cerr \u003c\u003c \"[BMP ERROR]: \" \u003c\u003c e.what() \u003c\u003c '\\n';\n    return EXIT_FAILURE;\n  }\n}\n```\n![shapes](images/shapes.bmp)\n\n## Features and bugs\nIf 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.\n\n[tracker]: https://github.com/baderouaich/BitmapPlusPlus/issues\n\n\n","funding_links":[],"categories":["Image Processing"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaderouaich%2FBitmapPlusPlus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbaderouaich%2FBitmapPlusPlus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbaderouaich%2FBitmapPlusPlus/lists"}