diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/nlmeans.c | 111 |
1 files changed, 108 insertions, 3 deletions
diff --git a/libhb/nlmeans.c b/libhb/nlmeans.c index 458a76ab5..dd1fe5b3e 100644 --- a/libhb/nlmeans.c +++ b/libhb/nlmeans.c @@ -72,8 +72,8 @@ #define NLMEANS_PREFILTER_MODE_MEAN5X5 2 #define NLMEANS_PREFILTER_MODE_MEDIAN3X3 4 #define NLMEANS_PREFILTER_MODE_MEDIAN5X5 8 -#define NLMEANS_PREFILTER_MODE_RESERVED16 16 // Reserved -#define NLMEANS_PREFILTER_MODE_RESERVED32 32 // Reserved +#define NLMEANS_PREFILTER_MODE_CSM3X3 16 +#define NLMEANS_PREFILTER_MODE_CSM5X5 32 #define NLMEANS_PREFILTER_MODE_RESERVED64 64 // Reserved #define NLMEANS_PREFILTER_MODE_RESERVED128 128 // Reserved #define NLMEANS_PREFILTER_MODE_REDUCE25 256 @@ -385,6 +385,99 @@ static void nlmeans_filter_median(const uint8_t *src, } +static void nlmeans_filter_csm(const uint8_t *src, + uint8_t *dst, + const int w, + const int h, + const int border, + const int size) +{ + // CSM filter + const int bw = w + 2 * border; + const int offset_min = -((size - 1) /2); + const int offset_max = (size + 1) /2; + uint8_t min, max, + min2, max2, + min3, max3, + median, + pixel; + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + for (int k = offset_min; k < offset_max; k++) + { + for (int j = offset_min; j < offset_max; j++) + { + if (k == 0 && j == 0) + { + // Ignore origin + goto end; + } + pixel = *(src + bw*(y+j) + (x+k)); + if (k == offset_min && j == offset_min) + { + // Start calculating neighborhood thresholds + min = pixel; + max = min; + goto end; + } + if (pixel < min) + { + min = pixel; + } + if (pixel > max) + { + max = pixel; + } + } + end: + continue; + } + + // Final neighborhood thresholds + // min = minimum neighbor pixel value + // max = maximum neighbor pixel value + + // Median + median = (min + max) / 2; + + // Additional thresholds for median-like filtering + min2 = (min + median) / 2; + max2 = (max + median) / 2; + min3 = (min2 + median) / 2; + max3 = (max2 + median) / 2; + + // Clamp to thresholds + pixel = *(src + bw*(y) + (x)); + if (pixel < min) + { + *(dst + bw*y + x) = min; + } + else if (pixel > max) + { + *(dst + bw*y + x) = max; + } + else if (pixel < min2) + { + *(dst + bw*y + x) = min2; + } + else if (pixel > max2) + { + *(dst + bw*y + x) = max2; + } + else if (pixel < min3) + { + *(dst + bw*y + x) = min3; + } + else if (pixel > max3) + { + *(dst + bw*y + x) = max3; + } + } + } +} + static void nlmeans_filter_edgeboost(const uint8_t *src, uint8_t *dst, const int w, @@ -496,7 +589,9 @@ static void nlmeans_prefilter(BorderedPlane *src, if (filter_type & NLMEANS_PREFILTER_MODE_MEAN3X3 || filter_type & NLMEANS_PREFILTER_MODE_MEAN5X5 || filter_type & NLMEANS_PREFILTER_MODE_MEDIAN3X3 || - filter_type & NLMEANS_PREFILTER_MODE_MEDIAN5X5) + filter_type & NLMEANS_PREFILTER_MODE_MEDIAN5X5 || + filter_type & NLMEANS_PREFILTER_MODE_CSM3X3 || + filter_type & NLMEANS_PREFILTER_MODE_CSM5X5) { // Source image @@ -537,6 +632,16 @@ static void nlmeans_prefilter(BorderedPlane *src, // Mean 3x3 nlmeans_filter_mean(image, image_pre, w, h, border, 3); } + else if (filter_type & NLMEANS_PREFILTER_MODE_CSM3X3) + { + // CSM 3x3 + nlmeans_filter_csm(image, image_pre, w, h, border, 3); + } + else if (filter_type & NLMEANS_PREFILTER_MODE_CSM5X5) + { + // CSM 5x5 + nlmeans_filter_csm(image, image_pre, w, h, border, 5); + } // Restore edges if (filter_type & NLMEANS_PREFILTER_MODE_EDGEBOOST) |