I am trying to mimic a vintage film grain effect as done by apple here. the problem lies in overlaying the grain image, when I composite it and crop it to the size of the original image, I am getting a bunch of weird patterns - this is consistent across multiple images and sizes, I have applied the grain image to a plain image to help show the effect.
As you can see, there is a consistent vertical and horizontal pattern, almost like a grid. Why is this happening and how can I prevent it from happening?
Grain generator function:
private func applyRandomGrain() {
/// generate grain & convert to grayscale
let grainGenerator = CIFilter.randomGenerator()
let grayscale = CIFilter.minimumComponent()
grayscale.inputImage = grainGenerator.outputImage
/// adjust brightness of grain image
let exposureFilter = CIFilter.exposureAdjust()
exposureFilter.inputImage = grayscale.outputImage
exposureFilter.ev = Float(settings.grainExposure)
/// adjust intensity of grain image with opacity
let alphaVector = CIVector(x: 0, y: 0, z: 0, w: settings.grainOpacity)
let alphaFilter = CIFilter.colorMatrix()
alphaFilter.inputImage = exposureFilter.outputImage
alphaFilter.aVector = alphaVector
guard let inputImage = outputImage else {
return
}
/// apply grain image to original image
let composite = CIFilter.sourceOverCompositing()
composite.backgroundImage = inputImage
composite.inputImage = alphaFilter.outputImage
guard let imageWithGrain = composite.outputImage else {
return
}
outputImage = imageWithGrain.cropped(to: inputImage)
}
EDIT: The example image is 1920x2560 - I have observed that the larger the image the more of a pattern there is. At a 100x100 image, there is no pattern.

The pattern generated by
CIRandomGeneratoris repeating. From the sample site you linked:This means every 512 pixels the pattern repeats. That's why you don't see the effect as strongly for smaller images.
If you want "true", non-repeating randomness, you have to implement your own filter kernel. For instance, one that implements Perlin noise.
Alternatively, if you don't mind using an internal filter from Apple (and that's a big if), you can use the
CIPhotoGrainfilter that does exactly that: simulate a photo grain effect caused by high ISO values.