├── .gitignore ├── .travis.yml ├── LICENSE ├── Pod └── Classes │ ├── .gitkeep │ ├── UIImage+Wechat.h │ └── UIImage+Wechat.m ├── README.md ├── WCImageCompress.podspec └── configure /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -workspace Example/${POD_NAME}.xcworkspace -scheme ${POD_NAME}-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 YangHu 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 | -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WearFlatShoesToWalkTheWorld/WCImageCompress/651a7869536e24f713c9d4b23ab5dd91ea58241c/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/UIImage+Wechat.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Wechat.h 3 | // 4 | // Created by tiger on 2017/2/21. 5 | // Copyright © 2017年 xinma. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface UIImage (Wechat) 11 | 12 | /** 13 | use session compress Strategy 14 | */ 15 | - (UIImage *)wcSessionCompress; 16 | 17 | /** 18 | use timeline compress Strategy 19 | */ 20 | - (UIImage *)wcTimelineCompress; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Pod/Classes/UIImage+Wechat.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Wechat.m 3 | // 4 | // Created by tiger on 2017/2/21. 5 | // Copyright © 2017年 xinma. All rights reserved. 6 | // 7 | 8 | #import "UIImage+Wechat.h" 9 | 10 | @implementation UIImage (Wechat) 11 | 12 | - (UIImage *)wcSessionCompress { 13 | return [self wcCompres:YES]; 14 | } 15 | 16 | - (UIImage *)wcTimelineCompress { 17 | return [self wcCompres:NO]; 18 | } 19 | 20 | /** 21 | wechat image compress 22 | 23 | @param isSession session image boundary is 800, timeline is 1280 24 | 25 | @return thumb image 26 | */ 27 | - (UIImage *)wcCompres:(Boolean)isSession { 28 | CGSize size = [self wxImageSize:isSession]; 29 | UIImage *reImage = [self resizedImage:size]; 30 | NSData *data = UIImageJPEGRepresentation(reImage, 0.5); 31 | return [[UIImage alloc] initWithData:data]; 32 | } 33 | 34 | 35 | /** 36 | get wechat compress image size 37 | 38 | @return thumb image size 39 | */ 40 | - (CGSize)wxImageSize:(Boolean)isSession { 41 | CGFloat width = self.size.width; 42 | CGFloat height = self.size.height; 43 | CGFloat boundary = 1280; 44 | 45 | // width, height <= 1280, Size remains the same 46 | if (width < boundary && height < boundary) { 47 | return CGSizeMake(width, height); 48 | } 49 | 50 | // aspect ratio 51 | CGFloat ratio = MAX(width, height) / MIN(width, height); 52 | if (ratio <= 2) { 53 | CGFloat x = MAX(width, height) / boundary; 54 | if (width > height) { 55 | width = boundary; 56 | height = height / x; 57 | } else { 58 | height = boundary; 59 | width = width / x; 60 | } 61 | } else { 62 | // width, height > 1280 63 | if (MIN(width, height) >= boundary) { 64 | boundary = isSession ? 800 : 1280; 65 | // Set the smaller value to the boundary, and the larger value is compressed 66 | CGFloat x = MIN(width, height) / boundary; 67 | if (width < height) { 68 | width = boundary; 69 | height = height / x; 70 | } else { 71 | height = boundary; 72 | width = width / x; 73 | } 74 | } 75 | } 76 | 77 | return CGSizeMake(width, height); 78 | } 79 | 80 | /** 81 | Zoom the picture to the specified size 82 | 83 | @param newSize session image boundary is 800, timeline is 1280 84 | 85 | @return new image 86 | */ 87 | - (UIImage *)resizedImage:(CGSize)newSize { 88 | CGRect newRect = CGRectMake(0, 0, newSize.width, newSize.height); 89 | UIGraphicsBeginImageContext(newRect.size); 90 | UIImage *newImage = [[UIImage alloc] initWithCGImage:self.CGImage scale:1 orientation:self. imageOrientation]; 91 | [newImage drawInRect:newRect]; 92 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 93 | UIGraphicsEndImageContext(); 94 | return newImage; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 项目描述 2 | 图片作为App中重要的一个元素,非常具有表现力,图片既要让用户能看清楚,又能让发布图片的用户能快速的上传。所以开发者要对图片进行裁切和质量压缩。但是裁切尺寸质量压缩比设置成多少却很难控制好,如果设置不当会导致图片显示效果很差。 3 | 4 | 微信里面的图片压缩是一个很好的参照物,被大家广为使用并接受。这个扩展就是通过朋友圈和会话发送了大量图片,对比原图与微信压缩后的图片逆向推算出来的压缩算法。 5 | 6 | [swift](https://github.com/hucool/WCImageCompress)看这里 7 | 8 | ## Integration 9 | CocoaPods (iOS 7+, OS X 10.9+) 10 | ```ruby 11 | platform :ios, '7.0' 12 | use_frameworks! 13 | 14 | target 'MyApp' do 15 | pod 'WCImageCompress' 16 | end 17 | ``` 18 | 19 | 20 | ## Usage 21 | ```objective-c 22 | #import "UIImage+Wechat.h" 23 | ``` 24 | ```objective-c 25 | UIImage *image = [UIImage imageNamed:@"name"]; 26 | ``` 27 | ```objective-c 28 | UIImage *thumbImage = [image wcSessionCompress]; 29 | ``` 30 | 31 | 32 | ## Effect comparison 33 | | original | wechat | this | 34 | | -------- | ----- | ---- | 35 | | 1500 * 4000, 2.5MB | 800 * 2134, 325KB | 800 * 2134, 306KB | 36 | | 960 * 600, 210KB | 960 * 600, 147KB | 960 * 600, 147KB | 37 | | 800 * 1280, 595KB | 800 * 1280, 140KB | 800 * 1280, 142KB | 38 | | 1080 * 1920, 1.8MB | 720 * 1280, 139KB | 720 * 1280, 140KB | 39 | | 640 * 1136, 505KB | 640 * 1136, 68KB | 640 * 1136 69KB | 40 | | 4000 * 3000, 497KB | 1280 * 960, 140KB | 1280 * 960, 139KB | 41 | | 2560 * 1600, 232KB | 1280 * 800 112KB | 1280 * 800, 112KB | 42 | | 800 * 2138, 307KB | 800 * 2134, 649KB | 800 * 2138, 599KB | 43 | | 3351 * 1430, 386KB | 1874 * 800, 296KB | 1875 * 800, 286KB | 44 | | 3000 * 1300, 458KB | 1846 * 800 322KB | 1847 * 800, 307KB | 45 | | 8323 * 5793, 19.67MB | 1280 * 890, 428KB | 1280 * 891, 465KB | 46 | 47 | 48 | ## 策略算法 49 | ### 图片尺寸 50 | * 宽高均 <= 1280,图片尺寸大小保持不变 51 | * 宽或高 > 1280 && 宽高比 <= 2,取较大值等于1280,较小值等比例压缩 52 | * 宽或高 > 1280 && 宽高比 > 2 && 宽或高 < 1280,图片尺寸大小保持不变 53 | * 宽高均 > 1280 && 宽高比 > 2,取较小值等于1280,较大值等比例压缩 54 | 55 | ``` 56 | 注:当宽和高均小于1280,并且宽高比大于2时,微信聊天会话和微信朋友圈的处理不一样。 57 | 朋友圈:取较小值等于1280,较大值等比例压缩 58 | 聊天会话:取较小值等于800,较大值等比例压缩 59 | ``` 60 | ### 图片质量 61 | 经过大量的测试,微信的图片压缩质量值 ≈0.5 62 | 63 | ```objective-c 64 | UIImageJPEGRepresentation(resizeImage, 0.5) 65 | ``` 66 | -------------------------------------------------------------------------------- /WCImageCompress.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'WCImageCompress' 3 | s.version = '0.1.0' 4 | s.summary = 'Image size quality compression, very close to WeChat picture compression strategy' 5 | s.homepage = 'https://github.com/hucool/WCImageCompress' 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { 'tiger' => 'tiger@socool@gmail.com' } 8 | s.source = { :git => 'https://github.com/hucool/WCImageCompress.git', :tag => s.version.to_s } 9 | s.ios.deployment_target = '8.0' 10 | s.source_files = 'Pod/Classes/**/*' 11 | s.frameworks = 'UIKit', 'Foundation' 12 | end 13 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $current_dir = File.dirname(File.expand_path(__FILE__)) 4 | Dir[File.join($current_dir, "setup/*.rb")].each do |file| 5 | require_relative(file) 6 | end 7 | 8 | pod_name = ARGV.shift 9 | Pod::TemplateConfigurator.new(pod_name).run 10 | --------------------------------------------------------------------------------