Fill a temp buffer for each line.
We don’t write into the memory right away, we first write to a temp buffer that we blit into the rotated image.
This commit is contained in:
parent
e3e0d3c20a
commit
049228b377
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -std=c++11 -W -Wall -O3 -ffast-math #-Werror
|
CXXFLAGS = -std=c++11 -W -Wall -O3 -ffast-math -Werror -g
|
||||||
BUILD_DIR=/tmp
|
BUILD_DIR=/tmp
|
||||||
|
|
||||||
all: rotation.cpp
|
all: rotation.cpp
|
||||||
|
|
112
rotation.cpp
112
rotation.cpp
|
@ -534,12 +534,13 @@ DPoint get_mapped_point(Image const& src, Point const& p, double const rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void rotate_pixel(Image const& src, Image& rotated,
|
void rotate_pixel(Image const& src, /*uint8_t* rotated,*/
|
||||||
DPoint const& src_rotated_point, Point const& rot_point,
|
DPoint const& src_rotated_point, /*Point const& rot_point,*/
|
||||||
unsigned int const src_limit, unsigned int const rot_limit)
|
unsigned int const src_limit, unsigned int const rot_limit,
|
||||||
|
uint8_t* rotate_buffer, unsigned int rot_index)
|
||||||
{
|
{
|
||||||
unsigned int src_index = ((int) src_rotated_point.y * src.width + (int) src_rotated_point.x) * 3;
|
unsigned int src_index = ((int) src_rotated_point.y * src.width + (int) src_rotated_point.x) * 3;
|
||||||
unsigned int rot_index = (rot_point.y * rotated.width + rot_point.x) * 3;
|
// unsigned int rot_index = (rot_point.y * rotated.width + rot_point.x) * 3;
|
||||||
|
|
||||||
// Out-of-bounds check
|
// Out-of-bounds check
|
||||||
if (src_index >= src_limit
|
if (src_index >= src_limit
|
||||||
|
@ -563,7 +564,10 @@ void rotate_pixel(Image const& src, Image& rotated,
|
||||||
// special case if we can directly map the src to the dest
|
// special case if we can directly map the src to the dest
|
||||||
if (x_delta == 0 && y_delta == 0)
|
if (x_delta == 0 && y_delta == 0)
|
||||||
{
|
{
|
||||||
memcpy(&rotated.buffer[rot_index], &src.buffer[src_index], 3 * sizeof (uint8_t));
|
// memcpy(&rotated.buffer[rot_index], &src.buffer[src_index], 3 * sizeof (uint8_t));
|
||||||
|
rotate_buffer[rot_index] = src.buffer[src_index];
|
||||||
|
rotate_buffer[rot_index + 1] = src.buffer[src_index + 1];
|
||||||
|
rotate_buffer[rot_index + 2] = src.buffer[src_index + 2];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,9 +593,9 @@ void rotate_pixel(Image const& src, Image& rotated,
|
||||||
top_left = _mm_add_ps(top_left, bottom_left);
|
top_left = _mm_add_ps(top_left, bottom_left);
|
||||||
|
|
||||||
// convert float values to uint8_t
|
// convert float values to uint8_t
|
||||||
rotated.buffer[rot_index] = top_left[3];
|
rotate_buffer[rot_index] = top_left[3];
|
||||||
rotated.buffer[rot_index + 1] = top_left[2];
|
rotate_buffer[rot_index + 1] = top_left[2];
|
||||||
rotated.buffer[rot_index + 2] = top_left[1];
|
rotate_buffer[rot_index + 2] = top_left[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Image* rotate(Image const& src, double angle)
|
Image* rotate(Image const& src, double angle)
|
||||||
|
@ -643,46 +647,72 @@ Image* rotate(Image const& src, double angle)
|
||||||
unsigned int const src_limit = src.width * src.height * 3;
|
unsigned int const src_limit = src.width * src.height * 3;
|
||||||
unsigned int const rot_limit = rotated->width * rotated->height * 3;
|
unsigned int const rot_limit = rotated->width * rotated->height * 3;
|
||||||
|
|
||||||
for (int y_i = 0; y_i <= (int) origin_nb_steps; ++y_i)
|
// for (int y_i = 0; y_i <= (int) origin_nb_steps; ++y_i)
|
||||||
|
// {
|
||||||
|
// // first column origin
|
||||||
|
// Point const rot_origin(tl.x + y_i * rotated_step.x, tl.y + y_i * rotated_step.y);
|
||||||
|
// Point rot_point(rot_origin.x, rot_origin.y);
|
||||||
|
// DPoint rot_delta(0.0, 0.0);
|
||||||
|
//
|
||||||
|
// Point previous = rot_origin;
|
||||||
|
//
|
||||||
|
// for (int x_i = 0; x_i <= (int) line_nb_steps; ++x_i)
|
||||||
|
// {
|
||||||
|
//
|
||||||
|
// Point const delta(rot_point.x - tl.x, rot_point.y - tl.y);
|
||||||
|
// DPoint src_rotated_point(src_tl.x + delta.x * src_delta_x.x + delta.y * src_delta_y.x,
|
||||||
|
// src_tl.y + delta.x * src_delta_x.y + delta.y * src_delta_y.y);
|
||||||
|
//
|
||||||
|
// rotate_pixel(src, *rotated, src_rotated_point, rot_point, src_limit, rot_limit);
|
||||||
|
//
|
||||||
|
// if (previous.x != rot_point.x && previous.y != rot_point.y)
|
||||||
|
// {
|
||||||
|
// int y_slope = rot_point.y > previous.y ? 1 : -1;
|
||||||
|
// int tmp_y = rot_point.y;
|
||||||
|
// rot_point.y = previous.y;
|
||||||
|
//
|
||||||
|
// src_rotated_point.x -= y_slope * src_delta_y.x;
|
||||||
|
// src_rotated_point.y -= y_slope * src_delta_y.y;
|
||||||
|
//
|
||||||
|
// rotate_pixel(src, *rotated, src_rotated_point, rot_point, src_limit, rot_limit);
|
||||||
|
//
|
||||||
|
// rot_point.y = tmp_y;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// previous = rot_point;
|
||||||
|
//
|
||||||
|
// rot_delta.x += bresenham.x;
|
||||||
|
// rot_point.x = rot_origin.x + (int) rot_delta.x;
|
||||||
|
//
|
||||||
|
// rot_delta.y += bresenham.y;
|
||||||
|
// rot_point.y = rot_origin.y + (int) rot_delta.y;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
DPoint const rot_origin_in_src_grid = get_mapped_point(*rotated, Point(0, 0), -rotation);
|
||||||
|
DPoint const rot_origin_in_src = convert_img_coord_precision(src, rot_origin_in_src_grid);
|
||||||
|
|
||||||
|
unsigned int const buffer_size = rotated->width * 3;
|
||||||
|
uint8_t buffer[buffer_size];
|
||||||
|
|
||||||
|
for (unsigned int y = 0; y < rotated->height; ++y)
|
||||||
{
|
{
|
||||||
// first column origin
|
memset(buffer, 0, buffer_size);
|
||||||
Point const rot_origin(tl.x + y_i * rotated_step.x, tl.y + y_i * rotated_step.y);
|
DPoint src_rotated_point(rot_origin_in_src.x + y * src_delta_y.x,
|
||||||
Point rot_point(rot_origin.x, rot_origin.y);
|
rot_origin_in_src.y + y * src_delta_y.y);
|
||||||
DPoint rot_delta(0.0, 0.0);
|
|
||||||
|
|
||||||
Point previous = rot_origin;
|
for (unsigned int x = 0; x < rotated->width; ++x)
|
||||||
|
|
||||||
for (int x_i = 0; x_i <= (int) line_nb_steps; ++x_i)
|
|
||||||
{
|
{
|
||||||
|
if (src_rotated_point.x >= 0 && src_rotated_point.x < src.width
|
||||||
Point const delta(rot_point.x - tl.x, rot_point.y - tl.y);
|
&& src_rotated_point.y >= 0 && src_rotated_point.y < src.height)
|
||||||
DPoint src_rotated_point(src_tl.x + delta.x * src_delta_x.x + delta.y * src_delta_y.x,
|
|
||||||
src_tl.y + delta.x * src_delta_x.y + delta.y * src_delta_y.y);
|
|
||||||
|
|
||||||
rotate_pixel(src, *rotated, src_rotated_point, rot_point, src_limit, rot_limit);
|
|
||||||
|
|
||||||
if (previous.x != rot_point.x && previous.y != rot_point.y)
|
|
||||||
{
|
{
|
||||||
int y_slope = rot_point.y > previous.y ? 1 : -1;
|
rotate_pixel(src, src_rotated_point, src_limit, rot_limit, buffer, x * 3);
|
||||||
int tmp_y = rot_point.y;
|
|
||||||
rot_point.y = previous.y;
|
|
||||||
|
|
||||||
src_rotated_point.x -= y_slope * src_delta_y.x;
|
|
||||||
src_rotated_point.y -= y_slope * src_delta_y.y;
|
|
||||||
|
|
||||||
rotate_pixel(src, *rotated, src_rotated_point, rot_point, src_limit, rot_limit);
|
|
||||||
|
|
||||||
rot_point.y = tmp_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previous = rot_point;
|
src_rotated_point.x += src_delta_x.x;
|
||||||
|
src_rotated_point.y += src_delta_x.y;
|
||||||
rot_delta.x += bresenham.x;
|
|
||||||
rot_point.x = rot_origin.x + (int) rot_delta.x;
|
|
||||||
|
|
||||||
rot_delta.y += bresenham.y;
|
|
||||||
rot_point.y = rot_origin.y + (int) rot_delta.y;
|
|
||||||
}
|
}
|
||||||
|
memcpy(rotated->buffer + buffer_size * y, buffer, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rotated;
|
return rotated;
|
||||||
|
|
Loading…
Reference in a new issue