Skip to content

Commit 48eb80b

Browse files
authored
Merge pull request #12 from JacobBorden/docs-update-20231120
Docs: Comprehensive project documentation update
2 parents 94455b4 + 58428fd commit 48eb80b

3 files changed

Lines changed: 255 additions & 154 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ All notable changes to this project will be documented in this file.
2020

2121
### Changed
2222
- The `bitmap` library now exposes the `BmpTool` API via `include/bitmap.hpp` for simplified bitmap operations.
23+
- **Documentation**:
24+
- Reviewed and significantly updated `README.md` for accuracy regarding features, API examples (old vs. new), build instructions, and added "Code Documentation" and "Contributing" sections.
25+
- Reviewed and extensively updated `src/matrix/Documentation/Matrix.MD` to align with the current `src/matrix/matrix.h` implementation, including documenting move semantics, new functions, and correcting outdated information.
2326

2427
## [0.2.0] - 2024-07-27
2528

README.md

Lines changed: 138 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ The library supports the following image manipulation functions:
99

1010
* **Color Adjustments:**
1111
* Greyscale Conversion
12-
* Brightness Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
13-
* Contrast Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
12+
* Brightness Adjustment (Overall)
13+
* Contrast Adjustment (Overall)
1414
* Saturation Adjustment (Overall and per R,G,B,Magenta,Yellow,Cyan channel)
1515
* Luminance Adjustment (per R,G,B,Magenta,Yellow,Cyan channel)
1616
* Invert Colors
@@ -19,125 +19,149 @@ The library supports the following image manipulation functions:
1919
* Box Blur
2020
* **Geometric Transformations:**
2121
* Shrink Image (reduce size)
22-
* Rotate Image (Clockwise and Counter-Clockwise)
22+
* Rotate Image (90 degrees Clockwise and Counter-Clockwise)
2323
* Mirror Image (horizontal flip)
2424
* Flip Image (vertical flip)
25-
* **Utility:**
25+
* **Utility (Old API - `src/bitmap/bitmap.h`):**
2626
* Screen Capture (Windows only: `ScreenShotWindow`)
27-
* Load BMP from file
28-
* Save BMP to file
27+
* Load BMP from file (`Bitmap::File::Open`)
28+
* Save BMP to file (`Bitmap::File::SaveAs`)
29+
* **Utility (New API - `include/bitmap.hpp`):**
30+
* Load BMP from memory (`BmpTool::load`)
31+
* Save BMP to memory (`BmpTool::save`)
32+
33+
Note: The old API (`src/bitmap/bitmap.h` and `src/bitmapfile/bitmap_file.h`) provides file-based loading/saving and additional pixel-level operations. The new `BmpTool` API (`include/bitmap.hpp`) focuses on memory span-based operations and provides a more modern interface for whole-image manipulations.
2934

3035
## Dependencies
3136

32-
This library utilizes:
33-
* A simple Matrix library (from `src/matrix`)
34-
* A BMP file handling library (from `src/bitmapfile`)
35-
These are now part of the main source tree under the `src/` directory.
37+
This library has internal dependencies:
38+
* A simple Matrix library (from `src/matrix`) used by the old API.
39+
* BMP file handling structures (from `src/bitmapfile`) used by both APIs.
40+
These are part of the main source tree under the `src/` directory. No external libraries are required for core functionality.
3641

3742
## Core Modules
38-
* **Bitmap Library (`src/bitmap`)**: Provides core image processing functions.
39-
* **Bitmap File Handler (`src/bitmapfile`)**: Handles loading and saving of BMP files.
40-
* **Matrix Library (`src/matrix`)**: A generic matrix manipulation library used by the bitmap processing functions.
43+
* **New Bitmap API (`include/bitmap.hpp`)**: Provides the `BmpTool` namespace for modern, span-based image processing. This is the recommended API for new projects.
44+
* **Old Bitmap Library (`src/bitmap`)**: Provides older image processing functions using the `Bitmap::File` class.
45+
* **Bitmap File Handler (`src/bitmapfile`)**: Contains structures and functions for handling BMP file headers and low-level data, used by both APIs.
46+
* **Matrix Library (`src/matrix`)**: A generic matrix manipulation library, primarily used by the old bitmap library.
4147

