├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── CHANGELOG.md ├── Demo ├── Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Demo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── Demo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── HomeCollectionViewCell.swift │ ├── HomeCollectionViewCell.xib │ ├── Info.plist │ └── ViewController.swift ├── FTImageSize.podspec ├── FTImageSize.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── FTImageSize ├── .DS_Store ├── FTImageSize.h └── FTImageSize.swift ├── LICENSE ├── Package.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | .DS_Store 6 | 7 | ## Build generated 8 | build/ 9 | DerivedData/ 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xcuserstate 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # FTImageSize 2 | 3 | ## CHNAGELOG 4 | 5 | | Version | Date | ChangeLog | 6 | | :--------: | :--------: | :-------- | 7 | | 0.0.1 | 2016-12-05 | uploading to cocoapods | 8 | | 0.0.2 | 2016-12-06 | make public | 9 | | 0.0.3 | 2016-12-07 | fix an issue | 10 | | 0.0.4 | 2016-12-14 | add max height support | 11 | | 0.0.5 | 2021-07-06 | update to swift 5 | 12 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2A52C0A02693F22A003DFE48 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A52C09F2693F22A003DFE48 /* AppDelegate.swift */; }; 11 | 2A52C0A42693F22A003DFE48 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A52C0A32693F22A003DFE48 /* ViewController.swift */; }; 12 | 2A52C0A72693F22A003DFE48 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2A52C0A52693F22A003DFE48 /* Main.storyboard */; }; 13 | 2A52C0A92693F22A003DFE48 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2A52C0A82693F22A003DFE48 /* Assets.xcassets */; }; 14 | 2A52C0AC2693F22A003DFE48 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2A52C0AA2693F22A003DFE48 /* LaunchScreen.storyboard */; }; 15 | 2ACF1356293ED34200D5A476 /* FTWaterFallLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 2ACF1355293ED34200D5A476 /* FTWaterFallLayout */; }; 16 | 2ACF1359293ED3D000D5A476 /* HomeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ACF1357293ED3D000D5A476 /* HomeCollectionViewCell.swift */; }; 17 | 2ACF135A293ED3D000D5A476 /* HomeCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2ACF1358293ED3D000D5A476 /* HomeCollectionViewCell.xib */; }; 18 | 2ACF135D293ED4A400D5A476 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 2ACF135C293ED4A400D5A476 /* Kingfisher */; }; 19 | 2ACF1360293ED4FE00D5A476 /* FTImageSize.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACF135F293ED4FE00D5A476 /* FTImageSize.framework */; }; 20 | 2ACF1361293ED4FE00D5A476 /* FTImageSize.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2ACF135F293ED4FE00D5A476 /* FTImageSize.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | 2ACF1362293ED4FF00D5A476 /* Embed Frameworks */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = ""; 28 | dstSubfolderSpec = 10; 29 | files = ( 30 | 2ACF1361293ED4FE00D5A476 /* FTImageSize.framework in Embed Frameworks */, 31 | ); 32 | name = "Embed Frameworks"; 33 | runOnlyForDeploymentPostprocessing = 0; 34 | }; 35 | /* End PBXCopyFilesBuildPhase section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 2A52C09C2693F22A003DFE48 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 2A52C09F2693F22A003DFE48 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 2A52C0A32693F22A003DFE48 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 41 | 2A52C0A62693F22A003DFE48 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 2A52C0A82693F22A003DFE48 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 2A52C0AB2693F22A003DFE48 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 2A52C0AD2693F22A003DFE48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 2ACF1357293ED3D000D5A476 /* HomeCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeCollectionViewCell.swift; sourceTree = ""; }; 46 | 2ACF1358293ED3D000D5A476 /* HomeCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HomeCollectionViewCell.xib; sourceTree = ""; }; 47 | 2ACF135F293ED4FE00D5A476 /* FTImageSize.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FTImageSize.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 2A52C0992693F22A003DFE48 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 2ACF135D293ED4A400D5A476 /* Kingfisher in Frameworks */, 56 | 2ACF1356293ED34200D5A476 /* FTWaterFallLayout in Frameworks */, 57 | 2ACF1360293ED4FE00D5A476 /* FTImageSize.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 2A52C0932693F22A003DFE48 = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2A52C09E2693F22A003DFE48 /* Demo */, 68 | 2A52C09D2693F22A003DFE48 /* Products */, 69 | 2ACF135E293ED4FE00D5A476 /* Frameworks */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | 2A52C09D2693F22A003DFE48 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 2A52C09C2693F22A003DFE48 /* Demo.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | 2A52C09E2693F22A003DFE48 /* Demo */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 2A52C09F2693F22A003DFE48 /* AppDelegate.swift */, 85 | 2A52C0A32693F22A003DFE48 /* ViewController.swift */, 86 | 2ACF1357293ED3D000D5A476 /* HomeCollectionViewCell.swift */, 87 | 2ACF1358293ED3D000D5A476 /* HomeCollectionViewCell.xib */, 88 | 2A52C0A52693F22A003DFE48 /* Main.storyboard */, 89 | 2A52C0A82693F22A003DFE48 /* Assets.xcassets */, 90 | 2A52C0AA2693F22A003DFE48 /* LaunchScreen.storyboard */, 91 | 2A52C0AD2693F22A003DFE48 /* Info.plist */, 92 | ); 93 | path = Demo; 94 | sourceTree = ""; 95 | }; 96 | 2ACF135E293ED4FE00D5A476 /* Frameworks */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 2ACF135F293ED4FE00D5A476 /* FTImageSize.framework */, 100 | ); 101 | name = Frameworks; 102 | sourceTree = ""; 103 | }; 104 | /* End PBXGroup section */ 105 | 106 | /* Begin PBXNativeTarget section */ 107 | 2A52C09B2693F22A003DFE48 /* Demo */ = { 108 | isa = PBXNativeTarget; 109 | buildConfigurationList = 2A52C0B02693F22A003DFE48 /* Build configuration list for PBXNativeTarget "Demo" */; 110 | buildPhases = ( 111 | 2A52C0982693F22A003DFE48 /* Sources */, 112 | 2A52C0992693F22A003DFE48 /* Frameworks */, 113 | 2A52C09A2693F22A003DFE48 /* Resources */, 114 | 2ACF1362293ED4FF00D5A476 /* Embed Frameworks */, 115 | ); 116 | buildRules = ( 117 | ); 118 | dependencies = ( 119 | ); 120 | name = Demo; 121 | packageProductDependencies = ( 122 | 2ACF1355293ED34200D5A476 /* FTWaterFallLayout */, 123 | 2ACF135C293ED4A400D5A476 /* Kingfisher */, 124 | ); 125 | productName = Demo; 126 | productReference = 2A52C09C2693F22A003DFE48 /* Demo.app */; 127 | productType = "com.apple.product-type.application"; 128 | }; 129 | /* End PBXNativeTarget section */ 130 | 131 | /* Begin PBXProject section */ 132 | 2A52C0942693F22A003DFE48 /* Project object */ = { 133 | isa = PBXProject; 134 | attributes = { 135 | BuildIndependentTargetsInParallel = 1; 136 | LastSwiftUpdateCheck = 1300; 137 | LastUpgradeCheck = 1300; 138 | TargetAttributes = { 139 | 2A52C09B2693F22A003DFE48 = { 140 | CreatedOnToolsVersion = 13.0; 141 | }; 142 | }; 143 | }; 144 | buildConfigurationList = 2A52C0972693F22A003DFE48 /* Build configuration list for PBXProject "Demo" */; 145 | compatibilityVersion = "Xcode 13.0"; 146 | developmentRegion = en; 147 | hasScannedForEncodings = 0; 148 | knownRegions = ( 149 | en, 150 | Base, 151 | ); 152 | mainGroup = 2A52C0932693F22A003DFE48; 153 | packageReferences = ( 154 | 2ACF1354293ED34200D5A476 /* XCRemoteSwiftPackageReference "FTWaterFallLayout" */, 155 | 2ACF135B293ED4A400D5A476 /* XCRemoteSwiftPackageReference "Kingfisher" */, 156 | ); 157 | productRefGroup = 2A52C09D2693F22A003DFE48 /* Products */; 158 | projectDirPath = ""; 159 | projectRoot = ""; 160 | targets = ( 161 | 2A52C09B2693F22A003DFE48 /* Demo */, 162 | ); 163 | }; 164 | /* End PBXProject section */ 165 | 166 | /* Begin PBXResourcesBuildPhase section */ 167 | 2A52C09A2693F22A003DFE48 /* Resources */ = { 168 | isa = PBXResourcesBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | 2A52C0AC2693F22A003DFE48 /* LaunchScreen.storyboard in Resources */, 172 | 2A52C0A92693F22A003DFE48 /* Assets.xcassets in Resources */, 173 | 2A52C0A72693F22A003DFE48 /* Main.storyboard in Resources */, 174 | 2ACF135A293ED3D000D5A476 /* HomeCollectionViewCell.xib in Resources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXResourcesBuildPhase section */ 179 | 180 | /* Begin PBXSourcesBuildPhase section */ 181 | 2A52C0982693F22A003DFE48 /* Sources */ = { 182 | isa = PBXSourcesBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | 2A52C0A42693F22A003DFE48 /* ViewController.swift in Sources */, 186 | 2A52C0A02693F22A003DFE48 /* AppDelegate.swift in Sources */, 187 | 2ACF1359293ED3D000D5A476 /* HomeCollectionViewCell.swift in Sources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXSourcesBuildPhase section */ 192 | 193 | /* Begin PBXVariantGroup section */ 194 | 2A52C0A52693F22A003DFE48 /* Main.storyboard */ = { 195 | isa = PBXVariantGroup; 196 | children = ( 197 | 2A52C0A62693F22A003DFE48 /* Base */, 198 | ); 199 | name = Main.storyboard; 200 | sourceTree = ""; 201 | }; 202 | 2A52C0AA2693F22A003DFE48 /* LaunchScreen.storyboard */ = { 203 | isa = PBXVariantGroup; 204 | children = ( 205 | 2A52C0AB2693F22A003DFE48 /* Base */, 206 | ); 207 | name = LaunchScreen.storyboard; 208 | sourceTree = ""; 209 | }; 210 | /* End PBXVariantGroup section */ 211 | 212 | /* Begin XCBuildConfiguration section */ 213 | 2A52C0AE2693F22A003DFE48 /* Debug */ = { 214 | isa = XCBuildConfiguration; 215 | buildSettings = { 216 | ALWAYS_SEARCH_USER_PATHS = NO; 217 | CLANG_ANALYZER_NONNULL = YES; 218 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 219 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 220 | CLANG_CXX_LIBRARY = "libc++"; 221 | CLANG_ENABLE_MODULES = YES; 222 | CLANG_ENABLE_OBJC_ARC = YES; 223 | CLANG_ENABLE_OBJC_WEAK = YES; 224 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_COMMA = YES; 227 | CLANG_WARN_CONSTANT_CONVERSION = YES; 228 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 229 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 230 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 236 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 237 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 238 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 239 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 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 = 15.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 | 2A52C0AF2693F22A003DFE48 /* 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 301 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 302 | CLANG_WARN_STRICT_PROTOTYPES = YES; 303 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 304 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | COPY_PHASE_STRIP = NO; 308 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 309 | ENABLE_NS_ASSERTIONS = NO; 310 | ENABLE_STRICT_OBJC_MSGSEND = YES; 311 | GCC_C_LANGUAGE_STANDARD = gnu11; 312 | GCC_NO_COMMON_BLOCKS = YES; 313 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 314 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 315 | GCC_WARN_UNDECLARED_SELECTOR = YES; 316 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 317 | GCC_WARN_UNUSED_FUNCTION = YES; 318 | GCC_WARN_UNUSED_VARIABLE = YES; 319 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 320 | MTL_ENABLE_DEBUG_INFO = NO; 321 | MTL_FAST_MATH = YES; 322 | SDKROOT = iphoneos; 323 | SWIFT_COMPILATION_MODE = wholemodule; 324 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 325 | VALIDATE_PRODUCT = YES; 326 | }; 327 | name = Release; 328 | }; 329 | 2A52C0B12693F22A003DFE48 /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | buildSettings = { 332 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 333 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 334 | CODE_SIGN_STYLE = Automatic; 335 | CURRENT_PROJECT_VERSION = 1; 336 | DEVELOPMENT_TEAM = E83AC9WR2F; 337 | GENERATE_INFOPLIST_FILE = YES; 338 | INFOPLIST_FILE = Demo/Info.plist; 339 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 340 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 341 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 342 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 343 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 344 | LD_RUNPATH_SEARCH_PATHS = ( 345 | "$(inherited)", 346 | "@executable_path/Frameworks", 347 | ); 348 | MARKETING_VERSION = 1.0; 349 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.demoss; 350 | PRODUCT_NAME = "$(TARGET_NAME)"; 351 | SWIFT_EMIT_LOC_STRINGS = YES; 352 | SWIFT_VERSION = 5.0; 353 | TARGETED_DEVICE_FAMILY = "1,2"; 354 | }; 355 | name = Debug; 356 | }; 357 | 2A52C0B22693F22A003DFE48 /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 361 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 362 | CODE_SIGN_STYLE = Automatic; 363 | CURRENT_PROJECT_VERSION = 1; 364 | DEVELOPMENT_TEAM = E83AC9WR2F; 365 | GENERATE_INFOPLIST_FILE = YES; 366 | INFOPLIST_FILE = Demo/Info.plist; 367 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 368 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 369 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 370 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 371 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 372 | LD_RUNPATH_SEARCH_PATHS = ( 373 | "$(inherited)", 374 | "@executable_path/Frameworks", 375 | ); 376 | MARKETING_VERSION = 1.0; 377 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.demoss; 378 | PRODUCT_NAME = "$(TARGET_NAME)"; 379 | SWIFT_EMIT_LOC_STRINGS = YES; 380 | SWIFT_VERSION = 5.0; 381 | TARGETED_DEVICE_FAMILY = "1,2"; 382 | }; 383 | name = Release; 384 | }; 385 | /* End XCBuildConfiguration section */ 386 | 387 | /* Begin XCConfigurationList section */ 388 | 2A52C0972693F22A003DFE48 /* Build configuration list for PBXProject "Demo" */ = { 389 | isa = XCConfigurationList; 390 | buildConfigurations = ( 391 | 2A52C0AE2693F22A003DFE48 /* Debug */, 392 | 2A52C0AF2693F22A003DFE48 /* Release */, 393 | ); 394 | defaultConfigurationIsVisible = 0; 395 | defaultConfigurationName = Release; 396 | }; 397 | 2A52C0B02693F22A003DFE48 /* Build configuration list for PBXNativeTarget "Demo" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | 2A52C0B12693F22A003DFE48 /* Debug */, 401 | 2A52C0B22693F22A003DFE48 /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | /* End XCConfigurationList section */ 407 | 408 | /* Begin XCRemoteSwiftPackageReference section */ 409 | 2ACF1354293ED34200D5A476 /* XCRemoteSwiftPackageReference "FTWaterFallLayout" */ = { 410 | isa = XCRemoteSwiftPackageReference; 411 | repositoryURL = "https://github.com/liufengting/FTWaterFallLayout"; 412 | requirement = { 413 | kind = upToNextMajorVersion; 414 | minimumVersion = 0.0.9; 415 | }; 416 | }; 417 | 2ACF135B293ED4A400D5A476 /* XCRemoteSwiftPackageReference "Kingfisher" */ = { 418 | isa = XCRemoteSwiftPackageReference; 419 | repositoryURL = "https://github.com/onevcat/Kingfisher.git"; 420 | requirement = { 421 | kind = upToNextMajorVersion; 422 | minimumVersion = 7.0.0; 423 | }; 424 | }; 425 | /* End XCRemoteSwiftPackageReference section */ 426 | 427 | /* Begin XCSwiftPackageProductDependency section */ 428 | 2ACF1355293ED34200D5A476 /* FTWaterFallLayout */ = { 429 | isa = XCSwiftPackageProductDependency; 430 | package = 2ACF1354293ED34200D5A476 /* XCRemoteSwiftPackageReference "FTWaterFallLayout" */; 431 | productName = FTWaterFallLayout; 432 | }; 433 | 2ACF135C293ED4A400D5A476 /* Kingfisher */ = { 434 | isa = XCSwiftPackageProductDependency; 435 | package = 2ACF135B293ED4A400D5A476 /* XCRemoteSwiftPackageReference "Kingfisher" */; 436 | productName = Kingfisher; 437 | }; 438 | /* End XCSwiftPackageProductDependency section */ 439 | }; 440 | rootObject = 2A52C0942693F22A003DFE48 /* Project object */; 441 | } 442 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "ftwaterfalllayout", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/liufengting/FTWaterFallLayout", 7 | "state" : { 8 | "revision" : "7b0efc4fd1ea9f20f94cd9cbead5fe13aee90283", 9 | "version" : "0.0.9" 10 | } 11 | }, 12 | { 13 | "identity" : "kingfisher", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/onevcat/Kingfisher.git", 16 | "state" : { 17 | "revision" : "44e891bdb61426a95e31492a67c7c0dfad1f87c5", 18 | "version" : "7.4.1" 19 | } 20 | } 21 | ], 22 | "version" : 2 23 | } 24 | -------------------------------------------------------------------------------- /Demo/Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Demo 4 | // 5 | // Created by LiuFengting on 2021/7/6. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Demo/Demo/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 | -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Demo/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 | -------------------------------------------------------------------------------- /Demo/Demo/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 | 23 | 24 | 25 | 26 | 27 | 28 | 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 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Demo/Demo/HomeCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeCollectionViewCell.swift 3 | // Demo 4 | // 5 | // Created by LiuFengting on 2021/7/1. 6 | // 7 | 8 | import UIKit 9 | import Kingfisher 10 | 11 | public let homeCellReuseIdentifier = "HomeCollectionViewCellIdentifier" 12 | 13 | class HomeCollectionViewCell: UICollectionViewCell { 14 | 15 | @IBOutlet weak var imageView: UIImageView! 16 | 17 | override func awakeFromNib() { 18 | self.layer.cornerRadius = 5 19 | self.imageView.layer.cornerRadius = 5 20 | self.selectedBackgroundView = self.selectedBGView 21 | } 22 | 23 | func setupWith(imageURLString: String) { 24 | if let url = URL(string: imageURLString) { 25 | self.imageView.kf.setImage(with: url) 26 | } 27 | } 28 | 29 | var selectedBGView: UIView { 30 | let view = UIView(frame: self.bounds) 31 | view.backgroundColor = UIColor.init(white: 0.95, alpha: 1) 32 | return view 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Demo/Demo/HomeCollectionViewCell.xib: -------------------------------------------------------------------------------- 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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Demo/Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppTransportSecurity 6 | 7 | NSAllowsArbitraryLoads 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Demo/Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Demo 4 | // 5 | // Created by LiuFengting on 2021/7/6. 6 | // 7 | 8 | import UIKit 9 | import FTImageSize 10 | import FTWaterFallLayout 11 | 12 | class ViewController: UIViewController , UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, FTWaterFallLayoutDelegate { 13 | 14 | @IBOutlet weak var collectionView: UICollectionView! 15 | 16 | var imageURLs: [String] = [ "https://wx4.sinaimg.cn/mw600/007wHJ1wly1gs6ocli7hlj318g0toary.jpg", 17 | "https://wx1.sinaimg.cn/orj360/006KDv0Jly1gs1hys0m1zj33402c0qv5.jpg", 18 | "https://wx1.sinaimg.cn/orj360/006KDv0Jly1gs1hytnobhj33402c0npd.jpg", 19 | "https://wx1.sinaimg.cn/orj360/006KDv0Jly1gs1hyxep3aj31hc0u044q.jpg", 20 | "https://wx1.sinaimg.cn/mw600/007wHJ1wly1gs1hnskhshj30go0fm41t.jpg", 21 | "https://wx1.sinaimg.cn/mw600/007wHJ1wly1gs1h6z1k8rj30jg0pygo8.jpg", 22 | "https://wx1.sinaimg.cn/mw600/007wHJ1wly1gs1gs24581j30u00wvwg7.jpg"] 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | 27 | self.collectionView.register(UINib(nibName: "HomeCollectionViewCell", bundle: Bundle.main), forCellWithReuseIdentifier: homeCellReuseIdentifier) 28 | self.collectionView.collectionViewLayout = collectionViewLayout 29 | } 30 | 31 | var collectionViewLayout: FTWaterFallLayout { 32 | let layout: FTWaterFallLayout = FTWaterFallLayout() 33 | layout.numberOfColumns = 2 34 | layout.sectionInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) 35 | layout.itemMaginSize = CGSize(width: 10, height: 10) 36 | layout.delegate = self 37 | return layout 38 | } 39 | 40 | 41 | // MARK: FTWaterFallLayoutDelegate 42 | 43 | func ftWaterFallLayout(_ layout: FTWaterFallLayout, heightForItemAt indexPath: IndexPath) -> CGFloat { 44 | let preferdWidth: CGFloat = (self.view.bounds.size.width - 30)/2 45 | let imageSize: CGSize = FTImageSize.shared.getImageSizeFromImageURL(imageURLs[indexPath.item], perferdWidth: preferdWidth) 46 | return imageSize.height 47 | } 48 | 49 | // MARK: UICollectionViewDataSource 50 | 51 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 52 | return imageURLs.count 53 | } 54 | 55 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 56 | let cell: HomeCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: homeCellReuseIdentifier, for: indexPath) as! HomeCollectionViewCell 57 | cell.setupWith(imageURLString: imageURLs[indexPath.item]) 58 | return cell 59 | } 60 | 61 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 62 | collectionView.deselectItem(at: indexPath, animated: true) 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /FTImageSize.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = "FTImageSize" 5 | s.version = "0.0.6" 6 | s.summary = "Get image size from image url synchronously" 7 | s.description = <<-DESC 8 | FTImageSize. Get image size from image url synchronously. 9 | DESC 10 | s.homepage = "https://github.com/liufengting/FTImageSize" 11 | s.license = { :type => "MIT", :file => "LICENSE" } 12 | s.author = { "liufengting" => "wo157121900@me.com" } 13 | s.platform = :ios, "8.0" 14 | s.source = { :git => "https://github.com/liufengting/FTImageSize.git", :tag => "#{s.version}" } 15 | s.source_files = ["FTImageSize/*.swift"] 16 | s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' } 17 | 18 | end 19 | -------------------------------------------------------------------------------- /FTImageSize.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2ADDCC0A268DA45B00210027 /* FTImageSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ADDCC09268DA45B00210027 /* FTImageSize.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 2ADDCC11268DA48100210027 /* FTImageSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2ADDCC10268DA48100210027 /* FTImageSize.swift */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 2ADDCC06268DA45B00210027 /* FTImageSize.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FTImageSize.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 2ADDCC09268DA45B00210027 /* FTImageSize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FTImageSize.h; sourceTree = ""; }; 17 | 2ADDCC10268DA48100210027 /* FTImageSize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTImageSize.swift; sourceTree = ""; }; 18 | /* End PBXFileReference section */ 19 | 20 | /* Begin PBXFrameworksBuildPhase section */ 21 | 2ADDCC03268DA45B00210027 /* Frameworks */ = { 22 | isa = PBXFrameworksBuildPhase; 23 | buildActionMask = 2147483647; 24 | files = ( 25 | ); 26 | runOnlyForDeploymentPostprocessing = 0; 27 | }; 28 | /* End PBXFrameworksBuildPhase section */ 29 | 30 | /* Begin PBXGroup section */ 31 | 2ADDCBFC268DA45B00210027 = { 32 | isa = PBXGroup; 33 | children = ( 34 | 2ADDCC08268DA45B00210027 /* FTImageSize */, 35 | 2ADDCC07268DA45B00210027 /* Products */, 36 | ); 37 | sourceTree = ""; 38 | }; 39 | 2ADDCC07268DA45B00210027 /* Products */ = { 40 | isa = PBXGroup; 41 | children = ( 42 | 2ADDCC06268DA45B00210027 /* FTImageSize.framework */, 43 | ); 44 | name = Products; 45 | sourceTree = ""; 46 | }; 47 | 2ADDCC08268DA45B00210027 /* FTImageSize */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | 2ADDCC09268DA45B00210027 /* FTImageSize.h */, 51 | 2ADDCC10268DA48100210027 /* FTImageSize.swift */, 52 | ); 53 | path = FTImageSize; 54 | sourceTree = ""; 55 | }; 56 | /* End PBXGroup section */ 57 | 58 | /* Begin PBXHeadersBuildPhase section */ 59 | 2ADDCC01268DA45B00210027 /* Headers */ = { 60 | isa = PBXHeadersBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 2ADDCC0A268DA45B00210027 /* FTImageSize.h in Headers */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXHeadersBuildPhase section */ 68 | 69 | /* Begin PBXNativeTarget section */ 70 | 2ADDCC05268DA45B00210027 /* FTImageSize */ = { 71 | isa = PBXNativeTarget; 72 | buildConfigurationList = 2ADDCC0D268DA45B00210027 /* Build configuration list for PBXNativeTarget "FTImageSize" */; 73 | buildPhases = ( 74 | 2ADDCC01268DA45B00210027 /* Headers */, 75 | 2ADDCC02268DA45B00210027 /* Sources */, 76 | 2ADDCC03268DA45B00210027 /* Frameworks */, 77 | 2ADDCC04268DA45B00210027 /* Resources */, 78 | ); 79 | buildRules = ( 80 | ); 81 | dependencies = ( 82 | ); 83 | name = FTImageSize; 84 | productName = FTImageSize; 85 | productReference = 2ADDCC06268DA45B00210027 /* FTImageSize.framework */; 86 | productType = "com.apple.product-type.framework"; 87 | }; 88 | /* End PBXNativeTarget section */ 89 | 90 | /* Begin PBXProject section */ 91 | 2ADDCBFD268DA45B00210027 /* Project object */ = { 92 | isa = PBXProject; 93 | attributes = { 94 | BuildIndependentTargetsInParallel = 1; 95 | LastUpgradeCheck = 1300; 96 | TargetAttributes = { 97 | 2ADDCC05268DA45B00210027 = { 98 | CreatedOnToolsVersion = 13.0; 99 | LastSwiftMigration = 1300; 100 | }; 101 | }; 102 | }; 103 | buildConfigurationList = 2ADDCC00268DA45B00210027 /* Build configuration list for PBXProject "FTImageSize" */; 104 | compatibilityVersion = "Xcode 13.0"; 105 | developmentRegion = en; 106 | hasScannedForEncodings = 0; 107 | knownRegions = ( 108 | en, 109 | Base, 110 | ); 111 | mainGroup = 2ADDCBFC268DA45B00210027; 112 | productRefGroup = 2ADDCC07268DA45B00210027 /* Products */; 113 | projectDirPath = ""; 114 | projectRoot = ""; 115 | targets = ( 116 | 2ADDCC05268DA45B00210027 /* FTImageSize */, 117 | ); 118 | }; 119 | /* End PBXProject section */ 120 | 121 | /* Begin PBXResourcesBuildPhase section */ 122 | 2ADDCC04268DA45B00210027 /* Resources */ = { 123 | isa = PBXResourcesBuildPhase; 124 | buildActionMask = 2147483647; 125 | files = ( 126 | ); 127 | runOnlyForDeploymentPostprocessing = 0; 128 | }; 129 | /* End PBXResourcesBuildPhase section */ 130 | 131 | /* Begin PBXSourcesBuildPhase section */ 132 | 2ADDCC02268DA45B00210027 /* Sources */ = { 133 | isa = PBXSourcesBuildPhase; 134 | buildActionMask = 2147483647; 135 | files = ( 136 | 2ADDCC11268DA48100210027 /* FTImageSize.swift in Sources */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXSourcesBuildPhase section */ 141 | 142 | /* Begin XCBuildConfiguration section */ 143 | 2ADDCC0B268DA45B00210027 /* Debug */ = { 144 | isa = XCBuildConfiguration; 145 | buildSettings = { 146 | ALWAYS_SEARCH_USER_PATHS = NO; 147 | CLANG_ANALYZER_NONNULL = YES; 148 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 149 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 150 | CLANG_CXX_LIBRARY = "libc++"; 151 | CLANG_ENABLE_MODULES = YES; 152 | CLANG_ENABLE_OBJC_ARC = YES; 153 | CLANG_ENABLE_OBJC_WEAK = YES; 154 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 155 | CLANG_WARN_BOOL_CONVERSION = YES; 156 | CLANG_WARN_COMMA = YES; 157 | CLANG_WARN_CONSTANT_CONVERSION = YES; 158 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 159 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 160 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 161 | CLANG_WARN_EMPTY_BODY = YES; 162 | CLANG_WARN_ENUM_CONVERSION = YES; 163 | CLANG_WARN_INFINITE_RECURSION = YES; 164 | CLANG_WARN_INT_CONVERSION = YES; 165 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 166 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 167 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 169 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | COPY_PHASE_STRIP = NO; 177 | CURRENT_PROJECT_VERSION = 1; 178 | DEBUG_INFORMATION_FORMAT = dwarf; 179 | ENABLE_STRICT_OBJC_MSGSEND = YES; 180 | ENABLE_TESTABILITY = YES; 181 | GCC_C_LANGUAGE_STANDARD = gnu11; 182 | GCC_DYNAMIC_NO_PIC = NO; 183 | GCC_NO_COMMON_BLOCKS = YES; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | GCC_PREPROCESSOR_DEFINITIONS = ( 186 | "DEBUG=1", 187 | "$(inherited)", 188 | ); 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_UNDECLARED_SELECTOR = YES; 192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 193 | GCC_WARN_UNUSED_FUNCTION = YES; 194 | GCC_WARN_UNUSED_VARIABLE = YES; 195 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 196 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 197 | MTL_FAST_MATH = YES; 198 | ONLY_ACTIVE_ARCH = YES; 199 | SDKROOT = iphoneos; 200 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 201 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 202 | VERSIONING_SYSTEM = "apple-generic"; 203 | VERSION_INFO_PREFIX = ""; 204 | }; 205 | name = Debug; 206 | }; 207 | 2ADDCC0C268DA45B00210027 /* Release */ = { 208 | isa = XCBuildConfiguration; 209 | buildSettings = { 210 | ALWAYS_SEARCH_USER_PATHS = NO; 211 | CLANG_ANALYZER_NONNULL = YES; 212 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 213 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 214 | CLANG_CXX_LIBRARY = "libc++"; 215 | CLANG_ENABLE_MODULES = YES; 216 | CLANG_ENABLE_OBJC_ARC = YES; 217 | CLANG_ENABLE_OBJC_WEAK = YES; 218 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 219 | CLANG_WARN_BOOL_CONVERSION = YES; 220 | CLANG_WARN_COMMA = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 223 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 224 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 225 | CLANG_WARN_EMPTY_BODY = YES; 226 | CLANG_WARN_ENUM_CONVERSION = YES; 227 | CLANG_WARN_INFINITE_RECURSION = YES; 228 | CLANG_WARN_INT_CONVERSION = YES; 229 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 230 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 231 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 232 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 233 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 234 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 235 | CLANG_WARN_STRICT_PROTOTYPES = YES; 236 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 237 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 238 | CLANG_WARN_UNREACHABLE_CODE = YES; 239 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 240 | COPY_PHASE_STRIP = NO; 241 | CURRENT_PROJECT_VERSION = 1; 242 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 243 | ENABLE_NS_ASSERTIONS = NO; 244 | ENABLE_STRICT_OBJC_MSGSEND = YES; 245 | GCC_C_LANGUAGE_STANDARD = gnu11; 246 | GCC_NO_COMMON_BLOCKS = YES; 247 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 248 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 249 | GCC_WARN_UNDECLARED_SELECTOR = YES; 250 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 251 | GCC_WARN_UNUSED_FUNCTION = YES; 252 | GCC_WARN_UNUSED_VARIABLE = YES; 253 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 254 | MTL_ENABLE_DEBUG_INFO = NO; 255 | MTL_FAST_MATH = YES; 256 | SDKROOT = iphoneos; 257 | SWIFT_COMPILATION_MODE = wholemodule; 258 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 259 | VALIDATE_PRODUCT = YES; 260 | VERSIONING_SYSTEM = "apple-generic"; 261 | VERSION_INFO_PREFIX = ""; 262 | }; 263 | name = Release; 264 | }; 265 | 2ADDCC0E268DA45B00210027 /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | CLANG_ENABLE_MODULES = YES; 269 | CODE_SIGN_STYLE = Automatic; 270 | CURRENT_PROJECT_VERSION = 1; 271 | DEFINES_MODULE = YES; 272 | DEVELOPMENT_TEAM = E83AC9WR2F; 273 | DYLIB_COMPATIBILITY_VERSION = 1; 274 | DYLIB_CURRENT_VERSION = 1; 275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 276 | GENERATE_INFOPLIST_FILE = YES; 277 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 278 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 279 | LD_RUNPATH_SEARCH_PATHS = ( 280 | "$(inherited)", 281 | "@executable_path/Frameworks", 282 | "@loader_path/Frameworks", 283 | ); 284 | MARKETING_VERSION = 1.0; 285 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTImageSize; 286 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 287 | SKIP_INSTALL = YES; 288 | SWIFT_EMIT_LOC_STRINGS = YES; 289 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 290 | SWIFT_VERSION = 5.0; 291 | TARGETED_DEVICE_FAMILY = "1,2"; 292 | }; 293 | name = Debug; 294 | }; 295 | 2ADDCC0F268DA45B00210027 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | CLANG_ENABLE_MODULES = YES; 299 | CODE_SIGN_STYLE = Automatic; 300 | CURRENT_PROJECT_VERSION = 1; 301 | DEFINES_MODULE = YES; 302 | DEVELOPMENT_TEAM = E83AC9WR2F; 303 | DYLIB_COMPATIBILITY_VERSION = 1; 304 | DYLIB_CURRENT_VERSION = 1; 305 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 306 | GENERATE_INFOPLIST_FILE = YES; 307 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 308 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 309 | LD_RUNPATH_SEARCH_PATHS = ( 310 | "$(inherited)", 311 | "@executable_path/Frameworks", 312 | "@loader_path/Frameworks", 313 | ); 314 | MARKETING_VERSION = 1.0; 315 | PRODUCT_BUNDLE_IDENTIFIER = com.liufengting.FTImageSize; 316 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 317 | SKIP_INSTALL = YES; 318 | SWIFT_EMIT_LOC_STRINGS = YES; 319 | SWIFT_VERSION = 5.0; 320 | TARGETED_DEVICE_FAMILY = "1,2"; 321 | }; 322 | name = Release; 323 | }; 324 | /* End XCBuildConfiguration section */ 325 | 326 | /* Begin XCConfigurationList section */ 327 | 2ADDCC00268DA45B00210027 /* Build configuration list for PBXProject "FTImageSize" */ = { 328 | isa = XCConfigurationList; 329 | buildConfigurations = ( 330 | 2ADDCC0B268DA45B00210027 /* Debug */, 331 | 2ADDCC0C268DA45B00210027 /* Release */, 332 | ); 333 | defaultConfigurationIsVisible = 0; 334 | defaultConfigurationName = Release; 335 | }; 336 | 2ADDCC0D268DA45B00210027 /* Build configuration list for PBXNativeTarget "FTImageSize" */ = { 337 | isa = XCConfigurationList; 338 | buildConfigurations = ( 339 | 2ADDCC0E268DA45B00210027 /* Debug */, 340 | 2ADDCC0F268DA45B00210027 /* Release */, 341 | ); 342 | defaultConfigurationIsVisible = 0; 343 | defaultConfigurationName = Release; 344 | }; 345 | /* End XCConfigurationList section */ 346 | }; 347 | rootObject = 2ADDCBFD268DA45B00210027 /* Project object */; 348 | } 349 | -------------------------------------------------------------------------------- /FTImageSize.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FTImageSize.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FTImageSize/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liufengting/FTImageSize/9950fff2fe0eb78820af944e28ae9dc2bc1ed9f4/FTImageSize/.DS_Store -------------------------------------------------------------------------------- /FTImageSize/FTImageSize.h: -------------------------------------------------------------------------------- 1 | // 2 | // FTImageSize.h 3 | // FTImageSize 4 | // 5 | // Created by LiuFengting on 2021/7/1. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for FTImageSize. 11 | FOUNDATION_EXPORT double FTImageSizeVersionNumber; 12 | 13 | //! Project version string for FTImageSize. 14 | FOUNDATION_EXPORT const unsigned char FTImageSizeVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /FTImageSize/FTImageSize.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FTImageSize.swift 3 | // FTImageSize 4 | // 5 | // Created by liufengting on 02/12/2016. 6 | // Copyright © 2016 LiuFengting (https://github.com/liufengting) . All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension FTImageSize { 12 | 13 | /// get image size, with perfered width and max height 14 | /// 15 | /// - Parameters: 16 | /// - imageURL: image url 17 | /// - perferdWidth: perferd Width 18 | /// - maxHeight: max height 19 | /// - Returns: image size 20 | func getImageSizeFromImageURL(_ imageURL: String, perferdWidth: CGFloat, maxHeight: CGFloat = CGFloat(MAXFLOAT)) -> CGSize { 21 | return self.convertSize(size: self.getImageSize(imageURL), perferdWidth: perferdWidth, maxHeight: maxHeight) 22 | } 23 | 24 | /// private function: convertImageSize 25 | /// 26 | /// - Parameters: 27 | /// - size: original image size 28 | /// - perferdWidth: perfered width 29 | /// - maxHeight: max height 30 | /// - Returns: image size 31 | func convertSize(size: CGSize, perferdWidth: CGFloat, maxHeight: CGFloat = CGFloat(MAXFLOAT)) -> CGSize { 32 | var convertedSize : CGSize = CGSize.zero 33 | if size.width == 0 || size.height == 0 { 34 | return CGSize(width: perferdWidth, height: perferdWidth) 35 | } 36 | convertedSize.width = perferdWidth 37 | convertedSize.height = min((size.height * perferdWidth) / size.width, maxHeight) 38 | return convertedSize 39 | } 40 | } 41 | 42 | public class FTImageSize: NSObject { 43 | 44 | public static var shared: FTImageSize = { 45 | return FTImageSize() 46 | }() 47 | 48 | /// get remote image original size with image url 49 | /// 50 | /// - Parameter imageURL: image url 51 | /// - Returns: image original size 52 | public func getImageSize(_ urlString: String) -> CGSize { 53 | self.getImageSize(URL(string: urlString)) 54 | } 55 | 56 | 57 | public func getImageSize(_ url: URL?) -> CGSize { 58 | guard let url = url else { 59 | return CGSize.zero 60 | } 61 | var size = CGSize.zero 62 | let pathExtendsion = url.pathExtension.lowercased() 63 | if pathExtendsion == "png" { 64 | size = self.getPNGImageSize(url) 65 | } else if pathExtendsion == "gif" { 66 | size = self.getGIFImageSize(url) 67 | } else { 68 | size = self.getJPGImageSize(url) 69 | } 70 | if CGSize.zero.equalTo(size) { 71 | size = self.getImageSizeByDownload(url) 72 | } 73 | return size 74 | } 75 | 76 | 77 | private func sendSynchronousRequest(_ urlRequest: URLRequest) -> Data? { 78 | var data: Data? 79 | let semaphore = DispatchSemaphore(value:0) 80 | URLSession.shared.dataTask(with: urlRequest) { (resData, response, error) in 81 | data = resData 82 | semaphore.signal() 83 | }.resume() 84 | semaphore.wait() 85 | return data 86 | } 87 | 88 | private func getImageSizeByDownload(_ url: URL) -> CGSize { 89 | let data = self.sendSynchronousRequest(URLRequest(url: url)) 90 | guard let data = data else { 91 | return CGSize.zero 92 | } 93 | guard let image = UIImage(data: data) else { 94 | return CGSize.zero 95 | } 96 | return image.size 97 | } 98 | 99 | 100 | /// private function: getPNGImageSize 101 | /// 102 | /// - Parameter request: image request 103 | /// - Returns: image original size 104 | private func getPNGImageSize(_ url: URL) -> CGSize { 105 | var request: URLRequest = URLRequest(url: url) 106 | request.setValue("bytes=16-23", forHTTPHeaderField: "Range") 107 | guard let data = self.sendSynchronousRequest(request) else { 108 | return CGSize.zero 109 | } 110 | 111 | if data.count == 8 { 112 | var w1:Int = 0 113 | var w2:Int = 0 114 | var w3:Int = 0 115 | var w4:Int = 0 116 | (data as NSData).getBytes(&w1, range: NSMakeRange(0, 1)) 117 | (data as NSData).getBytes(&w2, range: NSMakeRange(1, 1)) 118 | (data as NSData).getBytes(&w3, range: NSMakeRange(2, 1)) 119 | (data as NSData).getBytes(&w4, range: NSMakeRange(3, 1)) 120 | 121 | let w = (w1 << 24) + (w2 << 16) + (w3 << 8) + w4 122 | var h1:Int = 0 123 | var h2:Int = 0 124 | var h3:Int = 0 125 | var h4:Int = 0 126 | (data as NSData).getBytes(&h1, range: NSMakeRange(4, 1)) 127 | (data as NSData).getBytes(&h2, range: NSMakeRange(5, 1)) 128 | (data as NSData).getBytes(&h3, range: NSMakeRange(6, 1)) 129 | (data as NSData).getBytes(&h4, range: NSMakeRange(7, 1)) 130 | let h = (h1 << 24) + (h2 << 16) + (h3 << 8) + h4 131 | 132 | return CGSize(width: CGFloat(w), height: CGFloat(h)); 133 | } 134 | return CGSize.zero; 135 | } 136 | 137 | /// private function: getGIFImageSize 138 | /// 139 | /// - Parameter request: image request 140 | /// - Returns: image original size 141 | private func getGIFImageSize(_ url: URL) -> CGSize { 142 | var request = URLRequest(url: url) 143 | request.setValue("bytes=6-9", forHTTPHeaderField: "Range") 144 | guard let data = self.sendSynchronousRequest(request) else { 145 | return CGSize.zero 146 | } 147 | if data.count == 4 { 148 | var w1:Int = 0 149 | var w2:Int = 0 150 | 151 | (data as NSData).getBytes(&w1, range: NSMakeRange(0, 1)) 152 | (data as NSData).getBytes(&w2, range: NSMakeRange(1, 1)) 153 | 154 | let w = w1 + (w2 << 8) 155 | var h1:Int = 0 156 | var h2:Int = 0 157 | 158 | (data as NSData).getBytes(&h1, range: NSMakeRange(2, 1)) 159 | (data as NSData).getBytes(&h2, range: NSMakeRange(3, 1)) 160 | let h = h1 + (h2 << 8) 161 | 162 | return CGSize(width: CGFloat(w), height: CGFloat(h)); 163 | } 164 | 165 | return CGSize.zero 166 | } 167 | 168 | /// private function: getJPGImageSize 169 | /// 170 | /// - Parameter request: image request 171 | /// - Returns: image original size 172 | private func getJPGImageSize(_ url: URL) -> CGSize { 173 | var request = URLRequest(url: url) 174 | request.setValue("bytes=0-209", forHTTPHeaderField: "Range") 175 | guard let data = self.sendSynchronousRequest(request) else { 176 | return CGSize.zero 177 | } 178 | 179 | if data.count <= 0x58 { 180 | return CGSize.zero 181 | 182 | } 183 | if data.count < 210 { 184 | var w1:Int = 0 185 | var w2:Int = 0 186 | 187 | (data as NSData).getBytes(&w1, range: NSMakeRange(0x60, 0x1)) 188 | (data as NSData).getBytes(&w2, range: NSMakeRange(0x61, 0x1)) 189 | 190 | let w = (w1 << 8) + w2 191 | var h1:Int = 0 192 | var h2:Int = 0 193 | 194 | (data as NSData).getBytes(&h1, range: NSMakeRange(0x5e, 0x1)) 195 | (data as NSData).getBytes(&h2, range: NSMakeRange(0x5f, 0x1)) 196 | let h = (h1 << 8) + h2 197 | 198 | return CGSize(width: CGFloat(w), height: CGFloat(h)); 199 | 200 | } else { 201 | var word = 0x0 202 | (data as NSData).getBytes(&word, range: NSMakeRange(0x15, 0x1)) 203 | if word == 0xdb { 204 | (data as NSData).getBytes(&word, range: NSMakeRange(0x5a, 0x1)) 205 | if word == 0xdb { 206 | var w1:Int = 0 207 | var w2:Int = 0 208 | 209 | (data as NSData).getBytes(&w1, range: NSMakeRange(0xa5, 0x1)) 210 | (data as NSData).getBytes(&w2, range: NSMakeRange(0xa6, 0x1)) 211 | 212 | let w = (w1 << 8) + w2 213 | var h1:Int = 0 214 | var h2:Int = 0 215 | 216 | (data as NSData).getBytes(&h1, range: NSMakeRange(0xa3, 0x1)) 217 | (data as NSData).getBytes(&h2, range: NSMakeRange(0xa4, 0x1)) 218 | let h = (h1 << 8) + h2 219 | 220 | return CGSize(width: CGFloat(w), height: CGFloat(h)); 221 | } else { 222 | var w1:Int = 0 223 | var w2:Int = 0 224 | 225 | (data as NSData).getBytes(&w1, range: NSMakeRange(0x60, 0x1)) 226 | (data as NSData).getBytes(&w2, range: NSMakeRange(0x61, 0x1)) 227 | 228 | let w = (w1 << 8) + w2 229 | var h1:Int = 0 230 | var h2:Int = 0 231 | 232 | (data as NSData).getBytes(&h1, range: NSMakeRange(0x5e, 0x1)) 233 | (data as NSData).getBytes(&h2, range: NSMakeRange(0x5f, 0x1)) 234 | let h = (h1 << 8) + h2 235 | 236 | return CGSize(width: CGFloat(w), height: CGFloat(h)); 237 | } 238 | } else { 239 | return CGSize.zero; 240 | } 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Liu Fengting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "FTImageSize", 7 | platforms: [ .iOS(.v12), .macOS(.v10_14)], 8 | products: [ 9 | .library(name: "FTImageSize", targets: ["FTImageSize"]), 10 | ], 11 | targets: [ 12 | .target(name: "FTImageSize", path: "FTImageSize") 13 | ], 14 | swiftLanguageVersions: [.v5] 15 | ) 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FTImageSize 2 | 3 | FTImageSize. Get image size from remote image url synchronously, without downloading it. 4 | 5 | [See full demo](https://github.com/liufengting/FTPinterest) 6 | 7 | 8 | --------------------------------------------------------------------------------