4

I'm trying to understand what is the most efficient way to create a CIImage with a pattern, based on an image file.

let patternImage = UIImage(named: "pattern.png")

The first approach I took:

// First create UIColor pattern
let uiColorPattern = UIColor(patternImage: patternImage!) 

// Than init CIColor using the UIColor pattern object
let ciColorPattern = CIColor(color: uiColorPattern)

// Finally, create CIImage using the CIColor initialiser
let ciImagePattern = CIImage(color: ciColorPattern) //

Sadly, for unknown reason the CIImage is simply blank. I also tried applying clampedToExtent() and than cropping it but it still blank.

The second approach I took (works but too slow):

UIGraphicsBeginImageContext(size) // create context

patternImage?.drawAsPattern(in: rect) // draw pattern as 'UIImage'

let patternUIImage = UIGraphicsGetImageFromCurrentImageContext() // fetch 'UIImage'

UIGraphicsEndImageContext() // end context

if let patternUIImage = patternUIImage {
     let ciImagePattern = CIImage(image: patternUIImage) // Create 'CIImage' using 'UIImage'
}    

this method works but as I said, too slow.


In general, my intuition was that if I could make the first approach work, it'll be a lot more efficient than the second approach.

Any other approaches/suggestions would be highly appreciated!

Roi Mulia
  • 5,626
  • 11
  • 54
  • 105
  • Why do you need this? What is the end result? How large is the pattern? – meaning-matters Dec 15 '17 at 20:46
  • Hey @meaning-matters . Thank you for replying. I need the CIImage to feed AVMutableVideoComposition->applyingCIFiltersWithHandler. (https://developer.apple.com/documentation/avfoundation/avasynchronousciimagefilteringrequest). The pattern image file is very small. But eventually the final rect i'll be applying it is about UIScreen bounds. Would love some assist over here :) – Roi Mulia Dec 16 '17 at 00:58
  • So are you applying this "pattern" over a strict bounds, or an infinite one? Have you actually tried any CIFIlter generators? –  Dec 18 '17 at 05:19
  • @dfd Yes, a strict bounds. (Let's assume I'm using UIScreen.main.bounds as my rect). I'm not trying CIFilter generator because I'm using file-based pattern. If there is a CIFilter that accept image as input and than generates CIImage pattern, it'll be perfect but I haven't found one – Roi Mulia Dec 18 '17 at 09:30
  • Hey @meaning-matters, Just PM'ing in case my comment didn't appear – Roi Mulia Dec 18 '17 at 22:27
  • Hey @dfd, Just PM'ing in case my comment didn't appear – Roi Mulia Dec 18 '17 at 22:28

1 Answers1

3

The first approach you are taking would not work as From WWDC 2013:

So, because, you know, and CIColor doesn't handle color spaces, it won't do CMYK color, it won't do patterns.

So, these are all things that you're going to lose.

If you ever think that you're going to need that, then probably not the right strategy.

So the second approach is what we can optimise on. I have a snippet which returns a pattern image you can give it a try.

        let myImage = UIImage.init(named: "www")
        let imageSize = myImage?.size
        let imageWidth = imageSize?.width
        let imageHeight = imageSize?.height
        let widthIterations = self.view.bounds.size.width / imageWidth!
        let heightIterations = self.view.bounds.size.height / imageHeight!

        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, true, UIScreen.main.scale)
        let context = UIGraphicsGetCurrentContext()


            for i in 0 ... Int(heightIterations) {
                let yPoint = CGFloat(i) * imageHeight!
                for j in 0 ... Int(widthIterations) {
                    let xPoint = CGFloat(j) * imageWidth!
                    myImage?.draw(at: CGPoint.init(x: xPoint, y: yPoint))
                }
            }
        let tempImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

enter image description here

Further reading

Md. Ibrahim Hassan
  • 5,359
  • 1
  • 25
  • 45