Walk through src pixel in order.
- Set background to red
This commit is contained in:
parent
ce3592e857
commit
b666b1b4a6
127
rotation.cpp
127
rotation.cpp
|
@ -20,7 +20,7 @@ struct TPoint {
|
|||
, y(b)
|
||||
{}
|
||||
};
|
||||
typedef TPoint<unsigned int> Point;
|
||||
typedef TPoint<int> Point;
|
||||
typedef TPoint<int> APoint; // absolute point, can be negative
|
||||
typedef TPoint<double> DPoint; // absolute point, can be negative
|
||||
template<typename Elem, typename Traits, typename T>
|
||||
|
@ -50,7 +50,7 @@ struct Image {
|
|||
this->width = w;
|
||||
this->height = h;
|
||||
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];
|
||||
memset(g_chan, 0, width * height * sizeof (uint8_t));
|
||||
b_chan = new uint8_t[width * height];
|
||||
|
@ -245,12 +245,12 @@ struct Image {
|
|||
// 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);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
angle = atan2(p.y, p.x);
|
||||
angle = atan2(-p.y, p.x);
|
||||
dist = sqrt(p.x * p.x + p.y * p.y);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -308,7 +315,7 @@ void compute_output_size(Image const& src, double const rotation, unsigned int&
|
|||
double max_h = 0;
|
||||
|
||||
//cout << "Image dimensions: " << src.width << " x " << src.height << endl;
|
||||
Point p(0, 0);
|
||||
APoint p(0, 0);
|
||||
double angle = convert_radian(src, p, ratio);
|
||||
DPoint tl = convert_abs_coord(angle + rotation, ratio);
|
||||
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
|
||||
//
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
Image rotated(w, h);
|
||||
|
||||
// debug print
|
||||
// if (rotation == 0.0)
|
||||
// corner points in rotated image
|
||||
DPoint tl_grid = get_mapped_point(src, APoint(0, 0), rotation);
|
||||
APoint tl = convert_img_coord(rotated, tl_grid);
|
||||
DPoint tr_grid = get_mapped_point(src, APoint(src.width - 1, 0), rotation);
|
||||
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);
|
||||
|
||||
// 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)
|
||||
{
|
||||
// first column origin
|
||||
DPoint const src_origin(src_tl.x + y_i * origin_x_inc, src_tl.y + y_i * origin_y_inc);
|
||||
APoint const rot_origin(tl.x + y_i * rotated_x_inc, tl.y + y_i * rotated_y_inc);
|
||||
|
||||
for (int x_i = 0; x_i < (int) line_nb_steps; ++x_i)
|
||||
{
|
||||
DPoint const src_rotated_point(src_origin.x + x_i * line_x_inc, src_origin.y + x_i * line_y_inc);
|
||||
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 << "src dimensions: " << src.width << " x " << src.height << endl;
|
||||
// cout << "rotated dimensions: " << w << " x " << h << endl;
|
||||
// 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;
|
||||
// }
|
||||
|
||||
for (int y = 0; y < (int) rotated.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < (int) rotated.width; ++x)
|
||||
{
|
||||
Point const p(x, y);
|
||||
DPoint const d = convert_grid_coord(rotated, p);
|
||||
double p_angle = 0;
|
||||
double dist = 0;
|
||||
convert_abs_to_polar_coord(d, p_angle, dist);
|
||||
DPoint const src_rotated_point = convert_polar_to_grid_coord(p_angle + rotation, dist);
|
||||
// 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 g = 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);
|
||||
rotated.set_pixel(p, 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;
|
||||
// }
|
||||
// }
|
||||
rotated.set_pixel(rot_point, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,8 +700,11 @@ int main()
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
|
@ -667,7 +715,12 @@ int main()
|
|||
cout << "rotate(" << rotation << "): " << duration_ms.count() << " ms" << endl;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue