Select Page
Latest 1.0 https://github.com/paulz/PerspectiveTransform MIT ios 12.2 UIKit, CoreGraphics, QuartzCore Paul Zabelin

# Perspective Transform

PerspectiveTransform caclulates homogeneous transformation matrix for a view 3D projection in 2D. It can be used to place views within given image visual perspective using Core Animation `CATransform3D` and `CALayer.tranform`. Projection is caclulated between source and destination perspectives that are defined by 4 corners, assuming they form a Quadrilateral.

## CATransform3D

To place an overlay image on top of a container image with matching persperctive we can use Core Animation transform matrix. `CATransform3D` is a tranformation matrix that is used to rotate, scale, translate, skew, and project the layer content. It can also be used to describe a perspective projectection of 2D shape in 3D space.

Container Overlay Combination

Core Animation allow applying `CATransform3D` to `CALayer` via `transform` property:

``````let layer = UIView().layer
layer.transform = CATransform3D(m11: sX,  m12: r12, m13: r13, m14: 0,
m21: r21, m22: sY,  m23: r23, m24: 0,
m31: r31, m32: r32, m33: 0,   m34: 0,
m41: tX,  m42: tY,  m43: 0,   m44: 1)``````

In detail `CATransform3D` is a 4 x 4 matrix which takes 16 parameters to build.

Translation and scale are represented by their axis components: (tX, tY) and (sX, sY) within the matrix. While 3D rotation is represented by multiple values: r12, r21, r13, r31, r32, r23.

## Perspective Transform based on 4 corners

We can easily see 4 points with container image where the corners of the overlay image should be. In general it is a 4 point polygon. Using an SVG editor we can draw that polygon using container image as a background. Here is preview of the SVG file desribing placement of iPad screen corners

Click image to see original SVG file defining `polygon` with `points`. From those 4 points we can calculate nessesary `CATransform3D` matrix using this `PerspectiveTransform` library.

## Visual Example

We can see how 4 points polygon fits on the background image:

### SVG Points

We can even take coordinates of those 4 points from SVG file:

``<polygon points="377.282671 41.4352201 459.781253 251.836131 193.321418 330.023027 108.315837 80.1687782 "></polygon>``

Those are 4 pairs of X and Y coordinates:

``````377.282671 41.4352201
459.781253 251.836131
193.321418 330.023027
108.315837 80.1687782``````

### Swift Code Example

Here is complete example of placing overlay view using those coordinates:

``````import PerspectiveTransform

// note order: top left, top right, bottom left, bottom right
let destination = Perspective(
CGPoint(x: 108.315837, y: 80.1687782),
CGPoint(x: 377.282671, y: 41.4352201),
CGPoint(x: 193.321418, y: 330.023027),
CGPoint(x: 459.781253, y: 251.836131)
)

// Starting perspective is the current overlay frame
let start = Perspective(overlayView.frame)

// Caclulate CATransform3D from start to destination
overlayView.layer.transform = start.projectiveTransform(destination: destination)
``````

### `CALayer` transform

Since `CALayer` transform is animatable property we can easily define smooth transition:

## Example Project

See Example iOS project illustating animation and interactive tranform within view controllers. To build Example project run `pod install` within Example folder.

Example project also includes Swift Playground with couple of live examples.

## Installation

PerspectiveTransform is available through CocoaPods. To install

``pod 'PerspectiveTransform'``

## Author

Paul Zabelin, http://github.com/paulz

### Latest podspec

```{
"name": "PerspectiveTransform",
"cocoapods_version": "~> 1.5",
"version": "1.0",
"summary": "Perspective Transform calculates CATransform3D",
"description": "Calculates CATransform3D to transform rectangular frame to convex quadrilateralnAllows to overlay images in UIView given 4 points.",
"homepage": "https://github.com/paulz/PerspectiveTransform",
"screenshots": "https://github.com/paulz/PerspectiveTransform/wiki/images/container-with-green-polygon.png",
"type": "MIT"
},
"authors": {
"Paul Zabelin": "https://github.com/paulz"
},
"source": {
"git": "https://github.com/paulz/PerspectiveTransform.git",
"tag": "1.0"
},
"platforms": {
"ios": "12.2"
},
"swift_versions": "5.0",
"source_files": "Pod/Classes/**/*",
"frameworks": [
"UIKit",
"CoreGraphics",
"QuartzCore"
],
"testspecs": [
{
"name": "UnitSpecs",
"test_type": "unit",
"requires_app_host": false,
"source_files": [
"Example/Specs/**/*.{h,swift}",
"Example/Tests/*Helper.swift"
],
"dependencies": {
"Quick": "~> 2.0",
"Nimble": "~> 8.0"
}
},
{
"name": "AppSpecs",
"test_type": "unit",
"requires_app_host": true,
"resources": "Example/Tests/**/*.{png,jpg,svg}",
"source_files": [
"Example/Tests/**/*.{h,swift}",
"Example/PerspectiveTransform/resetAnchorPoint.swift"
],
"dependencies": {
"Quick": "~> 2.0",
"Nimble-Snapshots": "~> 7.0",
"iOSSnapshotTestCase": "~> 6.0"
}
}
]
}```