├── 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 | --------------------------------------------------------------------------------