X-Git-Url: https://git.sesse.net/?p=movit;a=blobdiff_plain;f=resample_effect.cpp;h=30c40c4145fdd73903a7ce485d8ca75f7b28c783;hp=9b6d5f3d4d964168d0a4a0f191e8552b1f54217d;hb=425d68dcbdd681ad3157000360521e8f36eb6c4c;hpb=b1b5194238dd8b357148a3eee48d8d3a1ad04b35 diff --git a/resample_effect.cpp b/resample_effect.cpp index 9b6d5f3..30c40c4 100644 --- a/resample_effect.cpp +++ b/resample_effect.cpp @@ -1,7 +1,7 @@ // Three-lobed Lanczos, the most common choice. // Note that if you change this, the accuracy for LANCZOS_TABLE_SIZE // needs to be recomputed. -#define LANCZOS_RADIUS 3.0 +#define LANCZOS_RADIUS 3.0f #include #include @@ -90,7 +90,7 @@ float lanczos_weight_cached(float x) return 0.0f; } float table_pos = x * (LANCZOS_TABLE_SIZE / LANCZOS_RADIUS); - int table_pos_int = int(table_pos); // Truncate towards zero. + unsigned table_pos_int = int(table_pos); // Truncate towards zero. float table_pos_frac = table_pos - table_pos_int; assert(table_pos < LANCZOS_TABLE_SIZE + 2); return lanczos_table[table_pos_int] + @@ -109,7 +109,7 @@ unsigned gcd(unsigned a, unsigned b) } template -unsigned combine_samples(const Tap *src, Tap *dst, float num_subtexels, float inv_num_subtexels, unsigned num_src_samples, unsigned max_samples_saved) +unsigned combine_samples(const Tap *src, Tap *dst, float num_subtexels, float inv_num_subtexels, unsigned num_src_samples, unsigned max_samples_saved, float pos1_pos2_diff, float inv_pos1_pos2_diff) { // Cut off near-zero values at both sides. unsigned num_samples_saved = 0; @@ -157,7 +157,7 @@ unsigned combine_samples(const Tap *src, Tap *dst, float num_s DestFloat pos, total_weight; float sum_sq_error; - combine_two_samples(w1, w2, pos1, pos2, num_subtexels, inv_num_subtexels, &pos, &total_weight, &sum_sq_error); + combine_two_samples(w1, w2, pos1, pos1_pos2_diff, inv_pos1_pos2_diff, num_subtexels, inv_num_subtexels, &pos, &total_weight, &sum_sq_error); // If the interpolation error is larger than that of about sqrt(2) of // a level at 8-bit precision, don't combine. (You'd think 1.0 was enough, @@ -210,10 +210,12 @@ unsigned combine_many_samples(const Tap *weights, unsigned src_size, unsi { float num_subtexels = src_size / movit_texel_subpixel_precision; float inv_num_subtexels = movit_texel_subpixel_precision / src_size; + float pos1_pos2_diff = 1.0f / src_size; + float inv_pos1_pos2_diff = src_size; unsigned max_samples_saved = UINT_MAX; for (unsigned y = 0; y < dst_samples && max_samples_saved > 0; ++y) { - unsigned num_samples_saved = combine_samples(weights + y * src_samples, NULL, num_subtexels, inv_num_subtexels, src_samples, max_samples_saved); + unsigned num_samples_saved = combine_samples(weights + y * src_samples, NULL, num_subtexels, inv_num_subtexels, src_samples, max_samples_saved, pos1_pos2_diff, inv_pos1_pos2_diff); max_samples_saved = min(max_samples_saved, num_samples_saved); } @@ -228,7 +230,9 @@ unsigned combine_many_samples(const Tap *weights, unsigned src_size, unsi num_subtexels, inv_num_subtexels, src_samples, - max_samples_saved); + max_samples_saved, + pos1_pos2_diff, + inv_pos1_pos2_diff); assert(num_samples_saved == max_samples_saved); normalize_sum(bilinear_weights_ptr, src_bilinear_samples); } @@ -249,10 +253,10 @@ double compute_sum_sq_error(const Tap* weights, unsigned num_weights, // Find the effective range of the bilinear-optimized kernel. // Due to rounding of the positions, this is not necessarily the same // as the intended range (ie., the range of the original weights). - int lower_pos = int(floor(to_fp32(bilinear_weights[0].pos) * size - 0.5)); - int upper_pos = int(ceil(to_fp32(bilinear_weights[num_bilinear_weights - 1].pos) * size - 0.5)) + 2; - lower_pos = min(lower_pos, lrintf(weights[0].pos * size - 0.5)); - upper_pos = max(upper_pos, lrintf(weights[num_weights - 1].pos * size - 0.5) + 1); + int lower_pos = int(floor(to_fp32(bilinear_weights[0].pos) * size - 0.5f)); + int upper_pos = int(ceil(to_fp32(bilinear_weights[num_bilinear_weights - 1].pos) * size - 0.5f)) + 2; + lower_pos = min(lower_pos, lrintf(weights[0].pos * size - 0.5f)); + upper_pos = max(upper_pos, lrintf(weights[num_weights - 1].pos * size - 0.5f) + 1); float* effective_weights = new float[upper_pos - lower_pos]; for (int i = 0; i < upper_pos - lower_pos; ++i) { @@ -271,7 +275,7 @@ double compute_sum_sq_error(const Tap* weights, unsigned num_weights, assert(x0 < upper_pos - lower_pos); assert(x1 < upper_pos - lower_pos); - effective_weights[x0] += to_fp32(bilinear_weights[i].weight) * (1.0 - f); + effective_weights[x0] += to_fp32(bilinear_weights[i].weight) * (1.0f - f); effective_weights[x1] += to_fp32(bilinear_weights[i].weight) * f; } @@ -638,11 +642,12 @@ ScalingWeights calculate_scaling_weights(unsigned src_size, unsigned dst_size, f int base_src_y = lrintf(center_src_y); // Now sample pixels on each side around that point. + float inv_src_size = 1.0 / float(src_size); for (int i = 0; i < src_samples; ++i) { int src_y = base_src_y + i - int_radius; float weight = lanczos_weight_cached(radius_scaling_factor * (src_y - center_src_y - subpixel_offset)); weights[y * src_samples + i].weight = weight * radius_scaling_factor; - weights[y * src_samples + i].pos = (src_y + 0.5) / float(src_size); + weights[y * src_samples + i].pos = (src_y + 0.5f) * inv_src_size; } }