• Stars
    star
    109
  • Rank 319,077 (Top 7 %)
  • Language
    Swift
  • Created about 9 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Demonstration of a Sketching App Using 3D Touch

ForceSketch

####Demonstration of a Sketching App Using 3D Touch

screenshot

#####Companion project to this blog post: http://flexmonkey.blogspot.co.uk/2015/10/forcesketch-3d-touch-drawing-app-using.html

Following on from my recent posts on 3D Touch and touch coalescing, combining the two things together in a simple drawing application seemed like an obvious next step. This also gives me the chance to tinker with CIImageAccumulator which was newly introduced in iOS 9.

My little demo app, ForceSketch, allows the user to draw on their iPhone 6 screen. Both the line weight and the line colour are linked to the touch pressure. Much like my ChromaTouch demo, the pressure controls the hue, so the very lightest touch is red, turning to green at a third of maximum pressure, to blue at two thirds and back to red at maximum pressure.

Once the user lifts their finger, two Core Image filters, CIColorControls and CIGaussianBlur kick in and fade the drawing out.

##Drawing Mechanics of ForceSketch

The drawing code is all called from my view controller's touchesMoved method. It's in here that I create a UIImage instance based on the coalesced touches and composite that image overthe existing image accumulator. In a production application, I'd probably do the image filtering in a background thread to improve the performance of the user interface but, for this demo, I think this approach is OK.

The opening guard statement ensures I have non-optional constants for the most important items:

    guard let touch = touches.first,
        event = event,
        coalescedTouches = event.coalescedTouchesForTouch(touch) else
    {
        return
    }

The next step is to prepare for creating the image object. To do this, I need to begin an image context and create a reference to the current context:

    UIGraphicsBeginImageContext(view.frame.size)

    let cgContext = UIGraphicsGetCurrentContext()

To ensure I get maximum fidelity of the user's gesture, I loop over the coalesced touches - this gives me all the intermediate touches that may have happened between invocations of touchesMoved().

    for coalescedTouch in coalescedTouches {

Using the force property of each touch, I create constants for the line segments colour and weight. To ensure users of non-3D Touch devices call still use the app, I check forceTouchCapability and give those users a fixed weight and colour:

    let lineWidth = (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) ?
        (coalescedTouch.force / coalescedTouch.maximumPossibleForce) * 20 :
        10
    
    let lineColor = (traitCollection.forceTouchCapability == UIForceTouchCapability.Available) ?
        UIColor(hue: coalescedTouch.force / coalescedTouch.maximumPossibleForce, saturation: 1, brightness: 1, alpha: 1).CGColor :
        UIColor.grayColor().CGColor

With these constants I can set the line width and stroke colour in the graphics context:

    CGContextSetLineWidth(cgContext, lineWidth)
    CGContextSetStrokeColorWithColor(cgContext, lineColor)

...and I'm now ready to define the beginning and end of my line segment for this coalesced touch:

    CGContextMoveToPoint(cgContext,
        previousTouchLocation!.x,
        previousTouchLocation!.y)

    CGContextAddLineToPoint(cgContext,
        coalescedTouch.locationInView(view).x,
        coalescedTouch.locationInView(view).y)

The final steps inside the coalesced touches loop is to stroke the path and update previousTouchLocation:

    CGContextStrokePath(cgContext)

    previousTouchLocation = coalescedTouch.locationInView(view)

Once all of the strokes have been added to the graphics context, it's one line of code to create a UIImage instance and then end the context:

    let drawnImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

##Displaying the Drawn Lines

To display the newly drawn lines held in drawnImage, I use a CISourceOverCompositing filter with drawnImage as the foreground image and the image accumulator's current image as the background:

    compositeFilter.setValue(CIImage(image: drawnImage),
        forKey: kCIInputImageKey)
        
    compositeFilter.setValue(imageAccumulator.image(),
        forKey: kCIInputBackgroundImageKey)

Then take the output of the source over compositor, pass that back into the accumulator and populate my UIImageView with the accumulator's image:

    imageAccumulator.setImage(compositeFilter.valueForKey(kCIOutputImageKey) as! CIImage)

    imageView.image = UIImage(CIImage: imageAccumulator.image())

##Blurry Fade Out

Once the user lifts their finger, I do a "blurry fade out" of the drawn image. This effect uses two Core Image filters which are defined as constants:

    let hsb = CIFilter(name: "CIColorControls",
        withInputParameters: [kCIInputBrightnessKey: 0.05])!
    let gaussianBlur = CIFilter(name: "CIGaussianBlur",
        withInputParameters: [kCIInputRadiusKey: 1])!

The first part of the effect is to use a CADisplayLink which will invoke step() with each screen refresh:

    let displayLink = CADisplayLink(target: self, selector: Selector("step"))
    displayLink.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)

