diff --git a/example02_threaded_raytracing/src/main.cpp b/example02_threaded_raytracing/src/main.cpp index 25a2720..924d7a6 100644 --- a/example02_threaded_raytracing/src/main.cpp +++ b/example02_threaded_raytracing/src/main.cpp @@ -133,7 +133,10 @@ int main(int argc, char **argv) { auto pixels = Ex02::RT::renderColorsWithSpheres(outputWidth, outputHeight, threadCount); - auto outFilename = pixels.writeToFile(outputFile); + // auto outFilename = pixels.writeToFile(outputFile); + // std::cout << "Rendered image saved to " << outFilename << std::endl; + + auto outFilename = pixels.writeToPNG(outputFile); std::cout << "Rendered image saved to " << outFilename << std::endl; return 0; diff --git a/example02_threaded_raytracing/src/rayTracer.cpp b/example02_threaded_raytracing/src/rayTracer.cpp index 8f08da7..57a0de7 100644 --- a/example02_threaded_raytracing/src/rayTracer.cpp +++ b/example02_threaded_raytracing/src/rayTracer.cpp @@ -2,8 +2,10 @@ #include #include +#include #include #include +#include #include #include @@ -46,6 +48,66 @@ std::string Ex02::RT::Image::writeToFile(const std::string &filename) const { return outfilename; } +std::string Ex02::RT::Image::writeToPNG(const std::string &filename) const { + std::string outfilename = filename + ".png"; + + FILE *outfile = fopen(outfilename.c_str(), "wb"); + if (outfile == nullptr) { + return "ERROR"; + } + + const static auto pngErrorLFn = [](png_structp psp, png_const_charp message) { + std::cerr << "WARNING [libpng]: " << message << std::endl; + }; + + const static auto pngWarnLFn = [](png_structp psp, png_const_charp message) { + std::cerr << "ERROR [libpng]: " << message << std::endl; + }; + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, + pngErrorLFn, pngWarnLFn); + if (png_ptr == nullptr) { + fclose(outfile); + return "ERROR"; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == nullptr) { + png_destroy_write_struct(&png_ptr, nullptr); + fclose(outfile); + return "ERROR"; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(outfile); + return "ERROR"; + } + + png_init_io(png_ptr, outfile); + + png_set_IHDR(png_ptr, info_ptr, this->width, this->data.size() / this->width, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png_ptr, info_ptr); + + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + + for (unsigned int j = 0; j < this->data.size() / this->width; ++j) { + unsigned char *dataPtr = + reinterpret_cast(&this->data.at(j * this->width)); + png_write_rows(png_ptr, &dataPtr, 1); + } + + png_write_end(png_ptr, nullptr); + + png_destroy_write_struct(&png_ptr, &info_ptr); + + fclose(outfile); + return outfilename; +} + /* glm::mat4x4 Ex02::RT::Internal::defaultMVP() { glm::mat4x4 mvp = glm::perspective( diff --git a/example02_threaded_raytracing/src/rayTracer.hpp b/example02_threaded_raytracing/src/rayTracer.hpp index 1571328..3554608 100644 --- a/example02_threaded_raytracing/src/rayTracer.hpp +++ b/example02_threaded_raytracing/src/rayTracer.hpp @@ -18,7 +18,7 @@ constexpr float EX02_RAY_TRACER_GRAY_SPHERE_RADIUS = 1.5F; namespace Ex02::RT { -struct Pixel { +struct alignas(4) Pixel { Pixel(); unsigned char r, g, b; @@ -34,9 +34,12 @@ public: // returns actual output filename (it appends the file extension) std::string writeToFile(const std::string &filename) const; + // returns actual output filename (it appends the file extension) + std::string writeToPNG(const std::string &filename) const; + private: unsigned int width; - std::vector data; + mutable std::vector data; }; namespace Internal {