207
#WWDC17 © 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. David Hayward, Core Image Manager Advances in Core Image Filters, Metal, Vision, and More Session 510 Media

Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

#WWDC17

© 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

David Hayward, Core Image Manager

•Advances in Core Image •Filters, Metal, Vision, and More • Session 510

Media

Page 2: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Agenda

•A brief overview of Core Image •Highlights of what’s new this year •Details on new APIs and features

Page 3: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•A Brief Overview of Core Image

Page 4: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

A Very Brief Introduction to Core Image A simple, high-performance API to apply filters to images

OWorking Space

to OutputContrast

FilterHue

FilterSepia Filter

Input to

Original CIImage Output CIImage

Page 5: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

A Very Brief Introduction to Core Image Automatically tiles if images are large or graph is complex

OWorking Space

to OutputContrast

FilterHue

FilterSepia Filter

Input to

Original CIImage Output CIImage

Page 6: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

A Very Brief Introduction to Core Image Automatically tiles if only a region of the output is rendered

OWorking Space

to OutputContrast

FilterHue

FilterSepia Filter

Input to

Output CIImageOriginal CIImage

Page 7: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel vec4 sepia () kernel vec4 hue () kernel vec4 contrast ()

A Very Brief Introduction to Core Image Each CIFilter has one or more CIKernel functions

OWorking Space

to OutputContrast

FilterHue

FilterSepia Filter

Input to

Original CIImage Output CIImage

Page 8: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

OContrast

FilterSepia Filter

Working Space to Output

Hue Filter

Concatenated Program

A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance

kernel vec4 sepia ()

kernel vec4 hue ()

kernel vec4 contrast ()

Input to

Original CIImage Output CIImage

Page 9: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Page 10: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance

Page 11: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance Information

Page 12: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance Information Functionality

Page 13: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance Information Functionality

Write CIKernels in Metal CIRenderDestination API

Page 14: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance Information Functionality

Write CIKernels in Metal CIRenderDestination API

CIRenderInfo API Xcode Quick Looks

Page 15: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Performance Information Functionality

Write CIKernels in Metal CIRenderDestination API

CIRenderInfo API Xcode Quick Looks

New Filters Barcode Support

Depth Support

Page 16: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary of What’s New Our goal for this release is to enable developers to get better:

Image Editing with Depth WWDC 2017

Performance Information Functionality

Write CIKernels in Metal CIRenderDestination API

CIRenderInfo API Xcode Quick Looks

New Filters Barcode Support

Depth Support

Page 17: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•New Built-In CIFilters

Page 18: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

196 Built-In Filters

11

Page 19: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

196 Built-In FiltersAccordionFoldTransition AdditionCompositing AffineClamp AffineTile AffineTransform AreaAverage AreaHistogram AreaMaximum AreaMaximumAlpha AreaMinimum AreaMinimumAlpha AreaMinMaxRed AttributedTextImageGenerator AztecCodeGenerator BarcodeGenerator BarsSwipeTransition BicubicScaleTransform BlendWithAlphaMask BlendWithMask Bloom BokehBlur BoxBlur BumpDistortion BumpDistortionLinear CheckerboardGenerator CircleSplashDistortion CircularScreen CircularWrap Clamp CMYKHalftone Code128BarcodeGenerator ColorBlendMode

ColorBurnBlendMode ColorClamp ColorControls ColorCrossPolynomial ColorCube ColorCubesMixedWithMask ColorCubeWithColorSpace ColorCurves ColorDodgeBlendMode ColorInvert ColorMap ColorMatrix ColorMonochrome ColorPolynomial ColorPosterize ColumnAverage ComicEffect ConstantColorGenerator Convolution3X3 Convolution5X5 Convolution7X7 Convolution9Horizontal Convolution9Vertical CopyMachineTransition Crop Crystallize DarkenBlendMode DepthBlurEffect DepthOfField DepthToDisparity DifferenceBlendMode DiscBlur DisintegrateWithMaskTransition

DisparityToDepth DisplacementDistortion DissolveTransition DivideBlendMode DotScreen Droste EdgePreserveUpsampleFilter Edges EdgeWork EightfoldReflectedTile ExclusionBlendMode ExposureAdjust FalseColor FlashTransition FourfoldReflectedTile FourfoldRotatedTile FourfoldTranslatedTile GammaAdjust GaussianBlur GaussianGradient GlassDistortion GlassLozenge GlideReflectedTile Gloom HardLightBlendMode HatchedScreen HeightFieldFromMask HexagonalPixellate HighlightShadowAdjust HistogramDisplayFilter HoleDistortion HueAdjust HueBlendMode

HueSaturationValueGradient Kaleidoscope LabDeltaE LanczosScaleTransform LenticularHaloGenerator LightenBlendMode LightTunnel LinearBurnBlendMode LinearDodgeBlendMode LinearGradient LinearToSRGBToneCurve LineOverlay LineScreen LuminosityBlendMode MaskedVariableBlur MaskToAlpha MaximumComponent MaximumCompositing MedianFilter MinimumComponent MinimumCompositing ModTransition MorphologyGradient MorphologyMaximum MorphologyMinimum MotionBlur MultiplyBlendMode MultiplyCompositing NinePartStretched NinePartTiled NoiseReduction OpTile OverlayBlendMode

PageCurlTransition PageCurlWithShadowTransition ParallelogramTile PDF417BarcodeGenerator PerspectiveCorrection PerspectiveTile PerspectiveTransform PerspectiveTransformWithExtent PhotoEffectChrome PhotoEffectFade PhotoEffectInstant PhotoEffectMono PhotoEffectNoir PhotoEffectProcess PhotoEffectTonal PhotoEffectTransfer PinchDistortion PinLightBlendMode Pixellate Pointillize QRCodeGenerator RadialGradient RandomGenerator RippleTransition RowAverage SaturationBlendMode ScreenBlendMode SepiaTone ShadedMaterial SharpenLuminance SixfoldReflectedTile SixfoldRotatedTile SmoothLinearGradient

SoftLightBlendMode SourceAtopCompositing SourceInCompositing SourceOutCompositing SourceOverCompositing SpotColor SpotLight SRGBToneCurveToLinear StarShineGenerator StraightenFilter StretchCrop StripesGenerator SubtractBlendMode SunbeamsGenerator SwipeTransition TemperatureAndTint TextImageGenerator Thermal ToneCurve TorusLensDistortion TriangleKaleidoscope TriangleTile TwelvefoldReflectedTile TwirlDistortion UnsharpMask Vibrance Vignette VignetteEffect VortexDistortion WhitePointAdjust XRay ZoomBlur

11

Page 20: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-In CIFilters Some that are useful for Depth filtering

CIDepthToDisparity / CIDisparityToDepth

CIMorphologyMinimum / Maximum / Gradient

CIColorCubesMixedWithMask

CIAreaMinMaxRed

Page 21: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-In CIFilters Some that are useful for Depth filtering