I rely on previousTouchLocation being nil to infer the user has finished their touch. If that's the case, I simply pass the accumulator's current image into the HSB / colour control filter, pass that filter's output into the Gaussian Blur and finally the blur's output back into the accumulator:

    hsb.setValue(imageAccumulator.image(), forKey: kCIInputImageKey)
    gaussianBlur.setValue(hsb.valueForKey(kCIOutputImageKey) as! CIImage, forKey: kCIInputImageKey)
    
    imageAccumulator.setImage(gaussianBlur.valueForKey(kCIOutputImageKey) as! CIImage)

    imageView.image = UIImage(CIImage: imageAccumulator.image())

##Source Code

As always, the source code for this project is available in my GitHub repository here. Enjoy!

More Repositories

1

Filterpedia

Core Image Filter Explorer & Showcase
Swift
2,241
star
2

Blurable

Apply a Gaussian Blur to any UIView with Swift Protocol Extensions
Swift
932
star
3

Plum-O-Meter

3D Touch Application for Weighing Plums (and other small fruit!)
Swift
528
star
4

ParticleLab

Particle system that's both calculated and rendered on the GPU using the Metal framework
Swift
493
star
5

sweetcorn

Node based CIKernel creation
Swift
261
star
6

SmoothScribble

Smooth Drawing for iOS in Swift with Hermite Spline Interpolation
Swift
241
star
7

MarkingMenu

Swift MarkingMenu
Swift
217
star
8

CartoonEyes

Composite Cartoon Eyes over Face from Front Camera with CoreImage
Swift
163
star
9

LiveCameraFiltering

Demonstration of applying a Comic Book filter to a live video feed
Swift
151
star
10

SwiftSpace

CoreMotion Controlled Drawing in 3D Space
Swift
150
star
11

ShinpuruLayout

Simple Layout in Swift using HGroups & VGroups
Swift
128
star
12

ParticleCam

Metal based particle system influenced by iPad camera
Swift
102
star
13

ShinpuruImage

Syntactic Sugar for Accelerate/vImage and Core Image Filters
Swift
100
star
14

ShinpuruNodeUI

Node Based UI Component Written in Swift
Swift
98
star
15

ValentinesSwift

You love Swift & Swift loves you!
Swift
89
star
16

CoreImageForSwiftPlaygrounds

CoreImage For Swift Playgrounds
Swift
88
star
17

SnapSwift

SnapSeed Style Popup Menu for iOS
Swift
87
star
18

CoreImageHelpers

Syntactic sugar for displaying CIImage using OpenGL and grabbing CIImages from iOS cameras
Swift
73
star
19

VideoEffects

iPad app to open videos from file system, apply Core Image filters and save result back SavedPhotosAlbum
Swift
71
star
20

AudioKitNodality

AudioKitNodality
Swift
69
star
21

MetalReactionDiffusion

Reaction Diffusion using Swift & Metal
Swift
69
star
22

3D-Motion-Controller

Using MultipeerConnectivity and CoreMotion to allow an iPhone to act as a 3D mouse for an iPad app
Swift
67
star
23

Globular

Colourful SpriteKit Metaballs Controlled by 3D Touch
Swift
67
star
24

Interpolation-Playground-

Swift playground demonstrating lerp, smooth step, Catcall-Rom and others!
Swift
63
star
25

Nebula

