Interpolate on quantized values for tiled images.

This commit is contained in:
Fabien Freling 2014-07-08 08:04:43 +02:00
parent bb996596e4
commit 9a9db2d4fd
2 changed files with 34 additions and 45 deletions

View file

@ -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

View file

@ -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)