CIDepthToDisparity / CIDisparityToDepth

CIMorphologyMinimum / Maximum / Gradient

CIColorCubesMixedWithMask

CIAreaMinMaxRed

CIDepthBlurEffect

Page 22: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-In CIFilters Some that are useful for Depth filtering

CIDepthToDisparity / CIDisparityToDepth

CIMorphologyMinimum / Maximum / Gradient

CIColorCubesMixedWithMask

CIAreaMinMaxRed

CIDepthBlurEffect

Image Editing with Depth WWDC 2017

Page 23: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-in CIFilters Some that are often requested additions

CITextImageGenerator

CIColorCurves

CILabDeltaE

CIBicubicScaleTransform

CIBarcodeGenerator

Page 24: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-in CIFilters Some that are improved

CIHueBlendMode

CISaturationBlendMode

CIColorBlendMode

CILuminosityBlendMode

CILinearBurnBlendMode

Page 25: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New Built-in CIFilters Some that are improved

CIHueBlendMode

CISaturationBlendMode

CIColorBlendMode

CILuminosityBlendMode

CILinearBurnBlendMode

The demosaic and noise reduction filters used for RAW files

Page 26: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Tony Chu, Core Image Engineer

•Writing CIKernels in Metal

Page 27: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel vec4 sepia () kernel vec4 hue () kernel vec4 contrast ()

Writing CIKernels

OWorking Space

to OutputContrast

FilterHue

FilterSepiaFilter

Input to

Original CIImage Output CIImage

Page 28: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel vec4 sepia () kernel vec4 hue () kernel vec4 contrast ()

Writing CIKernels

OWorking Space

to OutputContrast

FilterHue

FilterSepiaFilter

Input to

Original CIImage Output CIImage

Page 29: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language

Page 30: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL

Page 31: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL• Language extensions to enable automatic tiling and subregion rendering

Page 32: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL• Language extensions to enable automatic tiling and subregion rendering destCoord()

Page 33: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL• Language extensions to enable automatic tiling and subregion rendering destCoord() samplerTransform(sampler src, vec2 p)

Page 34: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL• Language extensions to enable automatic tiling and subregion rendering destCoord() samplerTransform(sampler src, vec2 p) sample(sampler src, vec2 p)

Page 35: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels

Previously, kernels are written in CIKernel Language • Based on GLSL• Language extensions to enable automatic tiling and subregion rendering destCoord() samplerTransform(sampler src, vec2 p) sample(sampler src, vec2 p)

• Translated, concatenated, and compiled at run-time to Metal or GLSL

Page 36: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Compiling CIKernels on First Render

Translate CIKernels

Concatenate CIKernels

Compile to GPU Code

Compile CIKernels to Intermediate Representation Render

Page 37: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Compiling CIKernels on First Render

Translate CIKernels

Concatenate CIKernels

Compile to GPU Code

Compile CIKernels to Intermediate Representation Render

Page 38: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Compiling CIKernels on First Render

At run-time

At build-time (in Xcode)

Translate CIKernels

Concatenate CIKernels

Compile to GPU Code

Compile CIKernels to Intermediate Representation

Render

Page 39: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

NEW

Page 40: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits

NEW

Page 41: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits• Precompiled at build-time with error diagnostics

NEW

Page 42: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits• Precompiled at build-time with error diagnostics• More modern language features

NEW

Page 43: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits• Precompiled at build-time with error diagnostics• More modern language features• Still supports concatenation and tiling

NEW

Page 44: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits• Precompiled at build-time with error diagnostics• More modern language features• Still supports concatenation and tiling• Can be mixed with traditional CIKernels not written in Metal

NEW

Page 45: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Writing CIKernels in Metal

Now, you can write CIKernels directly in Metal Shading Language

Benefits• Precompiled at build-time with error diagnostics• More modern language features• Still supports concatenation and tiling• Can be mixed with traditional CIKernels not written in Metal

Supported on iOS (for A8 or newer devices), macOS, and tvOS

NEW

Page 46: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

Page 47: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file

Page 48: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file•2. Compile and link Metal shader file

Page 49: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file•2. Compile and link Metal shader file•3. Initialize CIKernel with function from Metal library

Page 50: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file •2. Compile and link Metal shader file •3. Initialize CIKernel with function from Metal library

Page 51: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIKernel Metal Library

New header file containing CIKernel extensions to the Metal Shading Language

NEW

Page 52: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIKernel Metal Library

New header file containing CIKernel extensions to the Metal Shading Language• CIKernel data types

NEW

Page 53: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIKernel Metal Library

New header file containing CIKernel extensions to the Metal Shading Language• CIKernel data types destination, sampler, sample_t

NEW

Page 54: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIKernel Metal Library

New header file containing CIKernel extensions to the Metal Shading Language• CIKernel data types destination, sampler, sample_t

• CIKernel functions

NEW

Page 55: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIKernel Metal Library

New header file containing CIKernel extensions to the Metal Shading Language• CIKernel data types destination, sampler, sample_t

• CIKernel functions premultiply, unpremultiply, srgb_to_linear, linear_to_srgb, compare, cossin, sincos

NEW

Page 56: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// CIKernelMetalLib.h

namespace coreimage {

struct destination { float2 coord() const; };

struct sampler { float2 transform(float2 p) const; float2 coord() const; float4 sample(float2 p) const; float4 extent() const; };

// ... }

Page 57: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// CIKernelMetalLib.h

namespace coreimage {

struct destination { float2 coord() const; };

struct sampler { float2 transform(float2 p) const; float2 coord() const; float4 sample(float2 p) const; float4 extent() const; };

// ... }

Page 58: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// CIKernelMetalLib.h

namespace coreimage {

struct destination { float2 coord() const; };

struct sampler { float2 transform(float2 p) const; float2 coord() const; float4 sample(float2 p) const; float4 extent() const; };

// ... }

Page 59: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Destination and Samplers

CIKernel Language Metal

Get destination coordinate destCoord() dest.coord()

Transform coordinate to sampler space samplerTransform(src, p) src.transform(p)

Get destination coordinate in sampler space samplerCoord(src) src.coord()

Sample from source image sample(src, p) src.sample(p)

Get extent of source image samplerExtent(src) src.extent()

Page 60: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Destination and Samplers

CIKernel Language Metal

Get destination coordinate destCoord() dest.coord()

Transform coordinate to sampler space samplerTransform(src, p) src.transform(p)

Get destination coordinate in sampler space samplerCoord(src) src.coord()

Sample from source image sample(src, p) src.sample(p)

Get extent of source image samplerExtent(src) src.extent()

Page 61: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIWarpKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float2 myWarp (destination dest) { float2 p = dest.coord(); // do something return p; }

}}

Page 62: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIWarpKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float2 myWarp (destination dest) { float2 p = dest.coord(); // do something return p; }

}}

Page 63: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIWarpKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float2 myWarp (destination dest) { float2 p = dest.coord(); // do something return p; }

}}

