From 68fb1b19513d61f7229e2140e768acccbdbe3660 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Mon, 7 Jul 2014 23:19:57 +0200 Subject: [PATCH] Do interpolation on quantized values. --- rotation.cpp | 89 ++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 52 deletions(-) diff --git a/rotation.cpp b/rotation.cpp index 2377dd8..6a81a0a 100644 --- a/rotation.cpp +++ b/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) { - int x = p.x + (img.width / 2.0f) - 0.5; - int y = p.y + (img.height / 2.0f) - 0.5; + double x = p.x + (img.width / 2.0f) - 0.5; + double y = p.y + (img.height / 2.0f) - 0.5; return DPoint(x, y); } @@ -592,21 +592,17 @@ DPoint get_mapped_point(Image const& src, Point const& p, double const rotation) } inline -void rotate_pixel(Image const& src, /*uint8_t* rotated,*/ - DPoint const& src_rotated_point, /*Point const& rot_point,*/ - unsigned int const src_limit, unsigned int const rot_limit, - uint8_t* rotate_buffer, unsigned int rot_index, - bool full_delta) +void rotate_pixel(Image const& src, + Point const& src_rotated_point, + unsigned int const src_limit, + uint8_t* rotate_buffer, unsigned int rot_index) { - int const src_x = (int) src_rotated_point.x; - 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; + unsigned int const quantize = 8; - // Out-of-bounds check - if (src_index >= src_limit - || rot_index >= rot_limit) - return; + int const src_x = src_rotated_point.x >> 3; + int const src_y = src_rotated_point.y >> 3; + + unsigned int src_index = (src_y * src.width + src_x) * 3; // Bilinear interpolation 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_4 = src_index_3 + 3; + // Out-of-bounds check if (src_index_4 >= src_limit) return; - // special case if we can directly map the src to the dest - if (full_delta) - { - memcpy(&rotate_buffer[rot_index], &src.buffer[src_index], 3 * sizeof (uint8_t)); - 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; + unsigned int x_delta = src_rotated_point.x & 0x07;; + unsigned int y_delta = src_rotated_point.y & 0x07; + unsigned int const inv_x = quantize - x_delta; + unsigned int const inv_y = quantize - y_delta; // No SIMD - 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; - 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; - 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; + 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) >> 6; + 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 + + (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) @@ -673,13 +661,6 @@ Image* rotate(Image const& src, double angle) 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.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) 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); 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 = 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); 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) { - //memset(buffer, 0, buffer_size); - DPoint src_rotated_point(rot_origin_in_src.x + y * src_delta_y.x, - rot_origin_in_src.y + y * src_delta_y.y); + Point const src_rotated_point((rot_origin_in_src.x + y * src_delta_y.x) * quantize, + (rot_origin_in_src.y + y * src_delta_y.y) * quantize); for (unsigned int x = 0; x < rotated->width; ++x) { - if (src_rotated_point.x >= 0 && src_rotated_point.x < src.width - && src_rotated_point.y >= 0 && src_rotated_point.y < src.height) + Point const src_runner(src_rotated_point.x + x * src_delta_x.x * quantize, + 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, - src_limit, rot_limit, - buffer, buffer_index * 3, full_delta); + rotate_pixel(src, src_runner, + src_limit, + buffer, buffer_index * 3); } - src_rotated_point.x += src_delta_x.x; - src_rotated_point.y += src_delta_x.y; + // Flush buffer to dest ++buffer_index; if (buffer_index == buffer_pixel_capacity) {