Native macOS UI

Co-authored-by: Cyril Zakka <1841186+cyrilzakka@users.noreply.github.com>
pull/15/head
Pedro Cuenca 1 year ago committed by GitHub
parent 2bdfcc593d
commit 06ce6e56b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -1 +1,2 @@
.DS_Store
xcuserdata/

@ -0,0 +1,100 @@
//
// ContentView.swift
// Diffusion-macOS
//
// Created by Cyril Zakka on 1/12/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import SwiftUI
import ImageIO
// AppKit version that uses NSImage, NSSavePanel
struct ShareButtons: View {
var image: CGImage
var name: String
var filename: String {
name.replacingOccurrences(of: " ", with: "_")
}
func showSavePanel() -> URL? {
let savePanel = NSSavePanel()
savePanel.allowedContentTypes = [.png]
savePanel.canCreateDirectories = true
savePanel.isExtensionHidden = false
savePanel.title = "Save your image"
savePanel.message = "Choose a folder and a name to store the image."
savePanel.nameFieldLabel = "File name:"
savePanel.nameFieldStringValue = filename
let response = savePanel.runModal()
return response == .OK ? savePanel.url : nil
}
func savePNG(cgImage: CGImage, path: URL) {
let image = NSImage(cgImage: cgImage, size: .zero)
let imageRepresentation = NSBitmapImageRep(data: image.tiffRepresentation!)
guard let pngData = imageRepresentation?.representation(using: .png, properties: [:]) else {
print("Error generating PNG data")
return
}
do {
try pngData.write(to: path)
} catch {
print("Error saving: \(error)")
}
}
var body: some View {
let imageView = Image(image, scale: 1, label: Text(name))
HStack {
ShareLink(item: imageView, preview: SharePreview(name, image: imageView))
Button() {
if let url = showSavePanel() {
savePNG(cgImage: image, path: url)
}
} label: {
Label("Save…", systemImage: "square.and.arrow.down")
}
}
}
}
struct ContentView: View {
@StateObject var generation = GenerationContext()
func toolbar() -> any View {
if case .complete(let prompt, let cgImage, _) = generation.state, let cgImage = cgImage {
return ShareButtons(image: cgImage, name: prompt)
} else {
let prompt = DEFAULT_PROMPT
let cgImage = NSImage(imageLiteralResourceName: "placeholder").cgImage(forProposedRect: nil, context: nil, hints: nil)!
return ShareButtons(image: cgImage, name: prompt)
}
}
var body: some View {
NavigationSplitView {
ControlsView()
.navigationSplitViewColumnWidth(min: 250, ideal: 300)
} detail: {
GeneratedImageView()
.aspectRatio(contentMode: .fit)
.frame(width: 512, height: 512)
.cornerRadius(15)
.toolbar {
AnyView(toolbar())
}
}
.environmentObject(generation)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

@ -0,0 +1,151 @@
//
// PromptView.swift
// Diffusion-macOS
//
// Created by Cyril Zakka on 1/12/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import Combine
import SwiftUI
import CompactSlider
enum PipelineState {
case downloading(Double)
case uncompressing
case loading
case ready
case failed(Error)
}
struct ControlsView: View {
@EnvironmentObject var generation: GenerationContext
static let models = ModelInfo.MODELS
static let modelNames = models.map { $0.modelVersion }
@State private var model = Settings.shared.currentModel.modelVersion
@State private var disclosedPrompt = true
// TODO: refactor download with similar code in Loading.swift (iOS)
@State private var stateSubscriber: Cancellable?
@State private var pipelineState: PipelineState = .downloading(0)
func modelDidChange(model: ModelInfo) {
print("Loading model \(model)")
Settings.shared.currentModel = model
pipelineState = .downloading(0)
Task.init {
let loader = PipelineLoader(model: model)
stateSubscriber = loader.statePublisher.sink { state in
DispatchQueue.main.async {
switch state {
case .downloading(let progress):
pipelineState = .downloading(progress)
case .uncompressing:
pipelineState = .uncompressing
case .readyOnDisk:
pipelineState = .loading
default:
break
}
}
}
do {
generation.pipeline = try await loader.prepare()
pipelineState = .ready
} catch {
print("Could not load model, error: \(error)")
pipelineState = .failed(error)
}
}
}
var body: some View {
VStack(alignment: .leading) {
Label("Adjustments", systemImage: "gearshape.2")
.font(.headline)
.fontWeight(.bold)
Divider()
ScrollView {
Group {
DisclosureGroup {
Picker("", selection: $model) {
ForEach(Self.modelNames, id: \.self) {
Text($0)
}
}
.onChange(of: model) { theModel in
guard let model = ModelInfo.from(modelVersion: theModel) else { return }
modelDidChange(model: model)
}
} label: {
Label("Model", systemImage: "cpu").foregroundColor(.secondary)
}
Divider()
DisclosureGroup(isExpanded: $disclosedPrompt) {
Group {
TextField("Positive prompt", text: $generation.positivePrompt,
axis: .vertical).lineLimit(5)
.textFieldStyle(.squareBorder)
.listRowInsets(EdgeInsets(top: 0, leading: -20, bottom: 0, trailing: 20))
TextField("Negative prompt", text: $generation.negativePrompt,
axis: .vertical).lineLimit(5)
.textFieldStyle(.squareBorder)
}.padding(.leading, 10)
} label: {
Label("Prompts", systemImage: "text.quote").foregroundColor(.secondary)
}
Divider()
DisclosureGroup {
CompactSlider(value: $generation.steps, in: 0...150, step: 5) {
Text("Steps")
Spacer()
Text("\(Int(generation.steps))")
}.padding(.leading, 10)
} label: {
Label("Step count", systemImage: "square.3.layers.3d.down.left").foregroundColor(.secondary)
}
Divider()
// DisclosureGroup() {
// CompactSlider(value: $generation.numImages, in: 0...10, step: 1) {
// Text("Number of Images")
// Spacer()
// Text("\(Int(generation.numImages))")
// }.padding(.leading, 10)
// } label: {
// Label("Number of images", systemImage: "photo.stack").foregroundColor(.secondary)
// }
// Divider()
DisclosureGroup() {
let sliderLabel = generation.seed < 0 ? "Random Seed" : "Seed"
CompactSlider(value: $generation.seed, in: -1...1000, step: 1) {
Text(sliderLabel)
Spacer()
Text("\(Int(generation.seed))")
}.padding(.leading, 10)
} label: {
Label("Seed", systemImage: "leaf").foregroundColor(.secondary)
}
}
}
StatusView(pipelineState: $pipelineState)
}
.padding()
.onAppear {
print(PipelineLoader.models)
modelDidChange(model: ModelInfo.from(modelVersion: model) ?? ModelInfo.v2Base)
}
}
}

@ -0,0 +1,12 @@
<?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>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

@ -0,0 +1,20 @@
//
// Diffusion_macOSApp.swift
// Diffusion-macOS
//
// Created by Cyril Zakka on 1/12/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import SwiftUI
@main
struct Diffusion_macOSApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
let runningOnMac = true

@ -0,0 +1,37 @@
//
// GeneratedImageView.swift
// Diffusion
//
// Created by Pedro Cuenca on 18/1/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import SwiftUI
struct GeneratedImageView: View {
@EnvironmentObject var generation: GenerationContext
var body: some View {
switch generation.state {
case .startup: return AnyView(Image("placeholder").resizable())
case .running(let progress):
guard let progress = progress, progress.stepCount > 0 else {
// The first time it takes a little bit before generation starts
return AnyView(ProgressView())
}
let step = Int(progress.step) + 1
let fraction = Double(step) / Double(progress.stepCount)
let label = "Step \(step) of \(progress.stepCount)"
return AnyView(ProgressView(label, value: fraction, total: 1).padding())
case .complete(_, let image, _):
guard let theImage = image else {
return AnyView(Image(systemName: "exclamationmark.triangle").resizable())
}
return AnyView(Image(theImage, scale: 1, label: Text("generated"))
.resizable()
.clipShape(RoundedRectangle(cornerRadius: 20))
)
}
}
}

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

@ -0,0 +1,90 @@
//
// StatusView.swift
// Diffusion-macOS
//
// Created by Cyril Zakka on 1/12/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import SwiftUI
struct StatusView: View {
@EnvironmentObject var generation: GenerationContext
var pipelineState: Binding<PipelineState>
func submit() {
if case .running = generation.state { return }
Task {
generation.state = .running(nil)
let interval: TimeInterval?
let image: CGImage?
(image, interval) = await generation.generate() ?? (nil, nil)
generation.state = .complete(generation.positivePrompt, image, interval)
}
}
func generationStatusView() -> any View {
switch generation.state {
case .startup: return EmptyView()
case .running(let progress):
guard let progress = progress, progress.stepCount > 0 else {
// The first time it takes a little bit before generation starts
return HStack {
Text("Preparing model…")
Spacer()
}
}
let step = Int(progress.step) + 1
let fraction = Double(step) / Double(progress.stepCount)
return HStack {
Text("Generating \(Int(round(100*fraction)))%")
Spacer()
}
case .complete(_, let image, let interval):
guard let _ = image else {
return HStack {
Text("Safety checker triggered, please try a different prompt or seed")
Spacer()
}
}
return HStack {
let intervalString = String(format: "Time: %.1fs", interval ?? 0)
Text(intervalString)
Spacer()
}.frame(maxHeight: 25)
}
}
var body: some View {
switch pipelineState.wrappedValue {
case .downloading(let progress):
ProgressView("Downloading…", value: progress*100, total: 110).padding()
case .uncompressing:
ProgressView("Uncompressing…", value: 100, total: 110).padding()
case .loading:
ProgressView("Loading…", value: 105, total: 110).padding()
case .ready:
VStack {
Button {
submit()
} label: {
Text("Generate")
.frame(maxWidth: .infinity)
.frame(height: 50)
}
.buttonStyle(.borderedProminent)
AnyView(generationStatusView())
}
case .failed:
Text("Pipeline loading error")
}
}
}
struct StatusView_Previews: PreviewProvider {
static var previews: some View {
StatusView(pipelineState: .constant(.downloading(0.2)))
}
}

@ -12,6 +12,19 @@
EBB5BA5829425E17003A2A5B /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = EBB5BA5729425E17003A2A5B /* Path */; };
EBB5BA5A29426E06003A2A5B /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5929426E06003A2A5B /* Downloader.swift */; };
EBB5BA5D294504DE003A2A5B /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EBB5BA5C294504DE003A2A5B /* ZIPFoundation */; };
EBDD7DAA29731F6C00C1C4B2 /* Pipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE75601293E91E200806B32 /* Pipeline.swift */; };
EBDD7DAB29731F7500C1C4B2 /* PipelineLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */; };
EBDD7DAD29731FB300C1C4B2 /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = EBDD7DAC29731FB300C1C4B2 /* Path */; };
EBDD7DAF29731FB300C1C4B2 /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EBDD7DAE29731FB300C1C4B2 /* ZIPFoundation */; };
EBDD7DB129731FB300C1C4B2 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = EBDD7DB029731FB300C1C4B2 /* StableDiffusion */; };
EBDD7DB32973200200C1C4B2 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD7DB22973200200C1C4B2 /* Utils.swift */; };
EBDD7DB42973200200C1C4B2 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD7DB22973200200C1C4B2 /* Utils.swift */; };
EBDD7DB52973201800C1C4B2 /* ModelInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE3FF4B295E1EFE00E921AA /* ModelInfo.swift */; };
EBDD7DB62973206600C1C4B2 /* Downloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB5BA5929426E06003A2A5B /* Downloader.swift */; };
EBDD7DB82976AAFE00C1C4B2 /* State.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD7DB72976AAFE00C1C4B2 /* State.swift */; };
EBDD7DB92976AAFE00C1C4B2 /* State.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD7DB72976AAFE00C1C4B2 /* State.swift */; };
EBDD7DBD2977FFB300C1C4B2 /* GeneratedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBDD7DBB2977FFB300C1C4B2 /* GeneratedImageView.swift */; };
EBDD7DC02978642200C1C4B2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EBE755CC293E37DD00806B32 /* Assets.xcassets */; };
EBE3FF4C295E1EFE00E921AA /* ModelInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE3FF4B295E1EFE00E921AA /* ModelInfo.swift */; };
EBE755C9293E37DD00806B32 /* DiffusionApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE755C8293E37DD00806B32 /* DiffusionApp.swift */; };
EBE755CB293E37DD00806B32 /* TextToImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE755CA293E37DD00806B32 /* TextToImage.swift */; };
@ -22,6 +35,12 @@
EBE755E7293E37DE00806B32 /* DiffusionUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE755E6293E37DE00806B32 /* DiffusionUITestsLaunchTests.swift */; };
EBE75602293E91E200806B32 /* Pipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE75601293E91E200806B32 /* Pipeline.swift */; };
EBE756092941178600806B32 /* Loading.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE756082941178600806B32 /* Loading.swift */; };
F15520242971093300DC009B /* Diffusion_macOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15520232971093300DC009B /* Diffusion_macOSApp.swift */; };
F15520262971093300DC009B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15520252971093300DC009B /* ContentView.swift */; };
F155202B2971093400DC009B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F155202A2971093400DC009B /* Preview Assets.xcassets */; };
F1552031297109C300DC009B /* ControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1552030297109C300DC009B /* ControlsView.swift */; };
F155203429710B3600DC009B /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F155203329710B3600DC009B /* StatusView.swift */; };
F155203C297118E700DC009B /* CompactSlider in Frameworks */ = {isa = PBXBuildFile; productRef = F155203B297118E700DC009B /* CompactSlider */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -45,6 +64,10 @@
EB33A51E2954E1BC00B16357 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
EBB5BA5229425BEE003A2A5B /* PipelineLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineLoader.swift; sourceTree = "<group>"; };
EBB5BA5929426E06003A2A5B /* Downloader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Downloader.swift; sourceTree = "<group>"; };
EBDD7DB22973200200C1C4B2 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
EBDD7DB72976AAFE00C1C4B2 /* State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = State.swift; sourceTree = "<group>"; };
EBDD7DBA2976F03600C1C4B2 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = config/debug.xcconfig; sourceTree = "<group>"; };
EBDD7DBB2977FFB300C1C4B2 /* GeneratedImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneratedImageView.swift; sourceTree = "<group>"; };
EBE3FF4A295DFE2400E921AA /* common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = common.xcconfig; path = config/common.xcconfig; sourceTree = "<group>"; };
EBE3FF4B295E1EFE00E921AA /* ModelInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelInfo.swift; sourceTree = "<group>"; };
EBE4438729488DCA00CDA605 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
@ -62,6 +85,13 @@
EBE755E6293E37DE00806B32 /* DiffusionUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffusionUITestsLaunchTests.swift; sourceTree = "<group>"; };
EBE75601293E91E200806B32 /* Pipeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pipeline.swift; sourceTree = "<group>"; };
EBE756082941178600806B32 /* Loading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Loading.swift; sourceTree = "<group>"; };
F15520212971093300DC009B /* Diffusers.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Diffusers.app; sourceTree = BUILT_PRODUCTS_DIR; };
F15520232971093300DC009B /* Diffusion_macOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Diffusion_macOSApp.swift; sourceTree = "<group>"; };
F15520252971093300DC009B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
F155202A2971093400DC009B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
F155202C2971093400DC009B /* Diffusion_macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Diffusion_macOS.entitlements; sourceTree = "<group>"; };
F1552030297109C300DC009B /* ControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsView.swift; sourceTree = "<group>"; };
F155203329710B3600DC009B /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -89,6 +119,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F155201E2971093300DC009B /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F155203C297118E700DC009B /* CompactSlider in Frameworks */,
EBDD7DB129731FB300C1C4B2 /* StableDiffusion in Frameworks */,
EBDD7DAD29731FB300C1C4B2 /* Path in Frameworks */,
EBDD7DAF29731FB300C1C4B2 /* ZIPFoundation in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -105,10 +146,12 @@
isa = PBXGroup;
children = (
EBE3FF4A295DFE2400E921AA /* common.xcconfig */,
EBDD7DBA2976F03600C1C4B2 /* debug.xcconfig */,
EBE4438729488DCA00CDA605 /* README.md */,
EBE443892948953600CDA605 /* LICENSE */,
EBE755FF293E910800806B32 /* Packages */,
EBE755C7293E37DD00806B32 /* Diffusion */,
F15520222971093300DC009B /* Diffusion-macOS */,
EBE755D9293E37DE00806B32 /* DiffusionTests */,
EBE755E3293E37DE00806B32 /* DiffusionUITests */,
EBE755C6293E37DD00806B32 /* Products */,
@ -122,6 +165,7 @@
EBE755C5293E37DD00806B32 /* Diffusion.app */,
EBE755D6293E37DE00806B32 /* DiffusionTests.xctest */,
EBE755E0293E37DE00806B32 /* DiffusionUITests.xctest */,
F15520212971093300DC009B /* Diffusers.app */,
);
name = Products;
sourceTree = "<group>";
@ -134,7 +178,9 @@
EBE7560A29411A5E00806B32 /* Views */,
EBB5BA5929426E06003A2A5B /* Downloader.swift */,
EBE755C8293E37DD00806B32 /* DiffusionApp.swift */,
EBDD7DB22973200200C1C4B2 /* Utils.swift */,
EBE3FF4B295E1EFE00E921AA /* ModelInfo.swift */,
EBDD7DB72976AAFE00C1C4B2 /* State.swift */,
EBE755CC293E37DD00806B32 /* Assets.xcassets */,
EBE755CE293E37DD00806B32 /* Diffusion.entitlements */,
EBE755CF293E37DD00806B32 /* Preview Content */,
@ -190,6 +236,28 @@
path = Views;
sourceTree = "<group>";
};
F15520222971093300DC009B /* Diffusion-macOS */ = {
isa = PBXGroup;
children = (
F15520232971093300DC009B /* Diffusion_macOSApp.swift */,
F15520252971093300DC009B /* ContentView.swift */,
EBDD7DBB2977FFB300C1C4B2 /* GeneratedImageView.swift */,
F1552030297109C300DC009B /* ControlsView.swift */,
F155203329710B3600DC009B /* StatusView.swift */,
F155202C2971093400DC009B /* Diffusion_macOS.entitlements */,
F15520292971093400DC009B /* Preview Content */,
);
path = "Diffusion-macOS";
sourceTree = "<group>";
};
F15520292971093400DC009B /* Preview Content */ = {
isa = PBXGroup;
children = (
F155202A2971093400DC009B /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -251,6 +319,29 @@
productReference = EBE755E0293E37DE00806B32 /* DiffusionUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
F15520202971093300DC009B /* Diffusion-macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = F155202F2971093400DC009B /* Build configuration list for PBXNativeTarget "Diffusion-macOS" */;
buildPhases = (
F155201D2971093300DC009B /* Sources */,
F155201E2971093300DC009B /* Frameworks */,
F155201F2971093300DC009B /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Diffusion-macOS";
packageProductDependencies = (
F155203B297118E700DC009B /* CompactSlider */,
EBDD7DAC29731FB300C1C4B2 /* Path */,
EBDD7DAE29731FB300C1C4B2 /* ZIPFoundation */,
EBDD7DB029731FB300C1C4B2 /* StableDiffusion */,
);
productName = "Diffusion-macOS";
productReference = F15520212971093300DC009B /* Diffusers.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -258,7 +349,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1410;
LastSwiftUpdateCheck = 1420;
LastUpgradeCheck = 1410;
TargetAttributes = {
EBE755C4293E37DD00806B32 = {
@ -272,6 +363,9 @@
CreatedOnToolsVersion = 14.1;
TestTargetID = EBE755C4293E37DD00806B32;
};
F15520202971093300DC009B = {
CreatedOnToolsVersion = 14.2;
};
};
};
buildConfigurationList = EBE755C0293E37DD00806B32 /* Build configuration list for PBXProject "Diffusion" */;
@ -287,6 +381,7 @@
EBB5BA5629425E17003A2A5B /* XCRemoteSwiftPackageReference "Path.swift" */,
EBB5BA5B294504DE003A2A5B /* XCRemoteSwiftPackageReference "ZIPFoundation" */,
EB33A51B2954D89F00B16357 /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */,
F155203A297118E600DC009B /* XCRemoteSwiftPackageReference "CompactSlider" */,
);
productRefGroup = EBE755C6293E37DD00806B32 /* Products */;
projectDirPath = "";
@ -295,6 +390,7 @@
EBE755C4293E37DD00806B32 /* Diffusion */,
EBE755D5293E37DE00806B32 /* DiffusionTests */,
EBE755DF293E37DE00806B32 /* DiffusionUITests */,
F15520202971093300DC009B /* Diffusion-macOS */,
);
};
/* End PBXProject section */
@ -323,6 +419,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F155201F2971093300DC009B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EBDD7DC02978642200C1C4B2 /* Assets.xcassets in Resources */,
F155202B2971093400DC009B /* Preview Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -335,8 +440,10 @@
EBB5BA5A29426E06003A2A5B /* Downloader.swift in Sources */,
EBE3FF4C295E1EFE00E921AA /* ModelInfo.swift in Sources */,
EBE756092941178600806B32 /* Loading.swift in Sources */,
EBDD7DB82976AAFE00C1C4B2 /* State.swift in Sources */,
EBB5BA5329425BEE003A2A5B /* PipelineLoader.swift in Sources */,
EBE755C9293E37DD00806B32 /* DiffusionApp.swift in Sources */,
EBDD7DB32973200200C1C4B2 /* Utils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -357,6 +464,24 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F155201D2971093300DC009B /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EBDD7DAB29731F7500C1C4B2 /* PipelineLoader.swift in Sources */,
EBDD7DAA29731F6C00C1C4B2 /* Pipeline.swift in Sources */,
F15520262971093300DC009B /* ContentView.swift in Sources */,
EBDD7DB92976AAFE00C1C4B2 /* State.swift in Sources */,
EBDD7DB42973200200C1C4B2 /* Utils.swift in Sources */,
F1552031297109C300DC009B /* ControlsView.swift in Sources */,
EBDD7DB62973206600C1C4B2 /* Downloader.swift in Sources */,
F155203429710B3600DC009B /* StatusView.swift in Sources */,
F15520242971093300DC009B /* Diffusion_macOSApp.swift in Sources */,
EBDD7DB52973201800C1C4B2 /* ModelInfo.swift in Sources */,
EBDD7DBD2977FFB300C1C4B2 /* GeneratedImageView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -484,7 +609,7 @@
};
EBE755EB293E37DE00806B32 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EBE3FF4A295DFE2400E921AA /* common.xcconfig */;
baseConfigurationReference = EBDD7DBA2976F03600C1C4B2 /* debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@ -511,7 +636,6 @@
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.1;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.pcuenca.DiffusionApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@ -552,7 +676,6 @@
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13.1;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.pcuenca.DiffusionApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@ -654,6 +777,65 @@
};
name = Release;
};
F155202D2971093400DC009B /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EBDD7DBA2976F03600C1C4B2 /* debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = "Diffusion-macOS/Diffusion_macOS.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Diffusion-macOS/Preview Content\"";
DEVELOPMENT_TEAM = 2EADP68M95;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.1;
MARKETING_VERSION = 1.0;
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
F155202E2971093400DC009B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EBE3FF4A295DFE2400E921AA /* common.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = "Diffusion-macOS/Diffusion_macOS.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Diffusion-macOS/Preview Content\"";
DEVELOPMENT_TEAM = 2EADP68M95;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.1;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.huggingface.Diffusers;
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -693,6 +875,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F155202F2971093400DC009B /* Build configuration list for PBXNativeTarget "Diffusion-macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F155202D2971093400DC009B /* Debug */,
F155202E2971093400DC009B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
@ -720,6 +911,14 @@
minimumVersion = 0.9.9;
};
};
F155203A297118E600DC009B /* XCRemoteSwiftPackageReference "CompactSlider" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/buh/CompactSlider.git";
requirement = {
branch = main;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@ -738,6 +937,26 @@
package = EBB5BA5B294504DE003A2A5B /* XCRemoteSwiftPackageReference "ZIPFoundation" */;
productName = ZIPFoundation;
};
EBDD7DAC29731FB300C1C4B2 /* Path */ = {
isa = XCSwiftPackageProductDependency;
package = EBB5BA5629425E17003A2A5B /* XCRemoteSwiftPackageReference "Path.swift" */;
productName = Path;
};
EBDD7DAE29731FB300C1C4B2 /* ZIPFoundation */ = {
isa = XCSwiftPackageProductDependency;
package = EBB5BA5B294504DE003A2A5B /* XCRemoteSwiftPackageReference "ZIPFoundation" */;
productName = ZIPFoundation;
};
EBDD7DB029731FB300C1C4B2 /* StableDiffusion */ = {
isa = XCSwiftPackageProductDependency;
package = EB33A51B2954D89F00B16357 /* XCRemoteSwiftPackageReference "ml-stable-diffusion" */;
productName = StableDiffusion;
};
F155203B297118E700DC009B /* CompactSlider */ = {
isa = XCSwiftPackageProductDependency;
package = F155203A297118E600DC009B /* XCRemoteSwiftPackageReference "CompactSlider" */;
productName = CompactSlider;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = EBE755BD293E37DD00806B32 /* Project object */;

@ -0,0 +1,50 @@
{
"pins" : [
{
"identity" : "compactslider",
"kind" : "remoteSourceControl",
"location" : "https://github.com/buh/CompactSlider.git",
"state" : {
"branch" : "main",
"revision" : "3cb37fb7385913835b6844c6af2680c64000dcd2"
}
},
{
"identity" : "ml-stable-diffusion",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/ml-stable-diffusion",
"state" : {
"branch" : "main",
"revision" : "fb1fa01c9d30e9b2e02a8b7ed35d905e272a0262"
}
},
{
"identity" : "path.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mxcl/Path.swift.git",
"state" : {
"revision" : "9c6f807b0a76be0e27aecc908bc6f173400d839e",
"version" : "1.4.0"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "fddd1c00396eed152c45a46bea9f47b98e59301d",
"version" : "1.2.0"
}
},
{
"identity" : "zipfoundation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/weichsel/ZIPFoundation.git",
"state" : {
"revision" : "43ec568034b3731101dbf7670765d671c30f54f3",
"version" : "0.9.16"
}
}
],
"version" : 2
}

@ -0,0 +1,19 @@
<?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>SchemeUserState</key>
<dict>
<key>Diffusion-macOS.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>Diffusion.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "labrador-x2.png",
"filename" : "diffusers_on_white_1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
@ -42,17 +42,19 @@
"size" : "256x256"
},
{
"filename" : "256x256@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"filename" : "256x256@2x.png",
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"filename" : "labrador-x2 1.png",
"filename" : "512x512@2x.png",
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

@ -17,7 +17,4 @@ struct DiffusionApp: App {
}
}
// A couple of helpers
extension String: Error {}
let runningOnMac = ProcessInfo.processInfo.isMacCatalystApp

