Skip to content

Commit b14427d

Browse files
committed
Merge pull request #21 from koher/dev-0.4.0
Develop 0.4.0
2 parents 6984b8d + 78e28de commit b14427d

62 files changed

Lines changed: 18308 additions & 2913 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
matrix:
2+
include:
3+
- os: osx
4+
language: objective-c
5+
osx_image: xcode9.2
6+
script:
7+
- set -o pipefail
8+
- xcodebuild test -scheme EasyImagy-macOS -configuration Debug | xcpretty -c
9+
- xcodebuild test -scheme EasyImagy-iOS -configuration Debug -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone X" | xcpretty -c
10+
- xcodebuild test -scheme EasyImagy-tvOS -configuration Debug -sdk appletvsimulator -destination "platform=tvOS Simulator,name=Apple TV 4K" | xcpretty -c
11+
- xcodebuild build -scheme EasyImagy-watchOS -configuration Debug -sdk watchsimulator -destination "platform=watchOS Simulator,name=Apple Watch Series 3 - 38mm" | xcpretty -c
12+
- os: osx
13+
language: generic
14+
osx_image: xcode9.2
15+
script:
16+
- swift --version
17+
- swift build
18+
- swift test
19+
- os: linux
20+
language: generic
21+
sudo: required
22+
env: SWIFT_VERSION=4.0
23+
install:
24+
- eval "$(curl -sL https://swiftenv.fuller.li/install.sh)"
25+
script:
26+
- swift --version
27+
- swift build
28+
- swift test

EasyImagy.xcodeproj/project.pbxproj

Lines changed: 256 additions & 56 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 82 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
EasyImagy
2-
===========================
1+
# EasyImagy
32

