Skip to content
Closed
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
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog

All notable changes to this project will be documented in this file.

## [0.1.0] - 2025-05-23

### Added
- New image manipulation functions:
- `InvertImageColors` / `InvertPixelColor`
- `ApplySepiaTone` / `ApplySepiaToPixel`
- `ApplyBoxBlur`
- Comprehensive unit testing framework (`tests/test_bitmap.cpp`) using basic assertions.
- Unit tests for most pixel-level functions (Greyscale, Invert, Sepia, Brightness, Contrast, Saturation, Luminance - including color-specific variants).
- Unit tests for image-level functions (`ApplyBoxBlur`, `ShrinkImage`, `RotateImageCounterClockwise`, and basic checks for others).
- This `README.md` and `CHANGELOG.md` file.

### Changed
- Refined contrast adjustment logic for secondary colors (`ChangePixelContrastMagenta`, `ChangePixelContrastYellow`, `ChangePixelContrastCyan`) to apply contrast to constituent primary channels directly.
- Improved inline code documentation (comments) in `src/bitmap.h` and `src/bitmap.cpp` for clarity and maintainability.
- Standardized clamping of pixel component values (0-255) in various functions.
- Corrected `std::min` usage in saturation and luminance functions.

### Fixed
- Corrected syntax errors in the original implementations of `ChangePixelContrastMagenta` and `ChangePixelContrastCyan`.
- Corrected variable name usage (`magenta` vs `cyan`) in `ChangePixelContrastCyan`.
- Improved GDI resource management in `ScreenShotWindow` by ensuring `DeleteDC`, `ReleaseDC`, and `DeleteObject` are called.
- Corrected a typo in `ChangePixelSaturationBlue` condition.
- Corrected a typo in the `ChangePixelBrightness` parameter name in `src/bitmap.h`.
20 changes: 13 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.10)
project(bitmap VERSION 1.0.0)

include(CTest)
Expand All @@ -22,12 +22,18 @@ FetchContent_MakeAvailable(matrix)

link_libraries(matrix)
link_libraries(bitmapfile)
add_library(bitmap STATIC src/bitmap.cpp )
link_libraries(bitmap)
add_executable(testexe main.cpp)
add_library(bitmap STATIC src/bitmap.cpp ) # Main library
link_libraries(bitmap) # Link bitmap library to subsequent targets if needed

# Executable for main.cpp (if it's a demo or separate utility)
add_executable(testexe main.cpp)
target_link_libraries(testexe PRIVATE bitmap bitmapfile matrix) # Link testexe against our libraries

