Do interpolation on quantized values.
This commit is contained in:
parent
0929a51dea
commit
68fb1b1951
89
rotation.cpp
89
rotation.cpp
|
@ -487,8 +487,8 @@ Point convert_img_coord(Image const& img, DPoint const& p)
|
||||||
|
|
||||||
DPoint convert_img_coord_precision(Image const& img, DPoint const& p)
|
DPoint convert_img_coord_precision(Image const& img, DPoint const& p)
|
||||||
{
|
{
|
||||||
int x = p.x + (img.width / 2.0f) - 0.5;
|
double x = p.x + (img.width / 2.0f) - 0.5;
|
||||||
int y = p.y + (img.height / 2.0f) - 0.5;
|
double y = p.y + (img.height / 2.0f) - 0.5;
|
||||||
return DPoint(x, y);
|
return DPoint(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,21 +592,17 @@ DPoint get_mapped_point(Image const& src, Point const& p, double const rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void rotate_pixel(Image const& src, /*uint8_t* rotated,*/
|
void rotate_pixel(Image const& src,
|
||||||
DPoint const& src_rotated_point, /*Point const& rot_point,*/
|
Point const& src_rotated_point,
|
||||||
unsigned int const src_limit, unsigned int const rot_limit,
|
unsigned int const src_limit,
|
||||||
uint8_t* rotate_buffer, unsigned int rot_index,
|
uint8_t* rotate_buffer, unsigned int rot_index)
|
||||||
bool full_delta)
|
|
||||||
{
|
{
|
||||||
int const src_x = (int) src_rotated_point.x;
|
unsigned int const quantize = 8;
|
||||||
int const src_y = (int) src_rotated_point.y;
|
|
||||||
unsigned int src_index = (src_y * src.width + src_x) * 3;
|
|
||||||
// unsigned int rot_index = (rot_point.y * rotated.width + rot_point.x) * 3;
|
|
||||||
|
|
||||||
// Out-of-bounds check
|
int const src_x = src_rotated_point.x >> 3;
|
||||||
if (src_index >= src_limit
|
int const src_y = src_rotated_point.y >> 3;
|
||||||
|| rot_index >= rot_limit)
|
|
||||||
return;
|
unsigned int src_index = (src_y * src.width + src_x) * 3;
|
||||||
|
|
||||||
// Bilinear interpolation
|
// Bilinear interpolation
|
||||||
unsigned int src_index_1 = src_index;
|
unsigned int src_index_1 = src_index;
|
||||||
|
@ -614,30 +610,22 @@ void rotate_pixel(Image const& src, /*uint8_t* rotated,*/
|
||||||
unsigned int src_index_3 = src_index_1 + 3 * src.width;
|
unsigned int src_index_3 = src_index_1 + 3 * src.width;
|
||||||
unsigned int src_index_4 = src_index_3 + 3;
|
unsigned int src_index_4 = src_index_3 + 3;
|
||||||
|
|
||||||
|
// Out-of-bounds check
|
||||||
if (src_index_4 >= src_limit)
|
if (src_index_4 >= src_limit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// special case if we can directly map the src to the dest
|
unsigned int x_delta = src_rotated_point.x & 0x07;;
|
||||||
if (full_delta)
|
unsigned int y_delta = src_rotated_point.y & 0x07;
|
||||||
{
|
unsigned int const inv_x = quantize - x_delta;
|
||||||
memcpy(&rotate_buffer[rot_index], &src.buffer[src_index], 3 * sizeof (uint8_t));
|
unsigned int const inv_y = quantize - y_delta;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double x_delta = src_rotated_point.x - src_x;
|
|
||||||
//round_if_very_small(x_delta);
|
|
||||||
double y_delta = src_rotated_point.y - src_y;
|
|
||||||
//round_if_very_small(y_delta);
|
|
||||||
double const inv_x = 1 - x_delta;
|
|
||||||
double const inv_y = 1 - y_delta;
|
|
||||||
|
|
||||||
// No SIMD
|
// No SIMD
|
||||||
rotate_buffer[rot_index] = (src.buffer[src_index_1] * inv_x + src.buffer[src_index_2] * x_delta) * inv_y
|
rotate_buffer[rot_index] = ((src.buffer[src_index_1] * inv_x + src.buffer[src_index_2] * x_delta) * inv_y
|
||||||
+ (src.buffer[src_index_3] * inv_x + src.buffer[src_index_4] * x_delta) * y_delta;
|
+ (src.buffer[src_index_3] * inv_x + src.buffer[src_index_4] * x_delta) * y_delta) >> 6;
|
||||||
rotate_buffer[rot_index + 1] = (src.buffer[src_index_1 + 1] * inv_x + src.buffer[src_index_2 + 1] * x_delta) * inv_y
|
rotate_buffer[rot_index + 1] = ((src.buffer[src_index_1 + 1] * inv_x + src.buffer[src_index_2 + 1] * x_delta) * inv_y
|
||||||
+ (src.buffer[src_index_3 + 1] * inv_x + src.buffer[src_index_4 + 1] * x_delta) * y_delta;
|
+ (src.buffer[src_index_3 + 1] * inv_x + src.buffer[src_index_4 + 1] * x_delta) * y_delta) >> 6;
|
||||||
rotate_buffer[rot_index + 2] = (src.buffer[src_index_1 + 2] * inv_x + src.buffer[src_index_2 + 2] * x_delta) * inv_y
|
rotate_buffer[rot_index + 2] = ((src.buffer[src_index_1 + 2] * inv_x + src.buffer[src_index_2 + 2] * x_delta) * inv_y
|
||||||
+ (src.buffer[src_index_3 + 2] * inv_x + src.buffer[src_index_4 + 2] * x_delta) * y_delta;
|
+ (src.buffer[src_index_3 + 2] * inv_x + src.buffer[src_index_4 + 2] * x_delta) * y_delta) >> 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image* rotate(Image const& src, double angle)
|
Image* rotate(Image const& src, double angle)
|
||||||
|
@ -673,13 +661,6 @@ Image* rotate(Image const& src, double angle)
|
||||||
src_delta_y.y = src_delta_y.y - src_origin.y;
|
src_delta_y.y = src_delta_y.y - src_origin.y;
|
||||||
round_if_very_small(src_delta_y.x);
|
round_if_very_small(src_delta_y.x);
|
||||||
round_if_very_small(src_delta_y.y);
|
round_if_very_small(src_delta_y.y);
|
||||||
bool full_delta = false;
|
|
||||||
if (src_delta_x.x - (int) src_delta_x.x == 0
|
|
||||||
&& src_delta_x.y - (int) src_delta_x.y == 0
|
|
||||||
&& src_delta_y.x - (int) src_delta_y.x == 0
|
|
||||||
&& src_delta_y.y - (int) src_delta_y.y == 0)
|
|
||||||
full_delta = true;
|
|
||||||
|
|
||||||
|
|
||||||
// // steps for first column in source image (y)
|
// // steps for first column in source image (y)
|
||||||
int origin_nb_steps = max(abs(bl.x - tl.x), abs(bl.y - tl.y));
|
int origin_nb_steps = max(abs(bl.x - tl.x), abs(bl.y - tl.y));
|
||||||
|
@ -693,7 +674,6 @@ Image* rotate(Image const& src, double angle)
|
||||||
DPoint const bresenham((tr.x - tl.x) / (float) line_nb_steps, (tr.y - tl.y) / (float) line_nb_steps);
|
DPoint const bresenham((tr.x - tl.x) / (float) line_nb_steps, (tr.y - tl.y) / (float) line_nb_steps);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
DPoint const rot_origin_in_src_grid = get_mapped_point(*rotated, Point(0, 0), -rotation);
|
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);
|
DPoint const rot_origin_in_src = convert_img_coord_precision(src, rot_origin_in_src_grid);
|
||||||
|
@ -705,24 +685,29 @@ Image* rotate(Image const& src, double angle)
|
||||||
memset(buffer, 0, buffer_size);
|
memset(buffer, 0, buffer_size);
|
||||||
unsigned int buffer_offset = 0;
|
unsigned int buffer_offset = 0;
|
||||||
|
|
||||||
|
unsigned int const quantize = 8;
|
||||||
|
int const& src_qwidth = src.width * quantize;
|
||||||
|
int const& src_qheight = src.height * quantize;
|
||||||
|
|
||||||
for (unsigned int y = 0; y < rotated->height; ++y)
|
for (unsigned int y = 0; y < rotated->height; ++y)
|
||||||
{
|
{
|
||||||
//memset(buffer, 0, buffer_size);
|
Point const src_rotated_point((rot_origin_in_src.x + y * src_delta_y.x) * quantize,
|
||||||
DPoint src_rotated_point(rot_origin_in_src.x + y * src_delta_y.x,
|
(rot_origin_in_src.y + y * src_delta_y.y) * quantize);
|
||||||
rot_origin_in_src.y + y * src_delta_y.y);
|
|
||||||
|
|
||||||
for (unsigned int x = 0; x < rotated->width; ++x)
|
for (unsigned int x = 0; x < rotated->width; ++x)
|
||||||
{
|
{
|
||||||
if (src_rotated_point.x >= 0 && src_rotated_point.x < src.width
|
Point const src_runner(src_rotated_point.x + x * src_delta_x.x * quantize,
|
||||||
&& src_rotated_point.y >= 0 && src_rotated_point.y < src.height)
|
src_rotated_point.y + x * src_delta_x.y * quantize);
|
||||||
|
|
||||||
|
if (src_runner.x >= 0 && src_runner.x < src_qwidth
|
||||||
|
&& src_runner.y >= 0 && src_runner.y < src_qheight)
|
||||||
{
|
{
|
||||||
rotate_pixel(src, src_rotated_point,
|
rotate_pixel(src, src_runner,
|
||||||
src_limit, rot_limit,
|
src_limit,
|
||||||
buffer, buffer_index * 3, full_delta);
|
buffer, buffer_index * 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
src_rotated_point.x += src_delta_x.x;
|
// Flush buffer to dest
|
||||||
src_rotated_point.y += src_delta_x.y;
|
|
||||||
++buffer_index;
|
++buffer_index;
|
||||||
if (buffer_index == buffer_pixel_capacity)
|
if (buffer_index == buffer_pixel_capacity)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue