├── .DS_Store ├── README.md ├── SwiftUIDallEAPI.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── anupamchugh.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── anupamchugh.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── SwiftUIDallEAPI ├── Assets.xcassets ├── AccentColor.colorset │ └── Contents.json ├── AppIcon.appiconset │ └── Contents.json ├── Contents.json └── person.imageset │ ├── Contents.json │ └── original.jpg ├── ContentView.swift ├── EditImageView.swift ├── Info.plist ├── Models.swift ├── MultipartFormDataRequest.swift ├── OpenAIService.swift ├── Preview Content └── Preview Assets.xcassets │ └── Contents.json ├── SwiftUIDallEAPIApp.swift ├── TabbedView.swift └── VisionRequester.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anupamchugh/SwiftUIDallEAPI/077affe4389c1f565d653d2108f6acba9a54fd18/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftUIDallEAPI 2 | Edit Faces using the DALL-E API by using the Vision Face Detection request 3 | 4 | Article Link: https://betterprogramming.pub/dall-e-api-in-swift-generate-faces-e39a2625a5a2 5 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1E382295292D0A6100CE5FB2 /* MultipartFormDataRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E382294292D0A6100CE5FB2 /* MultipartFormDataRequest.swift */; }; 11 | 1E382297292D0D5500CE5FB2 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E382296292D0D5500CE5FB2 /* Models.swift */; }; 12 | 1E382299292D0DBA00CE5FB2 /* VisionRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E382298292D0DBA00CE5FB2 /* VisionRequester.swift */; }; 13 | 1E38229D292D0EF800CE5FB2 /* EditImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E38229C292D0EF800CE5FB2 /* EditImageView.swift */; }; 14 | 1E38229F292D0F9200CE5FB2 /* TabbedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E38229E292D0F9200CE5FB2 /* TabbedView.swift */; }; 15 | 1E818667292BCF4A001BE7A1 /* SwiftUIDallEAPIApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E818666292BCF4A001BE7A1 /* SwiftUIDallEAPIApp.swift */; }; 16 | 1E818669292BCF4A001BE7A1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E818668292BCF4A001BE7A1 /* ContentView.swift */; }; 17 | 1E81866B292BCF4E001BE7A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1E81866A292BCF4E001BE7A1 /* Assets.xcassets */; }; 18 | 1E81866E292BCF4E001BE7A1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1E81866D292BCF4E001BE7A1 /* Preview Assets.xcassets */; }; 19 | 1E818675292BDE5E001BE7A1 /* OpenAIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E818674292BDE5E001BE7A1 /* OpenAIService.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 1E382294292D0A6100CE5FB2 /* MultipartFormDataRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipartFormDataRequest.swift; sourceTree = ""; }; 24 | 1E382296292D0D5500CE5FB2 /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = ""; }; 25 | 1E382298292D0DBA00CE5FB2 /* VisionRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisionRequester.swift; sourceTree = ""; }; 26 | 1E38229C292D0EF800CE5FB2 /* EditImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditImageView.swift; sourceTree = ""; }; 27 | 1E38229E292D0F9200CE5FB2 /* TabbedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbedView.swift; sourceTree = ""; }; 28 | 1E3822A0292D103500CE5FB2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 29 | 1E818663292BCF4A001BE7A1 /* SwiftUIDallEAPI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftUIDallEAPI.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 1E818666292BCF4A001BE7A1 /* SwiftUIDallEAPIApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIDallEAPIApp.swift; sourceTree = ""; }; 31 | 1E818668292BCF4A001BE7A1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 32 | 1E81866A292BCF4E001BE7A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | 1E81866D292BCF4E001BE7A1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 34 | 1E818674292BDE5E001BE7A1 /* OpenAIService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenAIService.swift; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 1E818660292BCF4A001BE7A1 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 1E81865A292BCF4A001BE7A1 = { 49 | isa = PBXGroup; 50 | children = ( 51 | 1E818665292BCF4A001BE7A1 /* SwiftUIDallEAPI */, 52 | 1E818664292BCF4A001BE7A1 /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 1E818664292BCF4A001BE7A1 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 1E818663292BCF4A001BE7A1 /* SwiftUIDallEAPI.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 1E818665292BCF4A001BE7A1 /* SwiftUIDallEAPI */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 1E3822A0292D103500CE5FB2 /* Info.plist */, 68 | 1E818666292BCF4A001BE7A1 /* SwiftUIDallEAPIApp.swift */, 69 | 1E818668292BCF4A001BE7A1 /* ContentView.swift */, 70 | 1E81866A292BCF4E001BE7A1 /* Assets.xcassets */, 71 | 1E81866C292BCF4E001BE7A1 /* Preview Content */, 72 | 1E818674292BDE5E001BE7A1 /* OpenAIService.swift */, 73 | 1E382294292D0A6100CE5FB2 /* MultipartFormDataRequest.swift */, 74 | 1E382296292D0D5500CE5FB2 /* Models.swift */, 75 | 1E382298292D0DBA00CE5FB2 /* VisionRequester.swift */, 76 | 1E38229C292D0EF800CE5FB2 /* EditImageView.swift */, 77 | 1E38229E292D0F9200CE5FB2 /* TabbedView.swift */, 78 | ); 79 | path = SwiftUIDallEAPI; 80 | sourceTree = ""; 81 | }; 82 | 1E81866C292BCF4E001BE7A1 /* Preview Content */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 1E81866D292BCF4E001BE7A1 /* Preview Assets.xcassets */, 86 | ); 87 | path = "Preview Content"; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXNativeTarget section */ 93 | 1E818662292BCF4A001BE7A1 /* SwiftUIDallEAPI */ = { 94 | isa = PBXNativeTarget; 95 | buildConfigurationList = 1E818671292BCF4E001BE7A1 /* Build configuration list for PBXNativeTarget "SwiftUIDallEAPI" */; 96 | buildPhases = ( 97 | 1E81865F292BCF4A001BE7A1 /* Sources */, 98 | 1E818660292BCF4A001BE7A1 /* Frameworks */, 99 | 1E818661292BCF4A001BE7A1 /* Resources */, 100 | ); 101 | buildRules = ( 102 | ); 103 | dependencies = ( 104 | ); 105 | name = SwiftUIDallEAPI; 106 | productName = SwiftUIDallEAPI; 107 | productReference = 1E818663292BCF4A001BE7A1 /* SwiftUIDallEAPI.app */; 108 | productType = "com.apple.product-type.application"; 109 | }; 110 | /* End PBXNativeTarget section */ 111 | 112 | /* Begin PBXProject section */ 113 | 1E81865B292BCF4A001BE7A1 /* Project object */ = { 114 | isa = PBXProject; 115 | attributes = { 116 | BuildIndependentTargetsInParallel = 1; 117 | LastSwiftUpdateCheck = 1410; 118 | LastUpgradeCheck = 1410; 119 | TargetAttributes = { 120 | 1E818662292BCF4A001BE7A1 = { 121 | CreatedOnToolsVersion = 14.1; 122 | }; 123 | }; 124 | }; 125 | buildConfigurationList = 1E81865E292BCF4A001BE7A1 /* Build configuration list for PBXProject "SwiftUIDallEAPI" */; 126 | compatibilityVersion = "Xcode 14.0"; 127 | developmentRegion = en; 128 | hasScannedForEncodings = 0; 129 | knownRegions = ( 130 | en, 131 | Base, 132 | ); 133 | mainGroup = 1E81865A292BCF4A001BE7A1; 134 | productRefGroup = 1E818664292BCF4A001BE7A1 /* Products */; 135 | projectDirPath = ""; 136 | projectRoot = ""; 137 | targets = ( 138 | 1E818662292BCF4A001BE7A1 /* SwiftUIDallEAPI */, 139 | ); 140 | }; 141 | /* End PBXProject section */ 142 | 143 | /* Begin PBXResourcesBuildPhase section */ 144 | 1E818661292BCF4A001BE7A1 /* Resources */ = { 145 | isa = PBXResourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 1E81866E292BCF4E001BE7A1 /* Preview Assets.xcassets in Resources */, 149 | 1E81866B292BCF4E001BE7A1 /* Assets.xcassets in Resources */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXResourcesBuildPhase section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | 1E81865F292BCF4A001BE7A1 /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | 1E38229F292D0F9200CE5FB2 /* TabbedView.swift in Sources */, 161 | 1E382299292D0DBA00CE5FB2 /* VisionRequester.swift in Sources */, 162 | 1E818669292BCF4A001BE7A1 /* ContentView.swift in Sources */, 163 | 1E818675292BDE5E001BE7A1 /* OpenAIService.swift in Sources */, 164 | 1E38229D292D0EF800CE5FB2 /* EditImageView.swift in Sources */, 165 | 1E382295292D0A6100CE5FB2 /* MultipartFormDataRequest.swift in Sources */, 166 | 1E818667292BCF4A001BE7A1 /* SwiftUIDallEAPIApp.swift in Sources */, 167 | 1E382297292D0D5500CE5FB2 /* Models.swift in Sources */, 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | }; 171 | /* End PBXSourcesBuildPhase section */ 172 | 173 | /* Begin XCBuildConfiguration section */ 174 | 1E81866F292BCF4E001BE7A1 /* Debug */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_ANALYZER_NONNULL = YES; 179 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 181 | CLANG_ENABLE_MODULES = YES; 182 | CLANG_ENABLE_OBJC_ARC = YES; 183 | CLANG_ENABLE_OBJC_WEAK = YES; 184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 185 | CLANG_WARN_BOOL_CONVERSION = YES; 186 | CLANG_WARN_COMMA = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 189 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 190 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 191 | CLANG_WARN_EMPTY_BODY = YES; 192 | CLANG_WARN_ENUM_CONVERSION = YES; 193 | CLANG_WARN_INFINITE_RECURSION = YES; 194 | CLANG_WARN_INT_CONVERSION = YES; 195 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 196 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 197 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 198 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 199 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 200 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 201 | CLANG_WARN_STRICT_PROTOTYPES = YES; 202 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 203 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 204 | CLANG_WARN_UNREACHABLE_CODE = YES; 205 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 206 | COPY_PHASE_STRIP = NO; 207 | DEBUG_INFORMATION_FORMAT = dwarf; 208 | ENABLE_STRICT_OBJC_MSGSEND = YES; 209 | ENABLE_TESTABILITY = YES; 210 | GCC_C_LANGUAGE_STANDARD = gnu11; 211 | GCC_DYNAMIC_NO_PIC = NO; 212 | GCC_NO_COMMON_BLOCKS = YES; 213 | GCC_OPTIMIZATION_LEVEL = 0; 214 | GCC_PREPROCESSOR_DEFINITIONS = ( 215 | "DEBUG=1", 216 | "$(inherited)", 217 | ); 218 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 219 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 220 | GCC_WARN_UNDECLARED_SELECTOR = YES; 221 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 222 | GCC_WARN_UNUSED_FUNCTION = YES; 223 | GCC_WARN_UNUSED_VARIABLE = YES; 224 | IPHONEOS_DEPLOYMENT_TARGET = 16.1; 225 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 226 | MTL_FAST_MATH = YES; 227 | ONLY_ACTIVE_ARCH = YES; 228 | SDKROOT = iphoneos; 229 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 230 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 231 | }; 232 | name = Debug; 233 | }; 234 | 1E818670292BCF4E001BE7A1 /* Release */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 240 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_ENABLE_OBJC_WEAK = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 251 | CLANG_WARN_EMPTY_BODY = YES; 252 | CLANG_WARN_ENUM_CONVERSION = YES; 253 | CLANG_WARN_INFINITE_RECURSION = YES; 254 | CLANG_WARN_INT_CONVERSION = YES; 255 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 257 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 259 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 260 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 261 | CLANG_WARN_STRICT_PROTOTYPES = YES; 262 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 263 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 264 | CLANG_WARN_UNREACHABLE_CODE = YES; 265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 266 | COPY_PHASE_STRIP = NO; 267 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 268 | ENABLE_NS_ASSERTIONS = NO; 269 | ENABLE_STRICT_OBJC_MSGSEND = YES; 270 | GCC_C_LANGUAGE_STANDARD = gnu11; 271 | GCC_NO_COMMON_BLOCKS = YES; 272 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 274 | GCC_WARN_UNDECLARED_SELECTOR = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 276 | GCC_WARN_UNUSED_FUNCTION = YES; 277 | GCC_WARN_UNUSED_VARIABLE = YES; 278 | IPHONEOS_DEPLOYMENT_TARGET = 16.1; 279 | MTL_ENABLE_DEBUG_INFO = NO; 280 | MTL_FAST_MATH = YES; 281 | SDKROOT = iphoneos; 282 | SWIFT_COMPILATION_MODE = wholemodule; 283 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 284 | VALIDATE_PRODUCT = YES; 285 | }; 286 | name = Release; 287 | }; 288 | 1E818672292BCF4E001BE7A1 /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 292 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 293 | CODE_SIGN_STYLE = Automatic; 294 | CURRENT_PROJECT_VERSION = 1; 295 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDallEAPI/Preview Content\""; 296 | DEVELOPMENT_TEAM = TU485M7VEU; 297 | ENABLE_PREVIEWS = YES; 298 | GENERATE_INFOPLIST_FILE = YES; 299 | INFOPLIST_FILE = SwiftUIDallEAPI/Info.plist; 300 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 301 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 302 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 303 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 304 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 305 | LD_RUNPATH_SEARCH_PATHS = ( 306 | "$(inherited)", 307 | "@executable_path/Frameworks", 308 | ); 309 | MARKETING_VERSION = 1.0; 310 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevie.SwiftUIDallEAPI; 311 | PRODUCT_NAME = "$(TARGET_NAME)"; 312 | SWIFT_EMIT_LOC_STRINGS = YES; 313 | SWIFT_VERSION = 5.0; 314 | TARGETED_DEVICE_FAMILY = "1,2"; 315 | }; 316 | name = Debug; 317 | }; 318 | 1E818673292BCF4E001BE7A1 /* Release */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 322 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 323 | CODE_SIGN_STYLE = Automatic; 324 | CURRENT_PROJECT_VERSION = 1; 325 | DEVELOPMENT_ASSET_PATHS = "\"SwiftUIDallEAPI/Preview Content\""; 326 | DEVELOPMENT_TEAM = TU485M7VEU; 327 | ENABLE_PREVIEWS = YES; 328 | GENERATE_INFOPLIST_FILE = YES; 329 | INFOPLIST_FILE = SwiftUIDallEAPI/Info.plist; 330 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 331 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 332 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 333 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 334 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 335 | LD_RUNPATH_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "@executable_path/Frameworks", 338 | ); 339 | MARKETING_VERSION = 1.0; 340 | PRODUCT_BUNDLE_IDENTIFIER = com.iosdevie.SwiftUIDallEAPI; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SWIFT_EMIT_LOC_STRINGS = YES; 343 | SWIFT_VERSION = 5.0; 344 | TARGETED_DEVICE_FAMILY = "1,2"; 345 | }; 346 | name = Release; 347 | }; 348 | /* End XCBuildConfiguration section */ 349 | 350 | /* Begin XCConfigurationList section */ 351 | 1E81865E292BCF4A001BE7A1 /* Build configuration list for PBXProject "SwiftUIDallEAPI" */ = { 352 | isa = XCConfigurationList; 353 | buildConfigurations = ( 354 | 1E81866F292BCF4E001BE7A1 /* Debug */, 355 | 1E818670292BCF4E001BE7A1 /* Release */, 356 | ); 357 | defaultConfigurationIsVisible = 0; 358 | defaultConfigurationName = Release; 359 | }; 360 | 1E818671292BCF4E001BE7A1 /* Build configuration list for PBXNativeTarget "SwiftUIDallEAPI" */ = { 361 | isa = XCConfigurationList; 362 | buildConfigurations = ( 363 | 1E818672292BCF4E001BE7A1 /* Debug */, 364 | 1E818673292BCF4E001BE7A1 /* Release */, 365 | ); 366 | defaultConfigurationIsVisible = 0; 367 | defaultConfigurationName = Release; 368 | }; 369 | /* End XCConfigurationList section */ 370 | }; 371 | rootObject = 1E81865B292BCF4A001BE7A1 /* Project object */; 372 | } 373 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI.xcodeproj/project.xcworkspace/xcuserdata/anupamchugh.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anupamchugh/SwiftUIDallEAPI/077affe4389c1f565d653d2108f6acba9a54fd18/SwiftUIDallEAPI.xcodeproj/project.xcworkspace/xcuserdata/anupamchugh.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftUIDallEAPI.xcodeproj/xcuserdata/anupamchugh.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftUIDallEAPI.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/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 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Assets.xcassets/person.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "original.jpg", 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 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Assets.xcassets/person.imageset/original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anupamchugh/SwiftUIDallEAPI/077affe4389c1f565d653d2108f6acba9a54fd18/SwiftUIDallEAPI/Assets.xcassets/person.imageset/original.jpg -------------------------------------------------------------------------------- /SwiftUIDallEAPI/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 21/11/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @ObservedObject var fetcher = OpenAIService() 13 | @State var photos : [Photo] = [] 14 | @State private var textPrompt: String = "" 15 | 16 | var body: some View { 17 | VStack { 18 | 19 | List { 20 | ForEach(photos, id: \.url) { photo in 21 | 22 | AsyncImage(url: URL(string: photo.url)) { image in 23 | image 24 | .resizable() 25 | .aspectRatio(contentMode: .fit) 26 | } placeholder: { 27 | Image(systemName: "photo.fill") 28 | }.frame(maxWidth: .infinity, maxHeight: 500) 29 | .listRowInsets(.init(.zero)) 30 | } 31 | } 32 | 33 | TextField("Enter the prompt", text: $textPrompt) 34 | .textFieldStyle(RoundedTextFieldStyle()) 35 | .padding() 36 | 37 | Button(action: runOpenAIGeneration, label: {Text("Generate Text From Prompt")}) 38 | } 39 | .padding() 40 | } 41 | 42 | func runOpenAIGeneration(){ 43 | Task{ 44 | do{ 45 | self.photos = try await fetcher.generateImage(from: textPrompt) 46 | }catch(let error){ 47 | print(error) 48 | } 49 | } 50 | } 51 | } 52 | 53 | struct RoundedTextFieldStyle: TextFieldStyle { 54 | func _body(configuration: TextField) -> some View { 55 | configuration 56 | .padding(.vertical) 57 | .padding(.horizontal, 24) 58 | .background( 59 | Color(UIColor.systemGray6) 60 | ) 61 | .clipShape(Capsule(style: .continuous)) 62 | } 63 | } 64 | 65 | struct ContentView_Previews: PreviewProvider { 66 | static var previews: some View { 67 | ContentView() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/EditImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EditImageView.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 22/11/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct EditImageView: View { 11 | 12 | @StateObject var visionProcessing = VisionRequester() 13 | @StateObject var fetcher = OpenAIService() 14 | @State var inputImage : UIImage = UIImage(named: "person")! 15 | @State var photos : [Photo] = [] 16 | 17 | var body: some View { 18 | 19 | 20 | HStack{ 21 | if let outputImage = self.visionProcessing.maskedImage{ 22 | Image(uiImage: outputImage) 23 | .resizable() 24 | .aspectRatio(contentMode:.fit) 25 | .onReceive(self.visionProcessing.$maskedImage, 26 | perform: { updated in 27 | if let _ = updated?.size{ 28 | Task{ 29 | do{ 30 | self.photos = try await fetcher.generateEditedImage(from: inputImage, with: outputImage) 31 | }catch(let error){ 32 | print(error) 33 | } 34 | } 35 | } 36 | }) 37 | } 38 | 39 | List { 40 | ForEach(photos, id: \.url) { photo in 41 | AsyncImage(url: URL(string: photo.url)) { image in 42 | image 43 | .resizable() 44 | .aspectRatio(contentMode: .fit) 45 | } placeholder: { 46 | Image(systemName: "photo.fill") 47 | }.frame(maxWidth: .infinity, maxHeight: .infinity) 48 | .listRowInsets(.init(.zero)) 49 | } 50 | } 51 | 52 | 53 | Button("Generate Face"){ 54 | visionProcessing.maskFaceUsingVisionRequest(inputImage: inputImage) 55 | } 56 | .padding() 57 | 58 | 59 | } 60 | } 61 | } 62 | 63 | struct EditImageView_Previews: PreviewProvider { 64 | static var previews: some View { 65 | EditImageView() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Models.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Models.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 22/11/22. 6 | // 7 | 8 | import Foundation 9 | 10 | struct DALLEResponse: Decodable { 11 | let created: Int 12 | let data: [Photo] 13 | } 14 | 15 | struct Photo: Decodable { 16 | let url: String 17 | } 18 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/MultipartFormDataRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MultipartFormDataRequest.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 22/11/22. 6 | // 7 | 8 | import Foundation 9 | 10 | struct MultipartFormDataRequest { 11 | 12 | private let boundaryString: String = "Boundary-\(UUID().uuidString)" 13 | var httpBody = NSMutableData() 14 | let url: URL 15 | 16 | init(url: URL) { 17 | self.url = url 18 | } 19 | 20 | func addTextField(named name: String, value: String) { 21 | httpBody.append(textFormField(named: name, value: value)) 22 | } 23 | 24 | private func textFormField(named name: String, value: String) -> Data { 25 | var fieldString = Data("--\(boundaryString)\r\n".utf8) 26 | fieldString += Data("Content-Disposition: form-data; name=\"\(name)\"\r\n".utf8) 27 | fieldString += Data("Content-Type: text/plain; charset=ISO-8859-1\r\n".utf8) 28 | fieldString += Data("\r\n".utf8) 29 | fieldString += Data("\(value)\r\n".utf8) 30 | 31 | return fieldString 32 | } 33 | 34 | 35 | func addDataField(fieldName: String, fileName: String, data: Data, mimeType: String) { 36 | httpBody.append(dataFormField(fieldName: fieldName,fileName:fileName,data: data, mimeType: mimeType)) 37 | } 38 | 39 | private func dataFormField(fieldName: String, 40 | fileName: String, 41 | data: Data, 42 | mimeType: String) -> Data { 43 | 44 | var fieldData = Data("--\(boundaryString)\r\n".utf8) 45 | 46 | fieldData += Data("Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(fileName)\"\r\n".utf8) 47 | fieldData += Data("Content-Type: \(mimeType)\r\n".utf8) 48 | fieldData += Data("\r\n".utf8) 49 | fieldData += data 50 | fieldData += Data("\r\n".utf8) 51 | return fieldData 52 | } 53 | 54 | func asURLRequest() -> URLRequest { 55 | var request = URLRequest(url: url) 56 | 57 | request.httpMethod = "POST" 58 | request.setValue("multipart/form-data; boundary=\(boundaryString)", forHTTPHeaderField: "Content-Type") 59 | 60 | httpBody.append(Data("--\(boundaryString)--".utf8)) 61 | request.httpBody = httpBody as Data 62 | return request 63 | } 64 | } 65 | 66 | extension NSMutableData { 67 | func appendString(_ string: String) { 68 | if let data = string.data(using: .utf8) { 69 | self.append(data) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/OpenAIService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // APIService.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 21/11/22. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | enum OpenAIEndpoint: String{ 12 | 13 | private var baseURL: String { return "https://api.openai.com/v1/images/" } 14 | 15 | case generations 16 | case edits 17 | 18 | var url: URL { 19 | guard let url = URL(string: baseURL) else { 20 | preconditionFailure("The url is not valid") 21 | } 22 | return url.appendingPathComponent(self.rawValue) 23 | } 24 | } 25 | 26 | class OpenAIService: ObservableObject{ 27 | 28 | let api_key_free = "" 29 | 30 | func generateImage(from prompt: String) async throws -> [Photo]{ 31 | var request = URLRequest(url: OpenAIEndpoint.generations.url) 32 | request.setValue("Bearer \(api_key_free)", forHTTPHeaderField: "Authorization") 33 | request.setValue("application/json", forHTTPHeaderField: "Content-Type") 34 | request.httpMethod = "POST" 35 | 36 | let parameters: [String: Any] = [ 37 | "prompt": prompt, 38 | "n": 1, 39 | "size": "256x256" 40 | ] 41 | 42 | let jsonData = try? JSONSerialization.data(withJSONObject: parameters) 43 | 44 | request.httpBody = jsonData 45 | 46 | let (data, _) = try await URLSession.shared.data(for: request) 47 | let dalleResponse = try? JSONDecoder().decode(DALLEResponse.self, from: data) 48 | 49 | return dalleResponse?.data ?? [] 50 | 51 | } 52 | 53 | func generateEditedImage(from image: UIImage, with mask: UIImage) async throws -> [Photo] { 54 | 55 | guard let imageData = image.pngData() else{return []} 56 | guard let maskData = mask.pngData() else{return []} 57 | 58 | let formFields: [String: String] = [ 59 | "prompt": "A woman wearing a red dress with a laughter face expression", 60 | "size": "256x256" 61 | ] 62 | 63 | let multipart = MultipartFormDataRequest(url: OpenAIEndpoint.edits.url) 64 | multipart.addDataField(fieldName: "image", fileName: "image.png", data: imageData, mimeType: "image/png") 65 | multipart.addDataField(fieldName: "mask", fileName: "mask.png", data: maskData, mimeType: "image/png") 66 | 67 | for (key, value) in formFields { 68 | multipart.addTextField(named: key, value: value) 69 | } 70 | 71 | var request = multipart.asURLRequest() 72 | request.setValue("Bearer \(api_key_free)", forHTTPHeaderField: "Authorization") 73 | 74 | let (data, _) = try await URLSession.shared.data(for: request) 75 | let dalleResponse = try? JSONDecoder().decode(DALLEResponse.self, from: data) 76 | 77 | return dalleResponse?.data ?? [] 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/SwiftUIDallEAPIApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIDallEAPIApp.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 21/11/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct SwiftUIDallEAPIApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | TabbedView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/TabbedView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabbedView.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 22/11/22. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TabbedView: View { 11 | var body: some View { 12 | 13 | TabView { 14 | ContentView() 15 | .tabItem { 16 | Text("Text Prompts") 17 | } 18 | .tag(0) 19 | EditImageView() 20 | .tabItem { 21 | Text("Edit Image") 22 | } 23 | .tag(1) 24 | } 25 | 26 | } 27 | } 28 | 29 | struct TabbedView_Previews: PreviewProvider { 30 | static var previews: some View { 31 | TabbedView() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SwiftUIDallEAPI/VisionRequester.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VisionRequester.swift 3 | // SwiftUIDallEAPI 4 | // 5 | // Created by Anupam Chugh on 22/11/22. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import Vision 11 | 12 | class VisionRequester: ObservableObject{ 13 | 14 | @Published var maskedImage: UIImage? 15 | //1 - @Published 16 | var faceRect: VNFaceObservation? 17 | 18 | func maskFaceUsingVisionRequest(inputImage: UIImage){ 19 | 20 | let request = VNDetectFaceRectanglesRequest() 21 | let handler = VNImageRequestHandler(cgImage: inputImage.cgImage!, options: [:]) 22 | Task{ 23 | do{ 24 | try handler.perform([request]) 25 | 26 | guard let results = request.results else {return} 27 | faceRect = results.first //2 28 | guard let faceRect else {return} 29 | 30 | let box = getBoundingBoxes(rect: faceRect, on: inputImage.size) 31 | 32 | await MainActor.run{ 33 | self.maskedImage = erase(region: box, from: inputImage) 34 | } 35 | 36 | }catch{ 37 | print(error) 38 | } 39 | } 40 | } 41 | 42 | func getBoundingBoxes(rect : VNFaceObservation, on imageSize: CGSize) -> CGRect { 43 | 44 | let transform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -imageSize.height) 45 | let scale = CGAffineTransform.identity.scaledBy(x: imageSize.width, y: imageSize.height) 46 | 47 | let bounds = rect.boundingBox.applying(scale).applying(transform) 48 | 49 | return bounds 50 | 51 | } 52 | 53 | func erase(region: CGRect, from image: UIImage) -> UIImage? { 54 | UIGraphicsBeginImageContext(image.size) 55 | image.draw(at: CGPoint.zero) 56 | let context = UIGraphicsGetCurrentContext()! 57 | let bez = UIBezierPath(rect: region) 58 | context.addPath(bez.cgPath) 59 | context.clip() 60 | context.clear(CGRect(x:0,y:0,width: image.size.width,height: image.size.height)) 61 | let newImage = UIGraphicsGetImageFromCurrentImageContext() 62 | UIGraphicsEndImageContext() 63 | 64 | return newImage 65 | } 66 | } 67 | --------------------------------------------------------------------------------