├── screenshot.png
├── JPG to HEIF Converter
├── Assets.xcassets
│ ├── Contents.json
│ ├── applogo.imageset
│ │ ├── logo.pdf
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ ├── 16x16.png
│ │ ├── 32x32.png
│ │ ├── 128x128.png
│ │ ├── 16x16@2x.png
│ │ ├── 256x256.png
│ │ ├── 32x32@2x.png
│ │ ├── 512x512.png
│ │ ├── 128x128@2x.png
│ │ ├── 256x256@2x.png
│ │ ├── 512x512@2x.png
│ │ └── Contents.json
├── JPG to HEIF Converter.entitlements
├── JPG_to_HEIF_Converter.entitlements
├── tr.lproj
│ ├── Localizable.strings
│ └── Main.strings
├── en.lproj
│ └── Localizable.strings
├── extensions
│ └── URL+contains.swift
├── controllers
│ ├── MainWindowController.swift
│ └── ViewController.swift
├── AppDelegate.swift
├── managers
│ └── UserDefaultsManager.swift
├── models
│ └── FileTypeEnum.swift
├── Info.plist
└── Base.lproj
│ └── Main.storyboard
├── JPG to HEIF Converter.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── README.md
├── LICENSE
└── .gitignore
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/screenshot.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/applogo.imageset/logo.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/applogo.imageset/logo.pdf
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/16x16.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/32x32.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/128x128.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/16x16@2x.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/256x256.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/32x32@2x.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/512x512.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/128x128@2x.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/256x256@2x.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/makoni/jpg-to-heif-converter/HEAD/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/512x512@2x.png
--------------------------------------------------------------------------------
/JPG to HEIF Converter/JPG to HEIF Converter.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/JPG_to_HEIF_Converter.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/tr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | JPG to HEIF Converter
4 |
5 | Created by Abuzer Emre Osmanoğlu on 14.07.2018.
6 | Copyright © 2018 Sergey Armodin. All rights reserved.
7 | */
8 |
9 | "of" = " ; ";
10 | "Converting complete" = "Dönüşüm tamamlandı";
11 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /*
2 | Localizable.strings
3 | JPG to HEIF Converter
4 |
5 | Created by Abuzer Emre Osmanoğlu on 14.07.2018.
6 | Copyright © 2018 Sergey Armodin. All rights reserved.
7 | */
8 |
9 | "of" = " of ";
10 | "Converting complete" = "Converting complete";
11 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/applogo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "logo.pdf",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/extensions/URL+contains.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URL+contains.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Sergei Armodin on 11.12.2020.
6 | // Copyright © 2020 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension URL {
12 | public func contains(_ other: URL) -> Bool {
13 | return autoreleasepool {
14 | return resolvingSymlinksInPath().absoluteString.lowercased().contains(other.resolvingSymlinksInPath().absoluteString.lowercased())
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/controllers/MainWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainWindowController.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Sergey Armodin on 21.05.2018.
6 | // Copyright © 2018 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 |
12 | class MainWindowController: NSWindowController {
13 |
14 | override func windowDidLoad() {
15 | super.windowDidLoad()
16 |
17 | let appDelegate = NSApp.delegate as! AppDelegate
18 | appDelegate.mainWindowController = self
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Sergey Armodin on 21.05.2018.
6 | // Copyright © 2018 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | /// Window controller
15 | var mainWindowController: MainWindowController? = nil
16 |
17 | func applicationDidFinishLaunching(_ aNotification: Notification) {
18 | // Insert code here to initialize your application
19 | }
20 |
21 | func applicationWillTerminate(_ aNotification: Notification) {
22 | // Insert code here to tear down your application
23 | }
24 |
25 | func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
26 | mainWindowController?.window?.makeKeyAndOrderFront(self)
27 | return false
28 | }
29 |
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jpg-to-heif-converter
2 |
3 | 
4 |
5 | macOS app for converting from JPG, JPEG and PNG to HEIF (HEIC)
6 |
7 | 
8 |
9 | With macOS 10.13 and iOS 11 Apple has introduced new file format for images called HEIF (High Efficiency Image File Format). Files has the same quality as old JPG but they are much smaller.
10 |
11 | This converter app allows you to open JPG/JPEG/PNG/NEF/CR2 files on Mac and save them in HEIF (files are with .HEIC extension).
12 |
13 | Download DMG: https://github.com/makoni/jpg-to-heif-converter/releases
14 |
15 | Home page: https://spaceinbox.me/jpg-to-heif-converter
16 |
17 | # Support the app ❤️
18 |
19 | - USDT (ERC20): 0xFB78198d9BdDd1CC77a46cc982fB2E13Df4D64D8
20 | - USDT (TRC20): TT6JSkgQdbsrBxm3HaDsYngYcKkUBtLvhc
21 | - ETH: 0xFB78198d9BdDd1CC77a46cc982fB2E13Df4D64D8
22 | - BTC: bc1q3m73k5jhhgv9gljuhle4mp7aa8fv6ukkyw5ym3
23 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/managers/UserDefaultsManager.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDefaultsManager.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Christopher Spradling on 9/5/18.
6 | // Copyright © 2018 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct UserDefaultsManager {
12 | // MARK: - Private properties
13 | private static let removeOriginalImagePreferenceKey = "removeOriginalImagePreferenceKey"
14 | private static let qualityPreferenceKey = "qualityPreferenceKey"
15 |
16 | // MARK: - Public properties
17 | static var preferToRemoveOriginals: Bool {
18 | get {
19 | return UserDefaults.standard.bool(forKey: removeOriginalImagePreferenceKey)
20 | }
21 | set {
22 | UserDefaults.standard.set(newValue, forKey: removeOriginalImagePreferenceKey)
23 | }
24 | }
25 |
26 | static var qualityPreference: Double? {
27 | get {
28 | return UserDefaults.standard.double(forKey: qualityPreferenceKey)
29 | }
30 | set {
31 | UserDefaults.standard.set(newValue, forKey: qualityPreferenceKey)
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Sergey Armodin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/models/FileTypeEnum.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FileTypeEnum.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Christopher Spradling on 8/31/18.
6 | // Copyright © 2018 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum FileType {
12 |
13 | case image
14 | case json
15 | case directory
16 | case invalid
17 |
18 | init(_ url: URL) {
19 | if FileType.allowedImageTypes.contains(url.pathExtension.lowercased()) {
20 | self = .image
21 | }
22 | else if FileType.directoryTypes.contains(url.pathExtension) {
23 | self = .directory
24 | }
25 | else if url.lastPathComponent.lowercased() == "contents.json" {
26 | self = .json
27 | }
28 | else {
29 | self = .invalid
30 | }
31 |
32 | }
33 |
34 | static var allowedImageTypes: [String] {
35 | return ["jpg", "jpeg", "png", "nef", "cr2", "sr2", "arw", "dng"]
36 | }
37 |
38 | static var directoryTypes: [String] {
39 | return ["xcassets", "imageset", ""]
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | LSApplicationCategoryType
24 | public.app-category.utilities
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSHumanReadableCopyright
28 | Copyright © 2018 Sergey Armodin. All rights reserved.
29 | NSMainStoryboardFile
30 | Main
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "16x16.png",
5 | "idiom" : "mac",
6 | "scale" : "1x",
7 | "size" : "16x16"
8 | },
9 | {
10 | "filename" : "16x16@2x.png",
11 | "idiom" : "mac",
12 | "scale" : "2x",
13 | "size" : "16x16"
14 | },
15 | {
16 | "filename" : "32x32.png",
17 | "idiom" : "mac",
18 | "scale" : "1x",
19 | "size" : "32x32"
20 | },
21 | {
22 | "filename" : "32x32@2x.png",
23 | "idiom" : "mac",
24 | "scale" : "2x",
25 | "size" : "32x32"
26 | },
27 | {
28 | "filename" : "128x128.png",
29 | "idiom" : "mac",
30 | "scale" : "1x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "filename" : "128x128@2x.png",
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "size" : "128x128"
38 | },
39 | {
40 | "filename" : "256x256.png",
41 | "idiom" : "mac",
42 | "scale" : "1x",
43 | "size" : "256x256"
44 | },
45 | {
46 | "filename" : "256x256@2x.png",
47 | "idiom" : "mac",
48 | "scale" : "2x",
49 | "size" : "256x256"
50 | },
51 | {
52 | "filename" : "512x512.png",
53 | "idiom" : "mac",
54 | "scale" : "1x",
55 | "size" : "512x512"
56 | },
57 | {
58 | "filename" : "512x512@2x.png",
59 | "idiom" : "mac",
60 | "scale" : "2x",
61 | "size" : "512x512"
62 | }
63 | ],
64 | "info" : {
65 | "author" : "xcode",
66 | "version" : 1
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 |
51 | # Carthage
52 | #
53 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
54 | # Carthage/Checkouts
55 |
56 | Carthage/Build
57 |
58 | # fastlane
59 | #
60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
61 | # screenshots whenever they are needed.
62 | # For more information about the recommended setup visit:
63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
64 |
65 | fastlane/report.xml
66 | fastlane/Preview.html
67 | fastlane/screenshots/**/*.png
68 | fastlane/test_output
69 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/tr.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSMenuItem"; title = "JPG to HEIF Converter"; ObjectID = "1Xt-HY-uBw"; */
3 | "1Xt-HY-uBw.title" = "JPG to HEIF Converter";
4 |
5 | /* Class = "NSMenuItem"; title = "Enter Full Screen"; ObjectID = "4J7-dP-txa"; */
6 | "4J7-dP-txa.title" = "Tam Ekran";
7 |
8 | /* Class = "NSMenuItem"; title = "Quit JPG to HEIF Converter"; ObjectID = "4sb-4s-VLi"; */
9 | "4sb-4s-VLi.title" = "Çık JPG to HEIF Converter";
10 |
11 | /* Class = "NSMenuItem"; title = "About JPG to HEIF Converter"; ObjectID = "5kV-Vb-QxS"; */
12 | "5kV-Vb-QxS.title" = "Hakkında JPG to HEIF Converter";
13 |
14 | /* Class = "NSButtonCell"; title = "Open files"; ObjectID = "93x-s1-82K"; */
15 | "93x-s1-82K.title" = "Fotoğrafları Seç";
16 |
17 | /* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */
18 | "AYu-sK-qS6.title" = "Ana Menü";
19 |
20 | /* Class = "NSMenuItem"; title = "Close"; ObjectID = "DVo-aG-piG"; */
21 | "DVo-aG-piG.title" = "Kapat";
22 |
23 | /* Class = "NSMenu"; title = "Help"; ObjectID = "F2S-fz-NVQ"; */
24 | "F2S-fz-NVQ.title" = "Yardım";
25 |
26 | /* Class = "NSMenuItem"; title = "JPG to HEIF Converter Help"; ObjectID = "FKE-Sm-Kum"; */
27 | "FKE-Sm-Kum.title" = "JPG to HEIF Converter Yardım";
28 |
29 | /* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */
30 | "H8h-7b-M4v.title" = "Görüntü";
31 |
32 | /* Class = "NSMenu"; title = "View"; ObjectID = "HyV-fh-RgO"; */
33 | "HyV-fh-RgO.title" = "Görüntü";
34 |
35 | /* Class = "NSWindow"; title = "Convert images to HEIF"; ObjectID = "IQv-IB-iLA"; */
36 | "IQv-IB-iLA.title" = "Fotoğrafları HEIF formatına çevir";
37 |
38 | /* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */
39 | "Kd2-mp-pUS.title" = "Hepsini Göster";
40 |
41 | /* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "LE2-aR-0XJ"; */
42 | "LE2-aR-0XJ.title" = "Hepsini Öne Getir";
43 |
44 | /* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */
45 | "NMo-om-nkz.title" = "Servisler";
46 |
47 | /* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "OY7-WF-poV"; */
48 | "OY7-WF-poV.title" = "Küçült";
49 |
50 | /* Class = "NSMenuItem"; title = "Hide JPG to HEIF Converter"; ObjectID = "Olw-nP-bQN"; */
51 | "Olw-nP-bQN.title" = "Gizle JPG to HEIF Converter";
52 |
53 | /* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "R4o-n2-Eq4"; */
54 | "R4o-n2-Eq4.title" = "Yakınlaştır";
55 |
56 | /* Class = "NSMenu"; title = "Window"; ObjectID = "Td7-aD-5lo"; */
57 | "Td7-aD-5lo.title" = "Pencere";
58 |
59 | /* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */
60 | "Vdr-fp-XzO.title" = "Diğerlerini Gizle";
61 |
62 | /* Class = "NSMenuItem"; title = "Print…"; ObjectID = "aTl-1u-JFS"; */
63 | "aTl-1u-JFS.title" = "Baskı…";
64 |
65 | /* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */
66 | "aUF-d1-5bR.title" = "Pencere";
67 |
68 | /* Class = "NSMenu"; title = "File"; ObjectID = "bib-Uj-vzu"; */
69 | "bib-Uj-vzu.title" = "Dosya";
70 |
71 | /* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */
72 | "dMs-cI-mzQ.title" = "Dosya";
73 |
74 | /* Class = "NSTextFieldCell"; title = "1 of 2 complete"; ObjectID = "dRN-in-KeR"; */
75 | "dRN-in-KeR.title" = "1 ; 2 tamamlandı";
76 |
77 | /* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */
78 | "hz9-B4-Xy5.title" = "Servisler";
79 |
80 | /* Class = "NSMenu"; title = "JPG to HEIF Converter"; ObjectID = "uQy-DD-JDr"; */
81 | "uQy-DD-JDr.title" = "JPG to HEIF Converter";
82 |
83 | /* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */
84 | "wpr-3q-Mcd.title" = "Yardım";
85 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/controllers/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // JPG to HEIF Converter
4 | //
5 | // Created by Sergey Armodin on 21.05.2018.
6 | // Copyright © 2018 Sergey Armodin. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import AVFoundation
11 | import CoreFoundation
12 |
13 |
14 | /// Converter state
15 | ///
16 | /// - launched: just launched
17 | /// - converting: converting right now
18 | /// - complete: convertion complete
19 | enum ConverterState: Int {
20 | case launched
21 | case converting
22 | case complete
23 | }
24 |
25 | typealias JSON = [String:Any]
26 |
27 | class ViewController: NSViewController {
28 |
29 | // MARK: - Outlets
30 |
31 | /// Open files button
32 | @IBOutlet fileprivate weak var openFilesButton: NSButtonCell!
33 | /// Indicator
34 | @IBOutlet fileprivate weak var progressIndicator: NSProgressIndicator!
35 | /// Complete label
36 | @IBOutlet fileprivate weak var completeLabel: NSTextField!
37 | /// Keep Originals checkbox
38 | @IBOutlet fileprivate weak var keepOriginalsCheckbox: NSButton!
39 | /// Quality value
40 | @IBOutlet fileprivate weak var qualityValueLabel: NSTextField!
41 | /// Quality slider
42 | @IBOutlet fileprivate weak var qualitySlider: NSSlider!
43 |
44 |
45 |
46 | // MARK: - Private properties
47 | private var quality: Double = 0.9
48 |
49 | /// Processed images number
50 | fileprivate var processedImages: Int = 0 {
51 | didSet {
52 | self.completeLabel.stringValue = "\(self.processedImages)" + NSLocalizedString("of", comment: "conjunction") + "\(self.totalImages)"
53 |
54 | self.progressIndicator.doubleValue = Double(self.processedImages)
55 | }
56 | }
57 |
58 | /// Total selected images number
59 | fileprivate var totalImages: Int = 0 {
60 | didSet {
61 | self.progressIndicator.maxValue = Double(totalImages)
62 | }
63 | }
64 |
65 | /// State
66 | fileprivate var converterState: ConverterState = .launched {
67 | didSet {
68 | switch converterState {
69 | case .launched:
70 | self.progressIndicator.isHidden = true
71 | self.completeLabel.isHidden = true
72 | case .converting:
73 | self.openFilesButton.isEnabled = false
74 | self.progressIndicator.isHidden = false
75 | self.completeLabel.isHidden = false
76 | case .complete:
77 | self.openFilesButton.isEnabled = true
78 | self.progressIndicator.isHidden = false
79 | self.completeLabel.isHidden = false
80 |
81 | self.completeLabel.stringValue = NSLocalizedString("Converting complete", comment: "Label")
82 | }
83 | }
84 | }
85 |
86 |
87 | override func viewDidLoad() {
88 | super.viewDidLoad()
89 |
90 | self.openFilesButton.isEnabled = true
91 | self.converterState = .launched
92 |
93 | keepOriginalsCheckbox.state = UserDefaultsManager.preferToRemoveOriginals ? .off : .on
94 |
95 | var preferredQuality = UserDefaultsManager.qualityPreference ?? 0.9
96 | if preferredQuality <= 0 {
97 | preferredQuality = 0.9
98 | }
99 | qualityValueLabel.stringValue = "\(preferredQuality)"
100 | qualitySlider.maxValue = 1 // lossless compression
101 | qualitySlider.minValue = 0 // maximum compression
102 | qualitySlider.doubleValue = preferredQuality
103 | quality = preferredQuality
104 | }
105 |
106 | override var representedObject: Any? {
107 | didSet {
108 | // Update the view, if already loaded.
109 | }
110 | }
111 | }
112 |
113 |
114 | // MARK: - Actions
115 | extension ViewController {
116 | @IBAction func sliderChanged(_ sender: Any) {
117 | quality = round(qualitySlider.doubleValue * 100) / 100
118 | UserDefaultsManager.qualityPreference = quality
119 | qualityValueLabel.stringValue = "\(quality)"
120 | }
121 |
122 | /// Keep Original Files checkbox checked/unchecked
123 | ///
124 | /// - Parameter sender: sender
125 | @IBAction func keepOriginalsCheckboxTouched(_ sender: Any) {
126 | UserDefaultsManager.preferToRemoveOriginals = (keepOriginalsCheckbox.state == .off)
127 | }
128 |
129 | /// Open files button touched
130 | ///
131 | /// - Parameter sender: NSButton
132 | @IBAction func openFilesButtonTouched(_ sender: Any) {
133 |
134 | totalImages = 0
135 | processedImages = 0
136 |
137 | let panel = NSOpenPanel.init()
138 | panel.allowsMultipleSelection = true
139 | panel.canChooseDirectories = true
140 | panel.canChooseFiles = true
141 | panel.isFloatingPanel = true
142 | panel.allowedFileTypes = FileType.allowedImageTypes + FileType.directoryTypes
143 |
144 | panel.beginSheetModal(for: self.view.window!) { [weak self] (result) in
145 | guard let self = self else { return }
146 | guard result == .OK, panel.urls.isEmpty == false else { return }
147 |
148 | self.processItems(panel.urls, deletingOriginals: UserDefaultsManager.preferToRemoveOriginals)
149 | }
150 | }
151 |
152 | /// Determine file types in a list and process each item accordingly
153 | ///
154 | /// - Parameter urls: [URL]
155 | /// - Parameter deletingOriginals: Boolean flag to indicate whether images should be preserved in their original format after conversion
156 | func processItems(_ urls: [URL], deletingOriginals: Bool) {
157 | converterState = .converting
158 | totalImages = 0
159 | processedImages = 0
160 |
161 | let group = DispatchGroup()
162 | let serialQueue = DispatchQueue(label: "me.spaceinbox.jpgtoheifconverter")
163 |
164 | for url in urls {
165 |
166 | switch FileType(url) {
167 | case .image: convertImage(url, group: group, queue: serialQueue, deletingOriginals: deletingOriginals)
168 | case .json: updateContentsFile(url, group: group, queue: serialQueue)
169 | case .directory: processFolder(url, group: group, queue: serialQueue, deletingOriginals: deletingOriginals)
170 | case .invalid: continue
171 | }
172 |
173 | }
174 |
175 | group.notify(queue: .main, execute: { [weak self] in
176 | guard let self = self else { return }
177 | self.converterState = .complete
178 | })
179 |
180 | }
181 |
182 | /// Traverse directories and convert any images to .heic
183 | ///
184 | /// - Parameter url: the file path to be processed
185 | /// - Parameter group: the DispatchGroup managing conversion work
186 | /// - Parameter queue: the serial queue to contain conversion work
187 | /// - Parameter deletingOriginals: Boolean flag to indicate whether images should be preserved in their original format after conversion
188 | func processFolder(_ url: URL, group: DispatchGroup, queue: DispatchQueue, deletingOriginals: Bool) {
189 | guard case .directory = FileType(url) else { return }
190 |
191 |
192 | let subPaths = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isDirectoryKey])
193 |
194 | var excludes: [URL] = []
195 |
196 | while let path = subPaths?.nextObject() as? URL {
197 | if !excludes.lazy.map({ path.contains($0) }).filter({ $0 }).isEmpty {
198 | continue
199 | }
200 |
201 | switch FileType(path) {
202 | case .image:
203 | convertImage(path, group: group, queue: queue, deletingOriginals: deletingOriginals)
204 | continue
205 | case .json:
206 | updateContentsFile(path, group: group, queue: queue)
207 | case .directory, .invalid:
208 | /* subdirectories' contents are also part of the enumerated sequence, so the directories themselves can be ignored */
209 | var shouldPass = false
210 | if path.pathExtension.lowercased() == "imageset" {
211 | if let subPaths = try? FileManager.default.subpathsOfDirectory(atPath: path.relativePath) {
212 | shouldPass = subPaths
213 | .map({ path.appendingPathComponent($0) })
214 | .map({ ($0, FileType($0)) })
215 | .filter({ $0.1 == FileType.image })
216 | .map({ $0.0 })
217 | .compactMap({ url in
218 | try? Data(contentsOf: url)
219 | })
220 | .map({ $0.count })
221 | .filter({ $0 > 1024*100 })
222 | .isEmpty
223 | }
224 |
225 | if
226 | !shouldPass,
227 | let json = try? JSONSerialization.jsonObject(with: Data(contentsOf: path.appendingPathComponent("Contents.json")), options: .mutableLeaves) as? JSON,
228 | let images = json["images"] as? [[String: Any]] {
229 | if !images.lazy.map({ !$0.lazy.filter({ $0.key.lowercased() == "resizing" }).isEmpty }).filter({ $0 }).isEmpty {
230 | shouldPass = true
231 | }
232 | }
233 | }
234 |
235 | if shouldPass {
236 | excludes.append(path)
237 | }
238 |
239 | continue
240 | }
241 |
242 | }
243 |
244 | }
245 |
246 | /// Convert a valid image to .heic
247 | ///
248 | /// - Parameter imageUrl: the file path to be converted
249 | /// - Parameter group: the DispatchGroup managing conversion work
250 | /// - Parameter queue: the serial queue to contain conversion work
251 | /// - Parameter deletingOriginals: Boolean flag to indicate whether images should be preserved in their original format after conversion
252 | func convertImage(_ imageUrl: URL, group: DispatchGroup, queue: DispatchQueue, deletingOriginals: Bool) {
253 |
254 | totalImages += 1
255 |
256 | group.enter()
257 | queue.async { [weak self] in
258 |
259 | guard let self = self else { return }
260 |
261 | guard case .image = FileType(imageUrl) else { return }
262 | guard let source = CGImageSourceCreateWithURL(imageUrl as CFURL, nil) else { return }
263 | guard let image = CGImageSourceCreateImageAtIndex(source, 0, nil) else { return }
264 | guard let imageMetadata = CGImageSourceCopyMetadataAtIndex(source, 0, nil) else { return }
265 |
266 | let pathWithName = imageUrl.deletingPathExtension()
267 | guard let outputUrl = URL(string: pathWithName.absoluteString + ".heic") else { return }
268 |
269 | guard let destination = CGImageDestinationCreateWithURL(
270 | outputUrl as CFURL,
271 | AVFileType.heic as CFString,
272 | 1, nil
273 | ) else {
274 | fatalError("unable to create CGImageDestination")
275 | }
276 |
277 | let options = [kCGImageDestinationLossyCompressionQuality: self.quality]
278 | CGImageDestinationAddImageAndMetadata(destination, image, imageMetadata, options as CFDictionary)
279 | CGImageDestinationFinalize(destination)
280 |
281 | if deletingOriginals {
282 | try? FileManager.default.removeItem(at: imageUrl)
283 | }
284 |
285 | DispatchQueue.main.async {
286 | self.processedImages += 1
287 | }
288 |
289 | group.leave()
290 | }
291 |
292 | }
293 |
294 | }
295 |
296 | // MARK: - Private methods
297 | private extension ViewController {
298 | /// Update the contents.json file in an imageset to reflect new file type
299 | ///
300 | /// - Parameter url: the file path to be processed
301 | /// - Parameter group: the DispatchGroup managing conversion work
302 | /// - Parameter queue: the serial queue to contain conversion work
303 | func updateContentsFile(_ url: URL, group: DispatchGroup, queue: DispatchQueue) {
304 | guard case .json = FileType(url) else { return }
305 |
306 | group.enter()
307 | queue.async { [weak self] in
308 |
309 | do {
310 | try self?.updateJSONContents(url)
311 | } catch let error {
312 | print(error)
313 | }
314 |
315 | group.leave()
316 | }
317 |
318 | }
319 |
320 | /// Attempt to translate a file path into JSON, process it, and overwrite the file with the result
321 | func updateJSONContents(_ url: URL) throws {
322 | guard let json = try JSONSerialization.jsonObject(with: Data(contentsOf: url), options: .mutableLeaves) as? JSON else { return }
323 | let processed = try JSONSerialization.data(withJSONObject: processJSON(json), options: .prettyPrinted)
324 | try processed.write(to: url)
325 |
326 | }
327 |
328 | /// Traverse a json object, changing only the path extension of values keyed for filename
329 | func processJSON(_ json: JSON) -> JSON {
330 | var json = json
331 | for (k, v) in json {
332 | if k == "filename", let value = v as? String {
333 | for type in FileType.allowedImageTypes {
334 | let newValue = value.replacingOccurrences(of: ".\(type)", with: ".heic")
335 | if newValue != value {
336 | json[k] = newValue
337 | }
338 | }
339 | } else if let value = v as? JSON {
340 | json[k] = processJSON(value)
341 | } else if let values = v as? [JSON] {
342 | json[k] = values.compactMap({ return processJSON($0) })
343 | }
344 | }
345 |
346 | return json
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 047E832220FA3D2400EDD4B0 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 047E832420FA3D2400EDD4B0 /* Localizable.strings */; };
11 | 2407286620B313EE00E704B8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2407286520B313EE00E704B8 /* AppDelegate.swift */; };
12 | 2407286820B313EE00E704B8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2407286720B313EE00E704B8 /* ViewController.swift */; };
13 | 2407286A20B313F000E704B8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2407286920B313F000E704B8 /* Assets.xcassets */; };
14 | 2407286D20B313F000E704B8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2407286B20B313F000E704B8 /* Main.storyboard */; };
15 | 2407287720B34D5500E704B8 /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2407287620B34D5500E704B8 /* MainWindowController.swift */; };
16 | 24F4F3B325836E6C00FF15A9 /* URL+contains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F4F3B225836E6C00FF15A9 /* URL+contains.swift */; };
17 | CD181F4A21407A9000D58033 /* UserDefaultsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD181F4921407A9000D58033 /* UserDefaultsManager.swift */; };
18 | CDF981C92139FB6500EBC90E /* FileTypeEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF981C82139FB6500EBC90E /* FileTypeEnum.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | 047E831F20FA3A7D00EDD4B0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Main.strings; sourceTree = ""; };
23 | 047E832320FA3D2400EDD4B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
24 | 047E832520FA3D2800EDD4B0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; };
25 | 2407286220B313EE00E704B8 /* JPG to HEIF Converter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "JPG to HEIF Converter.app"; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 2407286520B313EE00E704B8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
27 | 2407286720B313EE00E704B8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
28 | 2407286920B313F000E704B8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
29 | 2407286C20B313F000E704B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
30 | 2407286E20B313F000E704B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | 2407286F20B313F000E704B8 /* JPG_to_HEIF_Converter.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = JPG_to_HEIF_Converter.entitlements; sourceTree = ""; };
32 | 2407287520B31FF300E704B8 /* JPG to HEIF Converter.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "JPG to HEIF Converter.entitlements"; sourceTree = ""; };
33 | 2407287620B34D5500E704B8 /* MainWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; };
34 | 24F4F3B225836E6C00FF15A9 /* URL+contains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+contains.swift"; sourceTree = ""; };
35 | CD181F4921407A9000D58033 /* UserDefaultsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsManager.swift; sourceTree = ""; };
36 | CDF981C82139FB6500EBC90E /* FileTypeEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTypeEnum.swift; sourceTree = ""; };
37 | /* End PBXFileReference section */
38 |
39 | /* Begin PBXFrameworksBuildPhase section */
40 | 2407285F20B313EE00E704B8 /* Frameworks */ = {
41 | isa = PBXFrameworksBuildPhase;
42 | buildActionMask = 2147483647;
43 | files = (
44 | );
45 | runOnlyForDeploymentPostprocessing = 0;
46 | };
47 | /* End PBXFrameworksBuildPhase section */
48 |
49 | /* Begin PBXGroup section */
50 | 2407285920B313EE00E704B8 = {
51 | isa = PBXGroup;
52 | children = (
53 | 2407286420B313EE00E704B8 /* JPG to HEIF Converter */,
54 | 2407286320B313EE00E704B8 /* Products */,
55 | );
56 | sourceTree = "";
57 | };
58 | 2407286320B313EE00E704B8 /* Products */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 2407286220B313EE00E704B8 /* JPG to HEIF Converter.app */,
62 | );
63 | name = Products;
64 | sourceTree = "";
65 | };
66 | 2407286420B313EE00E704B8 /* JPG to HEIF Converter */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 24F4F3B125836E5C00FF15A9 /* extensions */,
70 | 2429921F232E7C6500477607 /* controllers */,
71 | 24299221232E7CD000477607 /* managers */,
72 | 24299220232E7CC700477607 /* models */,
73 | 2407287520B31FF300E704B8 /* JPG to HEIF Converter.entitlements */,
74 | 2407286F20B313F000E704B8 /* JPG_to_HEIF_Converter.entitlements */,
75 | 2407286E20B313F000E704B8 /* Info.plist */,
76 | 2407286520B313EE00E704B8 /* AppDelegate.swift */,
77 | 2407286920B313F000E704B8 /* Assets.xcassets */,
78 | 047E832420FA3D2400EDD4B0 /* Localizable.strings */,
79 | 2407286B20B313F000E704B8 /* Main.storyboard */,
80 | );
81 | path = "JPG to HEIF Converter";
82 | sourceTree = "";
83 | };
84 | 2429921F232E7C6500477607 /* controllers */ = {
85 | isa = PBXGroup;
86 | children = (
87 | 2407287620B34D5500E704B8 /* MainWindowController.swift */,
88 | 2407286720B313EE00E704B8 /* ViewController.swift */,
89 | );
90 | path = controllers;
91 | sourceTree = "";
92 | };
93 | 24299220232E7CC700477607 /* models */ = {
94 | isa = PBXGroup;
95 | children = (
96 | CDF981C82139FB6500EBC90E /* FileTypeEnum.swift */,
97 | );
98 | path = models;
99 | sourceTree = "";
100 | };
101 | 24299221232E7CD000477607 /* managers */ = {
102 | isa = PBXGroup;
103 | children = (
104 | CD181F4921407A9000D58033 /* UserDefaultsManager.swift */,
105 | );
106 | path = managers;
107 | sourceTree = "";
108 | };
109 | 24F4F3B125836E5C00FF15A9 /* extensions */ = {
110 | isa = PBXGroup;
111 | children = (
112 | 24F4F3B225836E6C00FF15A9 /* URL+contains.swift */,
113 | );
114 | path = extensions;
115 | sourceTree = "";
116 | };
117 | /* End PBXGroup section */
118 |
119 | /* Begin PBXNativeTarget section */
120 | 2407286120B313EE00E704B8 /* JPG to HEIF Converter */ = {
121 | isa = PBXNativeTarget;
122 | buildConfigurationList = 2407287220B313F000E704B8 /* Build configuration list for PBXNativeTarget "JPG to HEIF Converter" */;
123 | buildPhases = (
124 | 2407285E20B313EE00E704B8 /* Sources */,
125 | 2407285F20B313EE00E704B8 /* Frameworks */,
126 | 2407286020B313EE00E704B8 /* Resources */,
127 | );
128 | buildRules = (
129 | );
130 | dependencies = (
131 | );
132 | name = "JPG to HEIF Converter";
133 | productName = "JPG to HEIF Converter";
134 | productReference = 2407286220B313EE00E704B8 /* JPG to HEIF Converter.app */;
135 | productType = "com.apple.product-type.application";
136 | };
137 | /* End PBXNativeTarget section */
138 |
139 | /* Begin PBXProject section */
140 | 2407285A20B313EE00E704B8 /* Project object */ = {
141 | isa = PBXProject;
142 | attributes = {
143 | LastSwiftUpdateCheck = 0930;
144 | LastUpgradeCheck = 1220;
145 | ORGANIZATIONNAME = "Sergey Armodin";
146 | TargetAttributes = {
147 | 2407286120B313EE00E704B8 = {
148 | CreatedOnToolsVersion = 9.3.1;
149 | LastSwiftMigration = 1100;
150 | SystemCapabilities = {
151 | com.apple.Sandbox = {
152 | enabled = 0;
153 | };
154 | };
155 | };
156 | };
157 | };
158 | buildConfigurationList = 2407285D20B313EE00E704B8 /* Build configuration list for PBXProject "JPG to HEIF Converter" */;
159 | compatibilityVersion = "Xcode 9.3";
160 | developmentRegion = en;
161 | hasScannedForEncodings = 0;
162 | knownRegions = (
163 | en,
164 | Base,
165 | tr,
166 | );
167 | mainGroup = 2407285920B313EE00E704B8;
168 | productRefGroup = 2407286320B313EE00E704B8 /* Products */;
169 | projectDirPath = "";
170 | projectRoot = "";
171 | targets = (
172 | 2407286120B313EE00E704B8 /* JPG to HEIF Converter */,
173 | );
174 | };
175 | /* End PBXProject section */
176 |
177 | /* Begin PBXResourcesBuildPhase section */
178 | 2407286020B313EE00E704B8 /* Resources */ = {
179 | isa = PBXResourcesBuildPhase;
180 | buildActionMask = 2147483647;
181 | files = (
182 | 2407286A20B313F000E704B8 /* Assets.xcassets in Resources */,
183 | 047E832220FA3D2400EDD4B0 /* Localizable.strings in Resources */,
184 | 2407286D20B313F000E704B8 /* Main.storyboard in Resources */,
185 | );
186 | runOnlyForDeploymentPostprocessing = 0;
187 | };
188 | /* End PBXResourcesBuildPhase section */
189 |
190 | /* Begin PBXSourcesBuildPhase section */
191 | 2407285E20B313EE00E704B8 /* Sources */ = {
192 | isa = PBXSourcesBuildPhase;
193 | buildActionMask = 2147483647;
194 | files = (
195 | CDF981C92139FB6500EBC90E /* FileTypeEnum.swift in Sources */,
196 | CD181F4A21407A9000D58033 /* UserDefaultsManager.swift in Sources */,
197 | 24F4F3B325836E6C00FF15A9 /* URL+contains.swift in Sources */,
198 | 2407286820B313EE00E704B8 /* ViewController.swift in Sources */,
199 | 2407286620B313EE00E704B8 /* AppDelegate.swift in Sources */,
200 | 2407287720B34D5500E704B8 /* MainWindowController.swift in Sources */,
201 | );
202 | runOnlyForDeploymentPostprocessing = 0;
203 | };
204 | /* End PBXSourcesBuildPhase section */
205 |
206 | /* Begin PBXVariantGroup section */
207 | 047E832420FA3D2400EDD4B0 /* Localizable.strings */ = {
208 | isa = PBXVariantGroup;
209 | children = (
210 | 047E832320FA3D2400EDD4B0 /* en */,
211 | 047E832520FA3D2800EDD4B0 /* tr */,
212 | );
213 | name = Localizable.strings;
214 | sourceTree = "";
215 | };
216 | 2407286B20B313F000E704B8 /* Main.storyboard */ = {
217 | isa = PBXVariantGroup;
218 | children = (
219 | 2407286C20B313F000E704B8 /* Base */,
220 | 047E831F20FA3A7D00EDD4B0 /* tr */,
221 | );
222 | name = Main.storyboard;
223 | sourceTree = "";
224 | };
225 | /* End PBXVariantGroup section */
226 |
227 | /* Begin XCBuildConfiguration section */
228 | 2407287020B313F000E704B8 /* Debug */ = {
229 | isa = XCBuildConfiguration;
230 | buildSettings = {
231 | ALWAYS_SEARCH_USER_PATHS = NO;
232 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
233 | CLANG_ANALYZER_NONNULL = YES;
234 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
235 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
236 | CLANG_CXX_LIBRARY = "libc++";
237 | CLANG_ENABLE_MODULES = YES;
238 | CLANG_ENABLE_OBJC_ARC = YES;
239 | CLANG_ENABLE_OBJC_WEAK = YES;
240 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
241 | CLANG_WARN_BOOL_CONVERSION = YES;
242 | CLANG_WARN_COMMA = YES;
243 | CLANG_WARN_CONSTANT_CONVERSION = YES;
244 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
246 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
247 | CLANG_WARN_EMPTY_BODY = YES;
248 | CLANG_WARN_ENUM_CONVERSION = YES;
249 | CLANG_WARN_INFINITE_RECURSION = YES;
250 | CLANG_WARN_INT_CONVERSION = YES;
251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
252 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
253 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
255 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
256 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
257 | CLANG_WARN_STRICT_PROTOTYPES = YES;
258 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
259 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | CODE_SIGN_IDENTITY = "Mac Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = dwarf;
265 | ENABLE_STRICT_OBJC_MSGSEND = YES;
266 | ENABLE_TESTABILITY = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu11;
268 | GCC_DYNAMIC_NO_PIC = NO;
269 | GCC_NO_COMMON_BLOCKS = YES;
270 | GCC_OPTIMIZATION_LEVEL = 0;
271 | GCC_PREPROCESSOR_DEFINITIONS = (
272 | "DEBUG=1",
273 | "$(inherited)",
274 | );
275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
277 | GCC_WARN_UNDECLARED_SELECTOR = YES;
278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
279 | GCC_WARN_UNUSED_FUNCTION = YES;
280 | GCC_WARN_UNUSED_VARIABLE = YES;
281 | MACOSX_DEPLOYMENT_TARGET = 10.13;
282 | MTL_ENABLE_DEBUG_INFO = YES;
283 | ONLY_ACTIVE_ARCH = YES;
284 | SDKROOT = macosx;
285 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
286 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
287 | };
288 | name = Debug;
289 | };
290 | 2407287120B313F000E704B8 /* Release */ = {
291 | isa = XCBuildConfiguration;
292 | buildSettings = {
293 | ALWAYS_SEARCH_USER_PATHS = NO;
294 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
295 | CLANG_ANALYZER_NONNULL = YES;
296 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
297 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
298 | CLANG_CXX_LIBRARY = "libc++";
299 | CLANG_ENABLE_MODULES = YES;
300 | CLANG_ENABLE_OBJC_ARC = YES;
301 | CLANG_ENABLE_OBJC_WEAK = YES;
302 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
303 | CLANG_WARN_BOOL_CONVERSION = YES;
304 | CLANG_WARN_COMMA = YES;
305 | CLANG_WARN_CONSTANT_CONVERSION = YES;
306 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
307 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
308 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
309 | CLANG_WARN_EMPTY_BODY = YES;
310 | CLANG_WARN_ENUM_CONVERSION = YES;
311 | CLANG_WARN_INFINITE_RECURSION = YES;
312 | CLANG_WARN_INT_CONVERSION = YES;
313 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
314 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
317 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
318 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
319 | CLANG_WARN_STRICT_PROTOTYPES = YES;
320 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
321 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
322 | CLANG_WARN_UNREACHABLE_CODE = YES;
323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
324 | CODE_SIGN_IDENTITY = "Mac Developer";
325 | COPY_PHASE_STRIP = NO;
326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
327 | ENABLE_NS_ASSERTIONS = NO;
328 | ENABLE_STRICT_OBJC_MSGSEND = YES;
329 | GCC_C_LANGUAGE_STANDARD = gnu11;
330 | GCC_NO_COMMON_BLOCKS = YES;
331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
333 | GCC_WARN_UNDECLARED_SELECTOR = YES;
334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
335 | GCC_WARN_UNUSED_FUNCTION = YES;
336 | GCC_WARN_UNUSED_VARIABLE = YES;
337 | MACOSX_DEPLOYMENT_TARGET = 10.13;
338 | MTL_ENABLE_DEBUG_INFO = NO;
339 | SDKROOT = macosx;
340 | SWIFT_COMPILATION_MODE = wholemodule;
341 | SWIFT_OPTIMIZATION_LEVEL = "-O";
342 | };
343 | name = Release;
344 | };
345 | 2407287320B313F000E704B8 /* Debug */ = {
346 | isa = XCBuildConfiguration;
347 | buildSettings = {
348 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
349 | CODE_SIGN_IDENTITY = "-";
350 | CODE_SIGN_STYLE = Automatic;
351 | COMBINE_HIDPI_IMAGES = YES;
352 | CURRENT_PROJECT_VERSION = 8;
353 | DEVELOPMENT_TEAM = 345VKAJA5N;
354 | ENABLE_HARDENED_RUNTIME = YES;
355 | INFOPLIST_FILE = "JPG to HEIF Converter/Info.plist";
356 | LD_RUNPATH_SEARCH_PATHS = (
357 | "$(inherited)",
358 | "@executable_path/../Frameworks",
359 | );
360 | MACOSX_DEPLOYMENT_TARGET = 10.13;
361 | MARKETING_VERSION = 1.07;
362 | PRODUCT_BUNDLE_IDENTIFIER = "me.spaceinbox.JPG-to-HEIF-Converter";
363 | PRODUCT_NAME = "$(TARGET_NAME)";
364 | SWIFT_VERSION = 5.0;
365 | };
366 | name = Debug;
367 | };
368 | 2407287420B313F000E704B8 /* Release */ = {
369 | isa = XCBuildConfiguration;
370 | buildSettings = {
371 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
372 | CODE_SIGN_IDENTITY = "-";
373 | CODE_SIGN_STYLE = Automatic;
374 | COMBINE_HIDPI_IMAGES = YES;
375 | CURRENT_PROJECT_VERSION = 8;
376 | DEVELOPMENT_TEAM = 345VKAJA5N;
377 | ENABLE_HARDENED_RUNTIME = YES;
378 | INFOPLIST_FILE = "JPG to HEIF Converter/Info.plist";
379 | LD_RUNPATH_SEARCH_PATHS = (
380 | "$(inherited)",
381 | "@executable_path/../Frameworks",
382 | );
383 | MACOSX_DEPLOYMENT_TARGET = 10.13;
384 | MARKETING_VERSION = 1.07;
385 | PRODUCT_BUNDLE_IDENTIFIER = "me.spaceinbox.JPG-to-HEIF-Converter";
386 | PRODUCT_NAME = "$(TARGET_NAME)";
387 | SWIFT_VERSION = 5.0;
388 | };
389 | name = Release;
390 | };
391 | /* End XCBuildConfiguration section */
392 |
393 | /* Begin XCConfigurationList section */
394 | 2407285D20B313EE00E704B8 /* Build configuration list for PBXProject "JPG to HEIF Converter" */ = {
395 | isa = XCConfigurationList;
396 | buildConfigurations = (
397 | 2407287020B313F000E704B8 /* Debug */,
398 | 2407287120B313F000E704B8 /* Release */,
399 | );
400 | defaultConfigurationIsVisible = 0;
401 | defaultConfigurationName = Release;
402 | };
403 | 2407287220B313F000E704B8 /* Build configuration list for PBXNativeTarget "JPG to HEIF Converter" */ = {
404 | isa = XCConfigurationList;
405 | buildConfigurations = (
406 | 2407287320B313F000E704B8 /* Debug */,
407 | 2407287420B313F000E704B8 /* Release */,
408 | );
409 | defaultConfigurationIsVisible = 0;
410 | defaultConfigurationName = Release;
411 | };
412 | /* End XCConfigurationList section */
413 | };
414 | rootObject = 2407285A20B313EE00E704B8 /* Project object */;
415 | }
416 |
--------------------------------------------------------------------------------
/JPG to HEIF Converter/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
--------------------------------------------------------------------------------