Page 64: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIWarpKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float2 myWarp (destination dest) { float2 p = dest.coord(); // do something return p; }

}}

Page 65: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIWarpKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float2 myWarp (destination dest) { float2 p = dest.coord(); // do something return p; }

}}

kernel vec2 myWarp () { vec2 p = destCoord(); // do something return p;

}

Page 66: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIColorKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myColor (sample_t s) { // do something return s; }

}}

Page 67: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIColorKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myColor (sample_t s) { // do something return s; }

}}

Page 68: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIColorKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myColor (sample_t s) { // do something return s; }

}}

kernel vec4 myColor (__sample s) { // do something return s;

}

Page 69: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myKernel (sampler src) { float4 s = src.sample(src.coord()); // do something return s; }

}}

Page 70: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myKernel (sampler src) { float4 s = src.sample(src.coord()); // do something return s; }

}}

Page 71: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Metal CIKernel Source

#include <metal_stdlib> using namespace metal;

#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h

extern "C" { namespace coreimage {

float4 myKernel (sampler src) { float4 s = src.sample(src.coord()); // do something return s; }

}}

kernel vec4 myKernel (sampler src) { vec4 s = sample(src, samplerCoord(src)); // do something return s;

}

Page 72: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file •2. Compile and link Metal shader file •3. Initialize CIKernel with function from Metal library

Page 73: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Metal Library Data File

CIKernel Source File

Compiling and Linking CIKernels

Intermediate Representation File

.air .metallib.metal metal metallib

Page 74: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Metal Library Data File

CIKernel Source File

Compiling and Linking CIKernels

Intermediate Representation File

.air .metallib.metal metal

Options: -fcikernel

metallib

Page 75: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Metal Library Data File

CIKernel Source File

Compiling and Linking CIKernels

Intermediate Representation File

.air .metallib.metal metal

Options: -fcikernel -cikernel

metallib

Page 76: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel
Page 77: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel
Page 78: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

xcrun metal -fcikernel MyKernels.metal -o MyKernels.air xcrun metallib -cikernel MyKernels.air -o MyKernels.metallib

Page 79: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

How to Create Metal CIKernels

•1. Write CIKernel in Metal shader file •2. Compile and link Metal shader file •3. Initialize CIKernel with function from Metal library

Page 80: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIKernel API

init(functionName name: String, fromMetalLibraryData data: Data) throws init(functionName name: String, fromMetalLibraryData data: Data, outputPixelFormat format: CIFormat) throws

NEW

Page 81: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIKernel API

init(functionName name: String, fromMetalLibraryData data: Data) throws init(functionName name: String, fromMetalLibraryData data: Data, outputPixelFormat format: CIFormat) throws

NEW

// Example of initializing CIKernels

let url = Bundle.main.url(forResource: "default", withExtension: "metallib")! let data = try! Data(contentsOf: url)

let kernel = try? CIKernel(functionName: "myKernel", fromMetalLibraryData: data)

Page 82: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIKernel API

init(functionName name: String, fromMetalLibraryData data: Data) throws init(functionName name: String, fromMetalLibraryData data: Data, outputPixelFormat format: CIFormat) throws

NEW

// Example of initializing CIKernels

let url = Bundle.main.url(forResource: "default", withExtension: "metallib")! let data = try! Data(contentsOf: url)

let kernel = try? CIKernel(functionName: "myKernel", fromMetalLibraryData: data) let warpKernel = try? CIWarpKernel(functionName: "myWarp", fromMetalLibraryData: data) let colorKernel = try? CIColorKernel(functionName: "myColor", fromMetalLibraryData: data)

Page 83: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•New CIRenderDestination API

Page 84: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API

A consistent API to render to different destination types • IOSurface • CVPixelBuffer • Metal Texture • OpenGL Texture • Memory buffer

Page 85: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API

A consistent API to render to different destination types • IOSurface • CVPixelBuffer • Metal Texture • OpenGL Texture • Memory buffer

Returns immediately if render fails—with an error

Page 86: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API

Allow setting of common properties for the destination • Alpha mode behavior • Clamping mode behavior • Destination colorspace

Page 87: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API

Allow setting of common properties for the destination • Alpha mode behavior • Clamping mode behavior • Destination colorspace

And some advanced properties • Dithering • Blending

Page 88: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API

Allow setting of common properties for the destination • Alpha mode behavior • Clamping mode behavior • Destination colorspace

And some advanced properties • Dithering • Blending

Reduces the need for multiple CIContexts

Page 89: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API Performance Benefits

Existing CIContext APIs for rendering to IOSurface or CVPixelBuffer • Return to caller when render is completed

Page 90: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API Performance Benefits

Existing CIContext APIs for rendering to IOSurface or CVPixelBuffer • Return to caller when render is completed

New CIRenderDestination APIs • Return to caller when work is issued

Page 91: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

New CIRenderDestination API Performance Benefits

Existing CIContext APIs for rendering to IOSurface or CVPixelBuffer • Return to caller when render is completed

New CIRenderDestination APIs • Return to caller when work is issued

This allows CPU and GPU work to be pipelined efficiently

Page 92: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 93: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 94: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 95: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 96: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 97: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Clear Then Render Foreground Blended with Background

func renderImagePair (foregroundImage : CIImage, backgroundImage : CIImage, blend : CIBlendKernel = CIBlendKernel.sourceOver toSurface : IOSurface) { let dest = CIRenderDestination(ioSurface: toSurface) let ctx = getContext() // don’t create a context each time try? ctx.startTask(toClear: dest) try? ctx.startTask(toRender: backgroundImage, to: dest) dest.blendKernel = blend // use one of 37 built-in blend kernels or create your own try? ctx.startTask(toRender: foregroundImage, to: dest).waitUntilCompleted() }

Page 98: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

let ctx = getContext() // don’t create a context each time let texture = currentDrawable.texture let dest = CIRenderDestination(texture, commandBuffer: cmdBuffer)

try? ctx.startTask(toRender: image, to: dest)

Page 99: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

let ctx = getContext() // don’t create a context each time let texture = currentDrawable.texture let dest = CIRenderDestination(texture, commandBuffer: cmdBuffer)

try? ctx.startTask(toRender: image, to: dest)

Page 100: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

let ctx = getContext() // don’t create a context each time let texture = currentDrawable.texture let dest = CIRenderDestination(texture, commandBuffer: cmdBuffer)

try? ctx.startTask(toRender: image, to: dest)

Page 101: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

let ctx = getContext() // don’t create a context each time while stillDrawing { let texture = currentDrawable.texture let dest = CIRenderDestination(texture, commandBuffer: cmdBuffer)

try? ctx.startTask(toRender: image, to: dest) }

Page 102: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

CPU

GPU

Page 103: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Get drawable

CPU

GPU

Page 104: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Get drawableCall startTask

CPU

GPU

Page 105: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Get drawableCall startTask

CPU

GPU

Page 106: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Get drawable

startTask returns

Call startTask

CPU

GPU

Page 107: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Get drawable

startTask returns

Get drawableCall startTask

CPU

GPU

Page 108: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Get drawable

startTask returns

Get drawableCall startTask

CPU

GPU

Page 109: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Frame BI1 I2 D

Frame BI1 I2 D

Get drawable

startTask returns

Get drawableCall startTask Call startTask

CPU

GPU

Page 110: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures

Frame AI1 I2 D

Frame AI1 I2 D

Frame BI1 I2 D

Frame BI1 I2 D

Frame CI1 I2 D

Frame CI1 I2 D

Get drawable

startTask returns

Get drawableCall startTask Call startTask

CPU

GPU

Page 111: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

let ctx = getContext() // don’t create a context each time while stillDrawing { let dest = CIRenderDestination( width: 1024, height: 768, pixelFormat: MTLPixelFormat.rgba8Unorm, commandBuffer: cmdBuffer) { () -> MTLTexture in return currentDrawable.texture })

try? ctx.startTask(toRender: image, to: dest) }

