├── LICENSE ├── README.md ├── coreml-stable-diffusion-swift-example.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcuserdata │ │ └── igor.xcuserdatad │ │ └── IDEFindNavigatorScopes.plist └── xcuserdata │ └── igor.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── coreml-stable-diffusion-swift-example ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ └── logo.png │ ├── Contents.json │ └── app.imageset │ │ ├── Contents.json │ │ └── app.png ├── ContentView.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── controls │ ├── InputImageView.swift │ ├── Prompts.swift │ └── SlidersView.swift ├── coreml_stable_diffusion_swift_example.entitlements ├── coreml_stable_diffusion_swift_exampleApp.swift ├── enum │ └── LogEvenType.swift ├── helper │ └── HelperTpl.swift ├── model │ └── LogEvent.swift ├── protocol │ └── IEventLoger.swift ├── view │ ├── LoggerTpl.swift │ ├── OutputView.swift │ ├── SideBar.swift │ └── ToolBarContent.swift └── viewmodel │ └── ViewModel.swift ├── coreml-stable-diffusion-swift-exampleTests └── coreml_stable_diffusion_swift_exampleTests.swift ├── coreml-stable-diffusion-swift-exampleUITests ├── coreml_stable_diffusion_swift_exampleUITests.swift └── coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift └── img ├── img_01.png ├── img_03.png └── img_08.gif /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Software Engineer 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoreML stable diffusion image generation example app 2 | ### Please star the repository if you believe continuing the development of this package is worthwhile. This will help me understand which package deserves more effort. 3 | 4 | 5 | ## [Swift package source](https://github.com/swiftuiux/coreml-stable-diffusion-swift) 6 | ## [Documentation(API)](https://swiftpackageindex.com/swiftuiux/coreml-stable-diffusion-swift/main/documentation/coreml_stable_diffusion_swift) 7 | 8 | The example app for running text-to-image or image-to-image models to generate images using [Apple's Core ML Stable Diffusion implementation](https://github.com/apple/ml-stable-diffusion) 9 | 10 | ![The concept](https://github.com/swiftuiux/coreml-stable-diffusion-swift-example/blob/main/img/img_08.gif) 11 | 12 | ## How to get generated image 13 | 14 | ### Step 1 15 | Place at least one of your prepared split_einsum models into the ‘Local Models’ folder. Find the ‘Document’ folder through the interface by tapping on the ‘Local Models’ button. If the folder is empty, then create a folder named ‘models’. Refer to the folders’ hierarchy in the image below for guidance. 16 | The example app supports only ``split_einsum`` models. In terms of performance ``split_einsum`` is the fastest way to get result. 17 | ### Step 2 18 | Pick up the model that was placed at the local folder from the list. Click update button if you added a model while app was launched 19 | ### Step 3 20 | Enter a prompt or pick up a picture and press "Generate" (You don't need to prepare image size manually) It might take up to a minute or two to get the result 21 | 22 | ![The concept](https://github.com/swiftuiux/coreml-stable-diffusion-swift-example/blob/main/img/img_03.png) 23 | 24 | ### Typical set of files for a model und the purpose of each file 25 | 26 | | File Name | Description | 27 | |--------------------------------------|------------------------------------------------------------------| 28 | | `TextEncoder.mlmodelc` | Encodes input text into a vector space for further processing. | 29 | | `Unet.mlmodelc` | Core model handling the transformation of encoded vectors into intermediate image representations. | 30 | | `UnetChunk1.mlmodelc` | First segment of a segmented U-Net model for optimized processing in environments with memory constraints. | 31 | | `UnetChunk2.mlmodelc` | Second segment of the segmented U-Net model, completing the tasks started by the first chunk. | 32 | | `VAEDecoder.mlmodelc` | Decodes the latent representations into final image outputs. | 33 | | `VAEEncoder.mlmodelc` | Compresses input image data into a latent space for reconstruction or further processing. | 34 | | `SafetyChecker.mlmodelc` | Ensures generated content adheres to safety guidelines by checking against predefined criteria. | 35 | | `vocab.json` | Contains the vocabulary used by the text encoder for tokenization and encoding processes. | 36 | | `merges.txt` | Stores the merging rules for byte-pair encoding used in the text encoder. | 37 | 38 | 39 | ## Model set example 40 | [coreml-stable-diffusion-2-base](https://huggingface.co/pcuenq/coreml-stable-diffusion-2-base/blob/main/coreml-stable-diffusion-2-base_split_einsum_compiled.zip ) 41 | 42 | ### Performance 43 | 44 | The speed can be unpredictable. Sometimes a model will suddenly run a lot slower than before. It appears as if Core ML is trying to be smart in how to schedule things, but doesn’t always optimal. 45 | 46 | ### Deploying Transformers on the Apple Neural Engine [Case study](https://machinelearning.apple.com/research/neural-engine-transformers) 47 | 48 | 49 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7867962A2CF73B5600352F7A /* coreml-stable-diffusion-swift in Frameworks */ = {isa = PBXBuildFile; productRef = 786796292CF73B5600352F7A /* coreml-stable-diffusion-swift */; }; 11 | 7883737D2C58FCEC007C71A5 /* img_01.png in Resources */ = {isa = PBXBuildFile; fileRef = 7883737C2C58FCEC007C71A5 /* img_01.png */; }; 12 | 789DF2422A0BA5C9003AEAA3 /* img_08.gif in Resources */ = {isa = PBXBuildFile; fileRef = 789DF2412A0BA5C9003AEAA3 /* img_08.gif */; }; 13 | 789E96BC29CDC71600E7C50A /* coreml_stable_diffusion_swift_exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96BB29CDC71600E7C50A /* coreml_stable_diffusion_swift_exampleApp.swift */; }; 14 | 789E96BE29CDC71600E7C50A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96BD29CDC71600E7C50A /* ContentView.swift */; }; 15 | 789E96C029CDC71700E7C50A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 789E96BF29CDC71700E7C50A /* Assets.xcassets */; }; 16 | 789E96C329CDC71700E7C50A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 789E96C229CDC71700E7C50A /* Preview Assets.xcassets */; }; 17 | 789E96CE29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96CD29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleTests.swift */; }; 18 | 789E96D829CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96D729CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITests.swift */; }; 19 | 789E96DA29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96D929CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift */; }; 20 | 789E96F629CDC7CC00E7C50A /* IEventLoger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96EA29CDC7CC00E7C50A /* IEventLoger.swift */; }; 21 | 789E96F729CDC7CC00E7C50A /* OutputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96EC29CDC7CC00E7C50A /* OutputView.swift */; }; 22 | 789E96F829CDC7CC00E7C50A /* SideBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96ED29CDC7CC00E7C50A /* SideBar.swift */; }; 23 | 789E96F929CDC7CC00E7C50A /* ToolBarContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96EE29CDC7CC00E7C50A /* ToolBarContent.swift */; }; 24 | 789E96FA29CDC7CC00E7C50A /* LoggerTpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96EF29CDC7CC00E7C50A /* LoggerTpl.swift */; }; 25 | 789E96FB29CDC7CC00E7C50A /* Prompts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96F129CDC7CC00E7C50A /* Prompts.swift */; }; 26 | 789E96FC29CDC7CC00E7C50A /* InputImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96F229CDC7CC00E7C50A /* InputImageView.swift */; }; 27 | 789E96FD29CDC7CC00E7C50A /* SlidersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96F329CDC7CC00E7C50A /* SlidersView.swift */; }; 28 | 789E96FE29CDC7CC00E7C50A /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E96F529CDC7CC00E7C50A /* ViewModel.swift */; }; 29 | 789E970529CDC7D300E7C50A /* HelperTpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E970029CDC7D300E7C50A /* HelperTpl.swift */; }; 30 | 789E970629CDC7D300E7C50A /* LogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E970229CDC7D300E7C50A /* LogEvent.swift */; }; 31 | 789E970729CDC7D300E7C50A /* LogEvenType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789E970429CDC7D300E7C50A /* LogEvenType.swift */; }; 32 | 789E970929CDC98700E7C50A /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 789E970829CDC98600E7C50A /* README.md */; }; 33 | 78EEEE6F29DDCAA700EDF91F /* img_03.png in Resources */ = {isa = PBXBuildFile; fileRef = 78EEEE6E29DDCAA700EDF91F /* img_03.png */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXContainerItemProxy section */ 37 | 789E96CA29CDC71700E7C50A /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = 789E96B029CDC71600E7C50A /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = 789E96B729CDC71600E7C50A; 42 | remoteInfo = "coreml-stable-diffusion-swift-example"; 43 | }; 44 | 789E96D429CDC71700E7C50A /* PBXContainerItemProxy */ = { 45 | isa = PBXContainerItemProxy; 46 | containerPortal = 789E96B029CDC71600E7C50A /* Project object */; 47 | proxyType = 1; 48 | remoteGlobalIDString = 789E96B729CDC71600E7C50A; 49 | remoteInfo = "coreml-stable-diffusion-swift-example"; 50 | }; 51 | /* End PBXContainerItemProxy section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 7883737C2C58FCEC007C71A5 /* img_01.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_01.png; sourceTree = ""; }; 55 | 789DF2412A0BA5C9003AEAA3 /* img_08.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = img_08.gif; sourceTree = ""; }; 56 | 789E96B829CDC71600E7C50A /* coreml-stable-diffusion-swift-example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "coreml-stable-diffusion-swift-example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 789E96BB29CDC71600E7C50A /* coreml_stable_diffusion_swift_exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = coreml_stable_diffusion_swift_exampleApp.swift; sourceTree = ""; }; 58 | 789E96BD29CDC71600E7C50A /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 59 | 789E96BF29CDC71700E7C50A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 60 | 789E96C229CDC71700E7C50A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 61 | 789E96C429CDC71700E7C50A /* coreml_stable_diffusion_swift_example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = coreml_stable_diffusion_swift_example.entitlements; sourceTree = ""; }; 62 | 789E96C929CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "coreml-stable-diffusion-swift-exampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 789E96CD29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = coreml_stable_diffusion_swift_exampleTests.swift; sourceTree = ""; }; 64 | 789E96D329CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "coreml-stable-diffusion-swift-exampleUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 789E96D729CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = coreml_stable_diffusion_swift_exampleUITests.swift; sourceTree = ""; }; 66 | 789E96D929CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift; sourceTree = ""; }; 67 | 789E96EA29CDC7CC00E7C50A /* IEventLoger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IEventLoger.swift; sourceTree = ""; }; 68 | 789E96EC29CDC7CC00E7C50A /* OutputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutputView.swift; sourceTree = ""; }; 69 | 789E96ED29CDC7CC00E7C50A /* SideBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideBar.swift; sourceTree = ""; }; 70 | 789E96EE29CDC7CC00E7C50A /* ToolBarContent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolBarContent.swift; sourceTree = ""; }; 71 | 789E96EF29CDC7CC00E7C50A /* LoggerTpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoggerTpl.swift; sourceTree = ""; }; 72 | 789E96F129CDC7CC00E7C50A /* Prompts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prompts.swift; sourceTree = ""; }; 73 | 789E96F229CDC7CC00E7C50A /* InputImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputImageView.swift; sourceTree = ""; }; 74 | 789E96F329CDC7CC00E7C50A /* SlidersView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlidersView.swift; sourceTree = ""; }; 75 | 789E96F529CDC7CC00E7C50A /* ViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = ""; }; 76 | 789E970029CDC7D300E7C50A /* HelperTpl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperTpl.swift; sourceTree = ""; }; 77 | 789E970229CDC7D300E7C50A /* LogEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogEvent.swift; sourceTree = ""; }; 78 | 789E970429CDC7D300E7C50A /* LogEvenType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogEvenType.swift; sourceTree = ""; }; 79 | 789E970829CDC98600E7C50A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 80 | 78EEEE6E29DDCAA700EDF91F /* img_03.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = img_03.png; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 789E96B529CDC71600E7C50A /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | 7867962A2CF73B5600352F7A /* coreml-stable-diffusion-swift in Frameworks */, 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | 789E96C629CDC71700E7C50A /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | 789E96D029CDC71700E7C50A /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXFrameworksBuildPhase section */ 107 | 108 | /* Begin PBXGroup section */ 109 | 785A1A9329FBC89100B677B1 /* Frameworks */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | ); 113 | name = Frameworks; 114 | sourceTree = ""; 115 | }; 116 | 789E96AF29CDC71600E7C50A = { 117 | isa = PBXGroup; 118 | children = ( 119 | 78EEEE6729DDBB1100EDF91F /* img */, 120 | 789E970829CDC98600E7C50A /* README.md */, 121 | 789E96BA29CDC71600E7C50A /* coreml-stable-diffusion-swift-example */, 122 | 789E96CC29CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests */, 123 | 789E96D629CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests */, 124 | 789E96B929CDC71600E7C50A /* Products */, 125 | 785A1A9329FBC89100B677B1 /* Frameworks */, 126 | ); 127 | sourceTree = ""; 128 | }; 129 | 789E96B929CDC71600E7C50A /* Products */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 789E96B829CDC71600E7C50A /* coreml-stable-diffusion-swift-example.app */, 133 | 789E96C929CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests.xctest */, 134 | 789E96D329CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests.xctest */, 135 | ); 136 | name = Products; 137 | sourceTree = ""; 138 | }; 139 | 789E96BA29CDC71600E7C50A /* coreml-stable-diffusion-swift-example */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 789E970329CDC7D300E7C50A /* enum */, 143 | 789E96FF29CDC7D300E7C50A /* helper */, 144 | 789E970129CDC7D300E7C50A /* model */, 145 | 789E96F029CDC7CC00E7C50A /* controls */, 146 | 789E96E929CDC7CC00E7C50A /* protocol */, 147 | 789E96EB29CDC7CC00E7C50A /* view */, 148 | 789E96F429CDC7CC00E7C50A /* viewmodel */, 149 | 789E96BB29CDC71600E7C50A /* coreml_stable_diffusion_swift_exampleApp.swift */, 150 | 789E96BD29CDC71600E7C50A /* ContentView.swift */, 151 | 789E96BF29CDC71700E7C50A /* Assets.xcassets */, 152 | 789E96C429CDC71700E7C50A /* coreml_stable_diffusion_swift_example.entitlements */, 153 | 789E96C129CDC71700E7C50A /* Preview Content */, 154 | ); 155 | path = "coreml-stable-diffusion-swift-example"; 156 | sourceTree = ""; 157 | }; 158 | 789E96C129CDC71700E7C50A /* Preview Content */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 789E96C229CDC71700E7C50A /* Preview Assets.xcassets */, 162 | ); 163 | path = "Preview Content"; 164 | sourceTree = ""; 165 | }; 166 | 789E96CC29CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests */ = { 167 | isa = PBXGroup; 168 | children = ( 169 | 789E96CD29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleTests.swift */, 170 | ); 171 | path = "coreml-stable-diffusion-swift-exampleTests"; 172 | sourceTree = ""; 173 | }; 174 | 789E96D629CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 789E96D729CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITests.swift */, 178 | 789E96D929CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift */, 179 | ); 180 | path = "coreml-stable-diffusion-swift-exampleUITests"; 181 | sourceTree = ""; 182 | }; 183 | 789E96E929CDC7CC00E7C50A /* protocol */ = { 184 | isa = PBXGroup; 185 | children = ( 186 | 789E96EA29CDC7CC00E7C50A /* IEventLoger.swift */, 187 | ); 188 | path = protocol; 189 | sourceTree = ""; 190 | }; 191 | 789E96EB29CDC7CC00E7C50A /* view */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 789E96EC29CDC7CC00E7C50A /* OutputView.swift */, 195 | 789E96ED29CDC7CC00E7C50A /* SideBar.swift */, 196 | 789E96EE29CDC7CC00E7C50A /* ToolBarContent.swift */, 197 | 789E96EF29CDC7CC00E7C50A /* LoggerTpl.swift */, 198 | ); 199 | path = view; 200 | sourceTree = ""; 201 | }; 202 | 789E96F029CDC7CC00E7C50A /* controls */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 789E96F129CDC7CC00E7C50A /* Prompts.swift */, 206 | 789E96F229CDC7CC00E7C50A /* InputImageView.swift */, 207 | 789E96F329CDC7CC00E7C50A /* SlidersView.swift */, 208 | ); 209 | path = controls; 210 | sourceTree = ""; 211 | }; 212 | 789E96F429CDC7CC00E7C50A /* viewmodel */ = { 213 | isa = PBXGroup; 214 | children = ( 215 | 789E96F529CDC7CC00E7C50A /* ViewModel.swift */, 216 | ); 217 | path = viewmodel; 218 | sourceTree = ""; 219 | }; 220 | 789E96FF29CDC7D300E7C50A /* helper */ = { 221 | isa = PBXGroup; 222 | children = ( 223 | 789E970029CDC7D300E7C50A /* HelperTpl.swift */, 224 | ); 225 | path = helper; 226 | sourceTree = ""; 227 | }; 228 | 789E970129CDC7D300E7C50A /* model */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | 789E970229CDC7D300E7C50A /* LogEvent.swift */, 232 | ); 233 | path = model; 234 | sourceTree = ""; 235 | }; 236 | 789E970329CDC7D300E7C50A /* enum */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | 789E970429CDC7D300E7C50A /* LogEvenType.swift */, 240 | ); 241 | path = enum; 242 | sourceTree = ""; 243 | }; 244 | 78EEEE6729DDBB1100EDF91F /* img */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | 789DF2412A0BA5C9003AEAA3 /* img_08.gif */, 248 | 7883737C2C58FCEC007C71A5 /* img_01.png */, 249 | 78EEEE6E29DDCAA700EDF91F /* img_03.png */, 250 | ); 251 | path = img; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXGroup section */ 255 | 256 | /* Begin PBXNativeTarget section */ 257 | 789E96B729CDC71600E7C50A /* coreml-stable-diffusion-swift-example */ = { 258 | isa = PBXNativeTarget; 259 | buildConfigurationList = 789E96DD29CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-example" */; 260 | buildPhases = ( 261 | 789E96B429CDC71600E7C50A /* Sources */, 262 | 789E96B529CDC71600E7C50A /* Frameworks */, 263 | 789E96B629CDC71600E7C50A /* Resources */, 264 | ); 265 | buildRules = ( 266 | ); 267 | dependencies = ( 268 | ); 269 | name = "coreml-stable-diffusion-swift-example"; 270 | packageProductDependencies = ( 271 | 786796292CF73B5600352F7A /* coreml-stable-diffusion-swift */, 272 | ); 273 | productName = "coreml-stable-diffusion-swift-example"; 274 | productReference = 789E96B829CDC71600E7C50A /* coreml-stable-diffusion-swift-example.app */; 275 | productType = "com.apple.product-type.application"; 276 | }; 277 | 789E96C829CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests */ = { 278 | isa = PBXNativeTarget; 279 | buildConfigurationList = 789E96E029CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-exampleTests" */; 280 | buildPhases = ( 281 | 789E96C529CDC71700E7C50A /* Sources */, 282 | 789E96C629CDC71700E7C50A /* Frameworks */, 283 | 789E96C729CDC71700E7C50A /* Resources */, 284 | ); 285 | buildRules = ( 286 | ); 287 | dependencies = ( 288 | 789E96CB29CDC71700E7C50A /* PBXTargetDependency */, 289 | ); 290 | name = "coreml-stable-diffusion-swift-exampleTests"; 291 | productName = "coreml-stable-diffusion-swift-exampleTests"; 292 | productReference = 789E96C929CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests.xctest */; 293 | productType = "com.apple.product-type.bundle.unit-test"; 294 | }; 295 | 789E96D229CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests */ = { 296 | isa = PBXNativeTarget; 297 | buildConfigurationList = 789E96E329CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-exampleUITests" */; 298 | buildPhases = ( 299 | 789E96CF29CDC71700E7C50A /* Sources */, 300 | 789E96D029CDC71700E7C50A /* Frameworks */, 301 | 789E96D129CDC71700E7C50A /* Resources */, 302 | ); 303 | buildRules = ( 304 | ); 305 | dependencies = ( 306 | 789E96D529CDC71700E7C50A /* PBXTargetDependency */, 307 | ); 308 | name = "coreml-stable-diffusion-swift-exampleUITests"; 309 | productName = "coreml-stable-diffusion-swift-exampleUITests"; 310 | productReference = 789E96D329CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests.xctest */; 311 | productType = "com.apple.product-type.bundle.ui-testing"; 312 | }; 313 | /* End PBXNativeTarget section */ 314 | 315 | /* Begin PBXProject section */ 316 | 789E96B029CDC71600E7C50A /* Project object */ = { 317 | isa = PBXProject; 318 | attributes = { 319 | BuildIndependentTargetsInParallel = 1; 320 | LastSwiftUpdateCheck = 1420; 321 | LastUpgradeCheck = 1430; 322 | TargetAttributes = { 323 | 789E96B729CDC71600E7C50A = { 324 | CreatedOnToolsVersion = 14.2; 325 | }; 326 | 789E96C829CDC71700E7C50A = { 327 | CreatedOnToolsVersion = 14.2; 328 | TestTargetID = 789E96B729CDC71600E7C50A; 329 | }; 330 | 789E96D229CDC71700E7C50A = { 331 | CreatedOnToolsVersion = 14.2; 332 | TestTargetID = 789E96B729CDC71600E7C50A; 333 | }; 334 | }; 335 | }; 336 | buildConfigurationList = 789E96B329CDC71600E7C50A /* Build configuration list for PBXProject "coreml-stable-diffusion-swift-example" */; 337 | compatibilityVersion = "Xcode 14.0"; 338 | developmentRegion = en; 339 | hasScannedForEncodings = 0; 340 | knownRegions = ( 341 | en, 342 | Base, 343 | ); 344 | mainGroup = 789E96AF29CDC71600E7C50A; 345 | packageReferences = ( 346 | 786796282CF73AFB00352F7A /* XCRemoteSwiftPackageReference "coreml-stable-diffusion-swift" */, 347 | ); 348 | productRefGroup = 789E96B929CDC71600E7C50A /* Products */; 349 | projectDirPath = ""; 350 | projectRoot = ""; 351 | targets = ( 352 | 789E96B729CDC71600E7C50A /* coreml-stable-diffusion-swift-example */, 353 | 789E96C829CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleTests */, 354 | 789E96D229CDC71700E7C50A /* coreml-stable-diffusion-swift-exampleUITests */, 355 | ); 356 | }; 357 | /* End PBXProject section */ 358 | 359 | /* Begin PBXResourcesBuildPhase section */ 360 | 789E96B629CDC71600E7C50A /* Resources */ = { 361 | isa = PBXResourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 789E970929CDC98700E7C50A /* README.md in Resources */, 365 | 78EEEE6F29DDCAA700EDF91F /* img_03.png in Resources */, 366 | 789DF2422A0BA5C9003AEAA3 /* img_08.gif in Resources */, 367 | 789E96C329CDC71700E7C50A /* Preview Assets.xcassets in Resources */, 368 | 7883737D2C58FCEC007C71A5 /* img_01.png in Resources */, 369 | 789E96C029CDC71700E7C50A /* Assets.xcassets in Resources */, 370 | ); 371 | runOnlyForDeploymentPostprocessing = 0; 372 | }; 373 | 789E96C729CDC71700E7C50A /* Resources */ = { 374 | isa = PBXResourcesBuildPhase; 375 | buildActionMask = 2147483647; 376 | files = ( 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | }; 380 | 789E96D129CDC71700E7C50A /* Resources */ = { 381 | isa = PBXResourcesBuildPhase; 382 | buildActionMask = 2147483647; 383 | files = ( 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | }; 387 | /* End PBXResourcesBuildPhase section */ 388 | 389 | /* Begin PBXSourcesBuildPhase section */ 390 | 789E96B429CDC71600E7C50A /* Sources */ = { 391 | isa = PBXSourcesBuildPhase; 392 | buildActionMask = 2147483647; 393 | files = ( 394 | 789E96FA29CDC7CC00E7C50A /* LoggerTpl.swift in Sources */, 395 | 789E96FD29CDC7CC00E7C50A /* SlidersView.swift in Sources */, 396 | 789E96F829CDC7CC00E7C50A /* SideBar.swift in Sources */, 397 | 789E970629CDC7D300E7C50A /* LogEvent.swift in Sources */, 398 | 789E96FE29CDC7CC00E7C50A /* ViewModel.swift in Sources */, 399 | 789E96F929CDC7CC00E7C50A /* ToolBarContent.swift in Sources */, 400 | 789E96BE29CDC71600E7C50A /* ContentView.swift in Sources */, 401 | 789E96F629CDC7CC00E7C50A /* IEventLoger.swift in Sources */, 402 | 789E96FB29CDC7CC00E7C50A /* Prompts.swift in Sources */, 403 | 789E96BC29CDC71600E7C50A /* coreml_stable_diffusion_swift_exampleApp.swift in Sources */, 404 | 789E970729CDC7D300E7C50A /* LogEvenType.swift in Sources */, 405 | 789E96F729CDC7CC00E7C50A /* OutputView.swift in Sources */, 406 | 789E970529CDC7D300E7C50A /* HelperTpl.swift in Sources */, 407 | 789E96FC29CDC7CC00E7C50A /* InputImageView.swift in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | 789E96C529CDC71700E7C50A /* Sources */ = { 412 | isa = PBXSourcesBuildPhase; 413 | buildActionMask = 2147483647; 414 | files = ( 415 | 789E96CE29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleTests.swift in Sources */, 416 | ); 417 | runOnlyForDeploymentPostprocessing = 0; 418 | }; 419 | 789E96CF29CDC71700E7C50A /* Sources */ = { 420 | isa = PBXSourcesBuildPhase; 421 | buildActionMask = 2147483647; 422 | files = ( 423 | 789E96DA29CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift in Sources */, 424 | 789E96D829CDC71700E7C50A /* coreml_stable_diffusion_swift_exampleUITests.swift in Sources */, 425 | ); 426 | runOnlyForDeploymentPostprocessing = 0; 427 | }; 428 | /* End PBXSourcesBuildPhase section */ 429 | 430 | /* Begin PBXTargetDependency section */ 431 | 789E96CB29CDC71700E7C50A /* PBXTargetDependency */ = { 432 | isa = PBXTargetDependency; 433 | target = 789E96B729CDC71600E7C50A /* coreml-stable-diffusion-swift-example */; 434 | targetProxy = 789E96CA29CDC71700E7C50A /* PBXContainerItemProxy */; 435 | }; 436 | 789E96D529CDC71700E7C50A /* PBXTargetDependency */ = { 437 | isa = PBXTargetDependency; 438 | target = 789E96B729CDC71600E7C50A /* coreml-stable-diffusion-swift-example */; 439 | targetProxy = 789E96D429CDC71700E7C50A /* PBXContainerItemProxy */; 440 | }; 441 | /* End PBXTargetDependency section */ 442 | 443 | /* Begin XCBuildConfiguration section */ 444 | 789E96DB29CDC71700E7C50A /* Debug */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ALWAYS_SEARCH_USER_PATHS = NO; 448 | CLANG_ANALYZER_NONNULL = YES; 449 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 450 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 451 | CLANG_ENABLE_MODULES = YES; 452 | CLANG_ENABLE_OBJC_ARC = YES; 453 | CLANG_ENABLE_OBJC_WEAK = YES; 454 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 455 | CLANG_WARN_BOOL_CONVERSION = YES; 456 | CLANG_WARN_COMMA = YES; 457 | CLANG_WARN_CONSTANT_CONVERSION = YES; 458 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 459 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 460 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 461 | CLANG_WARN_EMPTY_BODY = YES; 462 | CLANG_WARN_ENUM_CONVERSION = YES; 463 | CLANG_WARN_INFINITE_RECURSION = YES; 464 | CLANG_WARN_INT_CONVERSION = YES; 465 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 466 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 467 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 468 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 469 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 470 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 471 | CLANG_WARN_STRICT_PROTOTYPES = YES; 472 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 473 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 474 | CLANG_WARN_UNREACHABLE_CODE = YES; 475 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 476 | COPY_PHASE_STRIP = NO; 477 | DEAD_CODE_STRIPPING = YES; 478 | DEBUG_INFORMATION_FORMAT = dwarf; 479 | ENABLE_STRICT_OBJC_MSGSEND = YES; 480 | ENABLE_TESTABILITY = YES; 481 | GCC_C_LANGUAGE_STANDARD = gnu11; 482 | GCC_DYNAMIC_NO_PIC = NO; 483 | GCC_NO_COMMON_BLOCKS = YES; 484 | GCC_OPTIMIZATION_LEVEL = 0; 485 | GCC_PREPROCESSOR_DEFINITIONS = ( 486 | "DEBUG=1", 487 | "$(inherited)", 488 | ); 489 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 490 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 491 | GCC_WARN_UNDECLARED_SELECTOR = YES; 492 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 493 | GCC_WARN_UNUSED_FUNCTION = YES; 494 | GCC_WARN_UNUSED_VARIABLE = YES; 495 | MACOSX_DEPLOYMENT_TARGET = 14.0; 496 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 497 | MTL_FAST_MATH = YES; 498 | ONLY_ACTIVE_ARCH = YES; 499 | SDKROOT = macosx; 500 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 501 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 502 | }; 503 | name = Debug; 504 | }; 505 | 789E96DC29CDC71700E7C50A /* Release */ = { 506 | isa = XCBuildConfiguration; 507 | buildSettings = { 508 | ALWAYS_SEARCH_USER_PATHS = NO; 509 | CLANG_ANALYZER_NONNULL = YES; 510 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 511 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 512 | CLANG_ENABLE_MODULES = YES; 513 | CLANG_ENABLE_OBJC_ARC = YES; 514 | CLANG_ENABLE_OBJC_WEAK = YES; 515 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 516 | CLANG_WARN_BOOL_CONVERSION = YES; 517 | CLANG_WARN_COMMA = YES; 518 | CLANG_WARN_CONSTANT_CONVERSION = YES; 519 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 520 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 521 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 522 | CLANG_WARN_EMPTY_BODY = YES; 523 | CLANG_WARN_ENUM_CONVERSION = YES; 524 | CLANG_WARN_INFINITE_RECURSION = YES; 525 | CLANG_WARN_INT_CONVERSION = YES; 526 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 527 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 528 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 529 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 530 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 531 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 532 | CLANG_WARN_STRICT_PROTOTYPES = YES; 533 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 534 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 535 | CLANG_WARN_UNREACHABLE_CODE = YES; 536 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 537 | COPY_PHASE_STRIP = NO; 538 | DEAD_CODE_STRIPPING = YES; 539 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 540 | ENABLE_NS_ASSERTIONS = NO; 541 | ENABLE_STRICT_OBJC_MSGSEND = YES; 542 | GCC_C_LANGUAGE_STANDARD = gnu11; 543 | GCC_NO_COMMON_BLOCKS = YES; 544 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 545 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 546 | GCC_WARN_UNDECLARED_SELECTOR = YES; 547 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 548 | GCC_WARN_UNUSED_FUNCTION = YES; 549 | GCC_WARN_UNUSED_VARIABLE = YES; 550 | MACOSX_DEPLOYMENT_TARGET = 14.0; 551 | MTL_ENABLE_DEBUG_INFO = NO; 552 | MTL_FAST_MATH = YES; 553 | SDKROOT = macosx; 554 | SWIFT_COMPILATION_MODE = wholemodule; 555 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 556 | }; 557 | name = Release; 558 | }; 559 | 789E96DE29CDC71700E7C50A /* Debug */ = { 560 | isa = XCBuildConfiguration; 561 | buildSettings = { 562 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 563 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 564 | CODE_SIGN_ENTITLEMENTS = "coreml-stable-diffusion-swift-example/coreml_stable_diffusion_swift_example.entitlements"; 565 | CODE_SIGN_IDENTITY = "Apple Development"; 566 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 567 | CODE_SIGN_STYLE = Manual; 568 | COMBINE_HIDPI_IMAGES = YES; 569 | CURRENT_PROJECT_VERSION = 1; 570 | DEAD_CODE_STRIPPING = YES; 571 | DEVELOPMENT_ASSET_PATHS = "\"coreml-stable-diffusion-swift-example/Preview Content\""; 572 | DEVELOPMENT_TEAM = ""; 573 | "DEVELOPMENT_TEAM[sdk=macosx*]" = FZ42RW4USG; 574 | ENABLE_HARDENED_RUNTIME = YES; 575 | ENABLE_PREVIEWS = YES; 576 | GENERATE_INFOPLIST_FILE = YES; 577 | INFOPLIST_KEY_CFBundleDisplayName = "CoreML stable diffusion image generation"; 578 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 579 | LD_RUNPATH_SEARCH_PATHS = ( 580 | "$(inherited)", 581 | "@executable_path/../Frameworks", 582 | ); 583 | MACOSX_DEPLOYMENT_TARGET = 14.0; 584 | MARKETING_VERSION = 1.0; 585 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.coreml-stable-diffusion-swift-example"; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | PROVISIONING_PROFILE_SPECIFIER = ""; 588 | SWIFT_EMIT_LOC_STRINGS = YES; 589 | SWIFT_VERSION = 5.0; 590 | }; 591 | name = Debug; 592 | }; 593 | 789E96DF29CDC71700E7C50A /* Release */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 597 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 598 | CODE_SIGN_ENTITLEMENTS = "coreml-stable-diffusion-swift-example/coreml_stable_diffusion_swift_example.entitlements"; 599 | CODE_SIGN_IDENTITY = "Apple Development"; 600 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; 601 | CODE_SIGN_STYLE = Manual; 602 | COMBINE_HIDPI_IMAGES = YES; 603 | CURRENT_PROJECT_VERSION = 1; 604 | DEAD_CODE_STRIPPING = YES; 605 | DEVELOPMENT_ASSET_PATHS = "\"coreml-stable-diffusion-swift-example/Preview Content\""; 606 | DEVELOPMENT_TEAM = ""; 607 | "DEVELOPMENT_TEAM[sdk=macosx*]" = FZ42RW4USG; 608 | ENABLE_HARDENED_RUNTIME = YES; 609 | ENABLE_PREVIEWS = YES; 610 | GENERATE_INFOPLIST_FILE = YES; 611 | INFOPLIST_KEY_CFBundleDisplayName = "CoreML stable diffusion image generation"; 612 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 613 | LD_RUNPATH_SEARCH_PATHS = ( 614 | "$(inherited)", 615 | "@executable_path/../Frameworks", 616 | ); 617 | MACOSX_DEPLOYMENT_TARGET = 14.0; 618 | MARKETING_VERSION = 1.0; 619 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.coreml-stable-diffusion-swift-example"; 620 | PRODUCT_NAME = "$(TARGET_NAME)"; 621 | PROVISIONING_PROFILE_SPECIFIER = ""; 622 | SWIFT_EMIT_LOC_STRINGS = YES; 623 | SWIFT_VERSION = 5.0; 624 | }; 625 | name = Release; 626 | }; 627 | 789E96E129CDC71700E7C50A /* Debug */ = { 628 | isa = XCBuildConfiguration; 629 | buildSettings = { 630 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 631 | BUNDLE_LOADER = "$(TEST_HOST)"; 632 | CODE_SIGN_STYLE = Automatic; 633 | CURRENT_PROJECT_VERSION = 1; 634 | DEAD_CODE_STRIPPING = YES; 635 | DEVELOPMENT_TEAM = FZ42RW4USG; 636 | GENERATE_INFOPLIST_FILE = YES; 637 | MACOSX_DEPLOYMENT_TARGET = 13.1; 638 | MARKETING_VERSION = 1.0; 639 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.igorshell.coreml-stable-diffusion-swift-exampleTests"; 640 | PRODUCT_NAME = "$(TARGET_NAME)"; 641 | SWIFT_EMIT_LOC_STRINGS = NO; 642 | SWIFT_VERSION = 5.0; 643 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/coreml-stable-diffusion-swift-example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/coreml-stable-diffusion-swift-example"; 644 | }; 645 | name = Debug; 646 | }; 647 | 789E96E229CDC71700E7C50A /* Release */ = { 648 | isa = XCBuildConfiguration; 649 | buildSettings = { 650 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 651 | BUNDLE_LOADER = "$(TEST_HOST)"; 652 | CODE_SIGN_STYLE = Automatic; 653 | CURRENT_PROJECT_VERSION = 1; 654 | DEAD_CODE_STRIPPING = YES; 655 | DEVELOPMENT_TEAM = FZ42RW4USG; 656 | GENERATE_INFOPLIST_FILE = YES; 657 | MACOSX_DEPLOYMENT_TARGET = 13.1; 658 | MARKETING_VERSION = 1.0; 659 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.igorshell.coreml-stable-diffusion-swift-exampleTests"; 660 | PRODUCT_NAME = "$(TARGET_NAME)"; 661 | SWIFT_EMIT_LOC_STRINGS = NO; 662 | SWIFT_VERSION = 5.0; 663 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/coreml-stable-diffusion-swift-example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/coreml-stable-diffusion-swift-example"; 664 | }; 665 | name = Release; 666 | }; 667 | 789E96E429CDC71700E7C50A /* Debug */ = { 668 | isa = XCBuildConfiguration; 669 | buildSettings = { 670 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 671 | CODE_SIGN_STYLE = Automatic; 672 | CURRENT_PROJECT_VERSION = 1; 673 | DEAD_CODE_STRIPPING = YES; 674 | DEVELOPMENT_TEAM = FZ42RW4USG; 675 | GENERATE_INFOPLIST_FILE = YES; 676 | MARKETING_VERSION = 1.0; 677 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.igorshell.coreml-stable-diffusion-swift-exampleUITests"; 678 | PRODUCT_NAME = "$(TARGET_NAME)"; 679 | SWIFT_EMIT_LOC_STRINGS = NO; 680 | SWIFT_VERSION = 5.0; 681 | TEST_TARGET_NAME = "coreml-stable-diffusion-swift-example"; 682 | }; 683 | name = Debug; 684 | }; 685 | 789E96E529CDC71700E7C50A /* Release */ = { 686 | isa = XCBuildConfiguration; 687 | buildSettings = { 688 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 689 | CODE_SIGN_STYLE = Automatic; 690 | CURRENT_PROJECT_VERSION = 1; 691 | DEAD_CODE_STRIPPING = YES; 692 | DEVELOPMENT_TEAM = FZ42RW4USG; 693 | GENERATE_INFOPLIST_FILE = YES; 694 | MARKETING_VERSION = 1.0; 695 | PRODUCT_BUNDLE_IDENTIFIER = "stable.diffusion.swift.igorshell.coreml-stable-diffusion-swift-exampleUITests"; 696 | PRODUCT_NAME = "$(TARGET_NAME)"; 697 | SWIFT_EMIT_LOC_STRINGS = NO; 698 | SWIFT_VERSION = 5.0; 699 | TEST_TARGET_NAME = "coreml-stable-diffusion-swift-example"; 700 | }; 701 | name = Release; 702 | }; 703 | /* End XCBuildConfiguration section */ 704 | 705 | /* Begin XCConfigurationList section */ 706 | 789E96B329CDC71600E7C50A /* Build configuration list for PBXProject "coreml-stable-diffusion-swift-example" */ = { 707 | isa = XCConfigurationList; 708 | buildConfigurations = ( 709 | 789E96DB29CDC71700E7C50A /* Debug */, 710 | 789E96DC29CDC71700E7C50A /* Release */, 711 | ); 712 | defaultConfigurationIsVisible = 0; 713 | defaultConfigurationName = Release; 714 | }; 715 | 789E96DD29CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-example" */ = { 716 | isa = XCConfigurationList; 717 | buildConfigurations = ( 718 | 789E96DE29CDC71700E7C50A /* Debug */, 719 | 789E96DF29CDC71700E7C50A /* Release */, 720 | ); 721 | defaultConfigurationIsVisible = 0; 722 | defaultConfigurationName = Release; 723 | }; 724 | 789E96E029CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-exampleTests" */ = { 725 | isa = XCConfigurationList; 726 | buildConfigurations = ( 727 | 789E96E129CDC71700E7C50A /* Debug */, 728 | 789E96E229CDC71700E7C50A /* Release */, 729 | ); 730 | defaultConfigurationIsVisible = 0; 731 | defaultConfigurationName = Release; 732 | }; 733 | 789E96E329CDC71700E7C50A /* Build configuration list for PBXNativeTarget "coreml-stable-diffusion-swift-exampleUITests" */ = { 734 | isa = XCConfigurationList; 735 | buildConfigurations = ( 736 | 789E96E429CDC71700E7C50A /* Debug */, 737 | 789E96E529CDC71700E7C50A /* Release */, 738 | ); 739 | defaultConfigurationIsVisible = 0; 740 | defaultConfigurationName = Release; 741 | }; 742 | /* End XCConfigurationList section */ 743 | 744 | /* Begin XCRemoteSwiftPackageReference section */ 745 | 786796282CF73AFB00352F7A /* XCRemoteSwiftPackageReference "coreml-stable-diffusion-swift" */ = { 746 | isa = XCRemoteSwiftPackageReference; 747 | repositoryURL = "https://github.com/swiftuiux/coreml-stable-diffusion-swift"; 748 | requirement = { 749 | branch = main; 750 | kind = branch; 751 | }; 752 | }; 753 | /* End XCRemoteSwiftPackageReference section */ 754 | 755 | /* Begin XCSwiftPackageProductDependency section */ 756 | 786796292CF73B5600352F7A /* coreml-stable-diffusion-swift */ = { 757 | isa = XCSwiftPackageProductDependency; 758 | package = 786796282CF73AFB00352F7A /* XCRemoteSwiftPackageReference "coreml-stable-diffusion-swift" */; 759 | productName = "coreml-stable-diffusion-swift"; 760 | }; 761 | /* End XCSwiftPackageProductDependency section */ 762 | }; 763 | rootObject = 789E96B029CDC71600E7C50A /* Project object */; 764 | } 765 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "6f95daad4d90f4f6a78fbfcd4a60f14c03ce9dcf239de02f0db6f75ac3dc1d81", 3 | "pins" : [ 4 | { 5 | "identity" : "coreml-stable-diffusion-swift", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/swiftuiux/coreml-stable-diffusion-swift", 8 | "state" : { 9 | "branch" : "main", 10 | "revision" : "602143c71202f99c152f4e740227ae0e2e34126f" 11 | } 12 | }, 13 | { 14 | "identity" : "files", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/JohnSundell/Files.git", 17 | "state" : { 18 | "revision" : "d273b5b7025d386feef79ef6bad7de762e106eaf", 19 | "version" : "4.2.0" 20 | } 21 | }, 22 | { 23 | "identity" : "ml-stable-diffusion", 24 | "kind" : "remoteSourceControl", 25 | "location" : "https://github.com/apple/ml-stable-diffusion.git", 26 | "state" : { 27 | "revision" : "5a170d29cf38e674b80541d7ce22929c6a11cdde", 28 | "version" : "1.1.1" 29 | } 30 | }, 31 | { 32 | "identity" : "swift-argument-parser", 33 | "kind" : "remoteSourceControl", 34 | "location" : "https://github.com/apple/swift-argument-parser.git", 35 | "state" : { 36 | "revision" : "41982a3656a71c768319979febd796c6fd111d5c", 37 | "version" : "1.5.0" 38 | } 39 | } 40 | ], 41 | "version" : 3 42 | } 43 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/project.xcworkspace/xcuserdata/igor.xcuserdatad/IDEFindNavigatorScopes.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/xcuserdata/igor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example.xcodeproj/xcuserdata/igor.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | coreml-stable-diffusion-swift-example.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "scale" : "1x", 6 | "size" : "16x16" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "scale" : "2x", 11 | "size" : "16x16" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "scale" : "1x", 16 | "size" : "32x32" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "scale" : "2x", 21 | "size" : "32x32" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "scale" : "1x", 26 | "size" : "128x128" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "scale" : "2x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "scale" : "1x", 36 | "size" : "256x256" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "scale" : "2x", 41 | "size" : "256x256" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "scale" : "1x", 46 | "size" : "512x512" 47 | }, 48 | { 49 | "filename" : "logo.png", 50 | "idiom" : "mac", 51 | "scale" : "2x", 52 | "size" : "512x512" 53 | } 54 | ], 55 | "info" : { 56 | "author" : "xcode", 57 | "version" : 1 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/AppIcon.appiconset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftuiux/coreml-stable-diffusion-swift-example/610d13285ccff9ad4bfb5436beb1bb2605b721df/coreml-stable-diffusion-swift-example/Assets.xcassets/AppIcon.appiconset/logo.png -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/app.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "app.png", 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 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Assets.xcassets/app.imageset/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftuiux/coreml-stable-diffusion-swift-example/610d13285ccff9ad4bfb5436beb1bb2605b721df/coreml-stable-diffusion-swift-example/Assets.xcassets/app.imageset/app.png -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | 11 | @available(macOS 13.1, *) 12 | struct ContentView: View { 13 | 14 | // MARK: - Life circle 15 | 16 | /// The type of view representing the body of this view. 17 | var body: some View { 18 | NavigationSplitView{ 19 | SideBar() 20 | } 21 | detail: { 22 | HStack(spacing: 0){ 23 | OutputView().frame(maxWidth: .infinity, maxHeight: .infinity) 24 | Divider() 25 | LoggerTpl().frame(width: 302) 26 | } 27 | } 28 | .navigationSplitViewStyle(.balanced) 29 | .toolbar{ 30 | ToolbarItemGroup{ 31 | ToolBarContent() 32 | } 33 | } 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/controls/InputImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputImageView.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import PhotosUI 10 | import coreml_stable_diffusion_swift 11 | 12 | @available(macOS 13.1, *) 13 | struct InputImageView: View { 14 | 15 | @EnvironmentObject var model : ViewModel 16 | 17 | @State private var selectedItem: PhotosPickerItem? 18 | 19 | @State private var image : Image? = nil 20 | 21 | @State private var imageSize : CGSize? = nil 22 | 23 | @State private var task : Task<(), Never>? 24 | 25 | // MARK: - Life circle 26 | 27 | /// The type of view representing the body of this view. 28 | var body: some View { 29 | VStack(alignment: .center, spacing: 5){ 30 | textTpl(for: imageSize) 31 | Rectangle().stroke(Color.gray, lineWidth: 0.5) 32 | .overlay(imageTpl) 33 | .overlay(cleanTpl, alignment: .bottomTrailing) 34 | .frame(height: 128) 35 | PhotosPicker( 36 | selection: $selectedItem, 37 | matching: .images 38 | ) { 39 | Text("Select a Photo") 40 | } 41 | .onChange(of: selectedItem) { _ in 42 | task = onChange() 43 | } 44 | } 45 | .onDisappear{ 46 | cancelTask() 47 | } 48 | } 49 | 50 | // MARK: - Private 51 | 52 | @ViewBuilder 53 | private func textTpl(for size: CGSize?) -> some View { 54 | if let size{ 55 | let roundedWidth = size.width.rounded() 56 | let roundedHeight = size.height.rounded() 57 | Rectangle().opacity(0.1).frame(height: 25) 58 | .overlay{ 59 | Text("Width: \(Int(roundedWidth)), Height: \(Int(roundedHeight))") 60 | } 61 | }else{ 62 | Rectangle().opacity(0.1).frame(height: 25) 63 | } 64 | } 65 | 66 | @ViewBuilder 67 | private var cleanTpl : some View{ 68 | Button{ 69 | model.inputImage = nil 70 | image = nil 71 | imageSize = nil 72 | }label: { 73 | Image(systemName: "x.circle") 74 | .font(.system(size: 14)) 75 | }.padding(.trailing, 5) 76 | .padding(.bottom, 5) 77 | .disabled(image == nil) 78 | } 79 | 80 | @ViewBuilder 81 | private var imageTpl : some View{ 82 | if let image{ 83 | image 84 | .resizable() 85 | .scaledToFit() 86 | .frame(height: 128) 87 | }else{ 88 | emptyImageTpl(height: 64) 89 | } 90 | } 91 | 92 | private func cancelTask(){ 93 | task?.cancel() 94 | } 95 | 96 | @MainActor 97 | private func update( image : NSImage?){ 98 | if let nsImage = image{ 99 | imageSize = nsImage.size 100 | model.outputImage = nil 101 | model.inputImage = nsImage.CGImage 102 | self.image = Image(nsImage: nsImage) 103 | }else{ 104 | model.addToEventLog("Could not prepare image", type: .error) 105 | } 106 | } 107 | 108 | @MainActor 109 | private func onChange() -> Task<(), Never>{ 110 | Task { 111 | if let data = try? await selectedItem?.loadTransferable(type: Data.self) { 112 | let nsImage = await getNSImage(from : data) 113 | update(image: nsImage) 114 | } 115 | } 116 | } 117 | } 118 | 119 | extension NSImage: @unchecked Sendable {} 120 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/controls/Prompts.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Prompts.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @available(macOS 13.1, *) 11 | /// Prompts controls 12 | struct Prompts: View { 13 | 14 | @EnvironmentObject var model : ViewModel 15 | 16 | /// The placement of focus within the scene changes. 17 | @FocusState private var focused: Bool 18 | 19 | // MARK: - Life circle 20 | 21 | /// The type of view representing the body of this view. 22 | var body: some View { 23 | VStack(alignment: .leading){ 24 | Text("Prompt".uppercased()) 25 | TextEditor(text: $model.prompt) 26 | .font(.body) 27 | .focused($focused) 28 | .frame(height: 68) 29 | .border(Color(nsColor: .gridColor)) 30 | .cornerRadius(4) 31 | 32 | Text("Negative prompt".uppercased()) 33 | TextEditor(text: $model.negativePrompt) 34 | .font(.body) 35 | .frame(height: 68) 36 | .border(Color(nsColor: .gridColor)) 37 | .cornerRadius(4) 38 | 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/controls/SlidersView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlidersView.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @available(macOS 13.1, *) 11 | struct SlidersView: View { 12 | 13 | @EnvironmentObject var model : ViewModel 14 | 15 | // MARK: - Life circle 16 | 17 | /// The type of view representing the body of this view. 18 | var body: some View { 19 | VStack(alignment: .leading, spacing: 20){ 20 | let guidance = String(format: "Guidance scale: %.1f", model.guidanceScale).uppercased() 21 | Text(guidance) 22 | Slider(value: $model.guidanceScale, in: 1...20, step: 0.5) 23 | { 24 | EmptyView() 25 | } minimumValueLabel: { 26 | Text("1") 27 | } maximumValueLabel: { 28 | Text("20") 29 | }.controlSize(.mini) 30 | 31 | let steps = String(format: "Steps: %.0f", model.stepCount).uppercased() 32 | Text(steps) 33 | Slider(value: $model.stepCount, in: 1...25, step: 1) 34 | { 35 | EmptyView() 36 | } minimumValueLabel: { 37 | Text("1") 38 | } maximumValueLabel: { 39 | Text("25") 40 | }.controlSize(.large) 41 | 42 | let strength = String(format: "Strength: %.1f", model.strength).uppercased() 43 | Text(strength) 44 | Slider(value: $model.strength, in: 0.1...1, step: 0.1) 45 | { 46 | EmptyView() 47 | 48 | } minimumValueLabel: { 49 | Text("0.1") 50 | } maximumValueLabel: { 51 | Text("1") 52 | }.controlSize(.mini) 53 | } 54 | } 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/coreml_stable_diffusion_swift_example.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/coreml_stable_diffusion_swift_exampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // coreml_stable_diffusion_swift_exampleApp.swift 3 | // coreml-stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import coreml_stable_diffusion_swift 10 | 11 | @main 12 | struct coreml_stable_diffusion_swift_exampleApp: App { 13 | 14 | /// Main view model managing process of generating images 15 | @StateObject var model = ViewModel(manager: GenerativeManager()) 16 | 17 | /// The type of view representing the body of this view. 18 | var body: some Scene { 19 | WindowGroup { 20 | ContentView() 21 | .onAppear{ 22 | initFolders() 23 | } 24 | .environmentObject(model) 25 | .task { 26 | await model.loadModels() 27 | } 28 | } 29 | } 30 | 31 | private func initFolders(){ 32 | // TODO: Add try/catch Inform user that there's difficulty while initializing the folder for models 33 | try? initFolder(name: "models") 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/enum/LogEvenType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogEvenType.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 23.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// Type of events 11 | @available(macOS 13.1, *) 12 | enum LogEvenType{ 13 | 14 | /// For an error 15 | case error 16 | /// Warning 17 | case warning 18 | /// Any message 19 | case message 20 | 21 | /// Image icon tpl 22 | @ViewBuilder 23 | var imageTpl : some View{ 24 | switch self{ 25 | case .error: Image(systemName: "asterisk.circle").font(.body).foregroundColor(.red) 26 | case .warning: Image(systemName: "exclamationmark.circle").font(.body).foregroundColor(.yellow) 27 | case .message : Image(systemName: "circle").font(.body).foregroundColor(.green) 28 | } 29 | } 30 | 31 | /// Event color 32 | var color : Color{ 33 | switch self{ 34 | case .error: return .red 35 | case .warning: return .yellow 36 | case .message : return .green 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/helper/HelperTpl.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelperTpl.swift 3 | // 4 | // 5 | // Created by Igor on 23.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// - Parameters: 11 | /// - width: Width 12 | /// - height: Height 13 | /// - systemName: Name for the image 14 | /// - Returns: Empty tpl 15 | @available(macOS 13.1, *) 16 | @ViewBuilder 17 | public func emptyImageTpl(width: CGFloat? = nil, height: CGFloat? = nil, systemName: String = "photo" ) -> some View{ 18 | Image(systemName: systemName) 19 | .resizable() 20 | .renderingMode(.template) 21 | .scaledToFit() 22 | .frame(width: width, height: height) 23 | } 24 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/model/LogEvent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Event.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 23.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// Event description 11 | @available(macOS 13.1, *) 12 | struct LogEvent: Identifiable, Hashable{ 13 | 14 | /// Identifier 15 | let id = UUID() 16 | 17 | /// Text for an event 18 | let text : String 19 | 20 | /// Event type take a look at ``LogEvenType`` 21 | let type: LogEvenType 22 | 23 | } 24 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/protocol/IEventLoger.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IEventLog.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import Foundation 9 | import StableDiffusion 10 | import SwiftUI 11 | 12 | @MainActor 13 | protocol IEventLoger: AnyObject{ 14 | 15 | /// List of events 16 | var logEvents: [LogEvent] { get set } 17 | 18 | } 19 | 20 | extension IEventLoger{ 21 | 22 | /// Add message about result of generation an image 23 | /// - Parameter result: Result image 24 | func logOutput(_ result: Image?){ 25 | if result == nil{ 26 | addToEventLog("Result is empty", type: .warning) 27 | }else{ 28 | addToEventLog("Finished successfully", type: .message) 29 | } 30 | } 31 | 32 | /// Clean event list 33 | func cleanEventLog() { 34 | logEvents = [] 35 | } 36 | 37 | /// Add an event message 38 | /// - Parameters: 39 | /// - text: Description of event 40 | /// - type: Type of event 41 | func addToEventLog(_ text : String, type: LogEvenType){ 42 | logEvents.insert(.init(text: text, type: type), at: 0) 43 | } 44 | 45 | /// Process an error 46 | /// - Parameter value: Error 47 | func logError(_ value : Error){ 48 | 49 | if let e = value as? PipelineError, e == .startingImageProvidedWithoutEncoder{ 50 | addToEventLog("The selected model does not support an input image", type: .error) 51 | addToEventLog("Clean up input image and type in only PROMPT", type: .warning) 52 | }else if let e = value as? Encoder.Error, e == .sampleInputShapeNotCorrect { 53 | addToEventLog("The sample input shape not correct", type: .error) 54 | }else{ 55 | addToEventLog("Unknown error \(value.localizedDescription)", type: .error) 56 | } 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/view/LoggerTpl.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoggerTpl.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 23.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @available(macOS 13.1, *) 11 | struct LoggerTpl: View { 12 | 13 | @EnvironmentObject var model : ViewModel 14 | 15 | // MARK: - Life circle 16 | 17 | /// The type of view representing the body of this view. 18 | var body: some View { 19 | VStack(alignment: .leading){ 20 | List(model.logEvents, id : \.self){ item in 21 | let color = item.type.color 22 | let image = item.type.imageTpl 23 | HStack{ 24 | image 25 | Text(item.text) 26 | Spacer() 27 | } 28 | .frame(maxWidth: .infinity) 29 | .padding(10) 30 | .background(bgTpl(color)) 31 | } 32 | .scrollContentBackground(.hidden) 33 | ZStack{ 34 | cleanTpl 35 | }.frame(maxWidth: .infinity, alignment: .trailing) 36 | } 37 | } 38 | 39 | @ViewBuilder 40 | private func bgTpl(_ color : Color) -> some View{ 41 | ZStack{ 42 | Capsule().fill(.gray.opacity(0.25)) 43 | Capsule().stroke(color, lineWidth: 0.5) 44 | } 45 | } 46 | 47 | /// Remove result image 48 | @ViewBuilder 49 | private var cleanTpl: some View{ 50 | Button{ 51 | model.cleanEventLog() 52 | }label: { 53 | HStack{ 54 | Image(systemName: "x.circle") 55 | .font(.system(size: 14)) 56 | } 57 | } 58 | .disabled(model.logEvents.isEmpty) 59 | .padding(.trailing, 25) 60 | .padding(.bottom, 25) 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/view/OutputView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OutputView.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import coreml_stable_diffusion_swift 10 | 11 | @available(macOS 13.1, *) 12 | struct OutputView: View { 13 | 14 | @EnvironmentObject var model : ViewModel 15 | 16 | // MARK: - Private properties 17 | 18 | /// Generation is running 19 | private var isRunning : Bool{ 20 | model.progress == .running 21 | } 22 | /// Generation is canceling 23 | private var isCanceling : Bool{ 24 | model.progress == .canceling 25 | } 26 | /// Background opacity 27 | private var bgOpacity : CGFloat{ 28 | isRunning || isCanceling ? 0.25 : 1 29 | } 30 | /// Offset to hide empty tpl 31 | private var offsetForEmpty : CGFloat { 32 | model.outputImage == nil ? 0 : -1000 33 | } 34 | 35 | // MARK: - Life circle 36 | 37 | /// The type of view representing the body of this view. 38 | var body: some View { 39 | VStack(alignment: .trailing){ 40 | shareTpl 41 | Spacer() 42 | ZStack{ 43 | emptyTpl 44 | .offset(y: offsetForEmpty) 45 | .animation(.spring(), value: model.outputImage) 46 | .opacity(bgOpacity) 47 | if let image = model.outputImage{ 48 | image 49 | .resizable() 50 | .scaledToFit() 51 | .padding() 52 | }else if isRunning{ 53 | progressTpl("Generating image") 54 | }else if isCanceling{ 55 | progressTpl("Canceling generation") 56 | } 57 | } 58 | Spacer() 59 | cleanTpl 60 | } 61 | .frame(minWidth: 302, maxWidth: .infinity, minHeight: 480, maxHeight: .infinity) 62 | } 63 | 64 | // MARK: - Private 65 | 66 | 67 | @ViewBuilder 68 | private var shareTpl: some View{ 69 | if let image = model.outputImage{ 70 | ShareLink(item: image, preview: SharePreview("Generated image", image: image)) 71 | .padding(.top) 72 | .padding(.trailing) 73 | }else{ 74 | EmptyView() 75 | } 76 | } 77 | 78 | @ViewBuilder 79 | private func progressTpl(_ text : String) -> some View{ 80 | VStack(spacing: 25){ 81 | ProgressView() 82 | Text(text) 83 | .font(.largeTitle) 84 | } 85 | } 86 | 87 | @ViewBuilder 88 | private var cleanTpl : some View{ 89 | Button{ 90 | model.cleanOutput() 91 | }label: { 92 | Image(systemName: "x.circle") 93 | .font(.system(size: 14)) 94 | } 95 | .padding(.trailing, 25) 96 | .padding(.bottom, 25) 97 | .disabled(model.outputImage == nil) 98 | } 99 | 100 | @ViewBuilder 101 | private var emptyTpl: some View{ 102 | VStack{ 103 | Image("app") 104 | .resizable() 105 | .scaleEffect(0.75, anchor: .center) 106 | .scaledToFit() 107 | .foregroundColor(.yellow) 108 | .fontWeight(.thin) 109 | HStack{ 110 | Text("Pick up a model") 111 | .font(.system(size: 50, design: .rounded)).fontWeight(.bold) 112 | .foregroundColor(.white.opacity(0.75)) 113 | Image(systemName: "arrow.turn.right.down") 114 | .font(.system(size: 80)).fontWeight(.regular) 115 | .foregroundColor(.pink) 116 | } 117 | Text("and select a photo or write a prompt") 118 | .font(.system(size: 27, design: .rounded)).fontWeight(.regular) 119 | .padding(.leading, 150) 120 | .foregroundColor(.gray) 121 | } 122 | } 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/view/SideBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBar.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import coreml_stable_diffusion_swift 10 | 11 | @available(macOS 13.1, *) 12 | struct SideBar: View{ 13 | 14 | @EnvironmentObject var model : ViewModel 15 | 16 | /// Current task generating an image 17 | @State private var task : Task<(), Never>? 18 | 19 | /// Scheduler description 20 | private var schedulerDescription : String{ 21 | model.scheduler.description 22 | } 23 | 24 | // MARK: - Life circle 25 | 26 | /// The type of view representing the body of this view. 27 | var body: some View{ 28 | VStack{ 29 | ScrollView{ 30 | VStack(alignment: .leading, spacing: 10){ 31 | headerTpl 32 | Divider() 33 | Group{ 34 | modelsPickerTpl 35 | schedulerPickerTpl 36 | Prompts() 37 | } 38 | .font(.system(size: 12, weight: .regular)) 39 | InputImageView() 40 | Group{ 41 | SlidersView() 42 | } 43 | .font(.system(size: 12, weight: .regular)) 44 | }.padding(.leading, 10) 45 | .padding(.trailing, 15) 46 | } 47 | Divider() 48 | VStack{ 49 | generateTpl 50 | cancelGenerateTpl 51 | }.padding() 52 | } 53 | .navigationTitle("Models") 54 | .navigationSplitViewColumnWidth(min: 300, ideal: 350, max: 600) 55 | } 56 | 57 | // MARK: - Private Tpl 58 | 59 | @ViewBuilder 60 | private var schedulerPickerTpl: some View{ 61 | VStack{ 62 | Text(schedulerDescription) 63 | .font(.caption2) 64 | .foregroundColor(.gray) 65 | Picker("".uppercased(),selection: $model.scheduler) { 66 | let data = GenerativeManager.schedulers 67 | ForEach(data, id : \.self){ item in 68 | Text(item.name).tag(item.name) 69 | } 70 | } 71 | } 72 | } 73 | 74 | @ViewBuilder 75 | private var headerTpl : some View{ 76 | HStack{ 77 | Image(systemName: "gear") 78 | Text("Parameters".uppercased()) 79 | }.font(.system(size: 14)) 80 | .foregroundColor(.white.opacity(0.75)) 81 | } 82 | 83 | /// Check fields validity 84 | private var isNotValid : Bool{ 85 | (model.selected.isEmpty || model.selected == "empty") || (model.prompt.isEmpty && model.inputImage == nil) 86 | } 87 | 88 | private var isRunning : Bool{ 89 | model.progress == .running 90 | } 91 | 92 | private var isCanceling : Bool{ 93 | model.progress == .canceling 94 | } 95 | 96 | /// Start task 97 | private func startTask(){ 98 | task = Task{ 99 | await model.generate() 100 | } 101 | } 102 | 103 | /// Cancel task 104 | private func cancelTask(){ 105 | task?.cancel() 106 | task = nil 107 | model.setCancellation() 108 | } 109 | 110 | // MARK: - Private Tpl 111 | 112 | @ViewBuilder 113 | private var generateTpl : some View{ 114 | Button{ 115 | if let task, !task.isCancelled{ 116 | cancelTask() 117 | } 118 | startTask() 119 | } 120 | label: { 121 | Text("Generate") 122 | .frame(maxWidth: .infinity) 123 | } 124 | .buttonStyle(.borderedProminent) 125 | .disabled(isNotValid || isRunning || isCanceling) 126 | } 127 | 128 | @ViewBuilder 129 | private var cancelGenerateTpl : some View{ 130 | Button{ 131 | cancelTask() 132 | } 133 | label: { 134 | Text("Cancel") 135 | .frame(maxWidth: .infinity) 136 | } 137 | .buttonStyle(.borderedProminent) 138 | .disabled(!isRunning) 139 | } 140 | 141 | @ViewBuilder 142 | private var modelsPickerTpl : some View{ 143 | HStack{ 144 | Picker("Models".uppercased(),selection: $model.selected) { 145 | Text("Empty").tag("empty") 146 | ForEach(model.models, id : \.self){ item in 147 | HStack{ 148 | Image(systemName: "photo.circle") 149 | Text(item.name) 150 | }.tag(item.name) 151 | } 152 | } 153 | .disabled(model.loadingModels) 154 | Button{ 155 | Task{ 156 | await model.loadModels() 157 | } 158 | }label: { 159 | Image(systemName: "arrow.counterclockwise") 160 | } 161 | }.onChange(of: model.selected){ 162 | model.updateModel($0) 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/view/ToolBarContent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ToolBarContent.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import SwiftUI 9 | import coreml_stable_diffusion_swift 10 | 11 | struct ToolBarContent: View { 12 | 13 | @EnvironmentObject var model : ViewModel 14 | 15 | @Environment(\.openURL) var openURL 16 | 17 | // MARK: - Life circle 18 | 19 | /// The type of view representing the body of this view. 20 | var body: some View { 21 | toolbarTpl 22 | } 23 | 24 | @ViewBuilder 25 | /// Set of controls for toolbar 26 | private var toolbarTpl : some View{ 27 | Button{ 28 | showInFinder() 29 | } label: { 30 | HStack{ 31 | Image(systemName: "circle.hexagonpath.fill") 32 | Text("Local models") 33 | 34 | }.foregroundColor(.green) 35 | .font(.title2) 36 | } 37 | .help("Models are expected in Document -> models folder") 38 | 39 | HStack { 40 | Divider() 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-example/viewmodel/ViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewModel.swift 3 | // stable-diffusion-swift-example 4 | // 5 | // Created by Igor on 22.03.2023. 6 | // 7 | 8 | import Foundation 9 | import coreml_stable_diffusion_swift 10 | import SwiftUI 11 | import StableDiffusion 12 | 13 | @available(macOS 13.1, *) 14 | @MainActor 15 | /// View model for managing image generation 16 | final class ViewModel: ObservableObject, IEventLoger{ 17 | 18 | // MARK: - Input 19 | 20 | ///Text prompt to guide sampling 21 | @Published var prompt : String = "an astronaut riding a horse on mars artstation, hd, dramatic lighting, detailed" 22 | /// Negative text prompt to guide sampling 23 | @Published var negativePrompt : String = "" 24 | /// Selected model 25 | @Published var selected : String = "empty" 26 | /// Starting image for image2image or in-painting 27 | @Published var inputImage: CGImage? = nil 28 | /// Strength 29 | @Published var strength: Float = 0.5 30 | /// Controls the influence of the text prompt on sampling process (0=random images) 31 | @Published var guidanceScale: Float = 7.5 32 | /// Number of inference steps to perform 33 | @Published var stepCount: Float = 11 34 | 35 | @Published var seed: UInt32 = 50 36 | /// Safety checks 37 | @Published var disableSafety: Bool = false 38 | /// Reduce memory if you use it on devises with limited memory amount 39 | @Published var reduceMemory: Bool = false 40 | 41 | @Published var scheduler: GenerativeManager.Scheduler = GenerativeManager.defaultScheduler 42 | 43 | // MARK: - Output 44 | 45 | /// Result image 46 | @Published var outputImage: Image? = nil 47 | 48 | // MARK: - Service properties 49 | 50 | /// Current progress 51 | @Published private(set) var progress : ProgressState = .idle 52 | 53 | 54 | /// List of available models 55 | @Published private(set) var models : [GenerativeModel] = [] 56 | { didSet{ loadingModels = models.isEmpty } } 57 | 58 | /// Indicate of the models loading process 59 | @Published private(set) var loadingModels : Bool = false 60 | 61 | /// List of events 62 | @Published var logEvents: [LogEvent] = [] 63 | 64 | // MARK: - Private 65 | 66 | /// Pipeline for generating images 67 | private var pipeline: StableDiffusionPipeline? = nil 68 | 69 | /// Image generating manager 70 | private var manager: IGenerativeManager 71 | 72 | // MARK: - Life circle 73 | 74 | public init(manager : IGenerativeManager){ 75 | self.manager = manager 76 | } 77 | 78 | // MARK: - API 79 | 80 | /// Load models 81 | public func loadModels() async{ 82 | resetModels() 83 | let list = await manager.loadModels() 84 | setModels(list) 85 | selectFirstModel(from: list) 86 | addToEventLog("Loaded \(list.count) models", type: .message) 87 | } 88 | 89 | /// Generate an image 90 | public func generate() async{ 91 | 92 | beforeGenerate() 93 | 94 | let config = manager.getConfig(prompt, negativePrompt, inputImage, seed, strength, guidanceScale, stepCount, disableSafety, scheduler.type) 95 | 96 | do{ 97 | guard let pipeline else{ throw Errors.pipelineIsNotDefined } 98 | 99 | let images: [CGImage?] = try await manager.generate( 100 | with: config, by: pipeline 101 | ) 102 | 103 | afterGenerate(images) 104 | }catch{ 105 | logError(error) 106 | setProgress(.failed) 107 | } 108 | } 109 | 110 | /// Set of actions on model has been changed 111 | /// - Parameter value: Name of the model 112 | public func updateModel(_ value : String) { 113 | 114 | guard let model = models.filter({ $0.name == value }).first, let url = model.url else{ 115 | return 116 | } 117 | 118 | guard let pipeline = try? getDiffusionPipeline( 119 | for: url, [], disableSafety, reduceMemory 120 | )else{ 121 | return 122 | } 123 | 124 | self.pipeline = pipeline 125 | } 126 | 127 | /// Clean output result 128 | public func cleanOutput() { 129 | outputImage = nil 130 | } 131 | 132 | /// Set progress state at **.canceling** 133 | public func setCancellation(){ 134 | setProgress(.canceling) 135 | } 136 | 137 | 138 | // MARK: - Private 139 | 140 | /// Set the current state of image generation 141 | /// - Parameter value: State 142 | private func setProgress(_ value : ProgressState){ 143 | progress = value 144 | } 145 | 146 | /// Set of actions before starting the generation result 147 | private func beforeGenerate(){ 148 | setProgress(.running) 149 | resetOutputImage() 150 | addToEventLog("Started processing", type: .message) 151 | } 152 | 153 | /// Set of actions after getting the generation result 154 | /// - Parameter images: Result of generation 155 | private func afterGenerate(_ images: [CGImage?]){ 156 | let output = getImage(cgImage: images.compactMap { $0 }.first) 157 | setOutputImage(output) 158 | setProgress(.finished) 159 | logOutput(output) 160 | } 161 | 162 | /// Select first model 163 | /// - Parameter list: First model from the list 164 | private func selectFirstModel(from list : [GenerativeModel]){ 165 | if let model = list.first{ 166 | selected = model.name 167 | } 168 | } 169 | 170 | /// Reset the result image 171 | private func resetOutputImage(){ 172 | outputImage = nil 173 | } 174 | 175 | /// Set output result 176 | /// - Parameter value: Result of generating an image 177 | private func setOutputImage(_ value : Image?){ 178 | outputImage = value 179 | } 180 | 181 | 182 | /// Set models picker to empty 183 | private func resetModels(){ 184 | selected = "empty" 185 | models = [] 186 | } 187 | 188 | /// Set models 189 | /// - Parameter value: Models 190 | private func setModels(_ value : [GenerativeModel]){ 191 | models += value 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-exampleTests/coreml_stable_diffusion_swift_exampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // coreml_stable_diffusion_swift_exampleTests.swift 3 | // coreml-stable-diffusion-swift-exampleTests 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import XCTest 9 | @testable import coreml_stable_diffusion_swift_example 10 | 11 | final class coreml_stable_diffusion_swift_exampleTests: XCTestCase { 12 | 13 | override func setUpWithError() throws { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDownWithError() throws { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() throws { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | // Any test you write for XCTest can be annotated as throws and async. 25 | // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. 26 | // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. 27 | } 28 | 29 | func testPerformanceExample() throws { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-exampleUITests/coreml_stable_diffusion_swift_exampleUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // coreml_stable_diffusion_swift_exampleUITests.swift 3 | // coreml-stable-diffusion-swift-exampleUITests 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import XCTest 9 | 10 | final class coreml_stable_diffusion_swift_exampleUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | func testExample() throws { 26 | // UI tests must launch the application that they test. 27 | let app = XCUIApplication() 28 | app.launch() 29 | 30 | // Use XCTAssert and related functions to verify your tests produce the correct results. 31 | } 32 | 33 | func testLaunchPerformance() throws { 34 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { 35 | // This measures how long it takes to launch your application. 36 | measure(metrics: [XCTApplicationLaunchMetric()]) { 37 | XCUIApplication().launch() 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /coreml-stable-diffusion-swift-exampleUITests/coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // coreml_stable_diffusion_swift_exampleUITestsLaunchTests.swift 3 | // coreml-stable-diffusion-swift-exampleUITests 4 | // 5 | // Created by Igor on 24.03.2023. 6 | // 7 | 8 | import XCTest 9 | 10 | final class coreml_stable_diffusion_swift_exampleUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | func testLaunch() throws { 21 | let app = XCUIApplication() 22 | app.launch() 23 | 24 | // Insert steps here to perform after app launch but before taking a screenshot, 25 | // such as logging into a test account or navigating somewhere in the app 26 | 27 | let attachment = XCTAttachment(screenshot: app.screenshot()) 28 | attachment.name = "Launch Screen" 29 | attachment.lifetime = .keepAlways 30 | add(attachment) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /img/img_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftuiux/coreml-stable-diffusion-swift-example/610d13285ccff9ad4bfb5436beb1bb2605b721df/img/img_01.png -------------------------------------------------------------------------------- /img/img_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftuiux/coreml-stable-diffusion-swift-example/610d13285ccff9ad4bfb5436beb1bb2605b721df/img/img_03.png -------------------------------------------------------------------------------- /img/img_08.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swiftuiux/coreml-stable-diffusion-swift-example/610d13285ccff9ad4bfb5436beb1bb2605b721df/img/img_08.gif --------------------------------------------------------------------------------