diff --git a/TODO.md b/TODO.md index 5c7f8c5..307058e 100644 --- a/TODO.md +++ b/TODO.md @@ -6,14 +6,14 @@ [ ] Fix out-of-bounds pixel set [ ] Optimization for square images? -[ ] Fixed point computation? +[X] Fixed point computation? # Cache [-] Rotate per channel -> no gain [ ] Load pixels in uint64-t [X] Cut image in tiles [ ] Overlap? - [ ] Rotate in one temp tile then copy/move it + [X] Rotate in one temp tile then copy/move it [-] Align memory -> no gain # Quality diff --git a/rotation.cpp b/rotation.cpp index f17cce6..b5e21d6 100644 --- a/rotation.cpp +++ b/rotation.cpp @@ -730,28 +730,15 @@ Image* rotate(Image const& src, double angle) template void rotate_pixel(TiledImage const& src, - DPoint const& src_rotated_point, - uint8_t* rot_tile, unsigned int rot_index, - bool full_delta) + Point const& src_rotated_point, + uint8_t* rot_tile, unsigned int rot_index) { - int const src_x = (int) src_rotated_point.x; - int const src_y = (int) src_rotated_point.y; + unsigned int const quantize = 8; + + int const src_x = src_rotated_point.x >> 3; + int const src_y = src_rotated_point.y >> 3; + uint8_t const* src_index_1 = src.access_pixel(src_x, src_y); - - // special case if we can directly map the src to the dest - if (full_delta) - { - memcpy(&rot_tile[rot_index], src_index_1, 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; - uint8_t const* src_index_2 = src.access_pixel(src_x + 1, src_y); uint8_t const* src_index_3 = src.access_pixel(src_x, src_y + 1); uint8_t const* src_index_4 = src.access_pixel(src_x + 1, src_y + 1); @@ -760,13 +747,18 @@ void rotate_pixel(TiledImage const& src, if (!src_index_4) return; + 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 - rot_tile[rot_index] = (src_index_1[0] * inv_x + src_index_2[0] * x_delta) * inv_y - + (src_index_3[0] * inv_x + src_index_4[0] * x_delta) * y_delta; - rot_tile[rot_index + 1] = (src_index_1[1] * inv_x + src_index_2[1] * x_delta) * inv_y - + (src_index_3[1] * inv_x + src_index_4[1] * x_delta) * y_delta; - rot_tile[rot_index + 2] = (src_index_1[2] * inv_x + src_index_2[2] * x_delta) * inv_y - + (src_index_3[2] * inv_x + src_index_4[2] * x_delta) * y_delta; + rot_tile[rot_index] = ((src_index_1[0] * inv_x + src_index_2[0] * x_delta) * inv_y + + (src_index_3[0] * inv_x + src_index_4[0] * x_delta) * y_delta) >> 6; + rot_tile[rot_index + 1] = ((src_index_1[1] * inv_x + src_index_2[1] * x_delta) * inv_y + + (src_index_3[1] * inv_x + src_index_4[1] * x_delta) * y_delta) >> 6; + rot_tile[rot_index + 2] = ((src_index_1[2] * inv_x + src_index_2[2] * x_delta) * inv_y + + (src_index_3[2] * inv_x + src_index_4[2] * x_delta) * y_delta) >> 6; } template @@ -791,13 +783,6 @@ rotate(TiledImage 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; - 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); @@ -805,6 +790,10 @@ rotate(TiledImage const& src, double angle) uint8_t tile[W * H * 3]; memset(tile, 0, W * H * 3); + 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->nb_row_tile; ++y) { for (unsigned int x = 0; x < rotated->nb_col_tile; ++x) @@ -816,20 +805,20 @@ rotate(TiledImage const& src, double angle) { int const y_index = y * H + j; int x_index = x * W; - DPoint src_rotated_point(rot_origin_in_src.x + x_index * src_delta_x.x + y_index * src_delta_y.x, - rot_origin_in_src.y + x_index * src_delta_x.y + y_index * src_delta_y.y); + DPoint const src_rotated_point((rot_origin_in_src.x + x_index * src_delta_x.x + y_index * src_delta_y.x) * quantize, + (rot_origin_in_src.y + x_index * src_delta_x.y + y_index * src_delta_y.y) * quantize); for (unsigned int i = 0; i < W; ++i) { - 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 + i * src_delta_x.x * quantize, + src_rotated_point.y + i * 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, - tile, rot_index, full_delta); + rotate_pixel(src, src_runner, tile, rot_index); } - src_rotated_point.x += src_delta_x.x; - src_rotated_point.y += src_delta_x.y; rot_index += 3; } } @@ -1022,10 +1011,9 @@ int main(int argc, char* argv[]) } } - Image img(argv[1]); - TiledImage<8, 8> tiled_img(argv[1]); // No tile + Image img(argv[1]); float average = 0.0; int i = 0; for (double rotation = 0; rotation < 360; rotation += 45) @@ -1046,6 +1034,7 @@ int main(int argc, char* argv[]) cout << " average: " << average / i << "ms" << endl << endl; // Tile + TiledImage<8, 8> tiled_img(argv[1]); average = 0.0; i = 0; for (double rotation = 0; rotation < 360; rotation += 45)