Page 112: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

let ctx = getContext() // don’t create a context each time while stillDrawing { let dest = CIRenderDestination( width: 1024, height: 768, pixelFormat: MTLPixelFormat.rgba8Unorm, commandBuffer: cmdBuffer) { () -> MTLTexture in return currentDrawable.texture })

try? ctx.startTask(toRender: image, to: dest) }

Page 113: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

let ctx = getContext() // don’t create a context each time while stillDrawing { let dest = CIRenderDestination( width: 1024, height: 768, pixelFormat: MTLPixelFormat.rgba8Unorm, commandBuffer: cmdBuffer) { () -> MTLTexture in return currentDrawable.texture })

try? ctx.startTask(toRender: image, to: dest) }

Page 114: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

let ctx = getContext() // don’t create a context each time while stillDrawing { let dest = CIRenderDestination( width: 1024, height: 768, pixelFormat: MTLPixelFormat.rgba8Unorm, commandBuffer: cmdBuffer) { () -> MTLTexture in return currentDrawable.texture })

try? ctx.startTask(toRender: image, to: dest) }

Page 115: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

Frame AI1 I2 D

Frame AI1 I2 D

Frame BI1 I2 D

Frame BI1 I2 D

Frame CI1 I2 D

Frame CI1 I2 D

CPU

GPU

Page 116: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Rendering to Metal Drawable Textures Improved

Frame AI1 I2 D

Frame AI1 I2 D

Frame BI1 I2 D

Frame BI1 I2 D

Frame CI1 I2 D

Frame CI1 I2 D

CPU

GPU

Page 117: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•Looking Inside Core Image •Quick Look support and other runtime information

Page 118: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Detailed Image and Render Information See how Core Image works internally

CIRenderTask returns a CIRenderInfo object when complete passCount kernelExecutionTime kernelPixelsProcessed

45

Page 119: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Detailed Image and Render Information Awesome Core Image Quick Looks in Xcode

46

Page 120: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Detailed Image and Render Information Awesome Core Image Quick Looks in Xcode

CIImage Shows the image graph as constructed

46

Page 121: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Detailed Image and Render Information Awesome Core Image Quick Looks in Xcode

CIImage Shows the image graph as constructed

CIRenderTask Shows how Core Image optimized the graph

46

Page 122: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Detailed Image and Render Information Awesome Core Image Quick Looks in Xcode

CIImage Shows the image graph as constructed

CIRenderTask Shows how Core Image optimized the graph

CIRenderInfo Shows concatenation, timing, and caching

46

Page 123: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load image and apply orientation var image = CIImage(

contentsOf: url options: [kCIImageApplyOrientationProperty: true])

// downsample by 2x image = image.applying(CGAffineTransform(scaleX:0.5, y:0.5))

CIImage Quick Look

Page 124: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load image and apply orientation var image = CIImage(

contentsOf: url options: [kCIImageApplyOrientationProperty: true])

// downsample by 2x image = image.applying(CGAffineTransform(scaleX:0.5, y:0.5))

CIImage Quick Look

(CIImage)0x0000000100e61630

Page 125: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load image and apply orientation var image = CIImage(

contentsOf: url options: [kCIImageApplyOrientationProperty: true])

// downsample by 2x image = image.applying(CGAffineTransform(scaleX:0.5, y:0.5))

CIImage Quick Look

(CIImage)0x0000000100e61630

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(189) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x100e61630>

Page 126: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(189) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x100e61630>

Page 127: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(189) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x100e61630>

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(418) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x1032005e0>

Page 128: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(189) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x100e61630>

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x1017ac560(276) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x1017a6c90>

Page 129: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100f483d0(189) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x100e61630>

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x1017ac560(276) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x1017a6c90>

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x1017ac560(276) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x1017a6c90>

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x1017ac560(276) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

CIImage <0x1017a6c90>

Page 130: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load disparity image and apply orientation var disparity = CIImage(

contentsOf: url,

options: [kCIImageAuxiliaryDisparity: true, kCIImageApplyOrientationProperty: true])

// cubic upsample by 2x disparity = disparity.applyingFilter(“CIBicubicScaleTransform”, withInputParameters: […])

// adjust disparity mask and blend foreground and background let mask = disparity.applyingFilter(“CIColorControls",

withInputParameters: [kCIInputContrastKey: 2.0]) mask = mask.applyingFilter(“CIColorClamp")

CIImage Quick Look

Page 131: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load disparity image and apply orientation var disparity = CIImage(

contentsOf: url,

options: [kCIImageAuxiliaryDisparity: true, kCIImageApplyOrientationProperty: true])

// cubic upsample by 2x disparity = disparity.applyingFilter(“CIBicubicScaleTransform”, withInputParameters: […])

// adjust disparity mask and blend foreground and background let mask = disparity.applyingFilter(“CIColorControls",

withInputParameters: [kCIInputContrastKey: 2.0]) mask = mask.applyingFilter(“CIColorClamp")

CIImage Quick Look

(CIImage) 0x0000000100f29480

Page 132: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// load disparity image and apply orientation var disparity = CIImage(

contentsOf: url,

options: [kCIImageAuxiliaryDisparity: true, kCIImageApplyOrientationProperty: true])

// cubic upsample by 2x disparity = disparity.applyingFilter(“CIBicubicScaleTransform”, withInputParameters: […])

// adjust disparity mask and blend foreground and background let mask = disparity.applyingFilter(“CIColorControls",

