Swift's functional Programming (III.)

Source: Internet
Author: User
Tags image filter types of filters

The article comes from "functional programing in Swift", this series is just a summary of some of the contents of the post-viewing

Wrapping Core Image

In the previous article, we introduced higher-order functions and demonstrated how functions are passed as parameters to other functions. In this chapter, we will show how to use higher-order functions to function-wrap an existing object-oriented API.

The Core Image is a very powerful framework for graphics processing, but sometimes its API is a bit cumbersome to use. The Coreimage API is loosely typed--image filters is configured using Key-value coding. This makes it easy to make errors in the type and the name of the parameter, resulting in a run-time error. Our new API will be secure and modular, using types to ensure there are no such run-time errors.

The Filter Type

Cifilter is used to create an image filter (filter), when you initialize a Cifilter object, you always provide an input image through the Kciinputimagekey, and then pass the Kcioutputimagekey to get the filtered result. You can then use the result as input to the next filter.

We will try to encapsulate the specifics of these key-value pairs and provide a secure, strongly typed API to our users.

Typealias Filter = ciimage-Ciimage

This is the basic type we're going to build.

Building Filters

Now that we have defined the basic types of filters, we can begin to define related functions for specific filters, and the parameters of these handy functions require a specific filter and return a filter.

Func myfilter (/* parameters */) Filter

Note The return filter type, which is also a function. Since then, this will help us assemble multiple filters to achieve the desired image effect.

To make us lives a bit easier, we will extend the Cifilter class by convenience initializer and a computed property to retrieve the output image

Typealias Parameters = dictionary<string, anyobject>extension cifilter {    convenience init (name:string, Parameters:parameters) {            self.init (name:name)                    setdefaults ()            for (key, value:anyobject) in Parameters { C4/>setvalue (value, Forkey:key)            }     }      var outputimage:ciimage {        return Self.valueforkey ( Kcioutputimagekey) as Ciimage    }    }                      

Our convenience constructor first invokes our specified constructor. This computed property outputimage provides an easy way to get the output image from the filter object. With this computed attribute, users who use our API no longer need to care about how to get such an operation.

Blur (Blur)

Blur filter requires only one blur radius as its parameter

Func blur (radius:double), Filter {return {image in let    parameters:parameters = [         Kciinputradiuskey:radiu S,         kciinputimagekey:image    ] let    filter = Cifilter (name: "Cigaussianblur", Parameters:parameters)     Return Filter.outputimage           }}

Blur functions returns a function that has an image of type ciimage and returns a new image. Because of this, the return value of the fuzzy function conforms to the filter type we defined earlier

(Typealias filter = Ciimage, ciimage). In this example, we are simply wrapping the filter in the original core image. We can use the same pattern over and over again to create our own filtering capabilities.

Color Overlay

We define a filter that overrides the color we selected on the image. There is no such filter by default in core image, but we can, of course, be made up of existing filters.

These two building blocks are we want to use the Color generator filter (ciconstantcolorgenerator) and Source-over compositing filter (cisourceovercompositing).

Func Colorgenerator (color:nscolor), Filter {     Return {_ in let        parameters:parameters = [kciinputcolorkey:c Olor] Let         filter = Cifilter (name: "Ciconstantcolorgenerator", Parameters:parameters)         return Filter.outputimage    }}

This is similar to the blur filter we defined earlier, but with a different point: this constant color generator filter is not associated with imput image, so we don't need the image parameter.

Func compositesourceover (overlay:ciimage), Filter {     return {image in let    parameters:parameters = [         KCI Inputbackgroundimagekey:image,         kciinputimagekey:overlay        ] let    filter = Cifilter (name: " Cisourceovercompositing ", parameters:parameters) let    croprect = image.extent ()    return Filter.outputImage.imageByCroppingToRect (Croprect)}}                

Here we clip the size of the output image to the size of the input image. This is not necessary, depending on the behavior of our filter. However, the work in this example is very good.

Finally, we combine the two filter into a color overlay filter:

Func Coloroverlay (color:nscolor), Filter {     return {image in let        overlay = Colorgenerator (color) (image) 
   
    return compositesourceover (overlay) (image)
    
}}

Composing Filters

Now we use our defined filter to apply to the actual picture:First we blur the image, and then we put a red overlay on top.

Let URL = Nsurl (string: "Http://tinyurl.com/m74sldb") Let image = Ciimage (contentsofurl:url)//Now we can apply both Filte RS to these by chaining them together:let Blurradius = 5.0let Overlaycolor = Nscolor.redcolor (). colorwithalphacomponent (0. 2) Let Blurredimage = Blur (Blurradius) (image) Let Overlaidimage = Coloroverlay (Overlaycolor) (blurredimage)

Function composition

Of course, the above filter combination we can use a statement:

Let result = Coloroverlay (Overlaycolor) (Blur (Blurradius) (image))

However, the code quickly becomes unreadable. A good way to do this is to customize the operation of a filter combination:

Func composefilters (Filter1:filter, Filter2:filter), Filter {     return {img in Filter2 (Filter1 (IMG))}}

Let MyFilter1 = Composefilters (Blur (Blurradius), Coloroverlay (Overlaycolor)) Let RESULT1 = MyFilter1 (image)

We can go further and make this more readable by using custom operators to combine

Infix operator >>> {associativity left}func >>> (Filter1:filter, Filter2:filter), Filter {     return {img in Filter2 (Filter1 (IMG)}}}

Let MyFilter2 = Blur (Blurradius) >>> coloroverlay (overlaycolor) Let result2 = MyFilter2 (image)

When we define >>> for the left to combine

Theoretical background:currying Curry function

The relevant knowledge about the function of the curry, not much introduction, the following links:

Swift's currying

Discussion

In this chapter, we will find that the API we have designed has several advantages:

1. Safety----It is almost impossible to create runtime errors arising from undefined keys or failed casts

2. Modularity---it is easy to compose filters using the >>> operator. Doing so allows-tease apart complex filters into smaller, simpler, reusable components. Additionally, composed filters has the exact same type as their building blocks, so can use them interchangeably.

3. Clarity---- Even if you had never used Core Image, you should being able to assemble simple filters using the F Unctions we have defined. To access the results, you don ' t need to know about special dictionary keys, such as Kcioutputimagekey, or worry about INI Tializing certain keys, such as Kciinputimagekey or Kciinputradiuskey. From the types alone, you can almost figure out how to use the API, even without further documentation

Swift's functional Programming (III.)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.