4248
## New Span-Based API (`BmpTool`)
4349

44-
For more direct memory-based operations and a stable interface, the `BmpTool` API is provided.
50+
For more direct memory-based operations and a stable interface, the `BmpTool` API is provided. This API operates on image data in memory buffers (`std::span`).
4551

4652
The main header for this API is `include/bitmap.hpp`.
4753

4854
Core components include:
49-
* `BmpTool::Bitmap`: A struct holding image dimensions (width, height, bits-per-pixel) and a `std::vector<uint8_t>` for RGBA pixel data.
50-
* `BmpTool::load()`: Loads BMP data from a `std::span<const uint8_t>` into a `BmpTool::Bitmap`.
51-
* `BmpTool::save()`: Saves a `BmpTool::Bitmap` to a `std::span<uint8_t>`.
52-
* `BmpTool::Result<T, E>`: Used for functions that can return a value or an error, with `BmpTool::BitmapError` providing specific error codes.
55+
* `BmpTool::Bitmap`: A struct holding image dimensions (width, height, bits-per-pixel) and a `std::vector<uint8_t>` for pixel data (typically RGBA).
56+
* `BmpTool::load(std::span<const uint8_t> bmp_data)`: Loads BMP data from a memory span into a `BmpTool::Bitmap`.
57+
* `BmpTool::save(const BmpTool::Bitmap& bitmap, std::span<uint8_t> out_bmp_buffer)`: Saves a `BmpTool::Bitmap` to a memory span. The size of the output BMP data can be determined from the `bfSize` field of the `BITMAPFILEHEADER` written to the beginning of the `out_bmp_buffer`.
58+
* `BmpTool::Result<T, BmpTool::BitmapError>`: Used by functions to return either a value `T` or a `BmpTool::BitmapError` enum, indicating the outcome of the operation. For functions that don't return a value on success (like `save`), `BmpTool::Result<void, BmpTool::BitmapError>` is used (internally represented as `Result<Success, BitmapError>`).
59+
60+
All image manipulation functions in the `BmpTool` namespace (e.g., `BmpTool::greyscale`, `BmpTool::shrink`) take a `const BmpTool::Bitmap&` as input and return a `BmpTool::Result<BmpTool::Bitmap, BmpTool::BitmapError>`.
5361

5462
### `BmpTool` API Usage Example
5563