withInputParameters: [kCIInputContrastKey: 2.0]) mask = mask.applyingFilter(“CIColorClamp")

CIImage Quick Look

(CIImage) 0x0000000100f29480

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(218) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100f29480>

Page 133: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(218) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100f29480>

Page 134: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(218) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100f29480>

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(428) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x103562690>

Page 135: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(218) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100f29480>

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(428) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x103562690>

Page 136: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e720c0(218) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100f29480>

Page 137: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade")

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir")

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

CIImage Quick Look

Page 138: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade")

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir")

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

CIImage Quick Look

(CIImage) 0x0000000100e341d0

Page 139: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade")

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir")

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

CIImage Quick Look

(CIImage) 0x0000000100e341d0

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

color_matrix r=(1.51572 0 0 0) g=(0 1.51572 0 0) b=(0 0 1.51572 0) a=(0 0 0 1) extent=[0 0 1512 2016] opaque

0

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x100e0aa10(29) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

color_matrix r=(0.659754 0 0 0) g=(0 0.659754 0 0) b=(0 0 0.659754 0) a=(0 0 0 1) extent=[0 0 1512 2016] opaque

1

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x100e17c00(213) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x100e341d0>

Page 140: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIImage Quick Look

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade") fg = fg.applyingFilter(“CIExposureAdjust", withInputParameters: [kCIInputEVKey : 0.6])

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir") bg = bg.applyingFilter("CIExposureAdjust", withInputParameters: [kCIInputEVKey : -0.6])

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10350fa60(427) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x103007610(441) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x10353a570>

Page 141: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIImage Quick Look

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade") fg = fg.applyingFilter(“CIExposureAdjust", withInputParameters: [kCIInputEVKey : 0.6])

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir") bg = bg.applyingFilter("CIExposureAdjust", withInputParameters: [kCIInputEVKey : -0.6])

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10350fa60(427) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x103007610(441) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x10353a570>

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10320a6b0(105) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x1017e4290(432) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x1017c9630>

Page 142: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIImage Quick Look

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade") fg = fg.applyingFilter(“CIExposureAdjust", withInputParameters: [kCIInputEVKey : 0.6])

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir") bg = bg.applyingFilter("CIExposureAdjust", withInputParameters: [kCIInputEVKey : -0.6])

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10350fa60(427) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x103007610(441) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x10353a570>

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10320a6b0(105) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x1017e4290(432) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x1017c9630>

Page 143: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIImage Quick Look

// adjustment for foreground let fg = image.applyingFilter("CIPhotoEffectFade") fg = fg.applyingFilter(“CIExposureAdjust", withInputParameters: [kCIInputEVKey : 0.6])

// adjustment for background let bg = image.applyingFilter("CIPhotoEffectNoir") bg = bg.applyingFilter("CIExposureAdjust", withInputParameters: [kCIInputEVKey : -0.6])

// combine foreground and background using mask let output = fg.applyingFilter("CIBlendWithMask",

withInputParameters: [ kCIInputBackgroundImageKey: bg,

kCIInputMaskImageKey: mask ])

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

0

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x10350fa60(427) seed:192 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

1

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x103007610(441) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x10353a570>

colorkernel _blendWithMask f=image_0 b=image_1 m=image_2 extent=[0 0 1512 2016]

color_matrix r=(1.51572 0 0 0) g=(0 1.51572 0 0) b=(0 0 1.51572 0) a=(0 0 0 1) extent=[0 0 1512 2016] opaque

0

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

colorkernel _colorcubeopaque_denorm im=image_3 cube=image_4 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

3

affine 0.5 0 0 0 0.5 0 extent=[0 0 1512 2016] opaque

affine 0 -1 0 1 0 4032 extent=[0 0 3024 4032] opaque

affine 1 0 0 0 -1 3024 extent=[0 0 4032 3024] opaque

colormatch Display P3_to_workingspace extent=[0 0 4032 3024] opaque

IOSurface 0x1017ac560(276) seed:1 YCC420f 601 alpha_one extent=[0 0 4032 3024] opaque

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

4

color_matrix r=(0.659754 0 0 0) g=(0 0.659754 0 0) b=(0 0 0.659754 0) a=(0 0 0 1) extent=[0 0 1512 2016] opaque

1

colormatch devicergb_to_workingspace extent=[0 0 1512 2016] opaque

colorkernel _colorcubeopaque_denorm im=image_5 cube=image_6 dims=[31 0.0322581 0.03125 0.000976562] extent=[0 0 1512 2016] opaque

colormatch workingspace_to_devicergb extent=[0 0 1512 2016] opaque

5

provider BGRA8 32x1024 alpha_one edge_clamp cache extent=[infinite][0 0 32 1024] opaque

6

premultiply extent=[-6 -6 1524 2028]

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] extent=[-6 -6 1524 2028]

unpremultiply extent=[-6 -6 1524 2028]

color_matrix r=(2 0 0 0) g=(0 2 0 0) b=(0 0 2 0) a=(0 0 0 1) bias=(-0.5 -0.5 -0.5 0) extent=[-6 -6 1524 2028]

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] extent=[-6 -6 1524 2028]

affine 0 -1 0 1 0 768 extent=[0 0 576 768] opaque

affine 1 0 0 0 -1 576 extent=[0 0 768 576] opaque

colormatch Linear Gray_to_workingspace extent=[0 0 768 576] opaque

IOSurface 0x102030610(424) seed:1 Lh alpha_one extent=[0 0 768 576] opaque

CIImage <0x10203ee60>

Page 144: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderTask Quick Look

Page 145: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderTask Quick Look

(CIRenderTask) 0x0000000102806b20

Page 146: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderTask Quick Look

(CIRenderTask) 0x0000000102806b20

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 147: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 148: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=4D4E88B6BBFF0AD7

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=13F371CE2F70DED8

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=5DB894F55B324B36

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=95344C24BB66968D

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=31D0858F8898BAAA

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=5798B49C0355C679

color_matrix_diag [1.51572, 1.51572, 1.51572] rois=[0 0 1512 2016] extent=[infinite][empty] digest=2E8BE17A9B399216

0

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=FD2602BEDC791422

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=5F1D349B4A7D3103

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28297F7CCAF68C70

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=68BC84D63D03C05B

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5F299E59E856714C

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=99F3F681729FA5A4

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=7543B6B4D80E35E3

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=CFB3EC1C5985E7E0

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=6BDBF61A00035E59

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=451AADCE04101EEA

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=7204E5EF519A51E

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

color_matrix_diag [0.659754, 0.659754, 0.659754] rois=[0 0 1512 2016] extent=[infinite][empty] digest=20886E97A0997F41

1

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=62EE4F9BA4F38815

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=BB9FF01CC7264603

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=3222277ADBB13242

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=68C5F0CDBA70E6A0

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5F299E59E856714C

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=99F3F681729FA5A4

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EABBB36892CA9483

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=2C584ECF0C37FCFC

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=D0513E6268CC22CD

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=6A0C39D82667D2A4

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=D92B86403F0804EC

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=19845A60A8CB4BDA

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=F61974C92D5B0B9E

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=179BA22AFF932D96

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=7476CC0097772826

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FF5B1FBE78FF1C9E

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 149: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 150: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 151: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

affine 1 0 0 0 -1 2016 rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310

