Skip to content

Commit

Permalink
support ios icons
Browse files Browse the repository at this point in the history
  • Loading branch information
kindlychung committed Dec 17, 2016
1 parent 610c896 commit 11c32b3
Show file tree
Hide file tree
Showing 7 changed files with 218 additions and 37 deletions.
8 changes: 8 additions & 0 deletions genicon.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
objects = {

/* Begin PBXBuildFile section */
BC3A58B41E057543009174F9 /* extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC3A58B31E057543009174F9 /* extension.swift */; };
BC3B068F1E033E7C00A89BE9 /* dataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9B8D891E01DFBF0096E77F /* dataModels.swift */; };
BC9B8D7E1E01AE220096E77F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9B8D7D1E01AE220096E77F /* main.swift */; };
BC9B8D851E01B2860096E77F /* execCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9B8D841E01B2860096E77F /* execCommand.swift */; };
BC9B8D8A1E01DFBF0096E77F /* dataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9B8D891E01DFBF0096E77F /* dataModels.swift */; };
BCA85D0F1E0567E000F7B41E /* generateJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCA85D0E1E0567E000F7B41E /* generateJson.swift */; };
BCD78DE81E03126F009A3BD3 /* testgenicon.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCD78DE71E03126F009A3BD3 /* testgenicon.swift */; };
/* End PBXBuildFile section */

Expand All @@ -27,13 +29,15 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
BC3A58B31E057543009174F9 /* extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = extension.swift; sourceTree = "<group>"; };
BC9B8D7A1E01AE220096E77F /* genicon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = genicon; sourceTree = BUILT_PRODUCTS_DIR; };
BC9B8D7D1E01AE220096E77F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
BC9B8D841E01B2860096E77F /* execCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = execCommand.swift; sourceTree = "<group>"; };
BC9B8D881E01D4C20096E77F /* MyPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = MyPlayground.playground; sourceTree = "<group>"; };
BC9B8D891E01DFBF0096E77F /* dataModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dataModels.swift; sourceTree = "<group>"; };
BCA410DF1E02B20E003F10A7 /* genicodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = genicodeTests.swift; sourceTree = "<group>"; };
BCA410E11E02B20E003F10A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BCA85D0E1E0567E000F7B41E /* generateJson.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = generateJson.swift; sourceTree = "<group>"; };
BCD78DE51E03126F009A3BD3 /* testgenicon.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = testgenicon.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
BCD78DE71E03126F009A3BD3 /* testgenicon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = testgenicon.swift; sourceTree = "<group>"; };
BCD78DE91E03126F009A3BD3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -83,6 +87,8 @@
BC9B8D841E01B2860096E77F /* execCommand.swift */,
BC9B8D881E01D4C20096E77F /* MyPlayground.playground */,
BC9B8D891E01DFBF0096E77F /* dataModels.swift */,
BCA85D0E1E0567E000F7B41E /* generateJson.swift */,
BC3A58B31E057543009174F9 /* extension.swift */,
);
path = genicon;
sourceTree = "<group>";
Expand Down Expand Up @@ -199,6 +205,8 @@
files = (
BC9B8D851E01B2860096E77F /* execCommand.swift in Sources */,
BC9B8D8A1E01DFBF0096E77F /* dataModels.swift in Sources */,
BCA85D0F1E0567E000F7B41E /* generateJson.swift in Sources */,
BC3A58B41E057543009174F9 /* extension.swift in Sources */,
BC9B8D7E1E01AE220096E77F /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Binary file not shown.
136 changes: 135 additions & 1 deletion genicon/MyPlayground.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,138 @@
import Foundation

let s = jsonify(pair: ("name", "Julia"), quoteValue: true)
print(s)
print(s)


enum Fruit {
case apple, pear, banana
}

enum Drink {
case beer, whisky, vodka
}

enum FruitPlusDrink {
case fruit(Fruit)
case drink(Drink)
}

enum FruitTimesDrink1 {
case value(fruit: Fruit, drink: Drink)
}

struct FruitTimesDrink {
let fruit: Fruit
let drink: Drink
}

// composition
let content = "10,20,40,30,80,60"
func extractElements(_ content: String) -> [String] {
return content.characters.split(separator: ",").map {String($0)}
}
func formatWithCurrency(content: [String]) -> [String] {
return content.map {"" + $0}
}
let composedFunciton = { data in
formatWithCurrency(content: extractElements(data))
}
print(composedFunciton(content))

infix operator |> : MultiplicationPrecedence
func |> <T, V>(f: @escaping (T) -> V, g: @escaping (V) -> V) -> (T) -> V {
return {
x in
g(f(x))
}
}

var res = (extractElements |> formatWithCurrency)(content)
print(res)

res = extractElements(content).sorted(by: {
(a, b) in
a > b
})
print(res)
// if the only param is a closure, then the syntax can be simplified as:
res = extractElements(content).sorted {
(a, b) in
a > b
}
print(res)
// this can be simplified further
res = extractElements(content).sorted {
$0 > $1
}
print(res)

func opOnNumber(number: Int, op: (Int) -> Bool) -> Bool {
return op(number)
}
// if the last param is a closure, you can write it this way (similar to scala):
// looks like functions are automatically curried.
var boolRes = opOnNumber(number: 3) {
$0 > 5
}
print(boolRes)

// tail recursion
func factorial(n: Int, accumulator: Int) -> Int {
return n == 0 ? accumulator : factorial(n: n-1, accumulator: n * accumulator)
}
print(factorial(n: 4, accumulator: 1))


class MemoizedPower2 {
var memo: [Int: Int] = [:]
func power2(n: Int) -> Int {
assert(n >= 0, "Negative power not supported!")
if let result = memo[n] {
return result
} else {
var result = 1
for _ in 1...n {
result *= 2
}
memo[n] = result
return result
}
}
init(memo: [Int:Int]) {
self.memo = memo
}
static let sharedInstance: MemoizedPower2 = {
let obj = MemoizedPower2(memo: [0:1, 1:2])
return obj
}()
}

func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
print("Time elapsed for \(title): \(timeElapsed) s")
}