4-
_EasyImagy_ makes it easy to handle images in Swift.
3+
[![Build Status](https://travis-ci.org/koher/EasyImagy.svg?branch=master)](https://travis-ci.org/koher/EasyImagy)
4+
5+
_EasyImagy_ makes it easy to process images in Swift.
56

67
```swift
7-
var image = Image<RGBA>(named: "ImageName")!
8+
var image = Image<RGBA<UInt8>>(named: "ImageName")!
89

910
print(image[x, y])
1011
image[x, y] = RGBA(red: 255, green: 0, blue: 0, alpha: 127)
@@ -15,40 +16,50 @@ for pixel in image {
1516
// ...
1617
}
1718

18-
// Converts the image (e.g. binarizations)
19-
let binarized: Image<RGBA> = image.map { $0.gray < 128 ? .black : .white }
19+
// Processes images (e.g. binarizations)
20+
let binarized: Image<Bool> = image.map { $0.gray >= 127 }
2021

2122
// From/to `UIImage`
22-
image = Image<RGBA>(uiImage: imageView.image!)!
23+
image = Image<RGBA<UInt8>>(uiImage: imageView.image!)
2324
imageView.image = image.uiImage
2425
```
2526

26-
Introduction
27-
---------------------------
27+
## Introduction
2828

29-
Handling images by _CoreGraphics_ is too complicated: various formats, old C APIs and painful memory management. _EasyImagy_ provides the easier way to handle images in exchange for some performance.
29+
Processing images by _CoreGraphics_ is complicated: various formats, old C APIs and painful memory management. _EasyImagy_ provides easier APIs to process images.
3030

31-
Typically `Image`s in _EasyImagy_ are used with `RGBA`. `RGBA` is a simple structure declared as follows.
31+
Typically the `Image` type is used with the `RGBA` type. The `RGBA` is a simple structure declared as follows.
3232

3333
```swift
34-
struct RGBA {
35-
var red: UInt8
36-
var green: UInt8
37-
var blue: UInt8
38-
var alpha: UInt8
34+
struct RGBA<Channel> {
35+
var red: Channel
36+
var green: Channel
37+
var blue: Channel
38+
var alpha: Channel
3939
}
4040
```
4141

42-
You can access to a pixel easily using subscripts like `image[x, y]` and its channels by properties `red`, `green`, `blue` and `alpha`.
42+
You can easily access to pixels using subscripts like `image[x, y]` and also their channels using properties `red`, `green`, `blue` and `alpha`.
4343

44-
`Image` and `RGBA` also provide some convenient methods and properties to make it easy to process images. For example, it is possible to convert an image to grayscale combining `Image#map` with `RGBA#gray` in one line as shown below.
44+
In addition, `Image` and `RGBA` provide some powerful APIs to process images. For example, it is possible to convert an image to grayscale combining `Image.map` with `RGBA.gray` in one line as shown below.
4545

4646
```swift
47-
let result = image.map { $0.gray }
47+
let grayscale: Image<UInt8> = image.map { $0.gray }
48+
```
49+
50+
Another notable feature of _EasyImagy_ is that the `Image` is a `struct`, i.e. a value type, with copy-on-write. It means
51+
52+
- `Image` instances never be shared
53+
- defensive copying is unnecessary
54+
- no wastful copying of `Image` instances
55+
- copying is executed lazily when it is required
56+
57+
```swift
58+
var another = image // Not copied here because of copy-on-write
59+
another[x, y] = RGBA(0xff0000ff) // Copied here lazily
4860
```
4961

50-
Usage
51-
---------------------------
62+
## Usage
5263

5364
### Import
5465

@@ -59,27 +70,35 @@ import EasyImagy
5970
### Initialization
6071

6172
```swift
62-
let image = Image<RGBA>(named: "ImageName")!
73+
let image = Image<RGBA<UInt8>>(named: "ImageName")!
74+
```
75+
76+
```swift
77+
let image = Image<RGBA<UInt8>>(contentsOfFile: "path/to/file")!
6378
```
6479

6580
```swift
66-
let image = Image<RGBA>(contentsOfFile: "path/to/file")!
81+
let image = Image<RGBA<UInt8>>(data: Data(/* ... */))!
6782
```
6883

6984
```swift
70-
let image = Image<RGBA>(data: NSData(/* ... */))!
85+
let image = Image<RGBA<UInt8>>(uiImage: imageView.image!) // from a UIImage
7186
```
7287

7388
```swift
74-
let image = Image<RGBA>(uiImage: imageView.image!)!
89+
let image = Image<RGBA<UInt8>>(width: 640, height: 480, pixels: pixels) // from pixels
7590
```
7691

7792
```swift
78-
let image = Image<RGBA>(width: 640, height: 480, pixel: .black) // a black image
93+
let image = Image<RGBA<UInt8>>(width: 640, height: 480, pixel: .black) // a black RGBA image
7994
```
8095

8196
```swift
82-
let image = Image<RGBA>(width: 640, height: 480, pixels: pixels)
97+
let image = Image<UInt8>(width: 640, height: 480, pixel: .min) // a black grayscale image
98+
```
99+
100+
```swift
101+
let image = Image<Bool>(width: 640, height: 480, pixel: false) // a black binary image
83102
```
84103

85104
### Access to a pixel
@@ -97,12 +116,12 @@ image[x, y].alpha = 127
97116

98117
```swift
99118
// Safe get for a pixel
100-
if let pixel = image.pixel(x, y) {
119+
if let pixel = image.pixelAt(x: x, y: y) {
101120
print(pixel.red)
102121
print(pixel.green)
103122
print(pixel.blue)
104123
print(pixel.alpha)
105-
124+
106125
print(pixel.gray) // (red + green + blue) / 3
107126
print(pixel) // formatted like "#FF0000FF"
108127
} else {
@@ -122,45 +141,46 @@ for pixel in image {
122141
### Rotation
123142

124143
```swift
125-
let result = image.rotate() // Rotate clockwise
144+
let result = image.rotated(by: .pi) // Rotated clockwise by π
126145
```
127146

128147
```swift
129-
let result = image.rotate(-1) // Rotate counterclockwise
148+
let result = image.rotated(byDegrees: 180) // Rotated clockwise by 180 degrees
130149
```
131150

132151
```swift
133-
let result = image.rotate(2) // Rotate by 180 degrees
152+
// Rotated clockwise by π / 4 and fill the background with red
153+
let result = image.rotated(by: .pi / 4, extrapolatedBy: .filling(.red))
134154
```
135155

136156
### Flip
137157

138158
```swift
139-
let result = image.flipX() // Flip Horizontally
159+
let result = image.xReversed() // Flip Horizontally
140160
```
141161

142162
```swift
143-
let result = image.flipY() // Flip Vertically
163+
let result = image.yReversed() // Flip Vertically
144164
```
145165

146166
### Resizing
147167

148168
```swift
149-
let result = image.resize(width: 100, height: 100)
169+
let result = image.resizedTo(width: 320, height: 240)
150170
```
151171

152172
```swift
153-
let result = image.resize(width: 100, height: 100,
154-
interpolationQuality: kCGInterpolationNone) // Nearest neighbor
173+
let result = image.resizedTo(width: 320, height: 240,
174+
interpolatedBy: .nearestNeighbor) // Nearest neighbor
155175
```
156176

157177
### Crop
158178

159-
Slicing is done with no copy cost.
179+
Slicing is executed with no copying costs.
160180

161181
```swift
162-
let slice: ImageSlice<RGBA> = image[32..<64, 32..<64] // no copy cost
163-
let cropped = Image<RGBA>(slice) // copy is done here
182+
let slice: ImageSlice<RGBA<UInt8>> = image[32..<64, 32..<64] // No copying costs
183+
let cropped = Image<RGBA<UInt8>>(slice) // Copying is executed here
164184
```
165185

166186
### Conversion
@@ -170,7 +190,7 @@ let cropped = Image<RGBA>(slice) // copy is done here
170190
#### Grayscale
171191

172192
```swift
173-
let result: Image<UInt8> = image.map { (pixel: RGBA) -> UInt8 in
193+
let result: Image<UInt8> = image.map { (pixel: RGBA<UInt8>) -> UInt8 in
174194
pixel.gray
175195
}
176196
```
@@ -183,21 +203,21 @@ let result = image.map { $0.gray }
183203
#### Binarization
184204

185205
```swift
186-
let result = image.map { (pixel: RGBA) -> RGBA in
187-
pixel.gray < 128 ? RGBA.black : RGBA.white
206+
let result: Image<Bool> = image.map { (pixel: RGBA<UInt8>) -> Bool in
207+
pixel.gray >= 128
188208
}
189209
```
190210

191211
```swift
192212
// Shortened form
193-
let result = image.map { $0.gray < 128 ? .black : .white }
213+
let result = image.map { $0.gray >= 128 }
194214
```
195215

196216
#### Binarization (auto threshold)
197217

198218
```swift
199219
let threshold = UInt8(image.reduce(0) { $0 + $1.grayInt } / image.count)
200-
let result = image.map { $0.gray < threshold ? .black : .white }
220+
let result = image.map { $0.gray >= threshold }
201221
```
202222

203223
#### Mean filter
@@ -220,28 +240,32 @@ let kernel = Image<Int>(width: 5, height: 5, pixels: [
220240
let result = image.convoluted(kernel)
221241
```
222242

223-
### With UIImage
224-
225-
#### From UIImage
243+
### With `UIImage`
226244

227245
```swift
228-
let image = Image<RGBA>(uiImage: imageView.image!)!
246+
// From `UIImage`
247+
let image = Image<RGBA<UInt8>>(uiImage: imageView.image!)
248+
249+
// To `UIImage`
250+
imageView.image = image.uiImage
229251
```
230252

231-
#### To UIImage
253+
### With `NSImage`
232254

233255
```swift
234-
imageView.image = image.uiImage
256+
// From `NSImage`
257+
let image = Image<RGBA<UInt8>>(nsImage: imageView.image!)
258+
259+
// To `NSImage`
260+
imageView.image = image.nsImage
235261
```
236262

237-
Requirements
238-
---------------------------
263+
## Requirements
239264

240265
- Swift 4 or later
241266
- Xcode 9 or later
242267

243-
Installation
244-
---------------------------
268+
## Installation
245269

246270
### Swift Package Manager
247271

@@ -256,7 +280,7 @@ import PackageDescription
256280
let package = Package(
257281
...
258282
dependencies: [
259-
.package(url: "https://github.com/koher/EasyImagy.git", from: "0.3.0-alpha.6"),
283+
.package(url: "https://github.com/koher/EasyImagy.git", from: "0.4.0"),
260284
],
261285
targets: [
262286
.target(
@@ -273,7 +297,7 @@ let package = Package(
273297
**Cartfile**
274298

275299
```
276-
github "koher/EasyImagy" "0.3.0-alpha.6"
300+
github "koher/EasyImagy" "0.4.0"
277301
```
278302

279303
### Manually
@@ -282,7 +306,6 @@ github "koher/EasyImagy" "0.3.0-alpha.6"
282306
2. Click your project icon and select the application target and the "General" tab.
283307
3. Add `EasyImagy.framework` to "Embedded Binaries".
284308

285-
License
286-
---------------------------
309+
## License
287310

288311
[The MIT License](LICENSE)

0 commit comments

Comments
 (0)