[FEAT] Add canvas ppm part.
This commit is contained in:
49
data/canvas.ppm
Normal file
49
data/canvas.ppm
Normal 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
|
||||||
@@ -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;
|
m_pixels[a_pos_x][a_pos_y] = a_color;
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,9 +28,11 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@@ -49,6 +51,11 @@ namespace Raytracer
|
|||||||
const Color &pixel_at(uint16_t a_pos_x, uint16_t a_pos_y) const;
|
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);
|
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:
|
private:
|
||||||
uint16_t m_width;
|
uint16_t m_width;
|
||||||
uint16_t m_height;
|
uint16_t m_height;
|
||||||
|
|||||||
@@ -28,13 +28,14 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
using namespace Raytracer;
|
using namespace Raytracer;
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
Color::Color(void) : m_red(0), m_green(0), m_blue(0)
|
Color::Color(void) : m_red(0), m_green(0), m_blue(0)
|
||||||
@@ -174,3 +175,46 @@ double Color::blue(void) const
|
|||||||
{
|
{
|
||||||
return m_blue;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
namespace Raytracer
|
namespace Raytracer
|
||||||
{
|
{
|
||||||
class Color
|
class Color
|
||||||
@@ -55,6 +59,13 @@ namespace Raytracer
|
|||||||
double green(void) const;
|
double green(void) const;
|
||||||
double blue(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:
|
private:
|
||||||
double m_red;
|
double m_red;
|
||||||
double m_green;
|
double m_green;
|
||||||
|
|||||||
@@ -56,3 +56,53 @@ TEST_CASE("[Canvas] Writing pixels to a canvas", "[Canvas]")
|
|||||||
|
|
||||||
REQUIRE(c.pixel_at(2, 3) == red);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user