printTimeElapsedWhenRunningCode(title: "power2") {
for _ in 1...200 {
let _ = MemoizedPower2.sharedInstance.power2(n: 55)
}
}
printTimeElapsedWhenRunningCode(title: "power2") {
for _ in 1...200 {
var x = 1
for i in 1...55 {
x *= 2
}
}
}

//func memoize<T: Hashable, U>(fn: ((T) -> U, T) -> U) -> (T) -> U {
//
//}




23 changes: 23 additions & 0 deletions genicon/extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// extension.swift
// genicon
//
// Created by Kaiyin Zhong on 12/17/16.
// Copyright © 2016 vu.co.kaiyin. All rights reserved.
//

import Foundation
extension String {
var absolutePath: String {
if self == "." {
return cwd
}
if self.hasPrefix("/") {
return self
}
return cwd + "/" + self
}
func fileURL(isDirectory: Bool) -> URL? {
return URL(fileURLWithPath: absolutePath, isDirectory: isDirectory)
}
}
25 changes: 25 additions & 0 deletions genicon/generateJson.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// generateJson.swift
// genicon
//
// Created by Kaiyin Zhong on 12/17/16.
// Copyright © 2016 vu.co.kaiyin. All rights reserved.
//

import Foundation

public func generateContents(sizes: [Int], scales: [Int]) -> Contents {
var contents = Contents()
for sz in sizes {
for sc in scales {
let img = ImageInfo(size: sz, scale: sc)
contents.images.append(img)
}
}
return contents
}

public let macSizes = [16, 32, 128, 512]
public let macScales = [1, 2]
public let iosSizes = [20, 29, 40, 60]
public let iosScales = [2, 3]
44 changes: 15 additions & 29 deletions genicon/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,24 @@

import Foundation

