Walk through src pixel in order.
- Set background to red
This commit is contained in:
parent
ce3592e857
commit
b666b1b4a6
129
rotation.cpp
129
rotation.cpp
|
@ -20,7 +20,7 @@ struct TPoint {
|
||||||
, y(b)
|
, y(b)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
typedef TPoint<unsigned int> Point;
|
typedef TPoint<int> Point;
|
||||||
typedef TPoint<int> APoint; // absolute point, can be negative
|
typedef TPoint<int> APoint; // absolute point, can be negative
|
||||||
typedef TPoint<double> DPoint; // absolute point, can be negative
|
typedef TPoint<double> DPoint; // absolute point, can be negative
|
||||||
template<typename Elem, typename Traits, typename T>
|
template<typename Elem, typename Traits, typename T>
|
||||||
|
@ -50,7 +50,7 @@ struct Image {
|
||||||
this->width = w;
|
this->width = w;
|
||||||
this->height = h;
|
this->height = h;
|
||||||
r_chan = new uint8_t[width * height];
|
r_chan = new uint8_t[width * height];
|
||||||
memset(r_chan, 0, width * height * sizeof (uint8_t));
|
memset(r_chan, 255, width * height * sizeof (uint8_t));
|
||||||
g_chan = new uint8_t[width * height];
|
g_chan = new uint8_t[width * height];
|
||||||
memset(g_chan, 0, width * height * sizeof (uint8_t));
|
memset(g_chan, 0, width * height * sizeof (uint8_t));
|
||||||
b_chan = new uint8_t[width * height];
|
b_chan = new uint8_t[width * height];
|
||||||
|
@ -245,12 +245,12 @@ struct Image {
|
||||||
// Trigonometry
|
// Trigonometry
|
||||||
//
|
//
|
||||||
|
|
||||||
DPoint convert_grid_coord(Image const& img, Point const& p)
|
DPoint convert_grid_coord(Image const& img, APoint const& p)
|
||||||
{
|
{
|
||||||
return DPoint(p.x - img.width / 2.0f + 0.5, p.y - img.height / 2.0f + 0.5);
|
return DPoint(p.x - img.width / 2.0f + 0.5, p.y - img.height / 2.0f + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
double convert_radian(Image const& img, Point const& p, double const ratio)
|
double convert_radian(Image const& img, APoint const& p, double const ratio)
|
||||||
{
|
{
|
||||||
DPoint centered = convert_grid_coord(img, p);
|
DPoint centered = convert_grid_coord(img, p);
|
||||||
double const cos_value = centered.x * ratio;
|
double const cos_value = centered.x * ratio;
|
||||||
|
@ -276,15 +276,22 @@ APoint convert_img_coord(Image const& img, DPoint const& p)
|
||||||
return APoint(x, y);
|
return APoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPoint convert_img_coord_precision(Image const& img, DPoint const& p)
|
||||||
|
{
|
||||||
|
int x = p.x + (img.width / 2.0f) - 0.5;
|
||||||
|
int y = p.y + (img.height / 2.0f) - 0.5;
|
||||||
|
return DPoint(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
void convert_abs_to_polar_coord(DPoint const& p, double& angle, double& dist)
|
void convert_abs_to_polar_coord(DPoint const& p, double& angle, double& dist)
|
||||||
{
|
{
|
||||||
angle = atan2(p.y, p.x);
|
angle = atan2(-p.y, p.x);
|
||||||
dist = sqrt(p.x * p.x + p.y * p.y);
|
dist = sqrt(p.x * p.x + p.y * p.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPoint convert_polar_to_grid_coord(double const angle, double const distance)
|
DPoint convert_polar_to_grid_coord(double const angle, double const distance)
|
||||||
{
|
{
|
||||||
return DPoint(cos(angle) * distance, (sin(angle) * distance));
|
return DPoint(cos(angle) * distance, - (sin(angle) * distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
double compute_ratio(Image const& img)
|
double compute_ratio(Image const& img)
|
||||||
|
@ -308,7 +315,7 @@ void compute_output_size(Image const& src, double const rotation, unsigned int&
|
||||||
double max_h = 0;
|
double max_h = 0;
|
||||||
|
|
||||||
//cout << "Image dimensions: " << src.width << " x " << src.height << endl;
|
//cout << "Image dimensions: " << src.width << " x " << src.height << endl;
|
||||||
Point p(0, 0);
|
APoint p(0, 0);
|
||||||
double angle = convert_radian(src, p, ratio);
|
double angle = convert_radian(src, p, ratio);
|
||||||
DPoint tl = convert_abs_coord(angle + rotation, ratio);
|
DPoint tl = convert_abs_coord(angle + rotation, ratio);
|
||||||
min_w = min(min_w, tl.x);
|
min_w = min(min_w, tl.x);
|
||||||
|
@ -457,6 +464,15 @@ void draw_outline(Image const& input, unsigned int degrees, string const& name)
|
||||||
// Image rotation
|
// Image rotation
|
||||||
//
|
//
|
||||||
|
|
||||||
|
DPoint get_mapped_point(Image const& src, APoint const& p, double const rotation)
|
||||||
|
{
|
||||||
|
DPoint const d = convert_grid_coord(src, p);
|
||||||
|
double p_angle = 0;
|
||||||
|
double dist = 0;
|
||||||
|
convert_abs_to_polar_coord(d, p_angle, dist);
|
||||||
|
return convert_polar_to_grid_coord(p_angle + rotation, dist);
|
||||||
|
}
|
||||||
|
|
||||||
Image rotate(Image const& src, double angle)
|
Image rotate(Image const& src, double angle)
|
||||||
{
|
{
|
||||||
double const rotation = (angle / 180.0f) * M_PI;
|
double const rotation = (angle / 180.0f) * M_PI;
|
||||||
|
@ -465,42 +481,71 @@ Image rotate(Image const& src, double angle)
|
||||||
compute_output_size(src, rotation, w, h);
|
compute_output_size(src, rotation, w, h);
|
||||||
Image rotated(w, h);
|
Image rotated(w, h);
|
||||||
|
|
||||||
// debug print
|
// corner points in rotated image
|
||||||
// if (rotation == 0.0)
|
DPoint tl_grid = get_mapped_point(src, APoint(0, 0), rotation);
|
||||||
// {
|
APoint tl = convert_img_coord(rotated, tl_grid);
|
||||||
// cout << "src dimensions: " << src.width << " x " << src.height << endl;
|
DPoint tr_grid = get_mapped_point(src, APoint(src.width - 1, 0), rotation);
|
||||||
// cout << "rotated dimensions: " << w << " x " << h << endl;
|
APoint tr = convert_img_coord(rotated, tr_grid);
|
||||||
// }
|
DPoint bl_grid = get_mapped_point(src, APoint(0, src.height - 1), rotation);
|
||||||
|
APoint bl = convert_img_coord(rotated, bl_grid);
|
||||||
|
|
||||||
for (int y = 0; y < (int) rotated.height; ++y)
|
// corner points in source image
|
||||||
|
DPoint src_tl = get_mapped_point(rotated, tl, -rotation);
|
||||||
|
src_tl = convert_img_coord_precision(src, src_tl);
|
||||||
|
DPoint src_tr = get_mapped_point(rotated, tr, -rotation);
|
||||||
|
src_tr = convert_img_coord_precision(src, src_tr);
|
||||||
|
DPoint src_bl = get_mapped_point(rotated, bl, -rotation);
|
||||||
|
src_bl = convert_img_coord_precision(src, src_bl);
|
||||||
|
|
||||||
|
// steps for first column in source image
|
||||||
|
int origin_nb_steps = max(abs(bl.x - tl.x), abs(bl.y - tl.y));
|
||||||
|
double origin_y_inc = (src_bl.y - src_tl.y) / origin_nb_steps;
|
||||||
|
double origin_x_inc = (src_bl.x - src_tl.x) / origin_nb_steps;
|
||||||
|
//cout << " origin steps: " << origin_nb_steps << " (" << origin_x_inc << ", " << origin_y_inc << ")" << endl;
|
||||||
|
|
||||||
|
// steps for line in source image
|
||||||
|
int line_nb_steps = max(abs(tr.x - tl.x), abs(tr.y - tl.y));
|
||||||
|
double line_y_inc = (src_tr.y - src_tl.y) / line_nb_steps;
|
||||||
|
double line_x_inc = (src_tr.x - src_tl.x) / line_nb_steps;
|
||||||
|
//cout << " line steps: " << line_nb_steps << " (" << line_x_inc << ", " << line_y_inc << ")" << endl;
|
||||||
|
|
||||||
|
// steps for first column in rotated image
|
||||||
|
double rotated_y_inc = (bl.y - tl.y) / (float) origin_nb_steps;
|
||||||
|
double rotated_x_inc = (bl.x - tl.x) / (float) origin_nb_steps;
|
||||||
|
|
||||||
|
// steps for line in rotated image
|
||||||
|
DPoint bresenham((tr.x - tl.x) / (float) line_nb_steps, (tr.y - tl.y) / (float) line_nb_steps);
|
||||||
|
cout << "bresenham: " << bresenham << endl;
|
||||||
|
|
||||||
|
for (int y_i = 0; y_i < (int) origin_nb_steps; ++y_i)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < (int) rotated.width; ++x)
|
// first column origin
|
||||||
{
|
DPoint const src_origin(src_tl.x + y_i * origin_x_inc, src_tl.y + y_i * origin_y_inc);
|
||||||
Point const p(x, y);
|
APoint const rot_origin(tl.x + y_i * rotated_x_inc, tl.y + y_i * rotated_y_inc);
|
||||||
DPoint const d = convert_grid_coord(rotated, p);
|
|
||||||
double p_angle = 0;
|
for (int x_i = 0; x_i < (int) line_nb_steps; ++x_i)
|
||||||
double dist = 0;
|
{
|
||||||
convert_abs_to_polar_coord(d, p_angle, dist);
|
DPoint const src_rotated_point(src_origin.x + x_i * line_x_inc, src_origin.y + x_i * line_y_inc);
|
||||||
DPoint const src_rotated_point = convert_polar_to_grid_coord(p_angle + rotation, dist);
|
APoint const rot_point(rot_origin.x + x_i * bresenham.x, rot_origin.y + x_i * bresenham.y);
|
||||||
|
|
||||||
|
// if (y_i < 2 && (x_i == 0 || x_i == line_nb_steps - 1))
|
||||||
|
// {
|
||||||
|
// cout << " y_i[" << y_i << "] x_i[" << x_i << "]" << endl;
|
||||||
|
// cout << " src origin: " << src_origin << endl;
|
||||||
|
// cout << " src rotated point: " << src_rotated_point << endl;
|
||||||
|
// cout << " rotated origin: " << rot_origin << endl;
|
||||||
|
// cout << " rotated point: " << rot_point << endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: Interpolation would be done here
|
||||||
|
APoint src_p(src_rotated_point.x, src_rotated_point.y);
|
||||||
|
|
||||||
// FIXME: get source points
|
|
||||||
APoint src_p = convert_img_coord(src, src_rotated_point);
|
|
||||||
uint8_t r = 0;
|
uint8_t r = 0;
|
||||||
uint8_t g = 0;
|
uint8_t g = 0;
|
||||||
uint8_t b = 0;
|
uint8_t b = 0;
|
||||||
// FIXME: bypass variables, access src pixels
|
// TODO: bypass variables, access src pixels
|
||||||
src.get_pixel(src_p, r, g, b);
|
src.get_pixel(src_p, r, g, b);
|
||||||
rotated.set_pixel(p, r, g, b);
|
rotated.set_pixel(rot_point, r, g, b);
|
||||||
|
|
||||||
// debug print
|
|
||||||
// if (rotation == 0.0)
|
|
||||||
// {
|
|
||||||
// if (x == 0)
|
|
||||||
// {
|
|
||||||
// cout << p << " -> " << d << " -> polar(" << p_angle << ", " << dist << ")";
|
|
||||||
// cout <<" -> " << src_rotated_point << " -> " << src_p << endl;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,8 +700,11 @@ int main()
|
||||||
}
|
}
|
||||||
|
|
||||||
Image img("img/luigi.ppm");
|
Image img("img/luigi.ppm");
|
||||||
|
//Image img("img/wallpaper.ppm");
|
||||||
|
// Image img("img/mini_luigi.ppm");
|
||||||
|
|
||||||
for (double rotation : {0, 1, 5, 15, 30, 45, 60, 75, 90, 110, 140, 160, 180})
|
//for (double rotation : {0, 1, 5, 15, 30, 45, 60, 75, 90, 110, 140, 160, 180, 200, 210, 235, 260, 270, 300, 315, 355, 359})
|
||||||
|
for (double rotation : {0, 45, 90})
|
||||||
{
|
{
|
||||||
auto const before = chrono::high_resolution_clock::now();
|
auto const before = chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
@ -667,7 +715,12 @@ int main()
|
||||||
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
|
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
|
||||||
|
|
||||||
stringstream filename;
|
stringstream filename;
|
||||||
filename << "rotated_" << rotation << ".ppm";
|
filename << "rotated_";
|
||||||
|
if (rotation < 100)
|
||||||
|
filename << "0";
|
||||||
|
if (rotation < 10)
|
||||||
|
filename << "0";
|
||||||
|
filename << rotation << ".ppm";
|
||||||
rotated.save(filename.str());
|
rotated.save(filename.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue