|
#include <metal_stdlib> |
|
using namespace metal; |
|
#include <CoreImage/CoreImage.h> |
|
|
|
extern "C" { namespace coreimage { |
|
float4 bilateralFilter(sampler src, float2 texelOffset, float distanceNormalizationFactor, destination dest) { |
|
const int gaussianSamples = 9; |
|
|
|
float2 blurCoordinates[9]; |
|
for (int i = 0; i < gaussianSamples; i++) { |
|
int multiplier = i - (gaussianSamples - 1) / 2; |
|
float2 blurStep = float(multiplier) * texelOffset; |
|
blurCoordinates[i] = dest.coord() + blurStep; |
|
} |
|
|
|
float4 centralColor = src.sample(src.transform(blurCoordinates[4])); |
|
float gaussianWeightTotal = 0.18; |
|
float4 sum = centralColor * gaussianWeightTotal; |
|
|
|
float4 sampleColor; |
|
float distanceFromCentralColor; |
|
float gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[0])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[1])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[2])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[3])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[5])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[6])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[7])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
sampleColor = src.sample(src.transform(blurCoordinates[8])); |
|
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0); |
|
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor); |
|
gaussianWeightTotal += gaussianWeight; |
|
sum += sampleColor * gaussianWeight; |
|
|
|
return sum / gaussianWeightTotal; |
|
} |
|
}} |