Interpolate on quantized values for tiled images.
This commit is contained in:
parent
bb996596e4
commit
9a9db2d4fd
4
TODO.md
4
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
|
||||
|
|
75
rotation.cpp
75
rotation.cpp
|
@ -730,28 +730,15 @@ Image* rotate(Image const& src, double angle)
|
|||
|
||||
template<unsigned int W, unsigned int H>
|
||||
void rotate_pixel(TiledImage<W, H> 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<W, H> 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<unsigned int W, unsigned int H>
|
||||
|
@ -791,13 +783,6 @@ rotate(TiledImage<W, H> 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<W, H> 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<W, H> 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)
|
||||
|
|
Loading…
Reference in a new issue