Core Image Volumetric Rendering
Swift
60
star
26

MetalKit-Particles

An implementation of my Metal ParticleLab component for OS X 10.11 and iOS 9
Swift
57
star
27

AdvancedTouch

Swift Advanced Touch Handling in iOS9: Coalescing and Prediction
Swift
50
star
28

MetalVideoCapture

Demo of Creating a Metal Texture from AVCaptureSession and Applying MetalPerformanceShaders In-Place
Swift
50
star
29

AudioSynthesis

CoreAudio for Sound Synthesis Demonstration
Swift
48
star
30

UIScrollViewDemo

A Node Based User Interface implemented with the Presentation Model Pattern
Swift
41
star
31

SwiftCFD

CPU Based Navier Stokes Computational Fluid Dynamics in Swift for iOS
Swift
41
star
32

StrangeAttractor

Lorenz Attractor in Swift & Metal
Swift
39
star
33

Spritely

Using SpriteKit events to trigger AudioKit sounds
Swift
39
star
34

SwiftGoo

Kai's Power Tools Goo - written in Swift!
Swift
38
star
35

Scribe

Handwriting and Stroke Recognition in Swift
Swift
37
star
36

DeepPressGestureRecognizer

UIGestureRecognizer for recognising deep press 3D Touch on iPhone 6s
Swift
35
star
37

MercurialPaint

Mercurial Painting using Metal and Core Image
Swift
33
star
38

PencilController

Using Apple Pencil as a 3D Controller for Image Editing
Swift
30
star
39

CoreImagePerspectivePlayground

Core Image Perspective Playground
Swift
28
star
40

GameplayKitAgents

A Look at Agents, Goals & Behaviours in GameplayKit
Swift
27
star
41

CoreImageFluidDynamics

CIFilter / CIKernel based fluid dynamics
Swift
26
star
42

SceneKitMaterialEditor

A very simple app for editing SceneKit materials
Swift
26
star
43

DepthOfFieldExplorer

SceneKit Depth of Field Demonstration
Swift
26
star
44

ChromaTouch

Introduction to 3D Touch in Swift with Peek, Pop and Preview Actions
Swift
26
star
45

3D-ReTouch

Experimental Retouching App using 3D Touch
Swift
26
star
46

FurrySketch

Using Apple Pencil's Azimuth & Altitude Data for Creating Directional Furry Brush Strokes
Swift
26
star
47

Purikura

Bulging eyes Purikura effect
Swift
25
star
48

SkyCubeTextureDemo

A demonstration of using MDLSkyCubeTexture in a SceneKit project
Swift
25
star
49

CoreImageConvolutionExplorer

CoreImageConvolutionExplorer
Swift
24
star
50

CIImage-UIImage-Orientation-Fix

Demo of UIImageOrientation to TIFF Orientation conversion that fixes orientation issues when creating CIImage from UIImage
Swift
24
star
51

ImageToneCurveEditor

Project demonstrating the use of CIToneCurve
Swift
24
star
52

PencilSynth

An Audiokit Synthesiser Controller by Apple Pencil
Swift
23
star
53

CoreImageTransitionExplorer

Simple slide show demonstration using Core Image Transitions and PHImageManager
Swift
22
star
54

SceneKitProceduralNormalMapping

Demo of Core Image filter to create SceneKit normal maps from procedural bump maps
Swift
22
star
55

ForceZoom

Zoom Into Image Details using 3D Touch Peek
Swift
21
star
56

PendulaTone

Audio driven by pendulum waves
Swift
20
star
57

Rotatable

Swift Protocol Extension to Rotate any UIView
Swift
19
star
58

PhotoBrowserDemo

A Swift image browser/picker for use with PHImageManager
Swift
19
star
59

Protocol-Extension-Event-Dispatcher

Implementation of EventDispatcher pattern using Swift Protocol Extensions
Swift
18
star
60

ImageProcessingWithMetal

An introduction to image processing with Metal and Swift
17
star
61

WheelTone

Audio synthesis driven by a network of friction gears
Swift
15
star
62

FilterChainingDemo

