Skip to content

Commit 0a989fd

Browse files
committed
Code cleanup.
1 parent 0f962c9 commit 0a989fd

File tree

14 files changed

+297
-327
lines changed

14 files changed

+297
-327
lines changed

FanOfAscii.xcodeproj/project.pbxproj

Lines changed: 163 additions & 171 deletions
Large diffs are not rendered by default.

FanOfAscii/Chapters/01-FanOfAscii.playgroundchapter/Manifest.plist

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
<string>02-HowImagesComposed.playgroundpage</string>
1111
<string>03-GrayscaleHistogramEqualization.playgroundpage</string>
1212
<string>04-Asciification.playgroundpage</string>
13-
<string>05-MoreToPlay.playgroundpage</string>
1413
</array>
1514
</dict>
1615
</plist>

FanOfAscii/Chapters/01-FanOfAscii.playgroundchapter/Pages/04-Asciification.playgroundpage/main.swift

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Here is a **character map** built with font “Fira Code”, by arranging charac
2828
*/
2929
//#-editable-code
3030

31-
let characterMap = "MWNXK0Okxdolc:;,'... "
31+
let characterMapStr = "MWNXK0Okxdolc:;,'... "
3232

3333
//#-end-editable-code
3434
/*:
@@ -49,20 +49,20 @@ smooth result.
4949
//#-editable-code
5050

5151
// The aspect ratio of characters in the font “Fira Code”
52-
let ratio = 1.70667
52+
let characterAspectRatio = 0.5860
5353

54-
func calculateCharacterRows(rawImage: RawImage, charactersPerRow: Int) -> Int {
55-
let scaledHeight = Double(rawImage.format.height) * Double(charactersPerRow) / Double(rawImage.format.width)
56-
return Int((scaledHeight / ratio).rounded())
57-
}
54+
var charactersPerRow = 80
55+
var rowCount: Int!
5856

59-
let charactersPerRow = 80
60-
let characterRows = 0
57+
func calculateRowCount(imageFormat: ImageFormat, charactersPerRow: Int) -> Int {
58+
let scaledHeight = Double(charactersPerRow) / imageFormat.aspectRatio
59+
return Int((scaledHeight * characterAspectRatio).rounded())
60+
}
6161

6262
func scaleImageForAsciification(rawImage: RawImage) -> RawImage? {
63-
characterRows = calculateCharacterRows(rawImage: rawImage, charactersPerRow: charactersPerRow)
63+
rowCount = calculateRowCount(imageFormat: rawImage.format, charactersPerRow: charactersPerRow)
6464
// Scale the image to match the dimension of resulting ASCII art.
65-
return rawImage.scaled(width: charactersPerRow, height: characterRows)
65+
return rawImage.scaled(width: charactersPerRow, height: rowCount)
6666
}
6767

6868
//#-end-editable-code
@@ -72,41 +72,40 @@ func scaleImageForAsciification(rawImage: RawImage) -> RawImage? {
7272
### 🔨Mapping Pixels with Characters
7373

7474
* Experiment:
75-
* In this experiment, we'll build another filter to turn an image into grayscaled version, with consideration.
76-
* Try to read and complete the following code snippet. When you finish, run your code and tap the *Switch to
77-
Grayscale* button below the image to see whether it works.
75+
* Following code snippet generates an ASCII art by mapping pixels to characters according to their brightness level.
76+
* Run this code and tap the *ASCIIfy* button to see experience the magic, Feel free to tune all these parameters.
7877
*/
7978
//#-editable-code
8079