# Add test executable
# It needs to compile the test source file, the bitmap source file, and the dependency's source file
add_executable(bitmap_tests tests/test_bitmap.cpp src/bitmap.cpp dependencies/bitmapfile/src/bitmap_file.cpp)
# Link bitmap_tests against the matrix library (as bitmap.cpp depends on it)
target_link_libraries(bitmap_tests PRIVATE matrix)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set( CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include (Cpack)
# Add test to CTest
add_test(NAME BitmapUnitTests COMMAND bitmap_tests)
88 changes: 88 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# C++ Bitmap Image Manipulation Library

A simple C++ library for performing various image manipulation operations on BMP (Bitmap) files.
This library currently focuses on pixel-level adjustments and basic geometric transformations.

## Features

The library supports the following image manipulation functions:

* **Color Adjustments:**
* Greyscale Conversion
* Brightness Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
* Contrast Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
* Saturation Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
* Luminance Adjustment (per R,G,B,Magenta,Yellow,Cyan channel)
* Invert Colors
* Sepia Tone
* **Effects & Filters:**
* Box Blur
* **Geometric Transformations:**
* Shrink Image (reduce size)
* Rotate Image (Clockwise and Counter-Clockwise)
* Mirror Image (horizontal flip)
* Flip Image (vertical flip)
* **Utility:**
* Screen Capture (Windows only: `ScreenShotWindow`)
* Load BMP from file
* Save BMP to file

## Dependencies

This library utilizes:
* A simple Matrix library (from `dependencies/matrix`)
* A BMP file handling library (from `dependencies/bitmapfile`)
These are included in the `dependencies` directory.

## Building the Project

The project uses CMake for building.

```bash
# Create a build directory
mkdir build
cd build

# Configure the project
cmake ..

# Build the library (if configured as a library) and executables (like main example and tests)
make
# or use your specific build system command e.g., mingw32-make

# Run tests (if configured)
ctest
# or directly run the test executable: ./bitmap_tests (or tests\bitmap_tests.exe on Windows)
```

## Basic Usage Example

```cpp
#include "src/bitmap.h" // Adjust path if necessary
#include <iostream>

int main() {
Bitmap::File myBitmap;

// Load an image
if (!myBitmap.Open("input.bmp")) {
std::cerr << "Error opening input.bmp" << std::endl;
return 1;
}

// Apply some manipulations
myBitmap = GreyscaleImage(myBitmap);
myBitmap = ChangeImageBrightness(myBitmap, 1.2f); // Increase brightness by 20%
myBitmap = ApplyBoxBlur(myBitmap, 2); // Apply box blur with radius 2

// Save the result
if (!myBitmap.SaveAs("output.bmp")) {
std::cerr << "Error saving output.bmp" << std::endl;
return 1;
}

std::cout << "Image processed and saved as output.bmp" << std::endl;
return 0;
}
```
Refer to `main.cpp` for more examples.
106 changes: 96 additions & 10 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,101 @@
#include "src/bitmap.h"
#include "src/bitmap.h" // Adjust path if necessary, assumes bitmap.h is in src/
#include <iostream> // For std::cout, std::cerr

int main()
{
Bitmap::File bitmapFile;
bitmapFile.Open("test.bmp");
bitmapFile = ShrinkImage(bitmapFile, 5);
//bitmapFile = GreyscaleImage(bitmapFile);
int main() {
Bitmap::File originalBitmap;
const char* inputFilename = "test.bmp";

bitmapFile = ChangeImageLuminanceYellow(bitmapFile, 2);
bitmapFile = ChangeImageSaturationYellow(bitmapFile, 0);
bitmapFile.SaveAs("test2.bmp");
std::cout << "Bitmap Processing Demo" << std::endl;
std::cout << "----------------------" << std::endl;
std::cout << "Attempting to load image: " << inputFilename << std::endl;

if (!originalBitmap.Open(inputFilename)) {
std::cerr << "********************************************************************************" << std::endl;
std::cerr << "Error: Could not open '" << inputFilename << "'." << std::endl;
std::cerr << "Please ensure this file exists in the same directory as the executable." << std::endl;
std::cerr << "You can copy any BMP image (e.g., from Windows, or download one) and rename it to 'test.bmp'." << std::endl;
std::cerr << "A common source of BMP files is MS Paint (save as BMP)." << std::endl;
std::cerr << "********************************************************************************" << std::endl;
return 1;
}
std::cout << "'" << inputFilename << "' loaded successfully." << std::endl << std::endl;

// --- Example 1: Invert Colors ---
std::cout << "Processing: Invert Colors..." << std::endl;
Bitmap::File invertedBitmap = InvertImageColors(originalBitmap);
if (invertedBitmap.IsValid()) {
if (invertedBitmap.SaveAs("output_inverted.bmp")) {
std::cout << "Saved: output_inverted.bmp" << std::endl;
} else {
std::cerr << "Error: Failed to save output_inverted.bmp." << std::endl;
}
} else {
std::cerr << "Error: Failed to invert colors." << std::endl;
}
std::cout << std::endl;

// --- Example 2: Apply Sepia Tone to the original ---
std::cout << "Processing: Apply Sepia Tone..." << std::endl;
Bitmap::File sepiaBitmap = ApplySepiaTone(originalBitmap);
if (sepiaBitmap.IsValid()) {
if (sepiaBitmap.SaveAs("output_sepia.bmp")) {
std::cout << "Saved: output_sepia.bmp" << std::endl;
} else {
std::cerr << "Error: Failed to save output_sepia.bmp." << std::endl;
}
} else {
std::cerr << "Error: Failed to apply sepia tone." << std::endl;
}
std::cout << std::endl;

// --- Example 3: Apply Box Blur and then change contrast ---
// We'll use a copy of the original for this chain of operations.
std::cout << "Processing: Box Blur (Radius 2) then Contrast (Factor 1.5)..." << std::endl;
Bitmap::File processedBitmap = originalBitmap; // Start with a fresh copy for multi-step processing

processedBitmap = ApplyBoxBlur(processedBitmap, 2); // Radius 2
if (!processedBitmap.IsValid()) {
std::cerr << "Error: Failed to apply box blur." << std::endl;
} else {
std::cout << "Step 1: Box blur applied." << std::endl;

processedBitmap = ChangeImageContrast(processedBitmap, 1.5f); // Increase contrast
if (!processedBitmap.IsValid()) {
std::cerr << "Error: Failed to change contrast after blur." << std::endl;
} else {
std::cout << "Step 2: Contrast increased." << std::endl;
if (processedBitmap.SaveAs("output_blurred_contrasted.bmp")) {
std::cout << "Saved: output_blurred_contrasted.bmp" << std::endl;
} else {
std::cerr << "Error: Failed to save output_blurred_contrasted.bmp." << std::endl;
}
}
}
std::cout << std::endl;

// --- Example 4: Demonstrate Shrink Image & Grayscale ---
std::cout << "Processing: Shrink Image (Factor 2) then Grayscale..." << std::endl;
Bitmap::File shrunkBitmap = originalBitmap; // Start with a fresh copy

shrunkBitmap = ShrinkImage(shrunkBitmap, 2);
if (!shrunkBitmap.IsValid()) {
std::cerr << "Error: Failed to shrink image." << std::endl;
} else {
std::cout << "Step 1: Image shrunk." << std::endl;
shrunkBitmap = GreyscaleImage(shrunkBitmap);
if(!shrunkBitmap.IsValid()){
std::cerr << "Error: Failed to apply greyscale after shrinking." << std::endl;
} else {
std::cout << "Step 2: Greyscale applied." << std::endl;
if(shrunkBitmap.SaveAs("output_shrunk_greyscale.bmp")){
std::cout << "Saved: output_shrunk_greyscale.bmp" << std::endl;
} else {
std::cerr << "Error: Failed to save output_shrunk_greyscale.bmp." << std::endl;
}
}
}
std::cout << std::endl;

std::cout << "Main example processing complete. Check for output_*.bmp files." << std::endl;
return 0;
}
Loading
Loading