clamp_to_alpha rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=7FF7DA85C4C272F

premultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=C1C4C4605B7A67F8

linear_to_srgb rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=28A3941A3DEF8ED3

unpremultiply rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=6E8216B0766EE943

colorkernel _blendWithMask f=(0) b=(1) m=(2) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=A03F1302AE52FA2

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=35A1ED32B7CF9623

0

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EAD1A08A4B0E2AFF

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=5888021ED6FE2240

colorkernel _colorcubeopaque_denorm im=(3) cube=(4) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=893D3744D6DC6041

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

3

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

affine 0 -0.5 1512 -0.5 -0 2016 rois=[0 0 1512 2016] extent=[infinite][empty] digest=F1AC6EB48CC9C297

color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=56878F059714A71E

curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=1227B74C49153950

color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=23C22371D291549D

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

4

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=28E64EF30464138A

1

srgb_to_linear rois=[0 0 1512 2016] extent=[infinite][empty] digest=EE71EA0E37C9BACA

unpremultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=59D03685D7B281C8

colorkernel _colorcubeopaque_denorm im=(5) cube=(6) dims=[31 0.0322581 0.03125 0.000976562] rois=[0 0 1512 2016] extent=[infinite][empty] digest=491D0A9935DB1FC7

premultiply rois=[0 0 1512 2016] extent=[infinite][empty] digest=41DC5A181A04E2FD

5

linear_to_srgb rois=[0 0 1512 2016] extent=[infinite][empty] digest=7085717B16282FC6

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

6

premultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=A151E67FC910233

2

colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=74289F843E3F4F71

unpremultiply rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=FCCD5FFF99FAFE12

color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=10DBE3AD6B4EF2A0

kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65

affine 0 -1 576 -1 -0 768 rois=[-1 -1 578 770] extent=[0 0 576 768] opaque digest=F26AE90AEAE2BD7E

color_matrix_rrra rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD

crop [0 0 768 576] rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=9310A62A244DBB44

swizzle_rrr1 rois=[0 0 768 576] extent=[infinite][empty] opaque digest=FEEF5EFAAB178D1C

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

optimized graph render_to_surface (metal context 1 frame 1) format=BGRA8 roi=[0 0 1512 2016]

Page 152: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderInfo Quick Look

Page 153: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderInfo Quick Look

(CIRenderInfo) 0x0000000100e082b0

Page 154: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// render output to an IOSurface let dest = CIRenderDestination(ioSurface: surface);

let context = self.context;

guard

let task = try? context.startTask(toRender: output, to: dest),

let info = try? task.waitUntilCompleted()

else { // handle render failure

}

CIRenderInfo Quick Look

(CIRenderInfo) 0x0000000100e082b0

program affine [1 0 0 -1 0 2016] clamp_to_alpha premultiply linear_to_srgb unpremultiply colorkernel _blendWithMask f b m premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(1) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (1) premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(2) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (2) premultiply colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] unpremultiply color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] (3) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310 time=15.05994 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

0provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

1

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

2program format=RGBAh kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] affine [0 -1 -1 -0 576 768] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65 time=1.52849 ms

3

program format=RGBAh color_matrix_rrra crop [0 0 768 576] swizzle_rrr1 rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD time=0.06279 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

program graph render_to_surface (metal context 1 frame 1 tile 1) format=BGRA8 roi=[0 0 1512 2016]

Page 155: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

program affine [1 0 0 -1 0 2016] clamp_to_alpha premultiply linear_to_srgb unpremultiply colorkernel _blendWithMask f b m premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(1) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (1) premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(2) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (2) premultiply colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] unpremultiply color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] (3) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310 time=15.05994 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

0provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

1

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

2program format=RGBAh kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] affine [0 -1 -1 -0 576 768] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65 time=1.52849 ms

3

program format=RGBAh color_matrix_rrra crop [0 0 768 576] swizzle_rrr1 rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD time=0.06279 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

program graph render_to_surface (metal context 1 frame 1 tile 1) format=BGRA8 roi=[0 0 1512 2016]

Page 156: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

program affine [1 0 0 -1 0 2016] clamp_to_alpha premultiply linear_to_srgb unpremultiply colorkernel _blendWithMask f b m premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(1) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (1) premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(2) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (2) premultiply colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] unpremultiply color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] (3) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310 time=15.05994 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

0provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

1

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

2program format=RGBAh kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] affine [0 -1 -1 -0 576 768] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65 time=1.52849 ms

3

program format=RGBAh color_matrix_rrra crop [0 0 768 576] swizzle_rrr1 rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD time=0.06279 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

program graph render_to_surface (metal context 1 frame 1 tile 1) format=BGRA8 roi=[0 0 1512 2016]

program affine [1 0 0 -1 0 2016] clamp_to_alpha premultiply linear_to_srgb unpremultiply colorkernel _blendWithMask f b m premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(1) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (1) premultiply srgb_to_linear unpremultiply colorkernel _colorcubeopaque_denorm im cube=(2) dims=[31 0.0322581 0.03125 0.000976562] premultiply linear_to_srgb affine [0 -0.5 -0.5 -0 1512 2016] color_matrix_3x3 r=[1.22486 -0.225095 1.43051e-05] g=[-0.0420312 1.04215 3.36338e-05] b=[-0.0196301 -0.0786319 1.09799] curve gamma=2.39999 a=0.947998 b=0.052002 c=0.0769958 d=0.0390015 e=0 f=0 color_matrix_3x4 r=[1 0 1.40752] g=[1 -0.345491 -0.716948] b=[1 1.77898 0] bias=[-0.70652 0.533302 -0.892976] (0) (2) premultiply colorkernel _colorClamp c lo=[0 0 0 0] hi=[1 1 1 1] unpremultiply color_matrix_3x4 r=[2 0 0] g=[0 2 0] b=[0 0 2] bias=[-0.5 -0.5 -0.5] (3) rois=[0 0 1512 2016] extent=[0 0 1512 2016] digest=114BF1F26BC2E310 time=15.05994 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 4032 3024] extent=[infinite][empty] opaque digest=33944A11D3550468

0provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=4EC4D10594168D56

1

provider BGRA8 32x1024 alpha_one edge_clamp rois=[0 0 32 1024] extent=[infinite][0 0 32 1024] opaque digest=9EA3D447FA8130A0

2program format=RGBAh kernel _cubicUpsample src scale=[0.380952 0.380952 0 0] coefsLT1=[1.5 -2.5 0 1] coefsLT2=[-0.5 2.5 -4 2] affine [0 -1 -1 -0 576 768] rois=[0 0 1512 2016] extent=[-6 -6 1524 2028] digest=EE11208C4277FD65 time=1.52849 ms

3

program format=RGBAh color_matrix_rrra crop [0 0 768 576] swizzle_rrr1 rois=[-1 -1 770 578] extent=[0 0 768 576] opaque digest=B8397104A14159DD time=0.06279 ms