64+
The following example demonstrates loading a BMP file into a buffer, processing it using `BmpTool`, and saving the result. This example is a simplified version of `main.cpp`.
65+
5666
```cpp
57-
#include "include/bitmap.hpp" // Public API
67+
#include "include/bitmap.hpp" // Public API for BmpTool
68+
#include "src/bitmapfile/bitmap_file.h" // For BITMAPFILEHEADER definition (to get actual size)
69+
5870
#include <vector>
59-
#include <fstream> // For reading/writing files to/from buffer for example
60-
#include <iostream>
71+
#include <fstream> // For std::ifstream, std::ofstream
72+
#include <iostream> // For std::cerr, std::cout
73+
#include <cstring> // For std::memcpy if reading header manually
6174

6275
// Helper to read a file into a vector
6376
std::vector<uint8_t> read_file_to_buffer(const std::string& filepath) {
6477
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
65-
if (!file) return {};
78+
if (!file) {
79+
std::cerr << "Failed to open " << filepath << std::endl;
80+
return {};
81+
}
6682
std::streamsize size = file.tellg();
6783
file.seekg(0, std::ios::beg);
68-
std::vector<uint8_t> buffer(size);
84+
std::vector<uint8_t> buffer(static_cast<size_t>(size));
6985
if (file.read(reinterpret_cast<char*>(buffer.data()), size)) {
7086
return buffer;
7187
}
88+
std::cerr << "Failed to read " << filepath << std::endl;
7289
return {};
7390
}
7491

75-
// Helper to write a buffer to a file
92+
// Helper to write a buffer of a specific size to a file
7693
bool write_buffer_to_file(const std::string& filepath, const std::vector<uint8_t>& buffer, size_t actual_size) {
7794
std::ofstream file(filepath, std::ios::binary);
78-
if (!file) return false;
95+
if (!file) {
96+
std::cerr << "Failed to open " << filepath << " for writing." << std::endl;
97+
return false;
98+
}
7999
file.write(reinterpret_cast<const char*>(buffer.data()), actual_size);
80100
return file.good();
81101
}
82102

83103
int main() {
84-
// Load an existing BMP into a buffer
85-
std::vector<uint8_t> input_bmp_data = read_file_to_buffer("input.bmp");
104+
const std::string input_filename = "input.bmp";
105+
const std::string output_filename = "output_processed.bmp";
106+
107+
// 1. Load an existing BMP into a buffer
108+
std::vector<uint8_t> input_bmp_data = read_file_to_buffer(input_filename);
86109
if (input_bmp_data.empty()) {
87-
std::cerr << "Failed to read input.bmp into buffer." << std::endl;
88110
return 1;
89111
}
90112

91-
// Use BmpTool::load
113+
// 2. Use BmpTool::load to parse the buffer
92114
BmpTool::Result<BmpTool::Bitmap, BmpTool::BitmapError> load_result = BmpTool::load(input_bmp_data);
93115

94116
if (load_result.isError()) {
95117
std::cerr << "BmpTool::load failed: " << static_cast<int>(load_result.error()) << std::endl;
96118
return 1;
97119
}
98120
BmpTool::Bitmap my_bitmap = load_result.value();
99-
std::cout << "Loaded input.bmp into BmpTool::Bitmap: "
121+
std::cout << "Loaded '" << input_filename << "': "
100122
<< my_bitmap.w << "x" << my_bitmap.h << " @ " << my_bitmap.bpp << "bpp" << std::endl;
101123

102-
// (Perform some manipulation on my_bitmap.data if desired)
103-
// For example, invert the red channel for all pixels:
104-
// for (size_t i = 0; i < my_bitmap.data.size(); i += 4) {
105-
// my_bitmap.data[i] = 255 - my_bitmap.data[i]; // Invert Red
106-
// }
124+
// 3. Perform some manipulation (e.g., greyscale)
125+
BmpTool::Result<BmpTool::Bitmap, BmpTool::BitmapError> greyscale_result = BmpTool::greyscale(my_bitmap);
126+
if(greyscale_result.isError()){
127+
std::cerr << "BmpTool::greyscale failed: " << static_cast<int>(greyscale_result.error()) << std::endl;
128+
return 1;
129+
}
130+
my_bitmap = greyscale_result.value(); // Update bitmap with processed one
131+
std::cout << "Applied greyscale." << std::endl;
107132

108-
// Prepare a buffer for saving
109-
// Estimate required size: headers (54) + data (W*H*4)
110-
size_t estimated_output_size = 54 + my_bitmap.w * my_bitmap.h * 4;
111-
std::vector<uint8_t> output_bmp_buffer(estimated_output_size);
133+
// 4. Prepare a buffer for saving. It must be large enough.
134+
// Max possible size: BMP headers (54 bytes) + data (Width * Height * 4 bytes/pixel for 32bpp RGBA)
135+
size_t max_output_size = 54 + my_bitmap.w * my_bitmap.h * 4;
136+
std::vector<uint8_t> output_bmp_buffer(max_output_size);
112137

113-
// Use BmpTool::save
138+
// 5. Use BmpTool::save
114139
BmpTool::Result<void, BmpTool::BitmapError> save_result = BmpTool::save(my_bitmap, output_bmp_buffer);
115140

116-
if (save_result.isError()) { // For Result<void,E>, isError() or checking error() != E::Ok
141+
if (save_result.isError()) {
117142
std::cerr << "BmpTool::save failed: " << static_cast<int>(save_result.error()) << std::endl;
118143
return 1;
119144
}
120-
std::cout << "BmpTool::Bitmap saved to buffer." << std::endl;
121-
122-
// To get the actual size of the BMP written to the buffer (needed for writing to file):
123-
// One way is to read bfSize from the header in output_bmp_buffer
124-
// For example:
125-
// #include "src/bitmapfile/bitmap_file.h" // For BITMAPFILEHEADER definition
126-
// BITMAPFILEHEADER* fh = reinterpret_cast<BITMAPFILEHEADER*>(output_bmp_buffer.data());
127-
// size_t actual_written_size = fh->bfSize;
128-
// This requires including the BITMAPFILEHEADER definition.
129-
// The save function itself doesn't return it, so this is a known aspect of the API.
130-
// For this example, we'll use estimated_output_size, but actual_written_size is more robust.
131-
// A more robust approach would be to parse bfSize or ensure save guarantees fitting within the span and updating its size.
132-
// For this example, we assume the buffer is large enough and we write what's estimated.
133-
// If the actual BMP is smaller, this might write extra uninitialized bytes from the buffer.
134-
// If actual is larger (should not happen with correct estimation and save), it's a problem.
135-
// The best is to parse bfSize from output_bmp_buffer.data().
136-
137-
if (write_buffer_to_file("output_new_api.bmp", output_bmp_buffer, estimated_output_size /* ideally actual_written_size from parsed header */)) {
138-
std::cout << "Output buffer saved to output_new_api.bmp" << std::endl;
145+
std::cout << "BmpTool::Bitmap saved to output buffer." << std::endl;
146+
147+
// 6. Determine actual size of BMP written to buffer and write to file
148+
// The BMP File Header (BITMAPFILEHEADER) is at the start of the buffer.
149+
// Its bfSize field contains the total size of the BMP file.
150+
BITMAPFILEHEADER* fh = reinterpret_cast<BITMAPFILEHEADER*>(output_bmp_buffer.data());
151+
size_t actual_written_size = fh->bfSize;
152+
153+
// Ensure actual_written_size is not greater than our buffer to prevent reading out of bounds.
154+
if (actual_written_size > max_output_size) {
155+
std::cerr << "Error: saved BMP size (" << actual_written_size
156+
<< ") exceeds buffer capacity (" << max_output_size << ")." << std::endl;
157+
return 1;
158+
}
159+
160+
if (write_buffer_to_file(output_filename, output_bmp_buffer, actual_written_size)) {
161+
std::cout << "Processed image saved to '" << output_filename << "'" << std::endl;
139162
} else {
140-
std::cerr << "Failed to write output_new_api.bmp." << std::endl;
163+
std::cerr << "Failed to write output to '" << output_filename << "'." << std::endl;
164+
return 1;
141165
}
142166

143167
return 0;
@@ -146,56 +170,88 @@ int main() {
146170
147171
## Building the Project
148172
149-
The project uses CMake for building.
173+
The project uses CMake for building. Ensure you have CMake (version 3.10 or newer) and a C++20 compatible compiler installed.
150174
151175
```bash
152-
# Create a build directory
176+
# Create a build directory (out-of-source build is recommended)
153177
mkdir build
154178
cd build
155179
156-
# Configure the project
180+
# Configure the project (from the build directory)
157181
cmake ..
158182
159-
# Build the library (if configured as a library) and executables (like main example and tests)
183+
# Build the library and executables (e.g., testexe, tests)
184+
# On Linux/macOS with Makefiles (default)
160185
make
161-
# or use your specific build system command e.g., mingw32-make
186+
# On Windows with Visual Studio, after cmake .. you might open the .sln or use:
187+
# cmake --build . --config Release
188+
# For MinGW users:
189+
# mingw32-make
162190
163-
# Run tests (if configured)
191+
# Run tests (if configured and built)
192+
# From the build directory
164193
ctest
165-
# or directly run the test executable: ./bitmap_tests (or tests\bitmap_tests.exe on Windows)
194+
# or directly run the test executable (e.g., ./tests/bitmap_tests or build\tests\Debug\bitmap_tests.exe)
166195
```
167196

168-
## Basic Usage Example
197+
## Basic Usage Example (Old API)
198+
199+
The following example demonstrates basic usage of the older, file-based API found in `src/bitmap/bitmap.h` and `src/bitmapfile/bitmap_file.h`.
169200

170201
```cpp
171-
#include "bitmap/bitmap.h" // Adjust path if necessary, assumes src/ is an include dir
202+
#include "bitmap/bitmap.h" // Old API (assumes src/ is an include directory or path adjusted)
172203
#include <iostream>
173204

