├── DepthDetection.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── zixuan.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── DepthDetection ├── Base.lproj │ └── Main.storyboard ├── CameraViewController.swift ├── DepthDetection-Bridging-Header.h ├── Info.plist ├── Shader │ └── DepthToGrayscale.metal ├── Supporting files │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── ItunesArtwork@2x.png │ │ ├── Contents.json │ │ ├── iTunesArtwork@1x.png │ │ ├── iTunesArtwork@2x.png │ │ ├── iTunesArtwork@3x.png │ │ └── shutter.imageset │ │ │ ├── Contents.json │ │ │ └── camera_button_366471.png │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ └── SceneDelegate.swift ├── ViewController.swift └── render │ ├── DepthToGrayscaleConverter.swift │ ├── FilterRenderer.swift │ ├── minMaxFromBuffer.h │ └── minMaxFromBuffer.m ├── README.md └── imgs └── flowchart.png /DepthDetection.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 541B08CB23505C8E0098326B /* DepthToGrayscaleConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541B08CA23505C8E0098326B /* DepthToGrayscaleConverter.swift */; }; 11 | 541B08CD23505CB10098326B /* FilterRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541B08CC23505CB00098326B /* FilterRenderer.swift */; }; 12 | 541B08D123505D220098326B /* minMaxFromBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 541B08D023505D220098326B /* minMaxFromBuffer.m */; }; 13 | 541B08D42350619B0098326B /* DepthToGrayscale.metal in Sources */ = {isa = PBXBuildFile; fileRef = 541B08D32350619B0098326B /* DepthToGrayscale.metal */; }; 14 | 542AFB97234F083C00538CEB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542AFB96234F083C00538CEB /* AppDelegate.swift */; }; 15 | 542AFB99234F083C00538CEB /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542AFB98234F083C00538CEB /* SceneDelegate.swift */; }; 16 | 542AFB9E234F083C00538CEB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 542AFB9C234F083C00538CEB /* Main.storyboard */; }; 17 | 542AFBA0234F084000538CEB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 542AFB9F234F084000538CEB /* Assets.xcassets */; }; 18 | 542AFBA3234F084000538CEB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 542AFBA1234F084000538CEB /* LaunchScreen.storyboard */; }; 19 | 542AFBAC234F08C700538CEB /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542AFBAB234F08C700538CEB /* CameraViewController.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 541B08CA23505C8E0098326B /* DepthToGrayscaleConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DepthToGrayscaleConverter.swift; path = ../render/DepthToGrayscaleConverter.swift; sourceTree = ""; }; 24 | 541B08CC23505CB00098326B /* FilterRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FilterRenderer.swift; path = ../render/FilterRenderer.swift; sourceTree = ""; }; 25 | 541B08CE23505D210098326B /* DepthDetection-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DepthDetection-Bridging-Header.h"; sourceTree = ""; }; 26 | 541B08CF23505D220098326B /* minMaxFromBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minMaxFromBuffer.h; path = ../render/minMaxFromBuffer.h; sourceTree = ""; }; 27 | 541B08D023505D220098326B /* minMaxFromBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = minMaxFromBuffer.m; path = ../render/minMaxFromBuffer.m; sourceTree = ""; }; 28 | 541B08D32350619B0098326B /* DepthToGrayscale.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = DepthToGrayscale.metal; sourceTree = ""; }; 29 | 542AFB93234F083C00538CEB /* DepthDetection.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DepthDetection.app; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 542AFB96234F083C00538CEB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 31 | 542AFB98234F083C00538CEB /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 32 | 542AFB9D234F083C00538CEB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 33 | 542AFB9F234F084000538CEB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 34 | 542AFBA2234F084000538CEB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 35 | 542AFBA4234F084000538CEB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 542AFBAB234F08C700538CEB /* CameraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 542AFB90234F083C00538CEB /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 541B08D5235061A20098326B /* Shader */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 541B08D32350619B0098326B /* DepthToGrayscale.metal */, 54 | ); 55 | path = Shader; 56 | sourceTree = ""; 57 | }; 58 | 541B08D62350677C0098326B /* Rendering */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 541B08CA23505C8E0098326B /* DepthToGrayscaleConverter.swift */, 62 | 541B08CC23505CB00098326B /* FilterRenderer.swift */, 63 | 541B08CF23505D220098326B /* minMaxFromBuffer.h */, 64 | 541B08D023505D220098326B /* minMaxFromBuffer.m */, 65 | ); 66 | path = Rendering; 67 | sourceTree = ""; 68 | }; 69 | 542AFB8A234F083C00538CEB = { 70 | isa = PBXGroup; 71 | children = ( 72 | 542AFB95234F083C00538CEB /* DepthDetection */, 73 | 542AFB94234F083C00538CEB /* Products */, 74 | ); 75 | sourceTree = ""; 76 | }; 77 | 542AFB94234F083C00538CEB /* Products */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 542AFB93234F083C00538CEB /* DepthDetection.app */, 81 | ); 82 | name = Products; 83 | sourceTree = ""; 84 | }; 85 | 542AFB95234F083C00538CEB /* DepthDetection */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 542AFB9C234F083C00538CEB /* Main.storyboard */, 89 | 542AFBAB234F08C700538CEB /* CameraViewController.swift */, 90 | 541B08D62350677C0098326B /* Rendering */, 91 | 541B08D5235061A20098326B /* Shader */, 92 | 542AFBAA234F085800538CEB /* Supporting files */, 93 | 541B08CE23505D210098326B /* DepthDetection-Bridging-Header.h */, 94 | 542AFBA4234F084000538CEB /* Info.plist */, 95 | ); 96 | path = DepthDetection; 97 | sourceTree = ""; 98 | }; 99 | 542AFBAA234F085800538CEB /* Supporting files */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 542AFB9F234F084000538CEB /* Assets.xcassets */, 103 | 542AFB96234F083C00538CEB /* AppDelegate.swift */, 104 | 542AFB98234F083C00538CEB /* SceneDelegate.swift */, 105 | 542AFBA1234F084000538CEB /* LaunchScreen.storyboard */, 106 | ); 107 | path = "Supporting files"; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | 542AFB92234F083C00538CEB /* DepthDetection */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = 542AFBA7234F084000538CEB /* Build configuration list for PBXNativeTarget "DepthDetection" */; 116 | buildPhases = ( 117 | 542AFB8F234F083C00538CEB /* Sources */, 118 | 542AFB90234F083C00538CEB /* Frameworks */, 119 | 542AFB91234F083C00538CEB /* Resources */, 120 | ); 121 | buildRules = ( 122 | ); 123 | dependencies = ( 124 | ); 125 | name = DepthDetection; 126 | productName = DepthDetection; 127 | productReference = 542AFB93234F083C00538CEB /* DepthDetection.app */; 128 | productType = "com.apple.product-type.application"; 129 | }; 130 | /* End PBXNativeTarget section */ 131 | 132 | /* Begin PBXProject section */ 133 | 542AFB8B234F083C00538CEB /* Project object */ = { 134 | isa = PBXProject; 135 | attributes = { 136 | LastSwiftUpdateCheck = 1100; 137 | LastUpgradeCheck = 1100; 138 | ORGANIZATIONNAME = Zixuan; 139 | TargetAttributes = { 140 | 542AFB92234F083C00538CEB = { 141 | CreatedOnToolsVersion = 11.0; 142 | LastSwiftMigration = 1100; 143 | }; 144 | }; 145 | }; 146 | buildConfigurationList = 542AFB8E234F083C00538CEB /* Build configuration list for PBXProject "DepthDetection" */; 147 | compatibilityVersion = "Xcode 9.3"; 148 | developmentRegion = en; 149 | hasScannedForEncodings = 0; 150 | knownRegions = ( 151 | en, 152 | Base, 153 | ); 154 | mainGroup = 542AFB8A234F083C00538CEB; 155 | productRefGroup = 542AFB94234F083C00538CEB /* Products */; 156 | projectDirPath = ""; 157 | projectRoot = ""; 158 | targets = ( 159 | 542AFB92234F083C00538CEB /* DepthDetection */, 160 | ); 161 | }; 162 | /* End PBXProject section */ 163 | 164 | /* Begin PBXResourcesBuildPhase section */ 165 | 542AFB91234F083C00538CEB /* Resources */ = { 166 | isa = PBXResourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 542AFBA3234F084000538CEB /* LaunchScreen.storyboard in Resources */, 170 | 542AFBA0234F084000538CEB /* Assets.xcassets in Resources */, 171 | 542AFB9E234F083C00538CEB /* Main.storyboard in Resources */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXResourcesBuildPhase section */ 176 | 177 | /* Begin PBXSourcesBuildPhase section */ 178 | 542AFB8F234F083C00538CEB /* Sources */ = { 179 | isa = PBXSourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 541B08D42350619B0098326B /* DepthToGrayscale.metal in Sources */, 183 | 542AFB97234F083C00538CEB /* AppDelegate.swift in Sources */, 184 | 541B08CB23505C8E0098326B /* DepthToGrayscaleConverter.swift in Sources */, 185 | 542AFB99234F083C00538CEB /* SceneDelegate.swift in Sources */, 186 | 541B08D123505D220098326B /* minMaxFromBuffer.m in Sources */, 187 | 541B08CD23505CB10098326B /* FilterRenderer.swift in Sources */, 188 | 542AFBAC234F08C700538CEB /* CameraViewController.swift in Sources */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | /* End PBXSourcesBuildPhase section */ 193 | 194 | /* Begin PBXVariantGroup section */ 195 | 542AFB9C234F083C00538CEB /* Main.storyboard */ = { 196 | isa = PBXVariantGroup; 197 | children = ( 198 | 542AFB9D234F083C00538CEB /* Base */, 199 | ); 200 | name = Main.storyboard; 201 | sourceTree = ""; 202 | }; 203 | 542AFBA1234F084000538CEB /* LaunchScreen.storyboard */ = { 204 | isa = PBXVariantGroup; 205 | children = ( 206 | 542AFBA2234F084000538CEB /* Base */, 207 | ); 208 | name = LaunchScreen.storyboard; 209 | sourceTree = ""; 210 | }; 211 | /* End PBXVariantGroup section */ 212 | 213 | /* Begin XCBuildConfiguration section */ 214 | 542AFBA5234F084000538CEB /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_ANALYZER_NONNULL = YES; 219 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 220 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 221 | CLANG_CXX_LIBRARY = "libc++"; 222 | CLANG_ENABLE_MODULES = YES; 223 | CLANG_ENABLE_OBJC_ARC = YES; 224 | CLANG_ENABLE_OBJC_WEAK = YES; 225 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 226 | CLANG_WARN_BOOL_CONVERSION = YES; 227 | CLANG_WARN_COMMA = YES; 228 | CLANG_WARN_CONSTANT_CONVERSION = YES; 229 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 230 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 231 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 232 | CLANG_WARN_EMPTY_BODY = YES; 233 | CLANG_WARN_ENUM_CONVERSION = YES; 234 | CLANG_WARN_INFINITE_RECURSION = YES; 235 | CLANG_WARN_INT_CONVERSION = YES; 236 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 237 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 238 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 239 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 240 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 241 | CLANG_WARN_STRICT_PROTOTYPES = YES; 242 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 243 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 244 | CLANG_WARN_UNREACHABLE_CODE = YES; 245 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 246 | COPY_PHASE_STRIP = NO; 247 | DEBUG_INFORMATION_FORMAT = dwarf; 248 | ENABLE_STRICT_OBJC_MSGSEND = YES; 249 | ENABLE_TESTABILITY = YES; 250 | GCC_C_LANGUAGE_STANDARD = gnu11; 251 | GCC_DYNAMIC_NO_PIC = NO; 252 | GCC_NO_COMMON_BLOCKS = YES; 253 | GCC_OPTIMIZATION_LEVEL = 0; 254 | GCC_PREPROCESSOR_DEFINITIONS = ( 255 | "DEBUG=1", 256 | "$(inherited)", 257 | ); 258 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 259 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 260 | GCC_WARN_UNDECLARED_SELECTOR = YES; 261 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 262 | GCC_WARN_UNUSED_FUNCTION = YES; 263 | GCC_WARN_UNUSED_VARIABLE = YES; 264 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 265 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 266 | MTL_FAST_MATH = YES; 267 | ONLY_ACTIVE_ARCH = YES; 268 | SDKROOT = iphoneos; 269 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 270 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 271 | }; 272 | name = Debug; 273 | }; 274 | 542AFBA6234F084000538CEB /* Release */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | ALWAYS_SEARCH_USER_PATHS = NO; 278 | CLANG_ANALYZER_NONNULL = YES; 279 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 280 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 281 | CLANG_CXX_LIBRARY = "libc++"; 282 | CLANG_ENABLE_MODULES = YES; 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | CLANG_ENABLE_OBJC_WEAK = YES; 285 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 286 | CLANG_WARN_BOOL_CONVERSION = YES; 287 | CLANG_WARN_COMMA = YES; 288 | CLANG_WARN_CONSTANT_CONVERSION = YES; 289 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 290 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 291 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 292 | CLANG_WARN_EMPTY_BODY = YES; 293 | CLANG_WARN_ENUM_CONVERSION = YES; 294 | CLANG_WARN_INFINITE_RECURSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 297 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 298 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 300 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 301 | CLANG_WARN_STRICT_PROTOTYPES = YES; 302 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 303 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 304 | CLANG_WARN_UNREACHABLE_CODE = YES; 305 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 306 | COPY_PHASE_STRIP = NO; 307 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 308 | ENABLE_NS_ASSERTIONS = NO; 309 | ENABLE_STRICT_OBJC_MSGSEND = YES; 310 | GCC_C_LANGUAGE_STANDARD = gnu11; 311 | GCC_NO_COMMON_BLOCKS = YES; 312 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 313 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 314 | GCC_WARN_UNDECLARED_SELECTOR = YES; 315 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 316 | GCC_WARN_UNUSED_FUNCTION = YES; 317 | GCC_WARN_UNUSED_VARIABLE = YES; 318 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 319 | MTL_ENABLE_DEBUG_INFO = NO; 320 | MTL_FAST_MATH = YES; 321 | SDKROOT = iphoneos; 322 | SWIFT_COMPILATION_MODE = wholemodule; 323 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 324 | VALIDATE_PRODUCT = YES; 325 | }; 326 | name = Release; 327 | }; 328 | 542AFBA8234F084000538CEB /* Debug */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 332 | CLANG_ENABLE_MODULES = YES; 333 | CODE_SIGN_STYLE = Automatic; 334 | DEVELOPMENT_TEAM = 8L3J5KKFY7; 335 | INFOPLIST_FILE = DepthDetection/Info.plist; 336 | LD_RUNPATH_SEARCH_PATHS = ( 337 | "$(inherited)", 338 | "@executable_path/Frameworks", 339 | ); 340 | PRODUCT_BUNDLE_IDENTIFIER = zixuan.DepthDetection; 341 | PRODUCT_NAME = "$(TARGET_NAME)"; 342 | SWIFT_OBJC_BRIDGING_HEADER = "DepthDetection/DepthDetection-Bridging-Header.h"; 343 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 344 | SWIFT_VERSION = 5.0; 345 | TARGETED_DEVICE_FAMILY = "1,2"; 346 | }; 347 | name = Debug; 348 | }; 349 | 542AFBA9234F084000538CEB /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 353 | CLANG_ENABLE_MODULES = YES; 354 | CODE_SIGN_STYLE = Automatic; 355 | DEVELOPMENT_TEAM = 8L3J5KKFY7; 356 | INFOPLIST_FILE = DepthDetection/Info.plist; 357 | LD_RUNPATH_SEARCH_PATHS = ( 358 | "$(inherited)", 359 | "@executable_path/Frameworks", 360 | ); 361 | PRODUCT_BUNDLE_IDENTIFIER = zixuan.DepthDetection; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | SWIFT_OBJC_BRIDGING_HEADER = "DepthDetection/DepthDetection-Bridging-Header.h"; 364 | SWIFT_VERSION = 5.0; 365 | TARGETED_DEVICE_FAMILY = "1,2"; 366 | }; 367 | name = Release; 368 | }; 369 | /* End XCBuildConfiguration section */ 370 | 371 | /* Begin XCConfigurationList section */ 372 | 542AFB8E234F083C00538CEB /* Build configuration list for PBXProject "DepthDetection" */ = { 373 | isa = XCConfigurationList; 374 | buildConfigurations = ( 375 | 542AFBA5234F084000538CEB /* Debug */, 376 | 542AFBA6234F084000538CEB /* Release */, 377 | ); 378 | defaultConfigurationIsVisible = 0; 379 | defaultConfigurationName = Release; 380 | }; 381 | 542AFBA7234F084000538CEB /* Build configuration list for PBXNativeTarget "DepthDetection" */ = { 382 | isa = XCConfigurationList; 383 | buildConfigurations = ( 384 | 542AFBA8234F084000538CEB /* Debug */, 385 | 542AFBA9234F084000538CEB /* Release */, 386 | ); 387 | defaultConfigurationIsVisible = 0; 388 | defaultConfigurationName = Release; 389 | }; 390 | /* End XCConfigurationList section */ 391 | }; 392 | rootObject = 542AFB8B234F083C00538CEB /* Project object */; 393 | } 394 | -------------------------------------------------------------------------------- /DepthDetection.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DepthDetection.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /DepthDetection.xcodeproj/xcuserdata/zixuan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DepthDetection.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DepthDetection/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /DepthDetection/CameraViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import AVFoundation 3 | import Photos 4 | import VideoToolbox 5 | 6 | @available(iOS 11.1, *) 7 | class CameraViewController: UIViewController, AVCapturePhotoCaptureDelegate { 8 | 9 | var videoPreviewLayer: AVCaptureVideoPreviewLayer? 10 | 11 | @IBOutlet weak var cameraView: UIView! 12 | 13 | let session: AVCaptureSession = AVCaptureSession() 14 | let photoOutput = AVCapturePhotoOutput() 15 | private let videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession( 16 | deviceTypes: [.builtInTrueDepthCamera], 17 | mediaType: .video, 18 | position: .front) 19 | 20 | private let sessionQueue = DispatchQueue(label: "SessionQueue", attributes: [], autoreleaseFrequency: .workItem) 21 | private let processingQueue = DispatchQueue(label: "photo processing queue", attributes: [], autoreleaseFrequency: .workItem) 22 | 23 | private let photoDepthConverter = DepthToGrayscaleConverter() 24 | 25 | override func viewDidLoad() { 26 | super.viewDidLoad() 27 | 28 | /* setup input and output */ 29 | let videoDevice: AVCaptureDevice? = videoDeviceDiscoverySession.devices.first 30 | guard 31 | let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!), session.canAddInput(videoDeviceInput) 32 | else { 33 | print("Cannot addd input") 34 | return 35 | } 36 | 37 | session.beginConfiguration() 38 | 39 | session.addInput(videoDeviceInput) 40 | 41 | guard session.canAddOutput(photoOutput) else { 42 | print("cannot add photo output") 43 | return 44 | } 45 | session.addOutput(photoOutput) 46 | session.sessionPreset = .photo 47 | 48 | session.commitConfiguration() 49 | 50 | photoOutput.isDepthDataDeliveryEnabled = photoOutput.isDepthDataDeliverySupported 51 | 52 | 53 | /* capture depth information */ 54 | 55 | // session.beginConfiguration() 56 | // 57 | // let depthFormats = videoDevice!.activeFormat.supportedDepthDataFormats 58 | // let filtered = depthFormats.filter({ 59 | // CMFormatDescriptionGetMediaSubType($0.formatDescription) == kCVPixelFormatType_DepthFloat16 60 | // }) 61 | // let selectedFormat = filtered.max(by: { 62 | // first, second in CMVideoFormatDescriptionGetDimensions(first.formatDescription).width < CMVideoFormatDescriptionGetDimensions(second.formatDescription).width 63 | // }) 64 | // 65 | // do { 66 | // try videoDevice!.lockForConfiguration() 67 | // videoDevice!.activeDepthDataFormat = selectedFormat 68 | // videoDevice!.unlockForConfiguration() 69 | // } catch { 70 | // print("Could not lock device for configuration: \(error)") 71 | // session.commitConfiguration() 72 | // return 73 | // } 74 | // 75 | // session.commitConfiguration() 76 | 77 | 78 | /* add live preview */ 79 | videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session) 80 | videoPreviewLayer?.frame = cameraView.layer.bounds 81 | cameraView.layer.addSublayer(videoPreviewLayer!) 82 | 83 | session.startRunning() 84 | } 85 | 86 | func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { 87 | print("captured") 88 | 89 | processingQueue.async { 90 | 91 | if let depthData = photo.depthData { 92 | let depthPixelBuffer = depthData.depthDataMap 93 | 94 | if !self.photoDepthConverter.isPrepared { 95 | var depthFormatDescription: CMFormatDescription? 96 | CMVideoFormatDescriptionCreateForImageBuffer(allocator: kCFAllocatorDefault, 97 | imageBuffer: depthPixelBuffer, 98 | formatDescriptionOut: &depthFormatDescription) 99 | 100 | /* 101 | outputRetainedBufferCountHint is the number of pixel buffers we expect to hold on to from the renderer. 102 | This value informs the renderer how to size its buffer pool and how many pixel buffers to preallocate. 103 | Allow 3 frames of latency to cover the dispatch_async call. 104 | */ 105 | if let unwrappedDepthFormatDescription = depthFormatDescription { 106 | self.photoDepthConverter.prepare(with: unwrappedDepthFormatDescription, outputRetainedBufferCountHint: 3) 107 | } 108 | } 109 | 110 | guard let convertedDepthPixelBuffer = self.photoDepthConverter.render(pixelBuffer: depthPixelBuffer) else { 111 | print("Unable to convert depth pixel buffer") 112 | return 113 | } 114 | 115 | let greyImage = UIImage.init(pixelBuffer: convertedDepthPixelBuffer) 116 | 117 | UIImageWriteToSavedPhotosAlbum(greyImage!, nil, nil, nil) 118 | 119 | } 120 | } 121 | 122 | //photo.fileDataRepresentation() 123 | 124 | PHPhotoLibrary.requestAuthorization { status in 125 | guard status == .authorized else { return } 126 | 127 | PHPhotoLibrary.shared().performChanges({ 128 | let creationRequest = PHAssetCreationRequest.forAsset() 129 | creationRequest.addResource(with: .photo, data: photo.fileDataRepresentation()!, options: nil) 130 | }, completionHandler: nil) 131 | } 132 | } 133 | 134 | func getSettings() -> AVCapturePhotoSettings { 135 | let setting = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc]) 136 | setting.isDepthDataDeliveryEnabled = photoOutput.isDepthDataDeliverySupported 137 | return setting 138 | } 139 | 140 | @IBAction func capture(_ sender: UIButton) { 141 | sessionQueue.async { 142 | self.photoOutput.capturePhoto(with: self.getSettings(), delegate: self) 143 | } 144 | 145 | /* button vibrate*/ 146 | UIImpactFeedbackGenerator(style: .light).impactOccurred() 147 | 148 | /* photo capture animation */ 149 | self.cameraView.layer.opacity = 0 150 | UIView.animate(withDuration: 0.25) { 151 | self.cameraView.layer.opacity = 1 152 | } 153 | } 154 | 155 | @objc 156 | func didEnterBackground(notification: NSNotification) { 157 | // Free up resources. 158 | processingQueue.async { 159 | self.photoDepthConverter.reset() 160 | } 161 | } 162 | } 163 | 164 | 165 | extension UIImage { 166 | public convenience init?(pixelBuffer: CVPixelBuffer) { 167 | var cgImage: CGImage? 168 | VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage) 169 | 170 | if let cgImage = cgImage { 171 | self.init(cgImage: cgImage, scale: 1.0, orientation: Orientation.right) 172 | } else { 173 | return nil 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /DepthDetection/DepthDetection-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "minMaxFromBuffer.h" 6 | -------------------------------------------------------------------------------- /DepthDetection/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | NSCameraUsageDescription 47 | 48 | NSPhotoLibraryUsageDescription 49 | 50 | UIRequiredDeviceCapabilities 51 | 52 | armv7 53 | 54 | UISupportedInterfaceOrientations 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationLandscapeLeft 58 | UIInterfaceOrientationLandscapeRight 59 | 60 | UISupportedInterfaceOrientations~ipad 61 | 62 | UIInterfaceOrientationPortrait 63 | UIInterfaceOrientationPortraitUpsideDown 64 | UIInterfaceOrientationLandscapeLeft 65 | UIInterfaceOrientationLandscapeRight 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /DepthDetection/Shader/DepthToGrayscale.metal: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Apple Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | Abstract: 7 | Metal compute shader that translates depth values to grayscale RGB values. 8 | */ 9 | 10 | #include 11 | using namespace metal; 12 | 13 | struct converterParameters { 14 | float offset; 15 | float range; 16 | }; 17 | 18 | // Compute kernel 19 | kernel void depthToGrayscale(texture2d inputTexture [[ texture(0) ]], 20 | texture2d outputTexture [[ texture(1) ]], 21 | constant converterParameters& converterParameters [[ buffer(0) ]], 22 | uint2 gid [[ thread_position_in_grid ]]) 23 | { 24 | // Don't read or write outside of the texture. 25 | if ((gid.x >= inputTexture.get_width()) || (gid.y >= inputTexture.get_height())) { 26 | return; 27 | } 28 | 29 | float depth = inputTexture.read(gid).x; 30 | 31 | // Normalize the value between 0 and 1. 32 | depth = (depth - converterParameters.offset) / (converterParameters.range); 33 | 34 | float4 outputColor = float4(float3(depth), 1.0); 35 | 36 | outputTexture.write(outputColor, gid); 37 | } 38 | -------------------------------------------------------------------------------- /DepthDetection/Supporting files/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // DepthDetection 4 | // 5 | // Created by Zixuan on 10/10/19. 6 | // Copyright © 2019 Zixuan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "ItunesArtwork@2x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@1x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@2x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/iTunesArtwork@3x.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/shutter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "camera_button_366471.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Assets.xcassets/shutter.imageset/camera_button_366471.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Olament/DepthDetection/a939b0de2ea8ddfea7bd5917f714c7aceb51d644/DepthDetection/Supporting files/Assets.xcassets/shutter.imageset/camera_button_366471.png -------------------------------------------------------------------------------- /DepthDetection/Supporting files/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /DepthDetection/Supporting files/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // DepthDetection 4 | // 5 | // Created by Zixuan on 10/10/19. 6 | // Copyright © 2019 Zixuan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /DepthDetection/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // DepthDetection 4 | // 5 | // Created by Zixuan on 10/10/19. 6 | // Copyright © 2019 Zixuan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view. 16 | } 17 | 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /DepthDetection/render/DepthToGrayscaleConverter.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Apple Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | 7 | Abstract: 8 | The depth-to-grayscale converter for displaying depth values. 9 | */ 10 | 11 | import CoreMedia 12 | import CoreVideo 13 | import Metal 14 | 15 | class DepthToGrayscaleConverter: FilterRenderer { 16 | 17 | var description: String = "Depth to Grayscale Converter" 18 | 19 | var isPrepared = false 20 | 21 | private(set) var inputFormatDescription: CMFormatDescription? 22 | 23 | private(set) var outputFormatDescription: CMFormatDescription? 24 | 25 | private var inputTextureFormat: MTLPixelFormat = .invalid 26 | 27 | private var outputPixelBufferPool: CVPixelBufferPool! 28 | 29 | private let metalDevice = MTLCreateSystemDefaultDevice()! 30 | 31 | private var computePipelineState: MTLComputePipelineState? 32 | 33 | private lazy var commandQueue: MTLCommandQueue? = { 34 | return self.metalDevice.makeCommandQueue() 35 | }() 36 | 37 | private var textureCache: CVMetalTextureCache! 38 | 39 | private var lowest: Float = 0.0 40 | 41 | private var highest: Float = 0.0 42 | 43 | struct DepthRenderParam { 44 | var offset: Float 45 | var range: Float 46 | } 47 | 48 | var range: DepthRenderParam = DepthRenderParam(offset: -4.0, range: 8.0) 49 | 50 | required init() { 51 | let defaultLibrary = metalDevice.makeDefaultLibrary()! 52 | let kernelFunction = defaultLibrary.makeFunction(name: "depthToGrayscale") 53 | do { 54 | computePipelineState = try metalDevice.makeComputePipelineState(function: kernelFunction!) 55 | } catch { 56 | fatalError("Unable to create depth converter pipeline state. (\(error))") 57 | } 58 | } 59 | 60 | static private func allocateOutputBuffers(with formatDescription: CMFormatDescription, outputRetainedBufferCountHint: Int) -> CVPixelBufferPool? { 61 | let inputDimensions = CMVideoFormatDescriptionGetDimensions(formatDescription) 62 | let outputPixelBufferAttributes: [String: Any] = [ 63 | kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA, 64 | kCVPixelBufferWidthKey as String: Int(inputDimensions.width), 65 | kCVPixelBufferHeightKey as String: Int(inputDimensions.height), 66 | kCVPixelBufferIOSurfacePropertiesKey as String: [:] 67 | ] 68 | 69 | let poolAttributes = [kCVPixelBufferPoolMinimumBufferCountKey as String: outputRetainedBufferCountHint] 70 | var cvPixelBufferPool: CVPixelBufferPool? 71 | // Create a pixel buffer pool with the same pixel attributes as the input format description 72 | CVPixelBufferPoolCreate(kCFAllocatorDefault, 73 | poolAttributes as NSDictionary?, 74 | outputPixelBufferAttributes as NSDictionary?, 75 | &cvPixelBufferPool) 76 | guard let pixelBufferPool = cvPixelBufferPool else { 77 | assertionFailure("Allocation failure: Could not create pixel buffer pool") 78 | return nil 79 | } 80 | return pixelBufferPool 81 | } 82 | 83 | func prepare(with formatDescription: CMFormatDescription, outputRetainedBufferCountHint: Int) { 84 | reset() 85 | 86 | outputPixelBufferPool = DepthToGrayscaleConverter.allocateOutputBuffers(with: formatDescription, 87 | outputRetainedBufferCountHint: outputRetainedBufferCountHint) 88 | if outputPixelBufferPool == nil { 89 | return 90 | } 91 | 92 | var pixelBuffer: CVPixelBuffer? 93 | var pixelBufferFormatDescription: CMFormatDescription? 94 | _ = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, outputPixelBufferPool!, &pixelBuffer) 95 | if let pixelBuffer = pixelBuffer { 96 | CMVideoFormatDescriptionCreateForImageBuffer(allocator: kCFAllocatorDefault, 97 | imageBuffer: pixelBuffer, 98 | formatDescriptionOut: &pixelBufferFormatDescription) 99 | } 100 | pixelBuffer = nil 101 | 102 | inputFormatDescription = formatDescription 103 | outputFormatDescription = pixelBufferFormatDescription 104 | 105 | let inputMediaSubType = CMFormatDescriptionGetMediaSubType(formatDescription) 106 | if inputMediaSubType == kCVPixelFormatType_DepthFloat16 || 107 | inputMediaSubType == kCVPixelFormatType_DisparityFloat16 { 108 | inputTextureFormat = .r16Float 109 | } else if inputMediaSubType == kCVPixelFormatType_DepthFloat32 || 110 | inputMediaSubType == kCVPixelFormatType_DisparityFloat32 { 111 | inputTextureFormat = .r32Float 112 | } else { 113 | assertionFailure("Input format not supported") 114 | } 115 | 116 | var metalTextureCache: CVMetalTextureCache? 117 | if CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, metalDevice, nil, &metalTextureCache) != kCVReturnSuccess { 118 | assertionFailure("Unable to allocate depth converter texture cache") 119 | } else { 120 | textureCache = metalTextureCache 121 | } 122 | 123 | isPrepared = true 124 | } 125 | 126 | func reset() { 127 | outputPixelBufferPool = nil 128 | outputFormatDescription = nil 129 | inputFormatDescription = nil 130 | textureCache = nil 131 | isPrepared = false 132 | } 133 | 134 | // MARK: - Depth to Grayscale Conversion 135 | func render(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer? { 136 | if !isPrepared { 137 | assertionFailure("Invalid state: Not prepared") 138 | return nil 139 | } 140 | 141 | var newPixelBuffer: CVPixelBuffer? 142 | CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, outputPixelBufferPool!, &newPixelBuffer) 143 | guard let outputPixelBuffer = newPixelBuffer else { 144 | print("Allocation failure: Could not get pixel buffer from pool (\(self.description))") 145 | return nil 146 | } 147 | 148 | guard let outputTexture = makeTextureFromCVPixelBuffer(pixelBuffer: outputPixelBuffer, textureFormat: .bgra8Unorm), 149 | let inputTexture = makeTextureFromCVPixelBuffer(pixelBuffer: pixelBuffer, textureFormat: inputTextureFormat) else { 150 | return nil 151 | } 152 | 153 | var min: Float = 0.0 154 | var max: Float = 0.0 155 | minMaxFromPixelBuffer(pixelBuffer, &min, &max, inputTextureFormat) 156 | if min < lowest { 157 | lowest = min 158 | } 159 | if max > highest { 160 | highest = max 161 | } 162 | range = DepthRenderParam(offset: lowest, range: highest - lowest) 163 | 164 | // Set up command queue, buffer, and encoder 165 | guard let commandQueue = commandQueue, 166 | let commandBuffer = commandQueue.makeCommandBuffer(), 167 | let commandEncoder = commandBuffer.makeComputeCommandEncoder() else { 168 | print("Failed to create Metal command queue") 169 | CVMetalTextureCacheFlush(textureCache!, 0) 170 | return nil 171 | } 172 | 173 | commandEncoder.label = "Depth to Grayscale" 174 | commandEncoder.setComputePipelineState(computePipelineState!) 175 | commandEncoder.setTexture(inputTexture, index: 0) 176 | commandEncoder.setTexture(outputTexture, index: 1) 177 | commandEncoder.setBytes( UnsafeMutableRawPointer(&range), length: MemoryLayout.size, index: 0) 178 | 179 | // Set up the thread groups. 180 | let width = computePipelineState!.threadExecutionWidth 181 | let height = computePipelineState!.maxTotalThreadsPerThreadgroup / width 182 | let threadsPerThreadgroup = MTLSizeMake(width, height, 1) 183 | let threadgroupsPerGrid = MTLSize(width: (inputTexture.width + width - 1) / width, 184 | height: (inputTexture.height + height - 1) / height, 185 | depth: 1) 186 | commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup) 187 | 188 | commandEncoder.endEncoding() 189 | 190 | commandBuffer.commit() 191 | 192 | return outputPixelBuffer 193 | } 194 | 195 | func makeTextureFromCVPixelBuffer(pixelBuffer: CVPixelBuffer, textureFormat: MTLPixelFormat) -> MTLTexture? { 196 | let width = CVPixelBufferGetWidth(pixelBuffer) 197 | let height = CVPixelBufferGetHeight(pixelBuffer) 198 | 199 | // Create a Metal texture from the image buffer 200 | var cvTextureOut: CVMetalTexture? 201 | CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, textureCache, pixelBuffer, nil, textureFormat, width, height, 0, &cvTextureOut) 202 | guard let cvTexture = cvTextureOut, let texture = CVMetalTextureGetTexture(cvTexture) else { 203 | print("Depth converter failed to create preview texture") 204 | 205 | CVMetalTextureCacheFlush(textureCache, 0) 206 | 207 | return nil 208 | } 209 | 210 | return texture 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /DepthDetection/render/FilterRenderer.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Apple Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | Abstract: 7 | Filter renderer protocol. 8 | */ 9 | 10 | import CoreMedia 11 | 12 | protocol FilterRenderer: class { 13 | 14 | var description: String { get } 15 | 16 | var isPrepared: Bool { get } 17 | 18 | // Prepare resources. 19 | func prepare(with inputFormatDescription: CMFormatDescription, outputRetainedBufferCountHint: Int) 20 | 21 | // Release resources. 22 | func reset() 23 | 24 | // The format description of the output pixel buffers. 25 | var outputFormatDescription: CMFormatDescription? { get } 26 | 27 | // The format description of the input pixel buffers. 28 | var inputFormatDescription: CMFormatDescription? { get } 29 | 30 | // Render the pixel buffer. 31 | func render(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer? 32 | } 33 | 34 | func allocateOutputBufferPool(with inputFormatDescription: CMFormatDescription, outputRetainedBufferCountHint: Int) ->( 35 | outputBufferPool: CVPixelBufferPool?, 36 | outputColorSpace: CGColorSpace?, 37 | outputFormatDescription: CMFormatDescription?) { 38 | 39 | let inputMediaSubType = CMFormatDescriptionGetMediaSubType(inputFormatDescription) 40 | if inputMediaSubType != kCVPixelFormatType_32BGRA { 41 | assertionFailure("Invalid input pixel buffer type \(inputMediaSubType)") 42 | return (nil, nil, nil) 43 | } 44 | 45 | let inputDimensions = CMVideoFormatDescriptionGetDimensions(inputFormatDescription) 46 | var pixelBufferAttributes: [String: Any] = [ 47 | kCVPixelBufferPixelFormatTypeKey as String: UInt(inputMediaSubType), 48 | kCVPixelBufferWidthKey as String: Int(inputDimensions.width), 49 | kCVPixelBufferHeightKey as String: Int(inputDimensions.height), 50 | kCVPixelBufferIOSurfacePropertiesKey as String: [:] 51 | ] 52 | 53 | // Get pixel buffer attributes and color space from the input format description. 54 | var cgColorSpace = CGColorSpaceCreateDeviceRGB() 55 | if let inputFormatDescriptionExtension = CMFormatDescriptionGetExtensions(inputFormatDescription) as Dictionary? { 56 | let colorPrimaries = inputFormatDescriptionExtension[kCVImageBufferColorPrimariesKey] 57 | 58 | if let colorPrimaries = colorPrimaries { 59 | var colorSpaceProperties: [String: AnyObject] = [kCVImageBufferColorPrimariesKey as String: colorPrimaries] 60 | 61 | if let yCbCrMatrix = inputFormatDescriptionExtension[kCVImageBufferYCbCrMatrixKey] { 62 | colorSpaceProperties[kCVImageBufferYCbCrMatrixKey as String] = yCbCrMatrix 63 | } 64 | 65 | if let transferFunction = inputFormatDescriptionExtension[kCVImageBufferTransferFunctionKey] { 66 | colorSpaceProperties[kCVImageBufferTransferFunctionKey as String] = transferFunction 67 | } 68 | 69 | pixelBufferAttributes[kCVBufferPropagatedAttachmentsKey as String] = colorSpaceProperties 70 | } 71 | 72 | if let cvColorspace = inputFormatDescriptionExtension[kCVImageBufferCGColorSpaceKey] { 73 | cgColorSpace = cvColorspace as! CGColorSpace 74 | } else if (colorPrimaries as? String) == (kCVImageBufferColorPrimaries_P3_D65 as String) { 75 | cgColorSpace = CGColorSpace(name: CGColorSpace.displayP3)! 76 | } 77 | } 78 | 79 | // Create a pixel buffer pool with the same pixel attributes as the input format description. 80 | let poolAttributes = [kCVPixelBufferPoolMinimumBufferCountKey as String: outputRetainedBufferCountHint] 81 | var cvPixelBufferPool: CVPixelBufferPool? 82 | CVPixelBufferPoolCreate(kCFAllocatorDefault, poolAttributes as NSDictionary?, pixelBufferAttributes as NSDictionary?, &cvPixelBufferPool) 83 | guard let pixelBufferPool = cvPixelBufferPool else { 84 | assertionFailure("Allocation failure: Could not allocate pixel buffer pool.") 85 | return (nil, nil, nil) 86 | } 87 | 88 | preallocateBuffers(pool: pixelBufferPool, allocationThreshold: outputRetainedBufferCountHint) 89 | 90 | // Get the output format description. 91 | var pixelBuffer: CVPixelBuffer? 92 | var outputFormatDescription: CMFormatDescription? 93 | let auxAttributes = [kCVPixelBufferPoolAllocationThresholdKey as String: outputRetainedBufferCountHint] as NSDictionary 94 | CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, pixelBufferPool, auxAttributes, &pixelBuffer) 95 | if let pixelBuffer = pixelBuffer { 96 | CMVideoFormatDescriptionCreateForImageBuffer(allocator: kCFAllocatorDefault, 97 | imageBuffer: pixelBuffer, 98 | formatDescriptionOut: &outputFormatDescription) 99 | } 100 | pixelBuffer = nil 101 | 102 | return (pixelBufferPool, cgColorSpace, outputFormatDescription) 103 | } 104 | 105 | /// - Tag: AllocateRenderBuffers 106 | private func preallocateBuffers(pool: CVPixelBufferPool, allocationThreshold: Int) { 107 | var pixelBuffers = [CVPixelBuffer]() 108 | var error: CVReturn = kCVReturnSuccess 109 | let auxAttributes = [kCVPixelBufferPoolAllocationThresholdKey as String: allocationThreshold] as NSDictionary 110 | var pixelBuffer: CVPixelBuffer? 111 | while error == kCVReturnSuccess { 112 | error = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, pool, auxAttributes, &pixelBuffer) 113 | if let pixelBuffer = pixelBuffer { 114 | pixelBuffers.append(pixelBuffer) 115 | } 116 | pixelBuffer = nil 117 | } 118 | pixelBuffers.removeAll() 119 | } 120 | -------------------------------------------------------------------------------- /DepthDetection/render/minMaxFromBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Apple Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | Abstract: 7 | Defines a function which extracts the smallest and largest values from a pixel buffer. 8 | */ 9 | 10 | #ifndef minMaxFromBuffer_h 11 | #define minMaxFromBuffer_h 12 | 13 | #import 14 | #import 15 | 16 | void minMaxFromPixelBuffer(CVPixelBufferRef pixelBuffer, float* minValue, float* maxValue, MTLPixelFormat pixelFormat); 17 | 18 | #endif /* minMaxFromBuffer_h */ 19 | -------------------------------------------------------------------------------- /DepthDetection/render/minMaxFromBuffer.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2019 Apple Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | Abstract: 7 | Implements a function which extracts the smallest and largest values from a pixel buffer. 8 | */ 9 | 10 | #import "minMaxFromBuffer.h" 11 | #import 12 | #import 13 | 14 | void minMaxFromPixelBuffer(CVPixelBufferRef pixelBuffer, float* minValue, float* maxValue, MTLPixelFormat pixelFormat) 15 | { 16 | int width = (int)CVPixelBufferGetWidth(pixelBuffer); 17 | int height = (int)CVPixelBufferGetHeight(pixelBuffer); 18 | int bytesPerRow = (int)CVPixelBufferGetBytesPerRow(pixelBuffer); 19 | 20 | CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); 21 | unsigned char* pixelBufferPointer = CVPixelBufferGetBaseAddress(pixelBuffer); 22 | __fp16* bufferP_F16 = (__fp16 *) pixelBufferPointer; 23 | float* bufferP_F32 = (float *) pixelBufferPointer; 24 | 25 | bool isFloat16 = (pixelFormat == MTLPixelFormatR16Float); 26 | uint32_t increment = isFloat16 ? bytesPerRow/sizeof(__fp16) : bytesPerRow/sizeof(float); 27 | 28 | float min = MAXFLOAT; 29 | float max = -MAXFLOAT; 30 | 31 | for (int j=0; j < height; j++) 32 | { 33 | for (int i=0; i < width; i++) 34 | { 35 | float val = ( isFloat16 ) ? bufferP_F16[i] : bufferP_F32[i] ; 36 | if (!isnan(val)) { 37 | if (val>max) max = val; 38 | if (val