diff options
author | Keuin <[email protected]> | 2022-04-11 12:07:58 +0800 |
---|---|---|
committer | Keuin <[email protected]> | 2022-04-11 12:08:11 +0800 |
commit | a15c8f6b3658095eb50da4bd75da697e37dbe033 (patch) | |
tree | ef4ec60e5c80b3c9031d60fe7caff52b331eb3e8 | |
parent | cdb0bdfc60481708ab1a9707c0e1e4458e6396bf (diff) |
Implement bitmap and PPM serialization (with a demo program).
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | bitmap.h | 74 | ||||
-rw-r--r-- | main_image_output.cpp | 20 |
3 files changed, 97 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a5c54e5..b822baa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,12 @@ set(CMAKE_VERBOSE_MAKEFILE on) # main executable -add_executable(rt main.cpp vec.h) +add_executable(rt main.cpp vec.h bitmap.h) +add_executable(image_output main_image_output.cpp vec.h bitmap.h) # googletest -add_executable(all_tests test.cpp) +add_executable(all_tests test.cpp vec.h bitmap.h) target_link_libraries(all_tests gtest_main) include(FetchContent) diff --git a/bitmap.h b/bitmap.h new file mode 100644 index 0000000..b94bb25 --- /dev/null +++ b/bitmap.h @@ -0,0 +1,74 @@ +// +// Created by Keuin on 2022/4/11. +// + +#ifndef RT_BITMAP_H +#define RT_BITMAP_H + +#include <vector> +#include <cstdint> +#include <ostream> +#include <cassert> + + +// T is some unsigned integer, do not use float point types! +template<typename T> +struct pixel { + T r, g, b; +}; + +// 8 bit pixel +using pixel8b = pixel<uint8_t>; + +template<typename T> +class bitmap { + const unsigned width, height; + std::vector<pixel<T>> content; // pixels scanned by rows, from top to bottom + + pixel<T> &image(unsigned x, unsigned y) { + assert(x < width); + assert(y < height); + return content[x * width + y]; + } + + pixel<T> &image(unsigned x, unsigned y) const { + assert(x < width); + assert(y < height); + return content[x * width + y]; + } + +public: + bitmap(unsigned int width, unsigned int height) : width(width), height(height) { + content.resize(width * height, pixel<T>{}); + } + + void set(unsigned x, unsigned y, const pixel<T> &pixel) { + image(x, y) = pixel; + } + + pixel<T> get(unsigned x, unsigned y) const { + return image(x, y); + } + + // Do not use float-point pixels, or this routine will break. + void write_plain_ppm(std::ostream &out) const; +}; + +template<typename T> +void bitmap<T>::write_plain_ppm(std::ostream &out) const { + const auto depth = (1ULL << (sizeof(T) * 8)) - 1ULL; // color depth of pixels + out << "P3\n" // file header + << width << ' ' << height << '\n' // image width and height + << depth << '\n'; // normalized max color depth (e.g. 255 for 8bit image) + + for (const auto &pixel: content) { + out << (unsigned long long) pixel.r << ' ' + << (unsigned long long) pixel.g << ' ' + << (unsigned long long) pixel.b << '\n'; + } +} + +using bitmap8b = bitmap<uint8_t>; + + +#endif //RT_BITMAP_H diff --git a/main_image_output.cpp b/main_image_output.cpp new file mode 100644 index 0000000..10301da --- /dev/null +++ b/main_image_output.cpp @@ -0,0 +1,20 @@ +// +// Created by Keuin on 2022/4/11. +// + +#include <iostream> +#include "bitmap.h" + +// write a test .PPM image +int main() { + bitmap8b image{256, 256}; + pixel8b p{}; + for (int x = 0; x < 256; ++x) { + for (int y = 0; y < 256; ++y) { + p.r = x; + p.b = y; + image.set(x, y, p); + } + } + image.write_plain_ppm(std::cout); +}
\ No newline at end of file |