Fabulous Image Processing in Swift

Related tags

Image Toucan
Overview

Toucan: Fabulous Image Processing in Swift

Build Status CocoaPods Carthage compatible

Toucan is a Swift library that provides a clean, quick API for processing images. It greatly simplifies the production of images, supporting resizing, cropping and stylizing your images.

Features

  • Easy and smart resizing
  • Elliptical and rounded rect masking
  • Mask with custom images
  • Chainable image processing stages

Requirements

  • Xcode 10.0+
  • iOS 11.0+

Setup

  • Install using CocoaPods: https://cocoapods.org/pods/Toucan
  • or manually include the Toucan framework by dragging it into your project and import the library in your code using import Toucan

Toucan Usage

Toucan provides two methods of interaction - either through wrapping an single image within a Toucan instance, or through the static functions, providing an image for each invocation. This allows for some very flexible usage.

Create an instance wrapper for easy method chaining:

let resizedAndMaskedImage = Toucan(image: myImage).resize(CGSize(width: 100, height: 150)).maskWithEllipse().image

Or, using static methods when you need a single operation:

let resizedImage = Toucan.Resize.resizeImage(myImage, size: CGSize(width: 100, height: 150))
let resizedAndMaskedImage = Toucan.maskWithEllipse(resizedImage)

Typically, the instance version is a bit cleaner to use, and the one you want.

Resizing

Resize the contained image to the specified size. Depending on what fitMode is supplied, the image may be clipped, cropped or scaled.

Toucan(image: myImage).resize(size: CGSize, fitMode: Toucan.Resize.FitMode)

Fit Mode

FitMode drives the resizing process to determine what to do with an image to make it fit the given size bounds.

Example Mode
Clip Clip Mode
Toucan.Resize.FitMode.Clip
Resizes the image to fit within the width and height boundaries without cropping or distorting the image.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Clip).image
Crop Crop Mode
Toucan.Resize.FitMode.crop
Resizes the image to fill the width and height boundaries and crops any excess image data.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Crop).image
Scale Scale Mode
Toucan.Resize.FitMode.scale
Scales the image to fit the constraining dimensions exactly.

Toucan(image: portraitImage).resize(CGSize(width: 500, height: 500), fitMode: Toucan.Resize.FitMode.Scale).image

Masking

Alter the original image with a mask; supports ellipse, rounded rect and image masks.

Ellipse Mask

Example Function
Ellipse Mask Mask the given image with an ellipse. Allows specifying an additional border to draw on the clipped image. For a circle, ensure the image width and height are equal!

Toucan(image: myImage).maskWithEllipse().image
Ellipse Mask w. Border When specifying a border width, it is draw on the clipped image.

Toucan(image: myImage).maskWithEllipse(borderWidth: 10, borderColor: UIColor.yellowColor()).image

Path Mask

Example Function
Path Mask Mask the given image with a path. The path will be scaled to fit the image correctly!

path.moveToPoint(CGPointMake(0, 50))
path.addLineToPoint(CGPointMake(50, 0))
path.addLineToPoint(CGPointMake(100, 50))
path.addLineToPoint(CGPointMake(50, 100))
path.closePath()
Toucan(image: myImage).maskWithPath(path: path).image
Path Mask w. Closure Mask the given image with a path provided via a closure. This allows you to construct your path relative to the bounds of the image!

Toucan(image: myImage).maskWithPathClosure(path: (rect: CGRect) -> (UIBezierPath)).image

Rounded Rect Mask

Example Function
Rounded Rect Mask Mask the given image with a rounded rectangle border. Allows specifying an additional border to draw on the clipped image.

Toucan(image: myImage).maskWithRoundedRect(cornerRadius: 30).image
Rounded Rect Mask w. Border When specifying a border width, it is draw on the clipped rounded rect.

Toucan(image: myImage).maskWithRoundedRect(cornerRadius: 30, borderWidth: 10, borderColor: UIColor.purpleColor()).image

Image Mask

Example Function
Image Mask Mask the given image with another image mask. Note that the areas in the original image that correspond to the black areas of the mask show through in the resulting image. The areas that correspond to the white areas of the mask aren’t painted. The areas that correspond to the gray areas in the mask are painted using an intermediate alpha value that’s equal to 1 minus the image mask sample value.

Toucan(image: myImage).maskWithImage(maskImage: octagonMask).image

Example Images

Example images used under Creative Commons with thanks to:

Contributing

  1. Please fork this project
  2. Implement new methods or changes in the Toucan.swift file.
  3. Write tests in the ToucanTests folder.
  4. Write appropriate docs and comments in the README.md
  5. Submit a pull request.

Contact

Raise an Issue or hit me up on Twitter @gavinbunney

License

Toucan is released under an MIT license. See LICENSE for more information.

