diff --git a/README.md b/README.md
index 5a2d5db..64bee5c 100644
--- a/README.md
+++ b/README.md
@@ -236,6 +236,57 @@ int main(void) {

+
+Rotate, Flip The Penguin
+
+
+```cpp
+#include "BitmapPlusPlus.hpp"
+#include
+
+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;
+ }
+}
+
+```
+
+
+
+
+
+
+
Chess Board
diff --git a/examples/rotation.cpp b/examples/rotation.cpp
new file mode 100644
index 0000000..33f30bf
--- /dev/null
+++ b/examples/rotation.cpp
@@ -0,0 +1,38 @@
+#include "BitmapPlusPlus.hpp"
+#include
+
+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;
+ }
+}
+
diff --git a/images/rotated/penguin_flipped_h.bmp b/images/rotated/penguin_flipped_h.bmp
new file mode 100644
index 0000000..90bbf7b
Binary files /dev/null and b/images/rotated/penguin_flipped_h.bmp differ
diff --git a/images/rotated/penguin_flipped_v.bmp b/images/rotated/penguin_flipped_v.bmp
new file mode 100644
index 0000000..bf6a34d
Binary files /dev/null and b/images/rotated/penguin_flipped_v.bmp differ
diff --git a/images/rotated/penguin_rotated_left.bmp b/images/rotated/penguin_rotated_left.bmp
new file mode 100644
index 0000000..ebecc75
Binary files /dev/null and b/images/rotated/penguin_rotated_left.bmp differ
diff --git a/images/rotated/penguin_rotated_right.bmp b/images/rotated/penguin_rotated_right.bmp
new file mode 100644
index 0000000..41cdf87
Binary files /dev/null and b/images/rotated/penguin_rotated_right.bmp differ
diff --git a/lib/include/BitmapPlusPlus.hpp b/lib/include/BitmapPlusPlus.hpp
index fe1336c..fc1b662 100644
--- a/lib/include/BitmapPlusPlus.hpp
+++ b/lib/include/BitmapPlusPlus.hpp
@@ -466,6 +466,70 @@ namespace bmp {
m_pixels[IX(x, y)] = color;
}
+
+ /**
+ * Vertically flips the bitmap and returns the flipped version
+ *
+ */
+ Bitmap flip_v() {
+ Bitmap finished(m_width, m_height);
+ for (std::int32_t x = 0; x < m_width; ++x) {
+ for (std::int32_t y = 0; y < m_height; ++y) {
+ // Calculate the reverse y-index
+ finished.m_pixels[IX(x, y)] = m_pixels[IX(x, m_height - 1 - y)];
+ }
+ }
+ return finished;
+ }
+
+ /**
+ * Horizontally flips the bitmap and returns the flipped version
+ *
+ */
+ Bitmap flip_h() {
+ Bitmap finished(m_width, m_height);
+ for (std::int32_t y = 0; y < m_height; ++y) {
+ for (std::int32_t x = 0; x < m_width; ++x) {
+ // Calculate the reverse x-index
+ finished.m_pixels[IX(x, y)] = m_pixels[IX(m_width - 1 - x, y)];
+ }
+ }
+ return finished;
+ }
+
+ /**
+ * Rotates the bitmap to the right and returns the rotated version
+ *
+ */
+ Bitmap rotate_90_left() {
+ Bitmap finished(m_height, m_width); // Swap dimensions
+
+ for (std::int32_t y = 0; y < m_height; ++y) {
+ std::int32_t y_offset = y * m_width; // Precompute row start index
+ for (std::int32_t x = 0; x < m_width; ++x) {
+ // Original pixel at (x, y) moves to (y, m_width - 1 - x)
+ finished.m_pixels[(m_width - 1 - x) * m_height + y] = m_pixels[y_offset + x];
+ }
+ }
+
+ return finished;
+ }
+
+ /**
+ * Rotates the bitmap to the left and returns the rotated version
+ *
+ */
+ Bitmap rotate_90_right() {
+ Bitmap finished(m_height, m_width); // Swap dimensions
+ for (std::int32_t y = 0; y < m_height; ++y) {
+ std::int32_t y_offset = y * m_width; // Precompute row start index
+ for (std::int32_t x = 0; x < m_width; ++x) {
+ finished.m_pixels[x * m_height + (m_height - 1 - y)] = m_pixels[y_offset + x];
+ }
+ }
+
+ return finished;
+ }
/**
* Saves Bitmap pixels into a file
* @throws bmp::Exception on error
@@ -584,7 +648,12 @@ namespace bmp {
[[nodiscard]] constexpr std::size_t IX(const std::int32_t x, const std::int32_t y) const noexcept {
return static_cast(x) + static_cast(m_width) * static_cast(y);
}
-
+ /**
+ * Converts 2D x,y coords into 1D index, with changed width
+ */
+ [[nodiscard]] constexpr std::size_t IX(const std::int32_t x, const std::int32_t y, const std::int32_t width) const noexcept {
+ return static_cast(x) + static_cast(m_width) * static_cast(y);
+ }
/**
* Returns true if x,y coords are within boundaries
*/