8180
func applyAsciification(rawImage: RawImage) -> UIImage? {
82-
let brightnessLevels = Double(characterMap.count)
81+
let characterMap: [Character] = Array(characterMapStr)
82+
let maxMappedBrightness = Double(characterMap.count - 1)
8383
var asciificationResult: String = ""
84-
for y in 0..<characterRows {
84+
85+
for y in 0..<rowCount {
8586
for x in 0..<charactersPerRow {
8687
if var pixel = rawImage.pixelAt(x: x, y: y) {
87-
let mappedBrightnessValue = pixel.brightness / 255.0 * (brightnessLevels - 1)
88-
asciificationResult.append(Array(characterMap)[Int(mappedBrightnessValue.rounded())])
88+
let mappedBrightnessValue = pixel.brightness / 255.0 * maxMappedBrightness
89+
asciificationResult.append(characterMap[Int(mappedBrightnessValue.rounded())])
8990
}
9091
}
9192
asciificationResult += "\n"
9293
}
93-
return RawImage.renderAsciifiedImage(
94+
95+
return AsciiArtRenderer.renderAsciifiedImage(
9496
asciificationResult,
95-
font: FiraCode.bold.rawValue,
96-
size: 14,
97-
charactersInRow: charactersPerRow,
98-
rows: characterRows,
99-
characterRatio: ratio)
97+
fontName: FontResourceProvider.FiraCode.bold.rawValue,
98+
size: 14.0,
99+
foreground: UIColor.black,
100+
background: UIColor.white,
101+
charactersPerRow: charactersPerRow,
102+
rows: rowCount,
103+
characterAspectRatio: characterAspectRatio)
100104
}
101105

102106
//#-end-editable-code
103-
/*:
104-
* Note:
105-
In this code snippet, we transform the image by multiplying it with a custom filter matrix. If you're not familiar
106-
with limier algebra, the following figure will explain how this transform matrix works.
107-
*/
108-
////#-hidden-code
109-
FiraCode.registerFont()
107+
//#-hidden-code
108+
FontResourceProvider.FiraCode.register()
110109

111110
let remoteView = remoteViewAsLiveViewProxy()
112111
let eventListener = EventListener(proxy: remoteView) { message in
@@ -131,4 +130,4 @@ let eventListener = EventListener(proxy: remoteView) { message in
131130
break
132131
}
133132
}
134-
////#-end-hidden-code
133+
//#-end-hidden-code

FanOfAscii/Chapters/01-FanOfAscii.playgroundchapter/Pages/05-MoreToPlay.playgroundpage/LiveView.swift

Lines changed: 0 additions & 10 deletions
This file was deleted.

FanOfAscii/Chapters/01-FanOfAscii.playgroundchapter/Pages/05-MoreToPlay.playgroundpage/Manifest.plist

Lines changed: 0 additions & 12 deletions
This file was deleted.

FanOfAscii/Chapters/01-FanOfAscii.playgroundchapter/Pages/05-MoreToPlay.playgroundpage/main.swift

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Copyright © 2020 Bunny Wong
3+
// Created by Bunny Wong on 2020/2/20.
4+
//
5+
6+
import UIKit
7+
8+
public class AsciiArtRenderer {
9+
10+
public static func renderAsciifiedImage(_ string: String,
11+
fontName: String,
12+
size: CGFloat,
13+
foreground: UIColor,
14+
background: UIColor,
15+
charactersPerRow: Int,
16+
rows: Int,
17+
characterAspectRatio: Double) -> UIImage {
18+
let characterWidth = size * CGFloat(characterAspectRatio)
19+
let characterHeight = size
20+
let drawingRect = CGRect(
21+
origin: CGPoint(x: 0, y: 0),
22+
size: CGSize(width: characterWidth * CGFloat(charactersPerRow), height: characterHeight * CGFloat(rows)))
23+
24+
let renderer = UIGraphicsImageRenderer(size: drawingRect.size)
25+
let img = renderer.image { ctx in
26+
background.setFill()
27+
ctx.fill(drawingRect)
28+
29+
let paragraphStyle = NSMutableParagraphStyle()
30+
paragraphStyle.alignment = .left
31+
paragraphStyle.lineSpacing = 0.0
32+
paragraphStyle.maximumLineHeight = size
33+
paragraphStyle.lineBreakMode = .byClipping
34+
let attrs = [
35+
NSAttributedString.Key.font: UIFont(name: fontName, size: size)!,
36+
NSAttributedString.Key.foregroundColor: foreground,
37+
NSAttributedString.Key.paragraphStyle: paragraphStyle
38+
]
39+
string.draw(
40+
with: drawingRect,
41+
options: .usesLineFragmentOrigin,
42+
attributes: attrs,
43+
context: nil)
44+
}
45+
return img
46+
}
47+
48+
}

FanOfAscii/Modules/BookAPI.playgroundmodule/Sources/Core/FireCode.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// Copyright © 2020 Bunny Wong
3+
// Created by Bunny Wong on 2020/2/20.
4+
//
5+
6+
import Foundation
7+
import CoreText
8+
9+
public protocol Font {
10+
11+
static var resourceName: String { get }
12+
static var resourceExtension: String { get }
13+
14+
static func register()
15+
16+
}
17+
18+
public extension Font {
19+
20+
static func register() {
21+
guard let fontURL = Bundle.main.url(forResource: resourceName, withExtension: resourceExtension) else {
22+
return
23+
}
24+
CTFontManagerRegisterFontsForURL(fontURL as CFURL, CTFontManagerScope.process, nil)
25+
}
26+
27+
}
28+
29+
public class FontResourceProvider {
30+
31+
public enum FiraCode: String, Font {
32+
33+
case light = "FiraCode-Light"
34+
case retina = "FiraCode-Light_Retina"
35+
case bold = "FiraCode-Light_Bold"
36+
case medium = "FiraCode-Light_Medium"
37+
case regular = "FiraCode-Light_Regular"
38+
39+
public static var resourceName: String {
40+
return "FiraCode-VF"
41+
}
42+
public static var resourceExtension: String {
43+
return "ttf"
44+
}
45+
46+
}
47+
48+
}
49+

FanOfAscii/Modules/BookCore.playgroundmodule/Sources/Core/LiveViewSupport.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public enum LiveViewIdentifier: String {
1111
case howImagesComposed
1212
case grayscaleHistogramEqualization
1313
case asciification
14-
case moreToPlay
1514
}
1615

1716
public func instantiateLiveView(identifier: LiveViewIdentifier) -> PlaygroundLiveViewable {

0 commit comments

Comments
 (0)