174205
int main() {
175-
Bitmap::File myBitmap;
206+
Bitmap::File myBitmap; // Uses the old Bitmap::File class
176207

177-
// Load an image
208+
// Load an image directly from a file path
178209
if (!myBitmap.Open("input.bmp")) {
179-
std::cerr << "Error opening input.bmp" << std::endl;
210+
std::cerr << "Error opening input.bmp using old API" << std::endl;
180211
return 1;
181212
}
213+
std::cout << "Loaded input.bmp using old API." << std::endl;
182214

183-
// Apply some manipulations
184-
myBitmap = GreyscaleImage(myBitmap);
185-
myBitmap = ChangeImageBrightness(myBitmap, 1.2f); // Increase brightness by 20%
186-
myBitmap = ApplyBoxBlur(myBitmap, 2); // Apply box blur with radius 2
215+
// Apply some manipulations (old API functions often return a new Bitmap::File)
216+
Bitmap::File processedBitmap = GreyscaleImage(myBitmap);
217+
processedBitmap = ChangeImageBrightness(processedBitmap, 1.2f); // Increase brightness by 20%
218+
processedBitmap = ApplyBoxBlur(processedBitmap, 2); // Apply box blur with radius 2
219+
std::cout << "Applied manipulations using old API." << std::endl;
187220

188-
// Save the result
189-
if (!myBitmap.SaveAs("output.bmp")) {
190-
std::cerr << "Error saving output.bmp" << std::endl;
221+
// Save the result to a new file path
222+
if (!processedBitmap.SaveAs("output_old_api.bmp")) {
223+
std::cerr << "Error saving output_old_api.bmp using old API" << std::endl;
191224
return 1;
192225
}
193226

194-
std::cout << "Image processed and saved as output.bmp" << std::endl;
227+
std::cout << "Image processed and saved as output_old_api.bmp using old API" << std::endl;
195228
return 0;
196229
}
197230
```
198-
Refer to `main.cpp` for more examples.
231+
The `main.cpp` in the root of the repository demonstrates usage of the **new `BmpTool` API**.
232+
233+
## Code Documentation
234+
235+
The public API for `BmpTool` in `include/bitmap.hpp` is documented using Doxygen-style comments.
236+
237+
If Doxygen is installed, you can generate the full HTML documentation by:
238+
1. Installing Doxygen.
239+
2. Creating a Doxyfile configuration (e.g., `doxygen -g Doxyfile` in the project root).
240+
3. Customizing the `Doxyfile` (e.g., set `INPUT` to `include/`, `RECURSIVE` to `YES`).
241+
4. Running `doxygen Doxyfile` from the project root.
242+
The documentation will then be available in the specified output directory (e.g., `html/`).
243+
244+
## Contributing
245+
246+
Contributions to this project are welcome! Please follow these basic guidelines:
247+
248+
1. **Fork the repository:** Create your own fork of the project on GitHub.
249+
2. **Create a branch:** Make a new branch in your fork for your feature or bug fix (e.g., `feature/new-filter` or `fix/brightness-bug`).
250+
3. **Make your changes:** Implement your changes, ensuring code is clear and follows existing style where possible.
251+
4. **Add tests:** If you're adding a new feature or fixing a bug, please add appropriate unit tests in the `tests/` directory. Ensure all tests pass by running `ctest` or the test executable.
252+
5. **Commit your changes:** Make clear, concise commit messages.
253+
6. **Push to your fork:** Push your changes to your branch on your fork.
254+
7. **Submit a Pull Request (PR):** Open a PR from your branch to the main repository's `main` branch. Provide a clear description of your changes in the PR.
199255

200256
## Fuzz Testing
201257

0 commit comments

Comments
 (0)