Dani
Dani

Reputation: 3637

Get average color of UIImage

I'm trying to do something similar to what Twitter and many other apps do - set the background to the average color of an image. The problem is that based on the array of images that I have, it gets the last average color and it's never being changed. The background color for the UIScrollView in which those images are located. I'm not sure why.

This is the code that I'm using to extract the average color (PS: I found it here)

import UIKit

extension UIImage {
    var averageColor: UIColor? {
        guard let inputImage = CIImage(image: self) else { return nil }
        let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height)

        guard let filter = CIFilter(name: "CIAreaAverage", withInputParameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil }
        guard let outputImage = filter.outputImage else { return nil }

        var bitmap = [UInt8](repeating: 0, count: 4)
        let context = CIContext(options: [kCIContextWorkingColorSpace: kCFNull])
        context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: kCIFormatRGBA8, colorSpace: nil)

        return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255)
    }
}

And here's the code for the function that's being called in the viewDidLoad():

    func setScrollView() {
    for  i in stride(from: 0, to: imagelist.count, by: 1) {
        var frame = CGRect.zero
        frame.origin.x = self.scrollView.frame.size.width * CGFloat(i)
        frame.origin.y = 0
        frame.size = self.scrollView.frame.size
        scrollView.isPagingEnabled = true

        let newUIImageView = UIImageView()
        let myImage:UIImage = UIImage(named: imagelist[i])!
        let bgColorFromImage = myImage.averageColor
        newUIImageView.image = myImage
        newUIImageView.frame =  frame

        newUIImageView.contentMode = UIViewContentMode.scaleAspectFit

        scrollView.backgroundColor = bgColorFromImage // Changes the color to the average color of the image
        scrollView.addSubview(newUIImageView)

        self.scrollView.contentSize = CGSize(width: self.scrollView.frame.size.width * CGFloat(imagelist.count), height: self.scrollView.frame.size.height)
        pageControl.addTarget(self, action: #selector(changePage), for: UIControlEvents.valueChanged)
    }
}

Upvotes: 3

Views: 1134

Answers (1)

Dani
Dani

Reputation: 3637

I figured it out. I needed to create an array of UIColors to store all of the colors of the images:

var colors = [UIColor]()

Then in setScrollView() append the color like so:

colors.append(myImage.averageColor!)

And lastly, in the scrollViewDidEndDecelerating(_ scrollView: UIScrollView) set the background like so:

scrollView.backgroundColor = colors[Int(pageNumber)]

Upvotes: 1

Related Questions