Have different quantifications.
I now have a precise quantification for point position and a more approximate one for pixel interpolation.
This commit is contained in:
parent
80b004a418
commit
760d6244d0
50
rotation.cpp
50
rotation.cpp
|
@ -165,33 +165,38 @@ void rotate_pixel(Image const& src,
|
|||
Point const& src_rotated_point,
|
||||
unsigned int const src_limit,
|
||||
pvalue_t* rotate_buffer, unsigned int rot_index,
|
||||
unsigned int q_pow, unsigned int q)
|
||||
unsigned int q_pow)
|
||||
{
|
||||
// Quantize on a 8x8 grid
|
||||
int const q_inter_pow = 3;
|
||||
int const q_inter = 1 << q_inter_pow;
|
||||
int const mask = 0x07;
|
||||
|
||||
int const src_x = src_rotated_point.x >> q_pow;
|
||||
int const src_y = src_rotated_point.y >> q_pow;
|
||||
|
||||
unsigned int src_index = (src_y * src.width + src_x) * src.pixel_size;
|
||||
|
||||
// Bilinear interpolation
|
||||
unsigned int src_index_1 = src_index;
|
||||
unsigned int src_index_3 = src_index_1 + src.pixel_size * src.width;
|
||||
unsigned int src_index_4 = src_index_3 + src.pixel_size;
|
||||
unsigned int const src_index_1 = (src_y * src.width + src_x) * src.pixel_size;
|
||||
unsigned int const src_index_3 = src_index_1 + src.pixel_size * src.width;
|
||||
unsigned int const src_index_4 = src_index_3 + src.pixel_size;
|
||||
|
||||
// Out-of-bounds check
|
||||
if (src_index_4 >= src_limit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int x_delta = src_rotated_point.x & 0x0f;
|
||||
unsigned int y_delta = src_rotated_point.y & 0x0f;
|
||||
unsigned int const inv_x = q - x_delta;
|
||||
unsigned int const inv_y = q - y_delta;
|
||||
unsigned int const x_delta = (src_rotated_point.x >> (q_pow - q_inter_pow)) & mask;
|
||||
unsigned int const y_delta = (src_rotated_point.y >> (q_pow - q_inter_pow)) & mask;
|
||||
unsigned int const inv_x = q_inter - x_delta;
|
||||
unsigned int const inv_y = q_inter - y_delta;
|
||||
|
||||
#ifndef SIMD
|
||||
|
||||
unsigned int src_index_2 = src_index_1 + src.pixel_size;
|
||||
|
||||
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) >> (2 * q_pow);
|
||||
+ (src.buffer[src_index_3] * inv_x + src.buffer[src_index_4] * x_delta) * y_delta) >> (q_inter_pow << 1);
|
||||
// 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) >> 6;
|
||||
// rotate_buffer[rot_index + 2] = ((src.buffer[src_index_1 + 2] * inv_x + src.buffer[src_index_2 + 2] * x_delta) * inv_y
|
||||
|
@ -237,12 +242,13 @@ Image* rotate(Image const& src, double angle)
|
|||
src_delta_x -= src_origin;
|
||||
src_delta_y -= src_origin;
|
||||
|
||||
// Quantized delta
|
||||
unsigned int const q_pow = 4;
|
||||
int const q = pow(2, q_pow);
|
||||
// Quantized position on a grid
|
||||
int const q_pos_pow = 10;
|
||||
int const q_pos = 1 << q_pos_pow;
|
||||
|
||||
// TODO: we could have only one delta and deduce the other one
|
||||
Point const qdx((src_delta_x.x * q) / src.width, (src_delta_x.y * q) / src.width);
|
||||
Point const qdy((src_delta_y.x * q) / src.height, (src_delta_y.y * q) / src.height);
|
||||
Point const qdx((src_delta_x.x * q_pos) / src.width, (src_delta_x.y * q_pos) / src.width);
|
||||
Point const qdy((src_delta_y.x * q_pos) / src.height, (src_delta_y.y * q_pos) / src.height);
|
||||
|
||||
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);
|
||||
|
@ -250,15 +256,15 @@ Image* rotate(Image const& src, double angle)
|
|||
unsigned int buffer_index = 0;
|
||||
pvalue_t* buffer = rotated->buffer;
|
||||
|
||||
int const src_qwidth = src.width * q;
|
||||
int const src_qheight = src.height * q;
|
||||
int64_t const src_qwidth = (int64_t) src.width * q_pos;
|
||||
int64_t const src_qheight = (int64_t) src.height * q_pos;
|
||||
|
||||
unsigned int const src_limit = src_qwidth * src_qheight * src.pixel_size;
|
||||
unsigned int const src_limit = src.width * src.height * src.pixel_size;
|
||||
|
||||
for (int y = 0; y < (int) rotated->height; ++y)
|
||||
{
|
||||
Point src_rotated_point((rot_origin_in_src.x * q) + y * qdy.x,
|
||||
(rot_origin_in_src.y * q) + y * qdy.y);
|
||||
Point src_rotated_point((rot_origin_in_src.x * q_pos) + y * qdy.x,
|
||||
(rot_origin_in_src.y * q_pos) + y * qdy.y);
|
||||
|
||||
for (unsigned int x = 0; x < rotated->width; ++x)
|
||||
{
|
||||
|
@ -268,7 +274,7 @@ Image* rotate(Image const& src, double angle)
|
|||
rotate_pixel(src, src_rotated_point,
|
||||
src_limit,
|
||||
buffer, buffer_index,
|
||||
q_pow, q);
|
||||
q_pos_pow);
|
||||
}
|
||||
|
||||
src_rotated_point += qdx;
|
||||
|
|
Loading…
Reference in a new issue