Yasuhito Nagatomo 1 year ago
commit 7aa853b6df

100
.gitignore vendored

@ -0,0 +1,100 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
# avoid checking CoreML models
merges.txt
vocab.json
*.mlmodelc
*.mlpackage
.DS_Store
README.md~
.gitignore~
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# Accio dependency management
Dependencies/
.accio/
# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/

@ -0,0 +1,49 @@
# Image Generator with Stable Diffusion v2
![AppIcon](images/appIcon180.png)
A minimal iOS app that generates images using Stable Diffusion v2.
The app uses
- stabilityai/Stable Diffusion v2 model, which was converted CoreML models using Apple's tool
- Apple / ml-stable-diffusion Swift Package (https://github.com/apple/ml-stable-diffusion#swift-requirements)
With the app, you can
- try the image generation with Stable Diffusion v2 and Apple's Swift Package
- see how the Apple / ml-stable-diffusion Library works
The project requires
- Xcode 14.1, macOS 13+
- iPhone 12+ iOS 16.2+ or iPad Pro/M1/M2 iPadOS 16.2+
Preparation
The coreml model files are too big to store in the GitHub repository. Git's file limitation is 100MB but the model files are total 2.5GB.
So the files were removed from the project.
You need to add the converted coreml model files yourself.
1. convert stabilityai/Stable-Diffusion-2-base PyTorch model to coreml models using Apple's tool.
2. add the files to the models2/Resources folder in the Xcode project.
- merges, TextEndoder, Unet, VAEDecoder, vocab
![Image](images/ss1_240.PNG)
![Image](images/ss2_240.PNG)
## Considerations
1. Chunked models: Chunked version, `UnetChunk1.mlmodelc` and `UnetChunk2.mlmodelc`, is better for iOS and iPadOS.
Follow the Apple's instructions. (https://github.com/apple/ml-stable-diffusion)
1. Large binary file: Since the model files are very large (about 2.5GB), it causes a large binary of the app.
The FAQ of Apple documentation says "The recommended option is to prompt the user to download
these assets upon first launch of the app. This keeps the app binary size independent of the
Core ML models being deployed. Disclosing the size of the download to the user is extremely
important as there could be data charges or storage impact that the user might not be comfortable with.".
## References
- Apple Swift Package / ml-stable-diffusion: https://github.com/apple/ml-stable-diffusion
![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

@ -0,0 +1,405 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
BA03C378293D785C001426DE /* imggensd2App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA03C377293D785C001426DE /* imggensd2App.swift */; };
BA03C37A293D785C001426DE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA03C379293D785C001426DE /* ContentView.swift */; };
BA03C37C293D785D001426DE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BA03C37B293D785D001426DE /* Assets.xcassets */; };
BA03C37F293D785D001426DE /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BA03C37E293D785D001426DE /* Preview Assets.xcassets */; };
BA03C388293D80A4001426DE /* CoreMLModels in Resources */ = {isa = PBXBuildFile; fileRef = BA03C387293D80A4001426DE /* CoreMLModels */; };
BA03C38B293D8362001426DE /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = BA03C38A293D8362001426DE /* StableDiffusion */; };
BA03C38D293D8773001426DE /* ImageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA03C38C293D8773001426DE /* ImageGenerator.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
BA03C374293D785C001426DE /* imggensd2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imggensd2.app; sourceTree = BUILT_PRODUCTS_DIR; };
BA03C377293D785C001426DE /* imggensd2App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = imggensd2App.swift; sourceTree = "<group>"; };
BA03C379293D785C001426DE /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
BA03C37B293D785D001426DE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
BA03C37E293D785D001426DE /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
BA03C386293D7CE5001426DE /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
BA03C387293D80A4001426DE /* CoreMLModels */ = {isa = PBXFileReference; lastKnownFileType = folder; path = CoreMLModels; sourceTree = "<group>"; };
BA03C38C293D8773001426DE /* ImageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageGenerator.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
BA03C371293D785C001426DE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BA03C38B293D8362001426DE /* StableDiffusion in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
BA03C36B293D785C001426DE = {
isa = PBXGroup;
children = (
BA03C386293D7CE5001426DE /* README.md */,
BA03C376293D785C001426DE /* imggensd2 */,
BA03C375293D785C001426DE /* Products */,
);
sourceTree = "<group>";
};
BA03C375293D785C001426DE /* Products */ = {
isa = PBXGroup;
children = (
BA03C374293D785C001426DE /* imggensd2.app */,
);
name = Products;
sourceTree = "<group>";
};
BA03C376293D785C001426DE /* imggensd2 */ = {
isa = PBXGroup;
children = (
BA03C377293D785C001426DE /* imggensd2App.swift */,
BA03C379293D785C001426DE /* ContentView.swift */,
BA03C38C293D8773001426DE /* ImageGenerator.swift */,
BA03C387293D80A4001426DE /* CoreMLModels */,
BA03C37B293D785D001426DE /* Assets.xcassets */,
BA03C37D293D785D001426DE /* Preview Content */,
);
path = imggensd2;
sourceTree = "<group>";
};
BA03C37D293D785D001426DE /* Preview Content */ = {
isa = PBXGroup;
children = (
BA03C37E293D785D001426DE /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
BA03C373293D785C001426DE /* imggensd2 */ = {
isa = PBXNativeTarget;
buildConfigurationList = BA03C382293D785D001426DE /* Build configuration list for PBXNativeTarget "imggensd2" */;
buildPhases = (
BA03C370293D785C001426DE /* Sources */,
BA03C371293D785C001426DE /* Frameworks */,
BA03C372293D785C001426DE /* Resources */,
BA03C385293D7A97001426DE /* ShellScript */,
);
buildRules = (
);
dependencies = (
);
name = imggensd2;
packageProductDependencies = (
BA03C38A293D8362001426DE /* StableDiffusion */,
);
productName = imggensd2;
productReference = BA03C374293D785C001426DE /* imggensd2.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
BA03C36C293D785C001426DE /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1410;
LastUpgradeCheck = 1410;
TargetAttributes = {
BA03C373293D785C001426DE = {
CreatedOnToolsVersion = 14.1;
};
};
};
buildConfigurationList = BA03C36F293D785C001426DE /* Build configuration list for PBXProject "imggensd2" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = BA03C36B293D785C001426DE;
packageReferences = (
BA03C389293D8362001426DE /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */,
);
productRefGroup = BA03C375293D785C001426DE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
BA03C373293D785C001426DE /* imggensd2 */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
BA03C372293D785C001426DE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BA03C388293D80A4001426DE /* CoreMLModels in Resources */,
BA03C37F293D785D001426DE /* Preview Assets.xcassets in Resources */,
BA03C37C293D785D001426DE /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
BA03C385293D7A97001426DE /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Adds support for Apple Silicon brew directory\nexport PATH=\"$PATH:/opt/homebrew/bin\"\n\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed.\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
BA03C370293D785C001426DE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BA03C37A293D785C001426DE /* ContentView.swift in Sources */,
BA03C38D293D8773001426DE /* ImageGenerator.swift in Sources */,
BA03C378293D785C001426DE /* imggensd2App.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
BA03C380293D785D001426DE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
BA03C381293D785D001426DE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
BA03C383293D785D001426DE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"imggensd2/Preview Content\"";
DEVELOPMENT_TEAM = J5CY9Q9UP5;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = ImgGenSD2;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.atarayosd.imggensd2;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
BA03C384293D785D001426DE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"imggensd2/Preview Content\"";
DEVELOPMENT_TEAM = J5CY9Q9UP5;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = ImgGenSD2;
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.atarayosd.imggensd2;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
BA03C36F293D785C001426DE /* Build configuration list for PBXProject "imggensd2" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BA03C380293D785D001426DE /* Debug */,
BA03C381293D785D001426DE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
BA03C382293D785D001426DE /* Build configuration list for PBXNativeTarget "imggensd2" */ = {
isa = XCConfigurationList;
buildConfigurations = (
BA03C383293D785D001426DE /* Debug */,
BA03C384293D785D001426DE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
BA03C389293D8362001426DE /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/apple/ml-stable-diffusion#swift-requirements";
requirement = {
branch = main;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
BA03C38A293D8362001426DE /* StableDiffusion */ = {
isa = XCSwiftPackageProductDependency;
package = BA03C389293D8362001426DE /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */;
productName = StableDiffusion;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = BA03C36C293D785C001426DE /* Project object */;
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

@ -0,0 +1,23 @@
{
"pins" : [
{
"identity" : "ml-stable-diffusion#swift-requirements",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/ml-stable-diffusion#swift-requirements",
"state" : {
"branch" : "main",
"revision" : "583cc04ece3dce9e1e8d44449f58d2eb7edef11c"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "fddd1c00396eed152c45a46bea9f47b98e59301d",
"version" : "1.2.0"
}
}
],
"version" : 2
}

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,14 @@
{
"images" : [
{
"filename" : "appicon1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,73 @@
//
// ContentView.swift
// imggensd2
//
// Created by Yasuhito Nagatomo on 2022/12/05.
//
import SwiftUI
struct ContentView: View {
@StateObject var imageGenerator = ImageGenerator()
@State private var generationParameter =
ImageGenerator.GenerationParameter(prompt: "a photo of an astronaut riding a horse on mars",
seed: 100, stepCount: 20,
imageCount: 1, disableSafety: false)
var body: some View {
ScrollView {
VStack {
Text("Stable Diffusion v2").font(.title).padding()
PromptView(parameter: $generationParameter)
.disabled(imageGenerator.generationState != .idle)
if imageGenerator.generationState == .idle {
Button(action: generate) {
Text("Generate").font(.title)
}.buttonStyle(.borderedProminent)
} else {
ProgressView()
}
if let generatedImages = imageGenerator.generatedImages {
ForEach(generatedImages.images) {
Image(uiImage: $0.uiImage)
.resizable()
.scaledToFit()
}
}
}
}
.padding()
}
func generate() {
imageGenerator.generateImages(generationParameter)
}
}
// struct ContentView_Previews: PreviewProvider {
// static var previews: some View {
// ContentView()
// }
// }
struct PromptView: View {
@Binding var parameter: ImageGenerator.GenerationParameter
var body: some View {
VStack {
TextField("Prompt:", text: $parameter.prompt)
.textFieldStyle(RoundedBorderTextFieldStyle())
Stepper(value: $parameter.imageCount, in: 1...10) {
Text("Image Count: \(parameter.imageCount)")
}
Stepper(value: $parameter.stepCount, in: 1...100) {
Text("Iteration steps: \(parameter.stepCount)")
}
Stepper(value: $parameter.seed, in: 0...10000) {
Text("Seed: \(parameter.seed)")
}
}.padding()
}
}

@ -0,0 +1,106 @@
//
// ImageGenerator.swift
// imggensd2
//
// Created by Yasuhito Nagatomo on 2022/12/05.
//
import UIKit
import StableDiffusion
@MainActor
final class ImageGenerator: ObservableObject {
struct GenerationParameter {
var prompt: String
var seed: Int
var stepCount: Int
var imageCount: Int
var disableSafety: Bool
}
struct GeneratedImage: Identifiable {
let id: UUID = UUID()
let uiImage: UIImage
}
struct GeneratedImages {
let prompt: String
let imageCount: Int
let stepCount: Int
let seed: Int
let disableSafety: Bool
let images: [GeneratedImage]
}
enum GenerationState: Equatable {
case idle
case generating(progressStep: Int)
static func == (lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case (.idle, idle): return true
case (.generating(let step1), .generating(let step2)):
if step1 == step2 { return true
} else { return false }
default:
return false
}
}
}
@Published var generationState: GenerationState = .idle
@Published var generatedImages: GeneratedImages?
private let sdpipeline: StableDiffusionPipeline
init() {
guard let path = Bundle.main.path(forResource: "CoreMLModels", ofType: nil, inDirectory: nil) else {
fatalError("Fatal error: failed to find the CoreML models.")
}
let resourceURL = URL(fileURLWithPath: path)
// TODO: move the pipeline creation to background task because it's heavy
if let pipeline = try? StableDiffusionPipeline(resourcesAt: resourceURL) {
sdpipeline = pipeline
} else {
fatalError("Fatal error: failed to create the Stable-Diffusion-Pipeline.")
}
}
func setState(_ state: GenerationState) { // for actor isolation
generationState = state
}
func setGeneratedImages(_ images: GeneratedImages) { // for actor isolation
generatedImages = images
}
func generateImages(_ parameter: GenerationParameter) {
guard generationState == .idle else { return }
Task.detached(priority: .high) {
await self.setState(.generating(progressStep: 0))
do {
// generateImages(prompt: String, imageCount: Int = 1, stepCount: Int = 50, seed: Int = 0,
// disableSafety: Bool = false,
// progressHandler: (StableDiffusionPipeline.Progress) -> Bool = { _ in true }) throws -> [CGImage?]
// TODO: use the progressHandler
let cgImages = try self.sdpipeline.generateImages(prompt: parameter.prompt,
imageCount: parameter.imageCount,
stepCount: parameter.stepCount,
seed: parameter.seed,
disableSafety: parameter.disableSafety)
print("images were generated.")
let uiImages = cgImages.compactMap { image in
if let cgImage = image { return UIImage(cgImage: cgImage)
} else { return nil }
}
await self.setGeneratedImages(GeneratedImages(prompt: parameter.prompt,
imageCount: parameter.imageCount,
stepCount: parameter.stepCount,
seed: parameter.seed,
disableSafety: parameter.disableSafety,
images: uiImages.map { uiImage in GeneratedImage(uiImage: uiImage) }))
} catch {
print("failed.")
}
await self.setState(.idle)
}
}
}

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

@ -0,0 +1,17 @@
//
// imggensd2App.swift
// imggensd2
//
// Created by Yasuhito Nagatomo on 2022/12/05.
//
import SwiftUI
@main
struct Imggensd2App: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Loading…
Cancel
Save