Walk through src pixel in order.

- Set background to red
master
Fabien Freling 2014-06-26 19:18:32 +02:00
parent ce3592e857
commit b666b1b4a6
1 changed files with 91 additions and 38 deletions

View File

@ -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)
// {
// cout << "src dimensions: " << src.width << " x " << src.height << endl;
// cout << "rotated dimensions: " << w << " x " << h << endl;
// }
// 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);
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)
{
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);
// 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 << " 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 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());
}