Demonstration of chaining a series of CIFilters together
Swift
15
star
63

ConvolutionExplorer

vImage / Accelerate convolution filter in Swift
Swift
14
star
64

Bokeh

Demonstration of simulation of hexagonal bokeh using Metal Performance Shaders
Swift
14
star
65

SpriteKitMotionBlur

SpriteKitMotionBlur
Swift
14
star
66

FMNixieDisplay

Nixie Tube Display Component on Swift
Swift
14
star
67

MercurialText

Embossed Type using SceneKit and CIShadedMaterial
Swift
14
star
68

GPUImageDemo

GPUImageDemo
Swift
12
star
69

Christmas-Tree-Bowling

Apple Pencil Controlled Christmas Tree Bowling!
Swift
12
star
70

GestureRecognizer

Demo of custom UIGestureRecognizer
Swift
11
star
71

NumericDialDemo

NumericDialDemo
Swift
11
star
72

ProgSConCompanion

ProgSConCompanion
Swift
10
star
73

CoreImageReactionDiffusion

Gary-Scott reaction Diffusion Implemented as a Core Image CIKernel
Swift
10
star
74

MetalKit-ReactionDiffusion

Reaction diffusion simulation using Metal Kit with parameter gradients controlled by the camera
Swift
10
star
75

PencilScale

Using an Apple Pencil with an iPad Pro as an electronic scale
Swift
9
star
76

GrayScott

Non GPU GrayScott Reaction Diffusion Experiment Using NSOperation
Swift
9
star
77

FMHierarchicalSelector

Hierarchical Selector Component based on UIPickerView & UICollectionView
Swift
9
star
78

NemoCam

Virtual underwater video recording using Filterpedia's Caustic Refraction Filter
Swift
9
star
79

InnerPlanetCurves

Draws Cubic Bezier Curve Between Earth & Venus Using Mercury & Mars as Control Points
Swift
8
star
80

BristlePaint

Embossed Painting with Individual Bristles using SpriteKit Normal Mapping
Swift
8
star
81

StackView

A first play with Swift 2's UIStackView
Swift
8
star
82

MPS_Equalisation

Demonstration of Histogram Equalisation with Metal Performance Shaders
Swift
7
star
83

CoreImageReductionFilterExplorer

App demonstrating extracting color data from CIAreaAverage and displaying Core Image Histograms
Swift
7
star
84

Vertigo

Vertigo inducing colourful painting...
Swift
6
star
85

CoreImageCathodeRayTube

Simple cathode ray tube simulation CIKernel processing live feed from iOS camera.
Swift
5
star
86

Swift3_CoreImageDemo

Swift3_CoreImageDemo
Swift
4
star
87

LondonSwiftDemo

Demo Project for London Swift
Swift
4
star
88

Swarm-Chemistry-GCD

New Version of Swarm Chemistry, using GCD and Bitmap creation
Swift
4
star
89

PHImageManagerTwitterDemo

Demonstration of PHImageManager and Twitter Integration
Swift
3
star
90

CoreImageVoronoi

Full screen animated Moroni noise!
Swift
3
star
91

PhysicsExperiments

Swift
3
star
92

InlineMethodTest

Testing performance of inline code versus instance methods versus class methods
Swift
3
star
93

StPatricksDay

Happy St Patricks Day!
Swift
3
star
94

HisogramSpecificationBlendDemo

Demonstration of Histogram Specification for Image Composition
Swift
2
star
95

SelectorPlayground

Demonstration of `#selector` expression
Swift
2
star
96

FlexMonkeyExamples

Files to support posts in http://flexmonkey.blogspot.co.uk/
Swift
2
star
97

SwiftExperiments

Swift experiments
Swift
1
star
98

Swarm-Chemistry

DEPRECATED: Multithreaded CPU based Swarm Chemistry
Swift
1
star
99

ArraySpeedTest

Some simple tests looking at the performance of different techniques populating and interrogating arrays
Swift
1
star
100

GaussianPlayground

Demonstration of creating a Gaussian blur using separate vertical and horizontal convolution filters.
Swift
1
star