Comments
  • Toucan Memory Leaks

    Toucan Memory Leaks

    Hi, I use your library to resize my images in my tableview and I noticed that the memory keeps increasing in my app when I use instruments. It shows your library and I checked out your code and I noticed that theres not memory management handling in your closures. It shows that on line 598 on the Toucan class reaching 200+mb's in the closure. Do you mind if I make a pull request and do a fix on it? I'm using your library for a production app

    bug 
    opened by DrewKiino 19
  • Crash

    Crash

    My app keeps crashing at this point when I try to resize an image and add a corner radius mask:

    The crash occurs at this point:

            static func drawImageWithClosure(size size: CGSize!, closure: (size: CGSize, context: CGContext) -> ()) -> UIImage {
                UIGraphicsBeginImageContextWithOptions(size, false, 0)
                closure(size: size, context: UIGraphicsGetCurrentContext()!)
                let image : UIImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image
            }
    

    UIGraphicsGetCurrentContext()! ==> fatal error: unexpectedly found nil while unwrapping an Optional value

    bug 
    opened by pjebs 5
  • Unable to compile Toucan (installed via Cocoapods) once main project has migrated to Swift 4.2

    Unable to compile Toucan (installed via Cocoapods) once main project has migrated to Swift 4.2

    Not sure what the desired way to resolve this would be:

    • The current podspec could be updated, with the spec.swift_version property set to '4.0'
    • Wait until Swift 4.2 has been released fully and migrate Toucan accordingly.

    In either case, setting the swift_version in the podspec would be a good idea to avoid this sort of thing in the future.

    Note that the migrations for Toucan are (so far) very simple, just several instances of

    UIImageOrientation has been renamed to UIImage.Orientation.

    opened by MattCarr147 4
  • resizeByScaling not working

    resizeByScaling not working

    I have the same code which I use on iPad mini 1 and iPhone 6. The code takes photo by camera and then applies resizeByScaling:CGSizeMake(128, 128).

    For iPad mini 1: it correctly resizes the image to 128x128. On iPhone 6, it is 256x256.

    I think there is something wrong with the function. Perhaps it doesn't factor in retina level????

    question 
    opened by pjebs 4
  • crash with resizing rotated image

    crash with resizing rotated image

    I am getting an exception when trying to resize the attached image (I hope the upload won't change the metadata)

    Toucan.swift: 549 in Util.CGImageWithCorrectOrientation

    : CGBitmapContextCreate: invalid data bytes/row: should be at least 4000 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipLast

    I think this is the same issue related to orientation: http://stackoverflow.com/a/11958833

    image

    opened by stachon 4
  • Make Toucan resilient

    Make Toucan resilient

    We've recently had some crashes in our app due to the overuse of force unwrapped optionals in Toucan, so we've created our own fork to avoid them. And maybe it is also useful for others, so here you have this PR 😄

    Basically what this PR does is just return an "empty" UIImage whenever something in the processing goes wrong.

    opened by polqf 3
  • How can I get the Toucan framework?

    How can I get the Toucan framework?

    I found that Toucan framework is not in zip file,so I tried to build and archive the Toucan project. Finally I got a Toucan.framework,but I found the header file just include:

    #import <UIKit/UIKit.h>
    
    //! Project version number for Toucan.
    FOUNDATION_EXPORT double ToucanVersionNumber;
    
    //! Project version string for Toucan.
    FOUNDATION_EXPORT const unsigned char ToucanVersionString[];
    

    Is anything I did wrong?

    opened by akring 3
  • Fix image dimensions for rotated images (left or right)

    Fix image dimensions for rotated images (left or right)

    It looks like the image dimensions are swapped for left or right orientated images. I get stretched/scaled images after calling resizeImage when the image orientation is left, left mirrored, right, or right mirrored (for example, images from the device camera in portrait orientation). This seemed to fix the issue.

    If we could get another v3 release as well, that would be great. Here are my changes for v3.

    opened by djtarazona 3
  • Disable code coverage on both iOS and tvOS targets

    Disable code coverage on both iOS and tvOS targets

    See https://developer.apple.com/library/content/qa/qa1964/_index.html#//apple_ref/doc/uid/DTS40017675 and https://github.com/Carthage/Carthage/pull/2057

    opened by mihai8804858 2
  • crash on selecting image taken by front camera

    crash on selecting image taken by front camera

    I got this error when i select image captured by front camera.

    let myImage = Toucan.init(image: images[0]).image

    This is the error message:

    UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
    The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
    Dec 27 22:56:42  mask It[469] <Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 1920 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipFirst.
    fatal error: unexpectedly found nil while unwrapping an Optional value
    
    opened by iballan 2
  • How to crop from top left

    How to crop from top left

    When using resize and crop mode, it appears to crop the image from the middle. How can we crop from the top left corner? For example, if I have a UIImageView that is 400 x 200 and I want the image to be 400 width but crop anything over 200 high so just the top 200 pixels are visible, how can I do that?

    opened by noctivityinc 2
  • Drawing off main thread

    Drawing off main thread

    Do you have any best practices/guide for using the API in a way that doesn't block the main thread?

    let roundImage = Toucan(image: image).maskWithEllipse(borderWidth: 3.0, borderColor: UIColor.white).image
    

    Especially when used in a TableView with lots of rounded images causes quite a bit of main thread activity.

    toucan
    opened by klische 0
  • Images are resized to integers not floats

    Images are resized to integers not floats

    The following code takes the upper bound of 170.6666 (which is 171) when UIScreen.main.scale is 3.0

    let size = 512 / UIScreen.main.scale
    let image = Toucan(image: item.image!).resize(CGSize(width: size, height: size), fitMode: Toucan.Resize.FitMode.clip).image!
    

    It should have been resized the image according to the float in size. Not the upper bound of it.

    opened by anonrig 0
  • Crash in CGImageWithCorrectOrientation

    Crash in CGImageWithCorrectOrientation

    We currently expire crashes in our app, which we "fixed" by removing force unwraps and adding logging to get more insights.

    Crashlog

    Crashed: com.apple.root.user-interactive-qos
    0  Rabbit                         0x104977fc4 specialized static Toucan.Util.CGImageWithCorrectOrientation(UIImage) -> CGImage (Toucan.swift:571)
    1  Rabbit                         0x10497871c specialized static Toucan.Resize.resizeImage(UIImage, size : CGSize, fitMode : Toucan.Resize.FitMode) -> UIImage? (Toucan.swift)
    2  Rabbit                         0x1049c9100 specialized ThumbnailGenerator.generate(for : UIImage) -> [ThumbnailGenerator.GeneratedThumbnail] (ThumbnailGenerator.swift:61)
    3  Rabbit                         0x1049fa134 specialized ContentMetadataFetcher.(generateVisualPreviews(for : Content, image : UIImage, storageController : LocalStorageController, completionHandler : ([VisualPreview]) -> ()) -> ()).(closure #2).(closure #1) (ContentMetadataFetcher+Thumbnails.swift:73)
    4  Rabbit                         0x1049fa08c partial apply for ContentMetadataFetcher.(generateVisualPreviews(for : Content, image : UIImage, storageController : LocalStorageController, completionHandler : ([VisualPreview]) -> ()) -> ()).(closure #2).(closure #1) (ContentMetadataFetcher+Thumbnails.swift)
    5  Rabbit                         0x10493db00 thunk (ContentCreationController.swift)
    6  libdispatch.dylib              0x1851a6a54 _dispatch_call_block_and_release + 24
    7  libdispatch.dylib              0x1851a6a14 _dispatch_client_callout + 16
    8  libdispatch.dylib              0x1851b3ea4 _dispatch_root_queue_drain + 1032
    9  libdispatch.dylib              0x1851b3a38 _dispatch_worker_thread3 + 120
    10 libsystem_pthread.dylib        0x18544f06c _pthread_wqthread + 1268
    11 libsystem_pthread.dylib        0x18544eb6c start_wqthread + 4
    

    Device and system information

    iOS 10 and iOS 11 iPad and iPhone

    Known stats from logging

    The crash is happening on this line which force unwraps the CGContext. It seems that scenarios exist in which the created context is nil.

    After adding a guard and logging in the return statement, we've seen logs like this:

    Error Domain=Toucan Code=-3 "width: 3840 height: 5760 bitsPerComponent: 8 bitmapInfo: 5" UserInfo={NSLocalizedDescription=width: 3840 height: 5760 bitsPerComponent: 8 bitmapInfo: 5}
    
    Error Domain=Toucan Code=-3 "width: 120 height: 160 bitsPerComponent: 8 bitmapInfo: 0" UserInfo={NSLocalizedDescription=width: 120 height: 160 bitsPerComponent: 8 bitmapInfo: 0}
    

    I've tried to reproduce the crash by hardcoding these values, but that didn't reproduce the crash. I've also made sure that the cgImage and Colorspace are non nil:

    guard let cgImage = image.cgImage else {
        throw NSError(domain: "Toucan", code: -1, userInfo: [NSLocalizedDescriptionKey: "CGImage is nil"])
    }
    
    guard let colorSpace = cgImage.colorSpace else {
        throw NSError(domain: "Toucan", code: -2, userInfo: [NSLocalizedDescriptionKey: "Color space is nil"])
    }
    

    We've never seen these being logged.

    Next steps

    We for now prevented this crash from happening again by adding guards and throws instead of force unwrapping. It would be great if we can find the cause of this crash and fix it instead.

    opened by AvdLee 2
  • Resize with FitMode.crop decrease image quality

    Resize with FitMode.crop decrease image quality

    Hello,

    We're using toucan in our app to resize product images using FitMode.crop. This fit mode produce really bad quality image even though the cropped image would maintain same aspect ratio as the original image.

    Resize code in UIImageExtension:

    Toucan(image: self).resize(CGSize(width: 345, height: 519), fitMode: Toucan.Resize.FitMode.crop).image!

    I couldn't find any reason why this is happening. Please help.

    opened by thebigkhaled 1
Owner
Gavin Bunney
Cloud tools and automation is my jam
Gavin Bunney
GPUImage 3 is a BSD-licensed Swift framework for GPU-accelerated video and image processing using Metal.

GPUImage 3 Janie Clayton http://redqueengraphics.com @RedQueenCoder Brad Larson http://www.sunsetlakesoftware.com @bradlarson contact@sunsetlakesoftwa

Brad Larson 2.4k Jan 3, 2023
A high-performance image library for downloading, caching, and processing images in Swift.

Features Asynchronous image downloader with priority queuing Advanced memory and database caching using YapDatabase (SQLite) Guarantee of only one ima

Yap Studios 72 Sep 19, 2022
An open source iOS framework for GPU-based image and video processing

GPUImage Brad Larson http://www.sunsetlakesoftware.com @bradlarson [email protected] Overview The GPUImage framework is a BSD-licensed iO

Brad Larson 20k Jan 1, 2023
A GPU accelerated image and video processing framework built on Metal.

MetalPetal An image processing framework based on Metal. Design Overview Goals Core Components MTIContext MTIImage MTIFilter MTIKernel Optimizations C

null 1.5k Jan 4, 2023
GPU-based media processing library using Metal written in Swift

GPU-based media processing library using Metal written in Swift. Overview MetalAcc is a GPU-Based media processing library that lets you apply GPU-acc

Jiawei Wang 259 Dec 17, 2022
IOS UIImage processing functions using the vDSP/Accellerate framework for speed.

UIImage Image Processing extensions using the vDSP/Accelerate framework.

null 372 Sep 1, 2022
Advanced framework for loading, caching, processing, displaying and preheating images.

Advanced framework for loading, caching, processing, displaying and preheating images. This framework is no longer maintained. Programming in Swift? C

Alexander Grebenyuk 1.2k Dec 23, 2022
PublisherKit - An open source implementation of Apple's Combine framework for processing asynchronous events over time

Publisher Kit Overview PublisherKit provides a declarative Swift API for processing asynchronous events over time. It is an open source version of App

null 5 Feb 22, 2022
An image download extension of the image view written in Swift for iOS, tvOS and macOS.

Moa, an image downloader written in Swift for iOS, tvOS and macOS Moa is an image download library written in Swift. It allows to download and show an

Evgenii Neumerzhitckii 330 Sep 9, 2022
AYImageKit is a Swift Library for Async Image Downloading, Show Name's Initials and Can View image in Separate Screen.

AYImageKit AYImageKit is a Swift Library for Async Image Downloading. Features Async Image Downloading. Can Show Text Initials. Can have Custom Styles

Adnan Yousaf 11 Jan 10, 2022
📷 A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 3, 2023
📷 A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 2, 2023
AsyncImage before iOS 15. Lightweight, pure SwiftUI Image view, that displays an image downloaded from URL, with auxiliary views and local cache.

URLImage URLImage is a SwiftUI view that displays an image downloaded from provided URL. URLImage manages downloading remote image and caching it loca

Dmytro Anokhin 1k Jan 4, 2023
A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image.

QRDecode A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image. QRDecode

David Phillip Oster 2 Oct 28, 2022
Convert the image to hexadecimal to send the image to e-paper

ConvertImageToHex Convert the image to hexadecimal to send the image to e-paper Conversion Order // 0. hex로 변환할 이미지 var image = UIImage(named: "sample

Hankyeol Park 0 Feb 26, 2022
Twitter Image Pipeline is a robust and performant image loading and caching framework for iOS clients

Twitter Image Pipeline (a.k.a. TIP) Background The Twitter Image Pipeline is a streamlined framework for fetching and storing images in an application

Twitter 1.8k Dec 17, 2022
Image-cropper - Image cropper for iOS

Image-cropper Example To run the example project, clone the repo, and run pod in

Song Vuthy 0 Jan 6, 2022
An instagram-like image editor that can apply preset filters passed to it and customized editings to a binded image.

CZImageEditor CZImageEditor is an instagram-like image editor with clean and intuitive UI. It is pure swift and can apply preset filters and customize

null 8 Dec 16, 2022
Agrume - 🍋 An iOS image viewer written in Swift with support for multiple images.

Agrume An iOS image viewer written in Swift with support for multiple images. Requirements Swift 5.0 iOS 9.0+ Xcode 10.2+ Installation Use Swift Packa

Jan Gorman 601 Dec 26, 2022