A lightweight command-line image processing tool implemented in C.
This project focuses on core systems-programming skills: file parsing, dynamic memory management, image data manipulation, and algorithmic correctness. It works with the ASCII PPM (P3) image format and provides a compact pipeline for loading, transforming, and saving images.
Convert supports a small but useful set of image operations:
- Reading and writing P3 PPM images
- Rotating images clockwise and counterclockwise
- Mirroring images horizontally and vertically
- Resizing images with cropping and black-padding behavior
- Flood-fill on 4-connected regions
The implementation is intentionally low-level and explicit. That makes it a good example of careful C programming, predictable memory usage, and modular design.
- PPM (P3) input/output
- Image transformations with deterministic behavior
- Flood-fill traversal on connected pixels of the same color
- Command-line interface with input/output redirection
- Automated test coverage
- Sanitizer-friendly memory management
# Build
make
# Read an image
./bin/convert read < input.ppm
# Read and write the same image
./bin/convert read-and-write > output.ppm < input.ppm
# Rotate an image clockwise
./bin/convert rotate-clockwise > output.ppm < input.ppm
# Resize an image
./bin/convert resize 300 300 > output.ppm < input.ppm
# Apply flood fill
./bin/convert flood 10 5 255 0 0 > output.ppm < input.ppm.
├── src/ # Core implementation
│ ├── file_io.* # Image read/write
│ ├── image_edit.c # Rotation, mirroring, resizing
│ ├── flood_fill.c # Flood-fill algorithm
│ └── structures.h # Shared data structures
├── tests/ # Automated tests
├── test/data/ # Sample input images
├── bin/ # Build output
└── Makefile
Images are stored in row-major order. For a pixel at coordinates (x, y), the index is:
index = y * width + x
This layout keeps the representation simple and makes iteration and transformation logic straightforward.
The codebase is organized by responsibility:
file_iohandles parsing and serializationimage_edithandles geometric transformationsflood_fillhandles region-based pixel replacement
That separation keeps the implementation easier to reason about, test, and extend.
The project uses explicit dynamic allocation for image buffers and resizes when necessary. The code is designed to avoid leaks, out-of-bounds access, and undefined behavior.
Input validation is treated as part of the implementation, not as an afterthought. Invalid formats, malformed dimensions, and out-of-bounds flood-fill coordinates are handled defensively.
Let n be the number of pixels in the image.
| Operation | Complexity | Notes |
|---|---|---|
| Read / Write | O(n) | Linear scan over image data |
| Rotate | O(n) | Index remapping |
| Mirror | O(n) | Pixel reordering |
| Resize | O(n) | Copy + crop/pad behavior |
| Flood Fill | O(n) | Traversal of connected region |
- Malformed or incomplete PPM input
- Incorrect magic number or unsupported format
- Invalid image dimensions
- Missing or invalid pixel values
- Resize requests larger or smaller than the original image
- Flood-fill coordinates outside image bounds
- Memory allocation failures
The project is validated with automated tests and sanitizer checks.
# Run all tests
./tests/run_tests.py
# Run a specific test
./tests/run_tests.py -t "public.read_and_write.basi0g01"
# Build and run tests
make checkA simple graphical interface is available for visual debugging of the implemented operations:
./bin/convert guiThis is useful when you want to inspect transformations visually instead of only through command-line output.
This project demonstrates practical experience with:
- Manual memory management in C
- File format parsing and serialization
- Image data processing
- Algorithm implementation under strict correctness constraints
- Writing code that is testable, modular, and maintainable
Potential extensions include:
- Support for additional Netpbm formats such as binary PPM (P6)
- More image operations such as grayscale, blur, or edge detection
- Performance optimizations for larger images
- Streaming support for lower memory usage on large inputs
- C compiler
- Make
- Unix-like environment recommended
This project is licensed under the GNU General Public License v3.0 (GPL-3.0).
See the LICENSE file for details.