@ -4,5 +4,7 @@
<dict>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>To be able to save generated images to your Photo Library, youll need to allow this.</string>
<key>CFBundleDisplayName</key>
<string>Diffusers</string>
</dict>
</plist>

@ -60,22 +60,37 @@ extension ModelInfo {
// TODO: repo does not exist yet
static let v14Base = ModelInfo(
modelId: "pcuenq/coreml-stable-diffusion-v1-4",
modelVersion: "1.4"
modelVersion: "CompVis/stable-diffusion-v1-4"
)
static let v15Base = ModelInfo(
modelId: "pcuenq/coreml-stable-diffusion-v1-5",
modelVersion: "1.5"
modelVersion: "runwayml/stable-diffusion-v1-5"
)
static let v2Base = ModelInfo(
modelId: "pcuenq/coreml-stable-diffusion-2-base",
modelVersion: "2-base"
modelVersion: "stabilityai/stable-diffusion-2-base"
)
static let v21Base = ModelInfo(
modelId: "pcuenq/coreml-stable-diffusion-2-1-base",
modelVersion: "2.1-base",
modelVersion: "stabilityai/stable-diffusion-2-1-base",
supportsEncoder: true
)
static let MODELS = [
// ModelInfo.v14Base,
ModelInfo.v15Base,
ModelInfo.v2Base,
ModelInfo.v21Base
]
static func from(modelVersion: String) -> ModelInfo? {
ModelInfo.MODELS.first(where: {$0.modelVersion == modelVersion})
}
static func from(modelId: String) -> ModelInfo? {
ModelInfo.MODELS.first(where: {$0.modelId == modelId})
}
}