if CommandLine.arguments.contains("--help") || CommandLine.arguments.contains("-h") || CommandLine.arguments.dropFirst().isEmpty {
print("\n genicon: A command line tool for generating icons for Cocoa apps.\n", "© Kaiyin Zhong 2016\n\n", "Usage: \n", "genicon INPUT OUTPUT_FOLDER")
let args = CommandLine.arguments
if args.contains("--help") || args.contains("-h") || args.dropFirst().isEmpty {
print("\n genicon: A command line tool for generating icons for Cocoa apps.\n", "© Kaiyin Zhong 2016\n\n", "Usage: \n", "genicon [options] INPUT OUTPUT_FOLDER\n\n", "--help, -h Print this message.\n", "--mac Generate icons for macOS.\n", "--ios Generate icons for iOS. When neither --mac nor --ios is given, mac icons are generated by default.\n")
exit(0)
}



let fm = FileManager.default
let cwd = fm.currentDirectoryPath
extension String {
var absolutePath: String {
if self == "." {
return cwd
}
if self.hasPrefix("/") {
return self
}
return cwd + "/" + self
}
func fileURL(isDirectory: Bool) -> URL? {
return URL(fileURLWithPath: absolutePath, isDirectory: isDirectory)
}
}


// set up folders
let inputFile: URL = CommandLine.arguments[1].fileURL(isDirectory: false)!
let outputFolder: URL = CommandLine.arguments[2].fileURL(isDirectory: true)!
let inputFile: URL = args[1].fileURL(isDirectory: false)!
let outputFolder: URL = args[2].fileURL(isDirectory: true)!
//let inputFile = URL(string: "file:///Users/kaiyin/Desktop/dr89/Dr89.svg")!
//let outputFolder = URL(string: "file:///tmp")!
let iconFolder = outputFolder.appendingPathComponent("AppIcon.appiconset", isDirectory: true)




do {
if !fm.fileExists(atPath: iconFolder.path) {
try fm.createDirectory(at: iconFolder, withIntermediateDirectories: true, attributes: [:])
Expand All @@ -52,14 +38,14 @@ do {
}

// generate Contents.json
var contents = Contents()
let size = [16, 32, 128, 512]
for sz in size {
for sc in 1...2 {
let img = ImageInfo(size: sz, scale: sc)
contents.images.append(img)
}
var contents: Contents = Contents()
// when neither --mac nor --ios is given, mac icons are generated by default.
if args.contains("--mac") || !args.contains("--ios"){
contents = generateContents(sizes: macSizes, scales: macScales)
} else if args.contains("--ios") {
contents = generateContents(sizes: iosSizes, scales: iosScales)
}

let jsonFilename = "Contents.json"
let jsonUrl = iconFolder.appendingPathComponent(jsonFilename)
do {
Expand Down
19 changes: 12 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# genicon: A command line tool for generating icons for Cocoa apps.
# genicon: A command line tool for generating icons for macOS/iOS apps.

This tool wraps imagemagick to provide a convenient utility for generating cocoa app icons that conform to Apple's standard. You should feed a large square image (>= 1024x1024), or (preferrably) an svg file, and get all appropriate sizes plus a proper json index in a `AppIcon.appiconset` folder, which can be directly copied into the `Assets.xcassets` folder in your cocoa project.
This tool wraps imagemagick to provide a convenient utility for generating macOS/iOS app icons that conform to Apple's standard. You should feed it a large square image (>= 1024x1024), or (preferrably) an svg file, and get all appropriate sizes plus a proper json index in a `AppIcon.appiconset` folder, which can be directly copied into the `Assets.xcassets` folder in your Xcode project.

# Usage

Type `genicon` or `genicon -h` in terminal:

$genicon

genicon: A command line tool for generating icons for Cocoa apps.
© Kaiyin Zhong 2016
$ genicon

Usage:
genicon INPUT OUTPUT_FOLDER
genicon: A command line tool for generating icons for Cocoa apps.
© Kaiyin Zhong 2016

Usage:
genicon [options] INPUT OUTPUT_FOLDER

--help, -h Print this message.
--mac Generate icons for macOS.
--ios Generate icons for iOS. When neither --mac nor --ios is given, mac icons are generated by default.

# Requirements

Expand Down

0 comments on commit 11c32b3

Please sign in to comment.