IOSurface 0x0(0) seed:0 Nil alpha_one edge_clamp rois=[0 0 768 576] extent=[infinite][empty] opaque digest=3A29A615F9F448A

program graph render_to_surface (metal context 1 frame 1 tile 1) format=BGRA8 roi=[0 0 1512 2016]

Page 157: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•CIBarcodeDescriptor API

Page 158: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Framework Barcode Support Several frameworks support various barcodes types

AztecQRCode

Code128

PDF417

Page 159: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Framework Barcode Support Several frameworks support various barcodes types

AVFoundation.framework Vision.framework CoreImage.framework

Detection of barcodesduring capture

Detection of barcodesafter capture Rendering barcodes

Page 160: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Framework Barcode Support Several frameworks support various barcodes types

AVFoundation.framework Vision.framework CoreImage.framework

Detection of barcodesduring capture

Detection of barcodesafter capture Rendering barcodes

CIBarcodeDescriptor

Page 161: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIBarcodeDescriptor Objects Contain

The errorCorrectedPayload of the barcode

Page 162: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIBarcodeDescriptor Objects Contain

The errorCorrectedPayload of the barcode

Additional code-specific properties such as

Page 163: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIBarcodeDescriptor Objects Contain

The errorCorrectedPayload of the barcode

Additional code-specific properties such as• Aztec’s layerCount

Page 164: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

CIBarcodeDescriptor Objects Contain

The errorCorrectedPayload of the barcode

Additional code-specific properties such as• Aztec’s layerCount• QRCode’s maskPattern

Page 165: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Get a CIBarcodeDescriptor from AVFoundation.framework

class MyMetadataOutputObjectsDelegate: NSObject, AVCaptureMetadataOutputObjectsDelegate { func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { if let mrc = metadataObjects.first as? AVMetadataMachineReadableCodeObject, let descriptor = mrc.descriptor { print(descriptor) } } }

Page 166: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Get a CIBarcodeDescriptor from AVFoundation.framework

class MyMetadataOutputObjectsDelegate: NSObject, AVCaptureMetadataOutputObjectsDelegate { func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { if let mrc = metadataObjects.first as? AVMetadataMachineReadableCodeObject, let descriptor = mrc.descriptor { print(descriptor) } } }

Page 167: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Detect a CIBarcodeDescriptor using Vision.framework

