Creating a collage by combining an array of images (macOS & iOS)

In NewsWave, when you are in the “Add Feed” view you have the option to search the RSS repository, add a RSS URL or choose from ‘recommended feeds’. 

Recommended feeds may change over time so, instead of using static images, NewsWave looks at the feeds from each recommended category and creates a collage to represent the group. Here’s an example from NewsWave for iOS:IMG 4EB8598DD377 1

For the upcoming NewsWave for Mac version however, the code needed some tweaking. Below you’ll find both the mac and iOS versions -the function takes a rect (size of the desired outcome image) and a collection of images for the collage-.

In the version below it will output 2 rows and 3 columns but that can be easily tweaked by changing ’totalNumberOfColumns’ and ’totalNumberOfRows’. 

Here’s the macOS version:

    func collageImage(rect: CGRect, images: [NSImage]) -> NSImage {

        if images.count == 1 {

            return images.first!

        }

        

        let outcomeImage = NSImage(size: NSSize(width: rect.width, height: rect.height))

        outcomeImage.lockFocus()

        //Charecteristics of output

        let totalNumberOfColumns: CGFloat = 3

        let totalNumberOfRows: CGFloat = 2

        //Process

        let heightOfSubImage: CGFloat = rect.height/totalNumberOfRows

        let widthOfSubImage = rect.width/totalNumberOfColumns

        var columnNumber = 0

        var rowNumber = 0

        var i=0

        while i<images.count {

            let rectToDrawIn = CGRect(x: CGFloat(columnNumber)*widthOfSubImage, y: CGFloat(rowNumber)*heightOfSubImage, width: widthOfSubImage, height: heightOfSubImage)

            images[i].draw(in: rectToDrawIn)

            if columnNumber == (Int(totalNumberOfColumns) 1){

                rowNumber = rowNumber + 1

                columnNumber = 0

            }

            else {

                columnNumber = columnNumber + 1

            }

            i = i + 1

        }

        

        outcomeImage.unlockFocus()

        return outcomeImage

    }

 

And the iOS version:

    func collageImage(rect: CGRect, images: [UIImage]) -> UIImage {

        if images.count == 1 {

            return images.first!

        }

        

        UIGraphicsBeginImageContextWithOptions(rect.size, falseUIScreen.main.scale)

        //Charecteristics of output

        let totalNumberOfColumns: CGFloat = 3

        let totalNumberOfRows: CGFloat = 2

        //Process

        let heightOfSubImage: CGFloat = rect.height/totalNumberOfRows

        let widthOfSubImage = rect.width/totalNumberOfColumns

        var columnNumber = 0

        var rowNumber = 0

        var i=0

        while i<images.count {

            let rectToDrawIn = CGRect(x: CGFloat(columnNumber)*widthOfSubImage, y: CGFloat(rowNumber)*heightOfSubImage, width: widthOfSubImage, height: heightOfSubImage)

            images[i].drawInRectAspectFill(rect: rectToDrawIn)

            if columnNumber == (Int(totalNumberOfColumns) 1){

                rowNumber = rowNumber + 1

                columnNumber = 0

            }

            else {

                columnNumber = columnNumber + 1

            }

            i = i + 1

        }

        

        let outputImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

        return outputImage!

    }

 

Until next time, 

Marc

—-

 

Twitter -> @MarcMasVi