@ -29,12 +29,13 @@ class Pipeline {
self.pipeline = pipeline
}
func generate(prompt: String, scheduler: StableDiffusionScheduler, numInferenceSteps stepCount: Int = 50, seed: UInt32? = nil) throws -> (CGImage, TimeInterval) {
func generate(prompt: String, negativePrompt: String = "", scheduler: StableDiffusionScheduler, numInferenceSteps stepCount: Int = 50, seed: UInt32? = nil) throws -> (CGImage, TimeInterval) {
let beginDate = Date()
print("Generating...")
let theSeed = seed ?? UInt32.random(in: 0..<UInt32.max)
let images = try pipeline.generateImages(
prompt: prompt,
negativePrompt: negativePrompt,
imageCount: 1,
stepCount: stepCount,
seed: theSeed,

@ -0,0 +1,81 @@
//
// State.swift
// Diffusion
//
// Created by Pedro Cuenca on 17/1/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import Combine
import SwiftUI
import StableDiffusion
let DEFAULT_MODEL = ModelInfo.v2Base
let DEFAULT_PROMPT = "Labrador in the style of Vermeer"
enum GenerationState {
case startup
case running(StableDiffusionProgress?)
case complete(String, CGImage?, TimeInterval?)
}
class GenerationContext: ObservableObject {
let scheduler = StableDiffusionScheduler.dpmSolverMultistepScheduler
@Published var pipeline: Pipeline? = nil {
didSet {
if let pipeline = pipeline {
progressSubscriber = pipeline
.progressPublisher
.receive(on: DispatchQueue.main)
.sink { progress in
guard let progress = progress else { return }
self.state = .running(progress)
}
}
}
}
@Published var state: GenerationState = .startup
@Published var positivePrompt = DEFAULT_PROMPT
@Published var negativePrompt = ""
// FIXME: Double to support the slider component
@Published var steps = 25.0
@Published var numImages = 1.0
@Published var seed = -1.0
private var progressSubscriber: Cancellable?
func generate() async -> (CGImage, TimeInterval)? {
guard let pipeline = pipeline else { return nil }
let seed = self.seed >= 0 ? UInt32(self.seed) : nil
return try? pipeline.generate(prompt: positivePrompt, negativePrompt: negativePrompt, scheduler: scheduler, numInferenceSteps: Int(steps), seed: seed)
}
}
class Settings {
static let shared = Settings()
let defaults = UserDefaults.standard
enum Keys: String {
case model
}
private init() {
defaults.register(defaults: [
Keys.model.rawValue: ModelInfo.v2Base.modelId
])
}
var currentModel: ModelInfo {
set {
defaults.set(newValue.modelId, forKey: Keys.model.rawValue)
}
get {
guard let modelId = defaults.string(forKey: Keys.model.rawValue) else { return DEFAULT_MODEL }
return ModelInfo.from(modelId: modelId) ?? DEFAULT_MODEL
}
}
}

@ -0,0 +1,11 @@
//
// Utils.swift
// Diffusion
//
// Created by Pedro Cuenca on 14/1/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import Foundation
extension String: Error {}

@ -11,12 +11,8 @@ import Combine
let model = ModelInfo.v2Base
class DiffusionGlobals: ObservableObject {
@Published var pipeline: Pipeline? = nil
}
struct LoadingView: View {
@StateObject var context = DiffusionGlobals()
@StateObject var generation = GenerationContext()
@State private var preparationPhase = "Downloading…"
@State private var downloadProgress: Double = 0
@ -41,7 +37,7 @@ struct LoadingView: View {
}
}
.animation(.easeIn, value: currentView)
.environmentObject(context)
.environmentObject(generation)
.onAppear {
Task.init {
let loader = PipelineLoader(model: model)
@ -63,7 +59,7 @@ struct LoadingView: View {
}
}
do {
context.pipeline = try await loader.prepare()
generation.pipeline = try await loader.prepare()
self.currentView = .textToImage
} catch {
self.currentView = .error("Could not load model, error: \(error)")

@ -10,21 +10,6 @@ import SwiftUI
import Combine
import StableDiffusion
// TODO: bind to UI controls
let scheduler = StableDiffusionScheduler.dpmSolverMultistepScheduler
let steps = 25
let seed: UInt32? = nil
func generate(pipeline: Pipeline?, prompt: String) async -> (CGImage, TimeInterval)? {
guard let pipeline = pipeline else { return nil }
return try? pipeline.generate(prompt: prompt, scheduler: scheduler, numInferenceSteps: steps, seed: seed)
}
enum GenerationState {
case startup
case running(StableDiffusionProgress?)
case idle(String, TimeInterval?)
}
/// Presents "Share" + "Save" buttons on Mac; just "Share" on iOS/iPadOS.
/// This is because I didn't find a way for "Share" to show a Save option when running on macOS.
@ -67,7 +52,6 @@ struct ShareButtons: View {
}
struct ImageWithPlaceholder: View {
var image: Binding<CGImage?>
var state: Binding<GenerationState>
var body: some View {
@ -82,8 +66,8 @@ struct ImageWithPlaceholder: View {
let fraction = Double(step) / Double(progress.stepCount)
let label = "Step \(step) of \(progress.stepCount)"
return AnyView(ProgressView(label, value: fraction, total: 1).padding())
case .idle(let lastPrompt, let interval):
guard let theImage = image.wrappedValue else {
case .complete(let lastPrompt, let image, let interval):
guard let theImage = image else {
return AnyView(Image(systemName: "exclamationmark.triangle").resizable())
}
@ -107,28 +91,23 @@ struct ImageWithPlaceholder: View {
}
struct TextToImage: View {
@EnvironmentObject var context: DiffusionGlobals
@State private var prompt = "Labrador in the style of Vermeer"
@State private var image: CGImage? = nil
@State private var state: GenerationState = .startup
@State private var progressSubscriber: Cancellable?
@EnvironmentObject var generation: GenerationContext
func submit() {
if case .running = state { return }
if case .running = generation.state { return }
Task {
state = .running(nil)
generation.state = .running(nil)
let interval: TimeInterval?
(image, interval) = await generate(pipeline: context.pipeline, prompt: prompt) ?? (nil, nil)
state = .idle(prompt, interval)
let image: CGImage?
(image, interval) = await generation.generate() ?? (nil, nil)
generation.state = .complete(generation.positivePrompt, image, interval)
}
}
var body: some View {
VStack {
HStack {
TextField("Prompt", text: $prompt)
TextField("Prompt", text: $generation.positivePrompt)
.textFieldStyle(.roundedBorder)
.onSubmit {
submit()
@ -139,16 +118,10 @@ struct TextToImage: View {
.padding()
.buttonStyle(.borderedProminent)
}
ImageWithPlaceholder(image: $image, state: $state)
ImageWithPlaceholder(state: $generation.state)
.scaledToFit()
Spacer()
}
.padding()
.onAppear {
progressSubscriber = context.pipeline!.progressPublisher.sink { progress in
guard let progress = progress else { return }
state = .running(progress)
}
}
}
}

@ -3,6 +3,7 @@
// DiffusionTests
//
// Created by Pedro Cuenca on December 2022.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import XCTest

@ -3,6 +3,7 @@
// DiffusionUITests
//
// Created by Pedro Cuenca on December 2022.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import XCTest

@ -3,6 +3,7 @@
// DiffusionUITests
//
// Created by Pedro Cuenca on December 2022.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
import XCTest

@ -3,13 +3,14 @@
// Diffusion
//
// Created by Pedro Cuenca on 202212.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
// Update if you fork this repo
DEVELOPMENT_TEAM = ZWDJQ796RU
PRODUCT_NAME = Diffusers
// Disable code-signing for macOS
CODE_SIGN_IDENTITY[sdk=macos*] =
// Update if you fork this repo
DEVELOPMENT_TEAM = 2EADP68M95
PRODUCT_BUNDLE_IDENTIFIER = com.huggingface.Diffusers

@ -0,0 +1,12 @@
//
// debug.xcconfig
// Diffusion
//
// Created by Pedro Cuenca on 17/1/23.
// See LICENSE at https://github.com/huggingface/swift-coreml-diffusers/LICENSE
//
#include "common.xcconfig"
// Disable code-signing for macOS
CODE_SIGN_IDENTITY[sdk=macos*] =
Loading…
Cancel
Save