Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,57 @@ int main(void) {
![modified-penguin](images/modified-penguin.bmp)


<br><br>
<strong>Rotate, Flip The Penguin</strong>
<br>

```cpp
#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](images/penguin.bmp)
![penguin_flipped_v](images/rotated/penguin_flipped_v.bmp)
![penguin_flipped_h](images/rotated/penguin_flipped_h.bmp)
![penguin_rotated_right](images/rotated/penguin_rotated_right.bmp)
![penguin_rotated_left](images/rotated/penguin_rotated_left.bmp)


<br><br>

<strong>Chess Board</strong>
Expand Down
38 changes: 38 additions & 0 deletions examples/rotation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#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;
}
}

Binary file added images/rotated/penguin_flipped_h.bmp
Binary file not shown.
Binary file added images/rotated/penguin_flipped_v.bmp
Binary file not shown.
Binary file added images/rotated/penguin_rotated_left.bmp
Binary file not shown.
Binary file added images/rotated/penguin_rotated_right.bmp
Binary file not shown.
71 changes: 70 additions & 1 deletion lib/include/BitmapPlusPlus.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<std::size_t>(x) + static_cast<std::size_t>(m_width) * static_cast<std::size_t>(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<std::size_t>(x) + static_cast<std::size_t>(m_width) * static_cast<std::size_t>(y);
}
/**
* Returns true if x,y coords are within boundaries
*/
Expand Down
Loading