[FEAT] Add canvas ppm part.

This commit is contained in:
NADAL Jean-Baptiste
2024-01-31 18:19:26 +01:00
parent 770b784383
commit ec96114111
6 changed files with 221 additions and 4 deletions

49
data/canvas.ppm Normal file
View File

@@ -0,0 +1,49 @@
P3
# Created by GIMP version 2.10.30 PNM plug-in
5 3
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0
255
255
255
0
0
0

View File

@@ -78,3 +78,59 @@ bool Canvas::write_pixel(uint16_t a_pos_x, uint16_t a_pos_y, const Color &a_colo
m_pixels[a_pos_x][a_pos_y] = a_color;
return true;
}
/* ------------------------------------------------------------------------- */
std::string Canvas::to_ppm(void)
{
std::string the_result;
// Header
the_result = "P3\n";
the_result += std::to_string(m_width) + " " + std::to_string(m_height) + "\n";
the_result += "255\n";
for (int j = 0; j < m_height; j++)
{
uint16_t the_col_number = 0;
for (int i = 0; i < m_width; i++)
{
Color the_color;
the_color = m_pixels[i][j];
add_color_component(the_result, the_col_number, the_color.red_to_integer());
add_color_component(the_result, the_col_number, the_color.green_to_integer());
add_color_component(the_result, the_col_number, the_color.blue_to_integer());
}
the_result += "\n";
the_col_number = 0;
}
return the_result;
}
/* ------------------------------------------------------------------------- */
bool Canvas::add_color_component(std::string &a_str_value, uint16_t &a_col_number, uint8_t a_color)
{
std::string the_color_value;
the_color_value = std::to_string(a_color);
if ((the_color_value.length() + 1 + a_col_number) >= 70)
{
a_str_value += "\n";
a_col_number = 0;
}
if (a_col_number != 0)
{
a_str_value += " ";
a_col_number++;
}
a_str_value += the_color_value;
a_col_number += the_color_value.length();
return true;
}

View File

@@ -28,9 +28,11 @@
/* ------------------------------------------------------------------------- */
#include <vector>
#include <cstdint>
#include <string>
#include <vector>
#include "color.h"
/* ------------------------------------------------------------------------- */
@@ -49,6 +51,11 @@ namespace Raytracer
const Color &pixel_at(uint16_t a_pos_x, uint16_t a_pos_y) const;
bool write_pixel(uint16_t a_pos_x, uint16_t a_pos_y, const Color &a_color);
std::string to_ppm(void);
private:
bool add_color_component(std::string &a_str_value, uint16_t &a_col_number, uint8_t a_color);
private:
uint16_t m_width;
uint16_t m_height;

View File

@@ -28,13 +28,14 @@
/* ------------------------------------------------------------------------- */
#include <cmath>
#include <cstdio>
#include "common.h"
#include "color.h"
using namespace Raytracer;
#include <cstdio>
/* ------------------------------------------------------------------------- */
Color::Color(void) : m_red(0), m_green(0), m_blue(0)
@@ -174,3 +175,46 @@ double Color::blue(void) const
{
return m_blue;
}
/* ------------------------------------------------------------------------- */
uint8_t Color::red_to_integer(void) const
{
return color_to_integer(m_red);
}
/* ------------------------------------------------------------------------- */
uint8_t Color::green_to_integer(void) const
{
return color_to_integer(m_green);
}
/* ------------------------------------------------------------------------- */
uint8_t Color::blue_to_integer(void) const
{
return color_to_integer(m_blue);
}
/* ------------------------------------------------------------------------- */
uint8_t Color::color_to_integer(double a_color) const
{
uint8_t the_value;
if (a_color < 0)
{
the_value = 0;
}
else if (a_color > 1.0)
{
the_value = 255;
}
else
{
the_value = round(a_color * 255);
}
return the_value;
}

View File

@@ -28,6 +28,10 @@
/* ------------------------------------------------------------------------- */
#include <cstdint>
/* ------------------------------------------------------------------------- */
namespace Raytracer
{
class Color
@@ -55,6 +59,13 @@ namespace Raytracer
double green(void) const;
double blue(void) const;
uint8_t red_to_integer(void) const;
uint8_t green_to_integer(void) const;
uint8_t blue_to_integer(void) const;
private:
uint8_t color_to_integer(double a_color) const;
private:
double m_red;
double m_green;

View File

@@ -56,3 +56,53 @@ TEST_CASE("[Canvas] Writing pixels to a canvas", "[Canvas]")
REQUIRE(c.pixel_at(2, 3) == red);
}
/* ------------------------------------------------------------------------- */
TEST_CASE("[Canvas] Constructing the PPM pixel data", "[Canvas]")
{
std::string ppm, the_ref_ppm;
Canvas c(5, 3);
Color c1(1.5, 0, 0);
Color c2(0, 0.5, 0);
Color c3(-0.5, 0, 1);
c.write_pixel(0, 0, c1);
c.write_pixel(2, 1, c2);
c.write_pixel(4, 2, c3);
ppm = c.to_ppm();
the_ref_ppm = "P3\n5 3\n255\n";
the_ref_ppm += "255 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
the_ref_ppm += "0 0 0 0 0 0 0 128 0 0 0 0 0 0 0\n";
the_ref_ppm += "0 0 0 0 0 0 0 0 0 0 0 0 0 0 255\n";
REQUIRE(ppm == the_ref_ppm);
}
/* ------------------------------------------------------------------------- */
TEST_CASE("[Canvas] Split long lines in PPM files", "[Canvas]")
{
std::string ppm, the_ref_ppm;
Canvas c(10, 2);
for (int j = 0; j < 2; ++j)
{
for (int i = 0; i < 10; ++i)
{
c.write_pixel(i, j, Color(1, 0.8, 0.6));
}
}
ppm = c.to_ppm();
the_ref_ppm = "P3\n10 2\n255\n";
the_ref_ppm += "255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204\n";
the_ref_ppm += "153 255 204 153 255 204 153 255 204 153 255 204 153\n";
the_ref_ppm += "255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204\n";
the_ref_ppm += "153 255 204 153 255 204 153 255 204 153 255 204 153\n";
REQUIRE(ppm == the_ref_ppm);
}