func descriptorFromImage(_ image: CIImage) -> CIBarcodeDescriptor? { // Create the request and request handler let requestHandler = VNImageRequestHandler(ciImage: image, options: [:]) let request = VNDetectBarcodesRequest(); // Send the request to the handler try? requestHandler.perform([request])

// Get the observation let firstResult = request.results?.first return firstResult?.barcodeDescriptor }

Page 168: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Detect a CIBarcodeDescriptor using Vision.framework

func descriptorFromImage(_ image: CIImage) -> CIBarcodeDescriptor? { // Create the request and request handler let requestHandler = VNImageRequestHandler(ciImage: image, options: [:]) let request = VNDetectBarcodesRequest(); // Send the request to the handler try? requestHandler.perform([request])

// Get the observation let firstResult = request.results?.first return firstResult?.barcodeDescriptor }

Page 169: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Detect a CIBarcodeDescriptor using Vision.framework

func descriptorFromImage(_ image: CIImage) -> CIBarcodeDescriptor? { // Create the request and request handler let requestHandler = VNImageRequestHandler(ciImage: image, options: [:]) let request = VNDetectBarcodesRequest(); // Send the request to the handler try? requestHandler.perform([request])

// Get the observation let firstResult = request.results?.first return firstResult?.barcodeDescriptor }

Page 170: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Detect a CIBarcodeDescriptor using Vision.framework

func descriptorFromImage(_ image: CIImage) -> CIBarcodeDescriptor? { // Create the request and request handler let requestHandler = VNImageRequestHandler(ciImage: image, options: [:]) let request = VNDetectBarcodesRequest(); // Send the request to the handler try? requestHandler.perform([request])

// Get the observation let firstResult = request.results?.first return firstResult?.barcodeDescriptor }

Page 171: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Create an image for a CIBarcodeDescriptor using CoreImage.framework

func imageFromBarcodeCodeDescriptor(_ descriptor: CIBarcodeDescriptor) -> CIImage? { return CIFilter(name: "CIBarcodeGenerator", withInputParameters: ["inputBarcodeDescriptor" : descriptor]) ?.outputImage }

Page 172: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Create an image for a CIBarcodeDescriptor using CoreImage.framework

func imageFromBarcodeCodeDescriptor(_ descriptor: CIBarcodeDescriptor) -> CIImage? { return CIFilter(name: "CIBarcodeGenerator", withInputParameters: ["inputBarcodeDescriptor" : descriptor]) ?.outputImage }

Page 173: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Create an image for a CIBarcodeDescriptor using CoreImage.framework

func imageFromBarcodeCodeDescriptor(_ descriptor: CIBarcodeDescriptor) -> CIImage? { return CIFilter(name: "CIBarcodeGenerator", withInputParameters: ["inputBarcodeDescriptor" : descriptor]) ?.outputImage }

Page 174: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Create an image for a CIBarcodeDescriptor using CoreImage.framework

func imageFromBarcodeCodeDescriptor(_ descriptor: CIBarcodeDescriptor) -> CIImage? { return CIFilter(name: "CIBarcodeGenerator", withInputParameters: ["inputBarcodeDescriptor" : descriptor]) ?.outputImage }

Page 175: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•Demo •Detection and Re-Generation of a QRCode

Page 176: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel
Page 177: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

•Using Core Image with Vision

Page 178: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Using Core Image with Vision

Page 179: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Using Core Image with Vision

Core Image can prepare images before being passed to Vision • For example: Cropping, Orienting, Converting to grayscale

Page 180: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Using Core Image with Vision

Core Image can prepare images before being passed to Vision • For example: Cropping, Orienting, Converting to grayscale

Vision can gather information before processing with Core Image • For example: Feature detection can guide which CIFilters to apply

Page 181: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

AVFoundation: Get the frames out of a short video

Page 182: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

AVFoundation: Get the frames out of a short video

Page 183: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Vision: Determine homography matrices to align frames

Page 184: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Vision: Determine homography matrices to align frames

Page 185: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Core Image: Align each video frame

Page 186: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Core Image: Make a photo from the median of the aligned frames

Page 187: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Core Image: Make a photo from the median of the aligned frames

Page 188: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Core Image: Make a photo from the median of the aligned frames

Page 189: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Photo from Video with Removal of Unwanted Objects

Core Image: Make a photo from the median of the aligned frames

Page 190: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Use Vision to find homographic registration and pass it to CI

func homographicTransform(from image: CIImage, to reference: CIImage) -> matrix_float3x3? {

// Create the request and request handler let request = VNHomographicImageRegistrationRequest(targetedCIImage: image);

let requestHandler = VNImageRequestHandler(ciImage: reference, options: [:]);

// Send the request to the handler

try? requestHandler.perform([request]);

// Get the observation guard let results = request.results,

let observation = results.first as? VNImageHomographicAlignmentObservation else {

return nil

} return observation.warpTransform }

Page 191: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Use Vision to find homographic registration and pass it to CI

func homographicTransform(from image: CIImage, to reference: CIImage) -> matrix_float3x3? {

// Create the request and request handler let request = VNHomographicImageRegistrationRequest(targetedCIImage: image);

let requestHandler = VNImageRequestHandler(ciImage: reference, options: [:]);

// Send the request to the handler

try? requestHandler.perform([request]);

// Get the observation guard let results = request.results,

let observation = results.first as? VNImageHomographicAlignmentObservation else {

return nil

} return observation.warpTransform }

Page 192: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Use Vision to find homographic registration and pass it to CI

func homographicTransform(from image: CIImage, to reference: CIImage) -> matrix_float3x3? {

// Create the request and request handler let request = VNHomographicImageRegistrationRequest(targetedCIImage: image);

let requestHandler = VNImageRequestHandler(ciImage: reference, options: [:]);

// Send the request to the handler

try? requestHandler.perform([request]);

// Get the observation guard let results = request.results,

let observation = results.first as? VNImageHomographicAlignmentObservation else {

return nil

} return observation.warpTransform }

Page 193: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Use Vision to find homographic registration and pass it to CI

func homographicTransform(from image: CIImage, to reference: CIImage) -> matrix_float3x3? {

// Create the request and request handler let request = VNHomographicImageRegistrationRequest(targetedCIImage: image);

let requestHandler = VNImageRequestHandler(ciImage: reference, options: [:]);

// Send the request to the handler

try? requestHandler.perform([request]);

// Get the observation guard let results = request.results,

let observation = results.first as? VNImageHomographicAlignmentObservation else {

return nil

} return observation.warpTransform }

Page 194: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Use Vision to find homographic registration and pass it to CI

func homographicTransform(from image: CIImage, to reference: CIImage) -> matrix_float3x3? {

// Create the request and request handler let request = VNHomographicImageRegistrationRequest(targetedCIImage: image);

let requestHandler = VNImageRequestHandler(ciImage: reference, options: [:]);

// Send the request to the handler

try? requestHandler.perform([request]);

// Get the observation guard let results = request.results,

let observation = results.first as? VNImageHomographicAlignmentObservation else {

return nil

} return observation.warpTransform }

Page 195: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to apply a homography matrix

float2 warpHomography(float3x3 h, destination dest)

{

float3 homogeneousDestCoord = float3(dest.coord(), 1.0);

float3 homogeneousSrcCoord = h * homogeneousDestCoord;

float2 srcCoord = homogeneousSrcCoord.xy / max(homogeneousSrcCoord.z, 0.000001);

return srcCoord;

}

Page 196: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to apply a homography matrix

float2 warpHomography(float3x3 h, destination dest)

{

float3 homogeneousDestCoord = float3(dest.coord(), 1.0);

float3 homogeneousSrcCoord = h * homogeneousDestCoord;

float2 srcCoord = homogeneousSrcCoord.xy / max(homogeneousSrcCoord.z, 0.000001);

return srcCoord;

}

Page 197: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to apply a homography matrix

float2 warpHomography(float3x3 h, destination dest)

{

float3 homogeneousDestCoord = float3(dest.coord(), 1.0);

float3 homogeneousSrcCoord = h * homogeneousDestCoord;

float2 srcCoord = homogeneousSrcCoord.xy / max(homogeneousSrcCoord.z, 0.000001);

return srcCoord;

}

Page 198: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to apply a homography matrix

float2 warpHomography(float3x3 h, destination dest)

{

float3 homogeneousDestCoord = float3(dest.coord(), 1.0);

float3 homogeneousSrcCoord = h * homogeneousDestCoord;

float2 srcCoord = homogeneousSrcCoord.xy / max(homogeneousSrcCoord.z, 0.000001);

return srcCoord;

}

Page 199: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to return the median of 5 images

inline void swap(thread float4 &a, thread float4 &b) { float4 tmp = a; a = min(a,b); b = max(tmp, b); // swap sort of two elements }

float4 medianReduction5(sample_t v0, sample_t v1, sample_t v2, sample_t v3, sample_t v4) {

// using a Bose-Nelson sorting network swap(v0, v1); swap(v3, v4); swap(v2, v4); swap(v2, v3); swap(v0, v3);

swap(v0, v2); swap(v1, v4); swap(v1, v3); swap(v1, v2);

return v2;

}

Page 200: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to return the median of 5 images

inline void swap(thread float4 &a, thread float4 &b) { float4 tmp = a; a = min(a,b); b = max(tmp, b); // swap sort of two elements }

float4 medianReduction5(sample_t v0, sample_t v1, sample_t v2, sample_t v3, sample_t v4) {

// using a Bose-Nelson sorting network swap(v0, v1); swap(v3, v4); swap(v2, v4); swap(v2, v3); swap(v0, v3);

swap(v0, v2); swap(v1, v4); swap(v1, v3); swap(v1, v2);

return v2;

}

Page 201: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

// Core Image Metal kernel to return the median of 5 images

inline void swap(thread float4 &a, thread float4 &b) { float4 tmp = a; a = min(a,b); b = max(tmp, b); // swap sort of two elements }

float4 medianReduction5(sample_t v0, sample_t v1, sample_t v2, sample_t v3, sample_t v4) {

// using a Bose-Nelson sorting network swap(v0, v1); swap(v3, v4); swap(v2, v4); swap(v2, v3); swap(v0, v3);

swap(v0, v2); swap(v1, v4); swap(v1, v3); swap(v1, v2);

return v2;

}

Page 202: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Sky Gao, Image Engineer

•Demo •Photo from Video with Removal of Unwanted Objects

Page 203: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Summary

Performance Information Functionality

Write CIKernels in Metal CIRenderDestination API

CIRenderInfo API Xcode Quick Looks

New Filters Barcode Support

Depth Support

Page 204: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

More Informationhttps://developer.apple.com/wwdc17/510

Page 205: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Related Sessions

Image Editing with Depth WWDC 2017

What's New in Photos APIs WWDC 2017

Vision Framework: Building on Core ML WWDC 2017

Capturing Depth in iPhone Photography WWDC 2017

Page 206: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel

Labs

Photos Editing and Core Image Lab Technology Lab F Thu 3:10PM–6:00PM

Photos Depth and Capture Lab Technology Lab A Thu 3:10PM–6:00PM

Photos Depth and Capture Lab Technology Lab F Fri 1:50PM–4:00PM

Page 207: Filters, Metal, Vision, and More€¦ · A Very Brief Introduction to Core Image Multiple CIKernels are concatenated to improve performance kernel vec4 sepia kernel vec4 hue kernel