├── Chapter1.playground
├── Contents.swift
├── Resources
│ └── monalisa.jpg
├── contents.xcplayground
├── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── simongladman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── timeline.xctimeline
├── Chapter2.playground
├── Pages
│ ├── Color Map Filter.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ │ ├── blueYellowWhite.png
│ │ │ ├── monalisa.jpg
│ │ │ └── window.jpg
│ │ └── timeline.xctimeline
│ ├── Creating & Applying Filters.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ │ └── carmascot.jpg
│ │ └── timeline.xctimeline
│ ├── Height Field & Shaded Material.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ │ ├── coreImageForSwift.png
│ │ │ ├── sphere.jpg
│ │ │ └── thisSideDown.png
│ │ └── timeline.xctimeline
│ ├── Querying Core Image for Filters.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ └── Setting Filter Parameters.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ └── sunflower.jpg
│ │ └── timeline.xctimeline
├── contents.xcplayground
└── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcshareddata
│ └── Chapter2.xcscmblueprint
│ └── xcuserdata
│ └── simongladman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter6.playground
├── Contents.swift
├── Resources
│ └── monalisa.jpg
├── contents.xcplayground
├── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── simongladman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── timeline.xctimeline
├── Chapter7.playground
├── Contents.swift
├── Resources
│ └── sunflower.jpg
├── contents.xcplayground
├── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── simongladman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── timeline.xctimeline
├── Chapter8.playground
├── Pages
│ ├── Barrel Distortion.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ └── RoI Callbacks.xcplaygroundpage
│ │ ├── Contents.swift
│ │ ├── Resources
│ │ └── bouy.jpg
│ │ └── timeline.xctimeline
├── contents.xcplayground
└── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── simongladman.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── Chapter9.playground
├── Contents.swift
├── Resources
│ └── monalisa.jpg
├── contents.xcplayground
├── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── simongladman.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── timeline.xctimeline
└── README.md
/Chapter1.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: ## Introducing Core Image
2 |
3 | import UIKit
4 |
5 | let mona = CIImage(image: UIImage(named: "monalisa.jpg")!)!
6 |
7 | let mono = CIFilter(name: "CIPhotoEffectMono",
8 | withInputParameters: [
9 | kCIInputImageKey: mona])!.outputImage!
10 |
11 | let falseColor = CIFilter(name: "CIFalseColor",
12 | withInputParameters: [
13 | kCIInputImageKey: mono,
14 | "inputColor0": CIColor(red: 0.15, green: 0.15, blue: 1),
15 | "inputColor1": CIColor(red: 1, green: 1, blue: 0.5)])!.outputImage!
16 |
17 | let vignette = CIFilter(name: "CIVignette",
18 | withInputParameters: [
19 | kCIInputImageKey: falseColor,
20 | kCIInputRadiusKey: 4,
21 | kCIInputIntensityKey: 4])?.outputImage
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | // end
30 |
--------------------------------------------------------------------------------
/Chapter1.playground/Resources/monalisa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter1.playground/Resources/monalisa.jpg
--------------------------------------------------------------------------------
/Chapter1.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter1.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter1.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter1.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter1.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
30 |
31 |
36 |
37 |
42 |
43 |
47 |
48 |
52 |
53 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: # Core Image for Swift
4 |
5 | //: ## Color Map Filter
6 |
7 | import UIKit
8 | import CoreImage
9 |
10 | //: ### Introduction
11 |
12 | let monaLisa = CIImage(image: UIImage(named: "monalisa.jpg")!)!
13 | let blueYellowWhite = CIImage(image: UIImage(named: "blueYellowWhite.png")!)!
14 |
15 | let final = monaLisa.imageByApplyingFilter("CIColorMap",
16 | withInputParameters: [kCIInputGradientImageKey: blueYellowWhite])
17 |
18 | //: ### Creating a Color Map
19 |
20 | let window = CIImage(image: UIImage(named: "window.jpg")!)!
21 |
22 | struct RGB
23 | {
24 | let a:UInt8 = 255
25 | let r:UInt8
26 | let g:UInt8
27 | let b:UInt8
28 |
29 | init(r: UInt8, g: UInt8, b: UInt8)
30 | {
31 | self.r = r
32 | self.g = g
33 | self.b = b
34 | }
35 |
36 | var luma: UInt8
37 | {
38 | return UInt8((Double(r) * 0.2126) +
39 | (Double(g) * 0.7152) +
40 | (Double(b) * 0.0722))
41 | }
42 | }
43 |
44 | func colorMapGradientFromColors(colors:[RGB]) -> CIImage
45 | {
46 | let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
47 | let bitmapInfo:CGBitmapInfo = CGBitmapInfo(
48 | rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
49 |
50 | let bitsPerComponent = 8
51 | let bitsPerPixel = 32
52 |
53 | var sortedColors = colors
54 | .sort({ $0.luma < $1.luma })
55 | .flatMap({ [RGB](count: 16, repeatedValue: $0) })
56 |
57 | let width = sortedColors.count
58 |
59 | let dataProvider = CGDataProviderCreateWithCFData(
60 | NSData(bytes: &sortedColors,
61 | length: sortedColors.count * sizeof(RGB)))
62 |
63 | let cgImage = CGImageCreate(
64 | width,
65 | 1,
66 | bitsPerComponent,
67 | bitsPerPixel,
68 | width * sizeof(RGB),
69 | rgbColorSpace,
70 | bitmapInfo,
71 | dataProvider,
72 | nil,
73 | true,
74 | .RenderingIntentDefault
75 | )
76 |
77 | return CIImage(CGImage: cgImage!)
78 | }
79 |
80 | let blueYellowWhiteColors = [
81 | RGB(r: 0, g: 0, b: 255),
82 | RGB(r: 255, g: 255, b: 0),
83 | RGB(r: 255, g: 255, b: 255)]
84 |
85 | let blueYellowWhiteColorMap = colorMapGradientFromColors(blueYellowWhiteColors)
86 |
87 | let blueYellowWhiteWindow = window
88 | .imageByApplyingFilter("CIColorMap",
89 | withInputParameters: [
90 | kCIInputGradientImageKey: blueYellowWhiteColorMap])
91 |
92 | //: ### Alternative Mapping Palettes
93 |
94 | func eightBitFromColorPalette(sourceImage sourceImage: CIImage,
95 | colors: [RGB]) -> CIImage
96 | {
97 | let colorMapGradient = colorMapGradientFromColors(colors)
98 |
99 | return sourceImage
100 | .imageByApplyingFilter("CIPixellate",
101 | withInputParameters: nil)
102 | .imageByApplyingFilter("CIColorMap",withInputParameters: [
103 | kCIInputGradientImageKey: colorMapGradient])
104 | }
105 |
106 | //: #### ZX Spectrum Dim
107 |
108 | let dimSpectrumColors = [
109 | RGB(r: 0x00, g: 0x00, b: 0x00),
110 | RGB(r: 0x00, g: 0x00, b: 0xCD),
111 | RGB(r: 0xCD, g: 0x00, b: 0x00),
112 | RGB(r: 0xCD, g: 0x00, b: 0xCD),
113 | RGB(r: 0x00, g: 0xCD, b: 0x00),
114 | RGB(r: 0x00, g: 0xCD, b: 0xCD),
115 | RGB(r: 0xCD, g: 0xCD, b: 0x00),
116 | RGB(r: 0xCD, g: 0xCD, b: 0xCD)]
117 |
118 | let spectrumDim = eightBitFromColorPalette(sourceImage: monaLisa, colors: dimSpectrumColors)
119 |
120 | //: #### ZX Spectrum Bright
121 |
122 | let brightSpectrumColors = [
123 | RGB(r: 0x00, g: 0x00, b: 0x00),
124 | RGB(r: 0x00, g: 0x00, b: 0xFF),
125 | RGB(r: 0xFF, g: 0x00, b: 0x00),
126 | RGB(r: 0xFF, g: 0x00, b: 0xFF),
127 | RGB(r: 0x00, g: 0xFF, b: 0x00),
128 | RGB(r: 0x00, g: 0xFF, b: 0xFF),
129 | RGB(r: 0xFF, g: 0xFF, b: 0x00),
130 | RGB(r: 0xFF, g: 0xFF, b: 0xFF)]
131 |
132 | let spectrumBright = eightBitFromColorPalette(sourceImage: monaLisa, colors: brightSpectrumColors)
133 |
134 | //: #### VIC-20
135 | let vic20Colors = [
136 | RGB(r: 0, g: 0, b: 0),
137 | RGB(r: 255, g: 255, b: 255),
138 | RGB(r: 141, g: 62, b: 55),
139 | RGB(r: 114, g: 193, b: 200),
140 | RGB(r: 128, g: 52, b: 139),
141 | RGB(r: 85, g: 160, b: 73),
142 | RGB(r: 64, g: 49, b: 141),
143 | RGB(r: 170, g: 185, b: 93),
144 | RGB(r: 139, g: 84, b: 41),
145 | RGB(r: 213, g: 159, b: 116),
146 | RGB(r: 184, g: 105, b: 98),
147 | RGB(r: 135, g: 214, b: 221),
148 | RGB(r: 170, g: 95, b: 182),
149 | RGB(r: 148, g: 224, b: 137),
150 | RGB(r: 128, g: 113, b: 204),
151 | RGB(r: 191, g: 206, b: 114)
152 | ]
153 |
154 | let vic20 = eightBitFromColorPalette(sourceImage: monaLisa, colors: vic20Colors)
155 |
156 | //: #### C-64
157 |
158 | let c64Colors = [
159 | RGB(r: 0, g: 0, b: 0),
160 | RGB(r: 255, g: 255, b: 255),
161 | RGB(r: 136, g: 57, b: 50),
162 | RGB(r: 103, g: 182, b: 189),
163 | RGB(r: 139, g: 63, b: 150),
164 | RGB(r: 85, g: 160, b: 73),
165 | RGB(r: 64, g: 49, b: 141),
166 | RGB(r: 191, g: 206, b: 114),
167 | RGB(r: 139, g: 84, b: 41),
168 | RGB(r: 87, g: 66, b: 0),
169 | RGB(r: 184, g: 105, b: 98),
170 | RGB(r: 80, g: 80, b: 80),
171 | RGB(r: 120, g: 120, b: 120),
172 | RGB(r: 148, g: 224, b: 137),
173 | RGB(r: 120, g: 105, b: 196),
174 | RGB(r: 159, g: 159, b: 159)
175 | ]
176 |
177 | let c64 = eightBitFromColorPalette(sourceImage: monaLisa, colors: c64Colors)
178 |
179 | //: #### Apple II
180 | let appleIIColors = [
181 | RGB(r: 0, g: 0, b: 0),
182 | RGB(r: 114, g: 38, b: 64),
183 | RGB(r: 64, g: 51, b: 127),
184 | RGB(r: 228, g: 52, b: 254),
185 | RGB(r: 14, g: 89, b: 64),
186 | RGB(r: 128, g: 128, b: 128),
187 | RGB(r: 27, g: 154, b: 254),
188 | RGB(r: 191, g: 179, b: 255),
189 | RGB(r: 64, g: 76, b: 0),
190 | RGB(r: 228, g: 101, b: 1),
191 | RGB(r: 128, g: 128, b: 128),
192 | RGB(r: 241, g: 166, b: 191),
193 | RGB(r: 27, g: 203, b: 1),
194 | RGB(r: 191, g: 204, b: 128),
195 | RGB(r: 141, g: 217, b: 191),
196 | RGB(r: 255, g: 255, b: 255)
197 | ]
198 |
199 | let appleII = eightBitFromColorPalette(sourceImage: monaLisa, colors: appleIIColors)
200 |
201 | //: [Next](@next)
202 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/blueYellowWhite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/blueYellowWhite.png
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/monalisa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/monalisa.jpg
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/window.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/Resources/window.jpg
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Color Map Filter.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
64 |
65 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Creating & Applying Filters.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: ## Creating & Applying Filters
4 |
5 | import UIKit
6 | import CoreImage
7 |
8 | //: ### Executing Filters
9 |
10 | let carMascot = CIImage(image: UIImage(named: "carmascot.jpg")!)!
11 |
12 | //: Setting parameters in constuctor
13 |
14 | let bloomFilteOne = CIFilter(name: "CIBloom",
15 | withInputParameters: [
16 | kCIInputRadiusKey: 8,
17 | kCIInputIntensityKey: 1.25,
18 | kCIInputImageKey: carMascot])!
19 |
20 | //: Setting parameters after creating using `setValue()`
21 |
22 | let bloomFilterTwo = CIFilter(name: "CIBloom")!
23 |
24 | bloomFilterTwo.setValue(8, forKey: kCIInputRadiusKey)
25 | bloomFilterTwo.setValue(1.25, forKey: kCIInputIntensityKey)
26 | bloomFilterTwo.setValue(carMascot, forKey: kCIInputImageKey)
27 |
28 | //: Final image using `outputImage`
29 |
30 | let finalImageOne = bloomFilteOne.outputImage!
31 |
32 | //: Final image using `valueForKey()`
33 |
34 | let finalImageTwo = bloomFilteOne
35 | .valueForKey(kCIOutputImageKey) as! CIImage
36 |
37 | //: Final image using `imageByApplyingFilter()`
38 |
39 | let finalImageThree = carMascot.imageByApplyingFilter("CIBloom",
40 | withInputParameters: [
41 | kCIInputRadiusKey: 8,
42 | kCIInputIntensityKey: 1.25
43 | ])
44 |
45 | //: ### Chaining Filters
46 |
47 | //: Setting parameters in constuctor
48 |
49 | let noirFilterOne = CIFilter(name: "CIPhotoEffectNoir",
50 | withInputParameters: [kCIInputImageKey: finalImageOne])!
51 |
52 | //: Setting parameters after creating using `setValue()`
53 |
54 | let noirFilter = CIFilter(name: "CIPhotoEffectNoir")!
55 |
56 | noirFilter.setValue(finalImageOne, forKey: kCIInputImageKey)
57 |
58 | //: Final image using `outputImage`
59 |
60 | let finalNoirImageOne = noirFilter.outputImage!
61 |
62 | //: Final image using `imageByApplyingFilter()`
63 |
64 | let finalNoirImageTwo = carMascot
65 | .imageByApplyingFilter("CIBloom",
66 | withInputParameters: [
67 | kCIInputRadiusKey: 8,
68 | kCIInputIntensityKey: 1.25])
69 | .imageByApplyingFilter("CIPhotoEffectNoir",
70 | withInputParameters: nil)
71 |
72 | //: ### Composite & Blend Filters
73 |
74 | let stripesImage = CIFilter(name: "CIStripesGenerator")!
75 | .outputImage!
76 | .imageByCroppingToRect(carMascot.extent)
77 |
78 | let negativeImage = carMascot
79 | .imageByApplyingFilter("CIColorInvert",
80 | withInputParameters: nil)
81 |
82 | //: Final composite using `setValue`
83 |
84 | let compositeFilter = CIFilter(name: "CIBlendWithMask")!
85 |
86 | compositeFilter.setValue(carMascot,
87 | forKey: kCIInputImageKey)
88 | compositeFilter.setValue(negativeImage,
89 | forKey: kCIInputBackgroundImageKey)
90 | compositeFilter.setValue(stripesImage,
91 | forKey: kCIInputMaskImageKey)
92 |
93 | let compositeImageOne = compositeFilter.outputImage!
94 |
95 | //: Final composite using `imageByApplyingFilter()`
96 |
97 | let compositeImageTwo = carMascot
98 | .imageByApplyingFilter("CIBlendWithMask",
99 | withInputParameters: [
100 | kCIInputBackgroundImageKey: negativeImage,
101 | kCIInputMaskImageKey: stripesImage])
102 |
103 |
104 | //: [Next](@next)
105 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Creating & Applying Filters.xcplaygroundpage/Resources/carmascot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Creating & Applying Filters.xcplaygroundpage/Resources/carmascot.jpg
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Creating & Applying Filters.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: ## Height Field & Shaded Material
4 |
5 | import UIKit
6 | import CoreImage
7 |
8 | //: ### Height Field Filter
9 |
10 | let coreImageForSwift = UIImage(named: "coreImageForSwift.png")!
11 |
12 | let image = CIImage(image: coreImageForSwift)!
13 |
14 | let colorInvert = CIFilter(name: "CIColorInvert",
15 | withInputParameters: [kCIInputImageKey: image])!
16 |
17 | let maskToAlpha = CIFilter(name: "CIMaskToAlpha",
18 | withInputParameters: [
19 | kCIInputImageKey: colorInvert.outputImage!])!
20 |
21 | let heightField = CIFilter(name: "CIHeightFieldFromMask",
22 | withInputParameters: [
23 | kCIInputImageKey: maskToAlpha.outputImage!])!
24 |
25 | let heightFieldImage = heightField.outputImage!
26 |
27 | //: ### Shaded Material Filter
28 |
29 | let sphere = UIImage(named: "sphere.jpg")!
30 |
31 | let shadingImage = CIImage(image: sphere)!
32 |
33 | let shadedMaterial = CIFilter(name: "CIShadedMaterial",
34 | withInputParameters: [
35 | kCIInputImageKey: heightField.outputImage!,
36 | kCIInputShadingImageKey: shadingImage])!
37 |
38 | let shadedImage = shadedMaterial.outputImage!
39 |
40 | //: ### Alternatives for Height Field Source
41 |
42 | //: `UILabel`
43 |
44 | let label = UILabel(frame:
45 | CGRect(x: 0, y: 0, width: 640, height: 160))
46 | label.text = "Core Image\nfor Swift"
47 | label.font = UIFont.boldSystemFontOfSize(200)
48 | label.adjustsFontSizeToFitWidth = true
49 | label.numberOfLines = 2
50 | label.textAlignment = .Center
51 |
52 | UIGraphicsBeginImageContextWithOptions(
53 | CGSize(width: label.frame.width,
54 | height: label.frame.height), false, 1)
55 |
56 | label.layer.renderInContext(UIGraphicsGetCurrentContext()!)
57 |
58 | let textImage = UIGraphicsGetImageFromCurrentImageContext()
59 |
60 | UIGraphicsEndImageContext()
61 |
62 | let labelColorInvert = CIFilter(name: "CIColorInvert",
63 | withInputParameters: [kCIInputImageKey: CIImage(image: textImage)!])!
64 |
65 | let labelMaskToAlpha = CIFilter(name: "CIMaskToAlpha",
66 | withInputParameters: [
67 | kCIInputImageKey: labelColorInvert.outputImage!])!
68 |
69 | let labelHeightField = CIFilter(name: "CIHeightFieldFromMask",
70 | withInputParameters: [
71 | kCIInputImageKey: labelMaskToAlpha.outputImage!])!
72 |
73 | let shadedLabelMaterial = CIFilter(name: "CIShadedMaterial",
74 | withInputParameters: [
75 | kCIInputImageKey: labelHeightField.outputImage!,
76 | kCIInputShadingImageKey: shadingImage])!
77 |
78 | let shadedLabelImage = shadedLabelMaterial.outputImage!
79 |
80 | //: Edge Work filter
81 |
82 | let thisSideDown = CIImage(image: UIImage(named: "thisSideDown.png")!)!
83 |
84 | let edgeWork = CIFilter(name: "CIEdgeWork",
85 | withInputParameters: [kCIInputImageKey: thisSideDown,
86 | kCIInputRadiusKey: 2])!
87 |
88 | let edgeWorkImage = edgeWork.outputImage!
89 |
90 | let thisSideDownHeightField = CIFilter(name: "CIHeightFieldFromMask",
91 | withInputParameters: [
92 | kCIInputImageKey: edgeWorkImage])!
93 |
94 | let thisSideDownShadedMaterial = CIFilter(name: "CIShadedMaterial",
95 | withInputParameters: [
96 | kCIInputImageKey: thisSideDownHeightField.outputImage!,
97 | kCIInputShadingImageKey: shadingImage])!
98 |
99 | let shadedThisSideDownImage = thisSideDownShadedMaterial.outputImage!
100 |
101 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/coreImageForSwift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/coreImageForSwift.png
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/sphere.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/sphere.jpg
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/thisSideDown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/Resources/thisSideDown.png
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Height Field & Shaded Material.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
64 |
65 |
69 |
70 |
74 |
75 |
79 |
80 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Querying Core Image for Filters.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: # Core Image for Swift
2 |
3 | //: ## Querying Core Image for Filters
4 |
5 | import UIKit
6 | import CoreImage
7 |
8 | //: ### Filter Categories
9 |
10 | kCICategoryHalftoneEffect
11 |
12 | CIFilter.localizedNameForCategory(kCICategoryHalftoneEffect)
13 |
14 | //: ### Querying for Filters
15 |
16 | CIFilter.filterNamesInCategory(kCICategoryHalftoneEffect)
17 |
18 | CIFilter.filterNamesInCategories(nil)
19 |
20 | CIFilter.filterNamesInCategories([kCICategoryVideo,
21 | kCICategoryStillImage])
22 |
23 | CIFilter.filterNamesInCategories([kCICategoryBlur,
24 | kCICategorySharpen])
25 |
26 | //: ### Using the Filter Name
27 |
28 | CIFilter.localizedNameForFilterName("CICMYKHalftone")
29 |
30 | CIFilter.localizedDescriptionForFilterName("CICMYKHalftone")
31 |
32 | CIFilter(name: "xyz")
33 |
34 | CIFilter(name: "CICMYKHalftone")
35 |
36 | //: ### Interrogating the Filter
37 |
38 | let filter = CIFilter(name: "CICMYKHalftone")!
39 | let inputKeys = filter.inputKeys
40 |
41 | filter.attributes.filter({ !inputKeys.contains($0.0) })
42 |
43 | filter.attributes.filter({ inputKeys.contains($0.0) })
44 |
45 | if let
46 | attribute = filter
47 | .attributes["inputGCR"] as? [String: AnyObject],
48 | minimum = attribute[kCIAttributeSliderMin] as? Float,
49 | maximum = attribute[kCIAttributeSliderMax] as? Float,
50 | defaultValue = attribute[kCIAttributeDefault] as? Float where
51 | (attribute[kCIAttributeClass] as? String) == "NSNumber"
52 | {
53 | let slider = UISlider()
54 |
55 | slider.minimumValue = minimum
56 | slider.maximumValue = maximum
57 | slider.value = defaultValue
58 | }
59 |
60 | Set(CIFilter.filterNamesInCategory(nil).flatMap {
61 | CIFilter(name: $0)!
62 | .attributes[kCIAttributeFilterCategories] as! [String]
63 | }).sort()
64 |
65 |
66 | //: [Next](@next)
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Querying Core Image for Filters.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Setting Filter Parameters.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | //: ## Setting Filter Parameters
4 |
5 | import UIKit
6 | import CoreImage
7 |
8 | let cropRect = CGRect(origin: CGPointZero,
9 | size: CGSize(width: 200, height: 200))
10 |
11 | //: ### `CIColor` - Core Image Color
12 |
13 | let inputColor0 = CIColor(red: 1, green: 1, blue: 0)
14 | let inputColor1 = CIColor(color: UIColor.purpleColor())
15 |
16 | let gradientFilter = CIFilter(name: "CILinearGradient",
17 | withInputParameters: ["inputColor0": inputColor0,
18 | "inputColor1": inputColor1])!
19 |
20 |
21 | let gradientImage = gradientFilter.outputImage?
22 | .imageByCroppingToRect(cropRect)
23 |
24 | //: ### `CIImage` - Core Image Image
25 |
26 | let redImage = CIImage(color: CIColor(red: 1, green: 0, blue: 0))
27 | .imageByCroppingToRect(cropRect)
28 |
29 | let sunflowerImage = CIImage(image: UIImage(named: "sunflower.jpg")!)!
30 |
31 | //: Filtering an image
32 |
33 | let tonalFilter = CIFilter(name: "CIPhotoEffectTonal",
34 | withInputParameters: [kCIInputImageKey: sunflowerImage])
35 |
36 | let tonalImage = tonalFilter?.outputImage
37 |
38 | //: Chaining two filters
39 |
40 | let blurFilter = CIFilter(name: "CIGaussianBlur",
41 | withInputParameters: [kCIInputImageKey: sunflowerImage])!
42 |
43 | let monochrome = CIFilter(name: "CIColorMonochrome",
44 | withInputParameters: [kCIInputImageKey: blurFilter.outputImage!])
45 |
46 | let monochromeImage = monochrome?.outputImage
47 |
48 | //: ### `CIVector` - Core Image Vector
49 |
50 | CIVector(CGPoint: CGPoint(x: 10, y: 10))
51 |
52 | CIVector(CGRect: CGRect(x: 10,
53 | y: 10,
54 | width: 100,
55 | height: 100))
56 |
57 | let convolutionFilter = CIFilter(name: "CIConvolution5X5")!
58 | let weightsAttribute = convolutionFilter.attributes[kCIInputWeightsKey]
59 | as! [String : AnyObject]
60 |
61 | let defaultValue = weightsAttribute[kCIAttributeDefault]
62 | as! CIVector
63 |
64 | let newValues = [CGFloat](count: defaultValue.count,
65 | repeatedValue: 0.0)
66 | let newVector = CIVector(values: newValues,
67 | count: newValues.count)
68 |
69 | convolutionFilter.setValue(newVector,
70 | forKey: kCIInputWeightsKey)
71 |
72 | //: ### `NSNumber` - Numeric Types
73 |
74 | let width: Int = 25
75 | let angle: Double = M_PI
76 | let sharpness: UInt = 16
77 | let gcr: Float = 2.6
78 | let ucr: CGFloat = 5.4
79 |
80 | let cmykHalftoneFilter = CIFilter(name: "CICMYKHalftone",
81 | withInputParameters: [kCIInputWidthKey: width,
82 | kCIInputAngleKey: angle,
83 | kCIInputSharpnessKey: sharpness,
84 | "inputGCR": gcr,
85 | "inputUCR": ucr])!
86 |
87 | //: ### `NSData` - Data Objects
88 |
89 | //: Barcode
90 |
91 | let message = "Core Image for Swift"
92 |
93 | let data = message.dataUsingEncoding(NSASCIIStringEncoding)!
94 |
95 | let barcodeGeneratorFilter = CIFilter(name: "CICode128BarcodeGenerator",
96 | withInputParameters: ["inputMessage": data])!
97 |
98 | let barcodeImage = barcodeGeneratorFilter.outputImage!
99 |
100 | //: Color Cube
101 |
102 | let cubeArray: [Double] = [
103 | 0.7, 0.5, 1.0, 0.6,
104 | 0.0, 1.0, 0.0, 1.0,
105 | 0.9, 0.6, 0.8, 0.2,
106 | 1.0, 0.4, 0.0, 1.0]
107 |
108 | let cubeData = NSData(bytes: cubeArray,
109 | length: sizeof(Double) * cubeArray.count)
110 |
111 | let colorCubeFilter = CIFilter(name: "CIColorCube",
112 | withInputParameters: [kCIInputImageKey: sunflowerImage,
113 | "inputCubeData": cubeData])!
114 |
115 | let colorCubeImage = colorCubeFilter.outputImage
116 |
117 | //: ### `NSObject` - Data Objects
118 |
119 | let colorSpace = CGColorSpaceCreateDeviceRGB()!
120 |
121 | let colorCubeWithColorSpace = CIFilter(name: "CIColorCubeWithColorSpace",
122 | withInputParameters: [kCIInputImageKey: sunflowerImage,
123 | "inputColorSpace": colorSpace])
124 |
125 |
126 | //: ### `NSString` - Strings
127 |
128 | let codeGenerator_L = CIFilter(name: "CIQRCodeGenerator",
129 | withInputParameters: [
130 | "inputMessage": data,
131 | "inputCorrectionLevel": "L"])!
132 |
133 | let codeGenerator_L_image = codeGenerator_L.outputImage
134 |
135 | let codeGenerator_H = CIFilter(name: "CIQRCodeGenerator",
136 | withInputParameters: [
137 | "inputMessage": data,
138 | "inputCorrectionLevel": "H"])!
139 |
140 | let codeGenerator_H_image = codeGenerator_H.outputImage
141 |
142 |
143 | //: [Next](@next)
144 |
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Setting Filter Parameters.xcplaygroundpage/Resources/sunflower.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/Pages/Setting Filter Parameters.xcplaygroundpage/Resources/sunflower.jpg
--------------------------------------------------------------------------------
/Chapter2.playground/Pages/Setting Filter Parameters.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
44 |
45 |
49 |
50 |
54 |
55 |
59 |
60 |
64 |
65 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Chapter2.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Chapter2.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter2.playground/playground.xcworkspace/xcshareddata/Chapter2.xcscmblueprint:
--------------------------------------------------------------------------------
1 | {
2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "02A0ECB974E15DEDCDD56ACCFB1EC75C8A4FB507",
3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4 |
5 | },
6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7 | "02A0ECB974E15DEDCDD56ACCFB1EC75C8A4FB507" : 0,
8 | "AF926AD93FBC4CA3B3862537931122351AFC10FB" : 0
9 | },
10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "D13E5393-F331-4DDB-BAB5-67858680ECF0",
11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 | "02A0ECB974E15DEDCDD56ACCFB1EC75C8A4FB507" : "Chapter2.playground\/",
13 | "AF926AD93FBC4CA3B3862537931122351AFC10FB" : ""
14 | },
15 | "DVTSourceControlWorkspaceBlueprintNameKey" : ".",
16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : ".",
18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 | {
20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/FlexMonkey\/Chapter2.playground.git",
21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "02A0ECB974E15DEDCDD56ACCFB1EC75C8A4FB507"
23 | },
24 | {
25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/FlexMonkey\/CoreImageForSwiftPlaygrounds.git",
26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "AF926AD93FBC4CA3B3862537931122351AFC10FB"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/Chapter2.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter2.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter6.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import CoreImage
3 |
4 | //: ## Custom Image Filters
5 |
6 | let mona = CIImage(image: UIImage(named: "monalisa.jpg")!)!
7 |
8 | //: ### General Kernel Pass Through
9 | class GeneralFilter: CIFilter
10 | {
11 | var inputImage : CIImage?
12 |
13 | var kernel = CIKernel(string:
14 | "kernel vec4 general(sampler image) \n" +
15 |
16 | "{ return sample(image, samplerCoord(image)); }"
17 | )
18 |
19 | override var outputImage : CIImage!
20 | {
21 | if let inputImage = inputImage, kernel = kernel
22 | {
23 | let extent = inputImage.extent
24 | let arguments = [inputImage]
25 |
26 | return kernel.applyWithExtent(extent,
27 | roiCallback:
28 | {
29 | (index, rect) in
30 | return rect
31 | },
32 | arguments: arguments)
33 | }
34 | return nil
35 | }
36 | }
37 |
38 | let generalFilter = GeneralFilter()
39 | generalFilter.inputImage = mona
40 |
41 | let generalResult = generalFilter.outputImage
42 |
43 | //: ### Color Kernel Pass Through
44 | class ColorFilter: CIFilter
45 | {
46 | var inputImage : CIImage?
47 |
48 | var colorKernel = CIColorKernel(string:
49 | "kernel vec4 thresholdFilter(__sample pixel)" +
50 | "{" +
51 | " return pixel;" +
52 | "}"
53 | )
54 |
55 | override var outputImage: CIImage!
56 | {
57 | guard let inputImage = inputImage,
58 | colorKernel = colorKernel else
59 | {
60 | return nil
61 | }
62 |
63 | let extent = inputImage.extent
64 | let arguments = [inputImage]
65 |
66 | return colorKernel.applyWithExtent(extent,
67 | arguments: arguments)
68 | }
69 | }
70 |
71 | let colorFilter = ColorFilter()
72 | colorFilter.inputImage = mona
73 |
74 | let colorResult = colorFilter.outputImage
75 |
76 | //: ### Warp Kernel Pass Through
77 | class WarpFilter: CIFilter
78 | {
79 | var inputImage : CIImage?
80 |
81 | let warpKernel = CIWarpKernel(string:
82 | "kernel vec2 warp()" +
83 | "{ return destCoord(); }"
84 | )
85 |
86 | override var outputImage : CIImage!
87 | {
88 | if let inputImage = inputImage, kernel = warpKernel
89 | {
90 | let extent = inputImage.extent
91 |
92 | return kernel.applyWithExtent(extent,
93 | roiCallback:
94 | {
95 | (index, rect) in
96 | return rect
97 | },
98 | inputImage: inputImage,
99 | arguments: [])
100 | }
101 | return nil
102 | }
103 | }
104 |
105 | let warpFilter = WarpFilter()
106 | warpFilter.inputImage = mona
107 |
108 | let warpResult = warpFilter.outputImage
109 |
110 |
111 |
112 |
113 |
114 |
115 | // ends
116 |
--------------------------------------------------------------------------------
/Chapter6.playground/Resources/monalisa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter6.playground/Resources/monalisa.jpg
--------------------------------------------------------------------------------
/Chapter6.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter6.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter6.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter6.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter6.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
19 |
20 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Chapter7.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: ## Composite Image Color Kernels
2 |
3 | import UIKit
4 | import CoreImage
5 | import XCPlayground
6 |
7 | let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 640, height: 640))
8 |
9 | imageView.contentMode = .Center
10 |
11 | let ciContext = CIContext()
12 |
13 | func imageFromCIImage(source: CIImage) -> UIImage
14 | {
15 | let cgImage = ciContext.createCGImage(source,
16 | fromRect: source.extent)
17 |
18 | return UIImage(CGImage: cgImage)
19 | }
20 |
21 | XCPlaygroundPage.currentPage.liveView = imageView
22 |
23 | //: ### RedGreenFilter
24 |
25 | class RedGreenFilter: CIFilter
26 | {
27 | var inputImage: CIImage?
28 | var inputBackgroundImage: CIImage?
29 |
30 | var extent: CGRect?
31 |
32 | var kernel = CIColorKernel(string:
33 | "kernel vec4 thresholdFilter(__sample image)" +
34 | "{" +
35 | " return vec4(image.r, image.g * 0.5, 0.0, image.a);" +
36 | "}"
37 | )
38 |
39 | override var outputImage: CIImage!
40 | {
41 | guard let inputImage = inputImage,
42 | kernel = kernel else
43 | {
44 | return nil
45 | }
46 |
47 | let extent = self.extent ?? inputImage.extent
48 |
49 | let arguments = [inputImage]
50 |
51 | return kernel.applyWithExtent(extent,
52 | arguments: arguments)
53 | }
54 | }
55 |
56 | //: ### BlueGreenFilter
57 |
58 | class BlueGreenFilter: CIFilter
59 | {
60 | var inputImage: CIImage?
61 | var inputBackgroundImage: CIImage?
62 |
63 | var extent: CGRect?
64 |
65 | var kernel = CIColorKernel(string:
66 | "kernel vec4 thresholdFilter(__sample image)" +
67 | "{" +
68 | " return vec4(0.0, image.g * 0.5, image.b, image.a);" +
69 | "}"
70 | )
71 |
72 | override var outputImage: CIImage!
73 | {
74 | guard let inputImage = inputImage,
75 | kernel = kernel else
76 | {
77 | return nil
78 | }
79 |
80 | let extent = self.extent ?? inputImage.extent
81 |
82 | let arguments = [inputImage]
83 |
84 | return kernel.applyWithExtent(extent,
85 | arguments: arguments)
86 | }
87 | }
88 |
89 | // ---
90 |
91 | let sunflower = CIImage(image: UIImage(named: "sunflower.jpg")!)!
92 |
93 | //: ### Landscape sunflower demonstration
94 | let blueGreenFilter = BlueGreenFilter()
95 | blueGreenFilter.inputImage = sunflower
96 | blueGreenFilter.extent = sunflower.extent.insetBy(dx: 0, dy: 200)
97 | let blueGreenOutput = blueGreenFilter.outputImage
98 |
99 | //imageView.image = imageFromCIImage(blueGreenOutput)
100 |
101 | //: ### Portrait sunflower demonstration
102 | let redGreenFilter = RedGreenFilter()
103 | redGreenFilter.inputImage = sunflower
104 | redGreenFilter.extent = sunflower.extent.insetBy(dx: 200, dy: 0)
105 | let redGreenOutput = redGreenFilter.outputImage
106 |
107 | //imageView.image = imageFromCIImage(redGreenOutput)
108 |
109 | let additionImageOne = blueGreenOutput
110 | .imageByApplyingFilter("CIAdditionCompositing",
111 | withInputParameters: [
112 | kCIInputBackgroundImageKey: redGreenOutput])
113 |
114 | // imageView.image = imageFromCIImage(additionImageOne)
115 |
116 | let blueGreenRender = CIImage(image: imageFromCIImage(blueGreenOutput))!
117 | .imageByApplyingTransform(CGAffineTransformMakeTranslation(0, 220))
118 |
119 | let redGreenRender = CIImage(image: imageFromCIImage(redGreenOutput))!
120 | .imageByApplyingTransform(CGAffineTransformMakeTranslation(220, 0))
121 |
122 | let additionImageTwo = blueGreenRender
123 | .imageByApplyingFilter("CIAdditionCompositing",
124 | withInputParameters: [
125 | kCIInputBackgroundImageKey: redGreenRender])
126 |
127 | // imageView.image = imageFromCIImage(additionImageTwo)
128 |
129 | //: ## Composite Image Color Kernels (Colored boxes)
130 |
131 | class AddComposite: CIFilter
132 | {
133 | var inputImage: CIImage?
134 | var inputBackgroundImage: CIImage?
135 |
136 | var extentFunction: (CGRect, CGRect) -> CGRect = { (a: CGRect, b: CGRect) in return CGRectZero }
137 |
138 | var kernel = CIColorKernel(string:
139 | "kernel vec4 thresholdFilter(__sample image, __sample backgroundImage)" +
140 | "{" +
141 | " return image + backgroundImage;" +
142 | "}"
143 | )
144 |
145 | override var outputImage: CIImage!
146 | {
147 | guard let inputImage = inputImage,
148 | inputBackgroundImage = inputBackgroundImage,
149 | addKernel = kernel else
150 | {
151 | return nil
152 | }
153 |
154 | let extent = extentFunction(inputImage.extent,
155 | inputBackgroundImage.extent)
156 |
157 | let arguments = [inputImage, inputBackgroundImage]
158 |
159 | return addKernel.applyWithExtent(extent,
160 | arguments: arguments)
161 | }
162 | }
163 |
164 | let red = CIColor(red: 1, green: 0, blue: 0)
165 | let blue = CIColor(red: 0, green: 0, blue: 1)
166 |
167 | let redPortrait = CIImage(color: red)
168 | .imageByCroppingToRect(CGRect(
169 | origin: CGPoint(x: 220, y: 20),
170 | size: CGSize(width: 200, height: 600)))
171 |
172 | let blueLandscape = CIImage(color: blue)
173 | .imageByCroppingToRect(CGRect(
174 | origin: CGPoint(x: 20, y: 220),
175 | size: CGSize(width: 600, height: 200)))
176 |
177 | let regularComposite = redPortrait
178 | .imageByApplyingFilter("CIAdditionCompositing",
179 | withInputParameters: [kCIInputBackgroundImageKey: blueLandscape])
180 |
181 |
182 |
183 |
184 | let addFilter = AddComposite()
185 | addFilter.inputImage = redPortrait
186 | addFilter.inputBackgroundImage = blueLandscape
187 |
188 | //: ### `portrait` demonstration
189 | addFilter.extentFunction = { (fore, back) in return fore }
190 | let portrait = addFilter.outputImage
191 | // imageView.image = imageFromCIImage(portrait)
192 |
193 | //: ### `landscape` demonstration
194 | addFilter.extentFunction = { (fore, back) in return back }
195 | let landscape = addFilter.outputImage
196 | // imageView.image = imageFromCIImage(landscape)
197 |
198 | //: ### `union` demonstration
199 | addFilter.extentFunction = { (fore, back) in return fore.union(back) }
200 | let union = addFilter.outputImage
201 | // imageView.image = imageFromCIImage(union)
202 |
203 | //: ### `intersect` demonstration
204 | addFilter.extentFunction = { (fore, back) in fore.intersect(back) }
205 | let intersect = addFilter.outputImage
206 | imageView.image = imageFromCIImage(intersect)
207 |
208 |
209 |
210 |
211 |
212 | // ends...
213 |
--------------------------------------------------------------------------------
/Chapter7.playground/Resources/sunflower.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter7.playground/Resources/sunflower.jpg
--------------------------------------------------------------------------------
/Chapter7.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter7.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter7.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter7.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter7.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
15 |
16 |
20 |
21 |
25 |
26 |
30 |
31 |
35 |
36 |
41 |
42 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Chapter8.playground/Pages/Barrel Distortion.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: ## Barrel Distortion Warp Filter
2 |
3 | import UIKit
4 | import CoreImage
5 |
6 | //: ### Warp Kernel
7 |
8 | class CRTWarpFilter: CIFilter
9 | {
10 | var inputImage : CIImage?
11 | var bend: CGFloat = 3.2
12 |
13 | let crtWarpKernel = CIWarpKernel(string:
14 | "kernel vec2 crtWarp(vec2 extent, float bend)" +
15 | "{" +
16 | " vec2 coord = ((destCoord() / extent) - 0.5) * 2.0;" +
17 |
18 | " coord.x *= 1.0 + pow((abs(coord.y) / bend), 2.0);" +
19 | " coord.y *= 1.0 + pow((abs(coord.x) / bend), 2.0);" +
20 |
21 | " coord = ((coord / 2.0) + 0.5) * extent;" +
22 |
23 | " return coord;" +
24 | "}"
25 | )
26 |
27 | override var outputImage : CIImage!
28 | {
29 | if let inputImage = inputImage,
30 | crtWarpKernel = crtWarpKernel
31 | {
32 | let arguments = [CIVector(x: inputImage.extent.size.width, y: inputImage.extent.size.height), bend]
33 | let extent = inputImage.extent
34 |
35 | return crtWarpKernel.applyWithExtent(extent,
36 | roiCallback:
37 | {
38 | (index, rect) in
39 |
40 | return rect
41 | },
42 | inputImage: inputImage,
43 | arguments: arguments)
44 | }
45 | return nil
46 | }
47 | }
48 |
49 | let ciContext = CIContext()
50 |
51 | func imageFromCIImage(source: CIImage) -> UIImage
52 | {
53 | let cgImage = ciContext.createCGImage(source,
54 | fromRect: source.extent)
55 |
56 | return UIImage(CGImage: cgImage)
57 | }
58 |
59 | //: ### Swift Implementation of barrel warp kernel
60 |
61 | //: `x` and `y` are pixel coordinates
62 | let x = 65.0
63 | let y = 55.0
64 |
65 | //: `width` and `height` are extent
66 | let width = 900.0
67 | let height = 300.0
68 |
69 | //: `crtWarpKernel` mechanics in Swift
70 | var coordX = ((x / width) - 0.5) * 2.0
71 | var coordY = ((y / height) - 0.5) * 2.0
72 |
73 | coordX *= 1 + pow((abs(coordY) / 3.2), 2.0)
74 | coordY *= 1 + pow((abs(coordX) / 3.2), 2.0)
75 |
76 | coordX = ((coordX / 2.0) + 0.5) * width
77 | coordY = ((coordY / 2.0) + 0.5) * height
78 |
79 | // ----
80 |
81 | let backgroundImage = CIFilter(name: "CICheckerboardGenerator",
82 | withInputParameters: [
83 | "inputColor0": CIColor(red: 0.1, green: 0.1, blue: 0.1),
84 | "inputColor1": CIColor(red: 0.15, green: 0.15, blue: 0.15),
85 | "inputCenter": CIVector(x: 0, y: 0),
86 | "inputWidth": 50])!
87 | .outputImage!.imageByCroppingToRect(CGRect(x: 1, y: 1, width: width - 2, height: height - 2))
88 | .imageByCompositingOverImage(CIImage(color: CIColor(red: 0, green: 0, blue: 0)))
89 | .imageByCroppingToRect(CGRect(origin: CGPointZero, size: CGSize(width: width, height: height)))
90 |
91 | let blueBox = CIImage(color: CIColor(red: 0.5, green: 0.5, blue: 1, alpha: 0.7))
92 | .imageByCroppingToRect(
93 | CGRect(origin: CGPoint(x: coordX - 5, y: coordY - 5), size: CGSize(width: 10, height: 10)))
94 |
95 | let redBox = CIImage(color: CIColor(red: 1, green: 0, blue: 0, alpha: 0.7))
96 | .imageByCroppingToRect(
97 | CGRect(origin: CGPoint(x: x - 5, y: y - 5), size: CGSize(width: 10, height: 10)))
98 |
99 | let warpFilter = CRTWarpFilter()
100 |
101 | warpFilter.inputImage = backgroundImage
102 |
103 | let composite = CIFilter(name: "CIAdditionCompositing",
104 | withInputParameters: [
105 | kCIInputBackgroundImageKey: warpFilter.outputImage,
106 | kCIInputImageKey: blueBox])!
107 | .outputImage!
108 | .imageByApplyingFilter("CIAdditionCompositing",
109 | withInputParameters: [kCIInputBackgroundImageKey: redBox])
110 |
111 | let result = composite
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/Chapter8.playground/Pages/Barrel Distortion.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
15 |
16 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Chapter8.playground/Pages/RoI Callbacks.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import UIKit
4 | import CoreImage
5 |
6 | //: ## Horizontal Scale Filter
7 |
8 | class StretchFilter: CIFilter
9 | {
10 | var inputImage: CIImage?
11 |
12 | var inputScaleX: CGFloat = 1
13 |
14 | let stretchKernel = CIWarpKernel(string:
15 | "kernel vec2 stretchKernel(float inputScaleX)" +
16 | "{" +
17 | " float y = destCoord().y; " +
18 | " float x = (destCoord().x / inputScaleX); " +
19 | " return vec2(x, y); " +
20 | "}"
21 | )
22 |
23 | override var outputImage : CIImage!
24 | {
25 | if let inputImage = inputImage,
26 | kernel = stretchKernel
27 | {
28 | let arguments = [ inputScaleX ]
29 |
30 | let extent = CGRect(origin: inputImage.extent.origin,
31 | size: CGSize(
32 | width: inputImage.extent.width * inputScaleX,
33 | height: inputImage.extent.height))
34 |
35 | return kernel.applyWithExtent(extent,
36 | roiCallback:
37 | {
38 | (index, rect) in
39 |
40 | let sampleX = rect.origin.x / self.inputScaleX
41 | let sampleWidth = rect.width / self.inputScaleX
42 |
43 | let sampleRect = CGRect(x: sampleX,
44 | y: rect.origin.y,
45 | width: sampleWidth,
46 | height: rect.height)
47 |
48 | return sampleRect
49 | },
50 | inputImage: inputImage,
51 | arguments: arguments)
52 | }
53 | return nil
54 | }
55 | }
56 |
57 | let bouy = CIImage(image: UIImage(named: "bouy.jpg")!)!
58 |
59 | let stretchFilter = StretchFilter()
60 |
61 | stretchFilter.inputScaleX = 4
62 |
63 | stretchFilter.inputImage = bouy
64 |
65 | print (stretchFilter.outputImage!.extent)
66 |
67 | let stretchedImage = stretchFilter.outputImage!
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | //: [Next](@next)
76 |
--------------------------------------------------------------------------------
/Chapter8.playground/Pages/RoI Callbacks.xcplaygroundpage/Resources/bouy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter8.playground/Pages/RoI Callbacks.xcplaygroundpage/Resources/bouy.jpg
--------------------------------------------------------------------------------
/Chapter8.playground/Pages/RoI Callbacks.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Chapter8.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Chapter8.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter8.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter8.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter9.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: ## Luminance Based Masked Variable Blur
2 |
3 | import UIKit
4 | import CoreImage
5 | //: ### MaskedVariableBlur filter
6 | class MaskedVariableBlur: CIFilter
7 | {
8 | var inputImage: CIImage?
9 | var inputBlurImage: CIImage?
10 | var inputBlurRadius: CGFloat = 5
11 |
12 | override var attributes: [String : AnyObject]
13 | {
14 | return [
15 | kCIAttributeFilterDisplayName: "Metal Pixellate",
16 |
17 | "inputImage": [kCIAttributeIdentity: 0,
18 | kCIAttributeClass: "CIImage",
19 | kCIAttributeDisplayName: "Image",
20 | kCIAttributeType: kCIAttributeTypeImage],
21 |
22 | "inputBlurImage": [kCIAttributeIdentity: 0,
23 | kCIAttributeClass: "CIImage",
24 | kCIAttributeDisplayName: "Image",
25 | kCIAttributeType: kCIAttributeTypeImage],
26 |
27 | "inputBlurRadius": [kCIAttributeIdentity: 0,
28 | kCIAttributeClass: "NSNumber",
29 | kCIAttributeDefault: 5,
30 | kCIAttributeDisplayName: "Pixel Height",
31 | kCIAttributeMin: 0,
32 | kCIAttributeSliderMin: 0,
33 | kCIAttributeSliderMax: 100,
34 | kCIAttributeType: kCIAttributeTypeScalar]
35 | ]
36 | }
37 |
38 | let maskedVariableBlur = CIKernel(string:
39 | "kernel vec4 lumaVariableBlur(sampler image, sampler blurImage, float blurRadius) " +
40 | "{ " +
41 | " vec2 d = destCoord(); " +
42 | " vec3 blurPixel = sample(blurImage, samplerCoord(blurImage)).rgb; " +
43 | " float blurAmount = dot(blurPixel, vec3(0.2126, 0.7152, 0.0722)); " +
44 | " float n = 0.0; " +
45 | " int radius = int(blurAmount * blurRadius); " +
46 | " vec3 accumulator = vec3(0.0, 0.0, 0.0); " +
47 | " for (int x = -radius; x <= radius; x++) " +
48 | " { " +
49 | " for (int y = -radius; y <= radius; y++) " +
50 | " { " +
51 | " vec2 workingSpaceCoordinate = d + vec2(x,y); " +
52 | " vec2 imageSpaceCoordinate = samplerTransform(image, workingSpaceCoordinate); " +
53 | " vec3 color = sample(image, imageSpaceCoordinate).rgb; " +
54 | " accumulator += color; " +
55 | " n += 1.0; " +
56 | " } " +
57 | " } " +
58 | " accumulator /= n; " +
59 | " return vec4(accumulator, 1.0); " +
60 | "} "
61 | )
62 |
63 | override var outputImage: CIImage!
64 | {
65 | guard let
66 | inputImage = inputImage,
67 | inputBlurImage = inputBlurImage else
68 | {
69 | return nil
70 | }
71 |
72 | let extent = inputImage.extent
73 |
74 | let blur = maskedVariableBlur?.applyWithExtent(
75 | inputImage.extent,
76 | roiCallback:
77 | {
78 | (index, rect) in
79 | return rect
80 | },
81 | arguments: [inputImage, inputBlurImage, inputBlurRadius])
82 |
83 | return blur!.imageByCroppingToRect(extent)
84 | }
85 | }
86 | //: ### Filter vendor
87 | class FilterVendor: NSObject, CIFilterConstructor
88 | {
89 | func filterWithName(name: String) -> CIFilter?
90 | {
91 | switch name
92 | {
93 | case "MaskedVariableBlur":
94 | return MaskedVariableBlur()
95 |
96 | default:
97 | return nil
98 | }
99 | }
100 | }
101 | //: ### Register filter
102 | CIFilter.registerFilterName("MaskedVariableBlur",
103 | constructor: FilterVendor(),
104 | classAttributes: [kCIAttributeFilterName: "MaskedVariableBlur"])
105 | //: ### Source Image
106 | let monaLisa = CIImage(image: UIImage(named: "monalisa.jpg")!)!
107 | //: ### Radial gradient
108 | let gradientImage = CIFilter(
109 | name: "CIRadialGradient",
110 | withInputParameters: [
111 | kCIInputCenterKey: CIVector(x: 310, y: 390),
112 | "inputRadius0": 100,
113 | "inputRadius1": 300,
114 | "inputColor0": CIColor(red: 0, green: 0, blue: 0),
115 | "inputColor1": CIColor(red: 1, green: 1, blue: 1)
116 | ])?
117 | .outputImage?
118 | .imageByCroppingToRect(monaLisa.extent)
119 | //: ### Final output
120 | let final = monaLisa.imageByApplyingFilter("MaskedVariableBlur", withInputParameters: ["inputBlurRadius": 10, "inputBlurImage": gradientImage!])
121 |
122 |
--------------------------------------------------------------------------------
/Chapter9.playground/Resources/monalisa.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter9.playground/Resources/monalisa.jpg
--------------------------------------------------------------------------------
/Chapter9.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Chapter9.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Chapter9.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FlexMonkey/CoreImageForSwiftPlaygrounds/82e2c8de64b155b33fff1d39dac11eb9b217e1ba/Chapter9.playground/playground.xcworkspace/xcuserdata/simongladman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Chapter9.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CoreImageForSwiftPlaygrounds
2 |
3 | Companion playgrounds for my book, [_Core Image for Swift_](https://itunes.apple.com/de/book/core-image-for-swift/id1073029980?l=en&mt=11)
4 |
5 | *Core Image for Swift* is available from:
6 |
7 | * [*Core Image for Swift* from iBooks Store](https://itunes.apple.com/us/book/core-image-for-swift/id1073029980?mt=13)
8 | * [*Core Image For Swift* from Gumroad](https://gumroad.com/l/CoreImageForSwift)
9 |
--------------------------------------------------------------------------------