├── 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 | ![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/makoni/jpg-to-heif-converter/total) 4 | 5 | macOS app for converting from JPG, JPEG and PNG to HEIF (HEIC) 6 | 7 | ![JPG to HEIF converter](https://spaceinbox.me/images/jpg-to-heif-converter2.webp "Screenshot") 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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 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 | --------------------------------------------------------------------------------