├── .gitattributes
├── .gitignore
├── .swift-version
├── LICENSE
├── Luban-iOSDemo
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Luban-iOS.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Luban-iOS
│ ├── Controller
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Luban_iOS_Extension_h
│ │ │ ├── UIImage+Luban_iOS_Extension_h.h
│ │ │ └── UIImage+Luban_iOS_Extension_h.m
│ │ ├── PhotoBrowserViewController.h
│ │ ├── PhotoBrowserViewController.m
│ │ ├── ViewController.h
│ │ └── ViewController.m
│ ├── Info.plist
│ ├── LaunchScreen.storyboard
│ ├── MacroFile.h
│ ├── Main.storyboard
│ ├── Resource
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ ├── ic_scqszj_sy.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ └── ic_scqszj_sy.png
│ │ │ └── ic_wd_jyfk_tj.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── ic_wd_jyfk_tj@2x.png
│ │ │ │ └── ic_wd_jyfk_tj@3x.png
│ │ └── IMG_1998.JPG
│ ├── Transition
│ │ ├── ModalTransitionAnimator.h
│ │ └── ModalTransitionAnimator.m
│ └── main.m
├── Luban-iOSTests
│ ├── Info.plist
│ └── Luban_iOSTests.m
├── Luban-iOSUITests
│ ├── Info.plist
│ └── Luban_iOSUITests.m
└── Luban_iOS_Extension_h
│ ├── UIImage+Luban_iOS_Extension_h.h
│ └── UIImage+Luban_iOS_Extension_h.m
├── Luban_iOS.podspec
├── Luban_iOS_Extension_h
├── UIImage+Luban_iOS_Extension_h.h
└── UIImage+Luban_iOS_Extension_h.m
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj merge=union
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 | ## Build generated
5 | build/
6 | DerivedData/
7 | ## Various settings
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata/
17 | ## Other
18 | *.moved-aside
19 | *.xcuserstate
20 | .DS_Store
21 | ## Obj-C/Swift specific
22 | *.hmap
23 | *.ipa
24 | *.dSYM.zip
25 | *.dSYM
26 | # CocoaPods
27 | #
28 | # We recommend against adding the Pods directory to your .gitignore. However
29 | # you should judge for yourself, the pros and cons are mentioned at:
30 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
31 | #
32 | Pods/
33 | # Carthage
34 | #
35 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
36 | # Carthage/Checkouts
37 | Carthage/Build
38 | # fastlane
39 | #
40 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
41 | # screenshots whenever they are needed.
42 | # For more information about the recommended setup visit:
43 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
44 | fastlane/report.xml
45 | fastlane/Preview.html
46 | fastlane/screenshots
47 | fastlane/test_output
48 | # Code Injection
49 | #
50 | # After new code Injection tools there's a generated folder /iOSInjectionProject
51 | # https://github.com/johnno1962/injectionforxcode
52 | iOSInjectionProject/
53 | Luban-iOS/Luban-iOS.xcodeproj/project.pbxproj
54 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 2.3
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 cook
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 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/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 |
27 |
28 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/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 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | BC6206311F1F3A3B00FCDC9E /* Luban_iOSTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6206301F1F3A3B00FCDC9E /* Luban_iOSTests.m */; };
11 | BC62063C1F1F3A3B00FCDC9E /* Luban_iOSUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BC62063B1F1F3A3B00FCDC9E /* Luban_iOSUITests.m */; };
12 | BC6206731F25C78800FCDC9E /* PhotoBrowserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC62066B1F25C78800FCDC9E /* PhotoBrowserViewController.m */; };
13 | BC6206741F25C78800FCDC9E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC62066D1F25C78800FCDC9E /* ViewController.m */; };
14 | BC6206751F25C78800FCDC9E /* IMG_1998.JPG in Resources */ = {isa = PBXBuildFile; fileRef = BC62066F1F25C78800FCDC9E /* IMG_1998.JPG */; };
15 | BC6206761F25C78800FCDC9E /* ModalTransitionAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6206721F25C78800FCDC9E /* ModalTransitionAnimator.m */; };
16 | BC62067A1F25C82900FCDC9E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BC6206771F25C82900FCDC9E /* Info.plist */; };
17 | BC62067B1F25C82900FCDC9E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6206791F25C82900FCDC9E /* main.m */; };
18 | BC62067D1F25C87D00FCDC9E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BC62067C1F25C87D00FCDC9E /* Assets.xcassets */; };
19 | BC6206801F25C8A300FCDC9E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BC62067E1F25C8A300FCDC9E /* LaunchScreen.storyboard */; };
20 | BC6206811F25C8A300FCDC9E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BC62067F1F25C8A300FCDC9E /* Main.storyboard */; };
21 | BC6206841F25C8C000FCDC9E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = BC6206831F25C8C000FCDC9E /* AppDelegate.m */; };
22 | BC62068C1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.m in Sources */ = {isa = PBXBuildFile; fileRef = BC62068B1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.m */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXContainerItemProxy section */
26 | BC62062D1F1F3A3B00FCDC9E /* PBXContainerItemProxy */ = {
27 | isa = PBXContainerItemProxy;
28 | containerPortal = BC62060B1F1F3A3B00FCDC9E /* Project object */;
29 | proxyType = 1;
30 | remoteGlobalIDString = BC6206121F1F3A3B00FCDC9E;
31 | remoteInfo = "Luban-iOS";
32 | };
33 | BC6206381F1F3A3B00FCDC9E /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = BC62060B1F1F3A3B00FCDC9E /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = BC6206121F1F3A3B00FCDC9E;
38 | remoteInfo = "Luban-iOS";
39 | };
40 | /* End PBXContainerItemProxy section */
41 |
42 | /* Begin PBXFileReference section */
43 | BC6206131F1F3A3B00FCDC9E /* Luban-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Luban-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
44 | BC62062C1F1F3A3B00FCDC9E /* Luban-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Luban-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
45 | BC6206301F1F3A3B00FCDC9E /* Luban_iOSTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Luban_iOSTests.m; sourceTree = ""; };
46 | BC6206321F1F3A3B00FCDC9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
47 | BC6206371F1F3A3B00FCDC9E /* Luban-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Luban-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
48 | BC62063B1F1F3A3B00FCDC9E /* Luban_iOSUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Luban_iOSUITests.m; sourceTree = ""; };
49 | BC62063D1F1F3A3B00FCDC9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
50 | BC62066A1F25C78800FCDC9E /* PhotoBrowserViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoBrowserViewController.h; sourceTree = ""; };
51 | BC62066B1F25C78800FCDC9E /* PhotoBrowserViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoBrowserViewController.m; sourceTree = ""; };
52 | BC62066C1F25C78800FCDC9E /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
53 | BC62066D1F25C78800FCDC9E /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
54 | BC62066F1F25C78800FCDC9E /* IMG_1998.JPG */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = IMG_1998.JPG; sourceTree = ""; };
55 | BC6206711F25C78800FCDC9E /* ModalTransitionAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalTransitionAnimator.h; sourceTree = ""; };
56 | BC6206721F25C78800FCDC9E /* ModalTransitionAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalTransitionAnimator.m; sourceTree = ""; };
57 | BC6206771F25C82900FCDC9E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | BC6206781F25C82900FCDC9E /* MacroFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroFile.h; sourceTree = ""; };
59 | BC6206791F25C82900FCDC9E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
60 | BC62067C1F25C87D00FCDC9E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
61 | BC62067E1F25C8A300FCDC9E /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
62 | BC62067F1F25C8A300FCDC9E /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
63 | BC6206821F25C8C000FCDC9E /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
64 | BC6206831F25C8C000FCDC9E /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
65 | BC62068A1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Luban_iOS_Extension_h.h"; sourceTree = ""; };
66 | BC62068B1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Luban_iOS_Extension_h.m"; sourceTree = ""; };
67 | /* End PBXFileReference section */
68 |
69 | /* Begin PBXFrameworksBuildPhase section */
70 | BC6206101F1F3A3B00FCDC9E /* Frameworks */ = {
71 | isa = PBXFrameworksBuildPhase;
72 | buildActionMask = 2147483647;
73 | files = (
74 | );
75 | runOnlyForDeploymentPostprocessing = 0;
76 | };
77 | BC6206291F1F3A3B00FCDC9E /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | BC6206341F1F3A3B00FCDC9E /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | );
89 | runOnlyForDeploymentPostprocessing = 0;
90 | };
91 | /* End PBXFrameworksBuildPhase section */
92 |
93 | /* Begin PBXGroup section */
94 | BC62060A1F1F3A3B00FCDC9E = {
95 | isa = PBXGroup;
96 | children = (
97 | BC6206151F1F3A3B00FCDC9E /* Luban-iOS */,
98 | BC62062F1F1F3A3B00FCDC9E /* Luban-iOSTests */,
99 | BC62063A1F1F3A3B00FCDC9E /* Luban-iOSUITests */,
100 | BC6206141F1F3A3B00FCDC9E /* Products */,
101 | );
102 | sourceTree = "";
103 | };
104 | BC6206141F1F3A3B00FCDC9E /* Products */ = {
105 | isa = PBXGroup;
106 | children = (
107 | BC6206131F1F3A3B00FCDC9E /* Luban-iOS.app */,
108 | BC62062C1F1F3A3B00FCDC9E /* Luban-iOSTests.xctest */,
109 | BC6206371F1F3A3B00FCDC9E /* Luban-iOSUITests.xctest */,
110 | );
111 | name = Products;
112 | sourceTree = "";
113 | };
114 | BC6206151F1F3A3B00FCDC9E /* Luban-iOS */ = {
115 | isa = PBXGroup;
116 | children = (
117 | BC62067E1F25C8A300FCDC9E /* LaunchScreen.storyboard */,
118 | BC62067F1F25C8A300FCDC9E /* Main.storyboard */,
119 | BC6206691F25C78800FCDC9E /* Controller */,
120 | BC62066E1F25C78800FCDC9E /* Resource */,
121 | BC6206701F25C78800FCDC9E /* Transition */,
122 | BC6206161F1F3A3B00FCDC9E /* Supporting Files */,
123 | );
124 | path = "Luban-iOS";
125 | sourceTree = "";
126 | };
127 | BC6206161F1F3A3B00FCDC9E /* Supporting Files */ = {
128 | isa = PBXGroup;
129 | children = (
130 | BC6206771F25C82900FCDC9E /* Info.plist */,
131 | BC6206781F25C82900FCDC9E /* MacroFile.h */,
132 | BC6206791F25C82900FCDC9E /* main.m */,
133 | );
134 | name = "Supporting Files";
135 | sourceTree = "";
136 | };
137 | BC62062F1F1F3A3B00FCDC9E /* Luban-iOSTests */ = {
138 | isa = PBXGroup;
139 | children = (
140 | BC6206301F1F3A3B00FCDC9E /* Luban_iOSTests.m */,
141 | BC6206321F1F3A3B00FCDC9E /* Info.plist */,
142 | );
143 | path = "Luban-iOSTests";
144 | sourceTree = "";
145 | };
146 | BC62063A1F1F3A3B00FCDC9E /* Luban-iOSUITests */ = {
147 | isa = PBXGroup;
148 | children = (
149 | BC62063B1F1F3A3B00FCDC9E /* Luban_iOSUITests.m */,
150 | BC62063D1F1F3A3B00FCDC9E /* Info.plist */,
151 | );
152 | path = "Luban-iOSUITests";
153 | sourceTree = "";
154 | };
155 | BC6206691F25C78800FCDC9E /* Controller */ = {
156 | isa = PBXGroup;
157 | children = (
158 | BC6206891F25C95100FCDC9E /* Luban_iOS_Extension_h */,
159 | BC6206821F25C8C000FCDC9E /* AppDelegate.h */,
160 | BC6206831F25C8C000FCDC9E /* AppDelegate.m */,
161 | BC62066A1F25C78800FCDC9E /* PhotoBrowserViewController.h */,
162 | BC62066B1F25C78800FCDC9E /* PhotoBrowserViewController.m */,
163 | BC62066C1F25C78800FCDC9E /* ViewController.h */,
164 | BC62066D1F25C78800FCDC9E /* ViewController.m */,
165 | );
166 | path = Controller;
167 | sourceTree = "";
168 | };
169 | BC62066E1F25C78800FCDC9E /* Resource */ = {
170 | isa = PBXGroup;
171 | children = (
172 | BC62067C1F25C87D00FCDC9E /* Assets.xcassets */,
173 | BC62066F1F25C78800FCDC9E /* IMG_1998.JPG */,
174 | );
175 | path = Resource;
176 | sourceTree = "";
177 | };
178 | BC6206701F25C78800FCDC9E /* Transition */ = {
179 | isa = PBXGroup;
180 | children = (
181 | BC6206711F25C78800FCDC9E /* ModalTransitionAnimator.h */,
182 | BC6206721F25C78800FCDC9E /* ModalTransitionAnimator.m */,
183 | );
184 | path = Transition;
185 | sourceTree = "";
186 | };
187 | BC6206891F25C95100FCDC9E /* Luban_iOS_Extension_h */ = {
188 | isa = PBXGroup;
189 | children = (
190 | BC62068A1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.h */,
191 | BC62068B1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.m */,
192 | );
193 | path = Luban_iOS_Extension_h;
194 | sourceTree = "";
195 | };
196 | /* End PBXGroup section */
197 |
198 | /* Begin PBXNativeTarget section */
199 | BC6206121F1F3A3B00FCDC9E /* Luban-iOS */ = {
200 | isa = PBXNativeTarget;
201 | buildConfigurationList = BC6206401F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOS" */;
202 | buildPhases = (
203 | BC62060F1F1F3A3B00FCDC9E /* Sources */,
204 | BC6206101F1F3A3B00FCDC9E /* Frameworks */,
205 | BC6206111F1F3A3B00FCDC9E /* Resources */,
206 | );
207 | buildRules = (
208 | );
209 | dependencies = (
210 | );
211 | name = "Luban-iOS";
212 | productName = "Luban-iOS";
213 | productReference = BC6206131F1F3A3B00FCDC9E /* Luban-iOS.app */;
214 | productType = "com.apple.product-type.application";
215 | };
216 | BC62062B1F1F3A3B00FCDC9E /* Luban-iOSTests */ = {
217 | isa = PBXNativeTarget;
218 | buildConfigurationList = BC6206431F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOSTests" */;
219 | buildPhases = (
220 | BC6206281F1F3A3B00FCDC9E /* Sources */,
221 | BC6206291F1F3A3B00FCDC9E /* Frameworks */,
222 | BC62062A1F1F3A3B00FCDC9E /* Resources */,
223 | );
224 | buildRules = (
225 | );
226 | dependencies = (
227 | BC62062E1F1F3A3B00FCDC9E /* PBXTargetDependency */,
228 | );
229 | name = "Luban-iOSTests";
230 | productName = "Luban-iOSTests";
231 | productReference = BC62062C1F1F3A3B00FCDC9E /* Luban-iOSTests.xctest */;
232 | productType = "com.apple.product-type.bundle.unit-test";
233 | };
234 | BC6206361F1F3A3B00FCDC9E /* Luban-iOSUITests */ = {
235 | isa = PBXNativeTarget;
236 | buildConfigurationList = BC6206461F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOSUITests" */;
237 | buildPhases = (
238 | BC6206331F1F3A3B00FCDC9E /* Sources */,
239 | BC6206341F1F3A3B00FCDC9E /* Frameworks */,
240 | BC6206351F1F3A3B00FCDC9E /* Resources */,
241 | );
242 | buildRules = (
243 | );
244 | dependencies = (
245 | BC6206391F1F3A3B00FCDC9E /* PBXTargetDependency */,
246 | );
247 | name = "Luban-iOSUITests";
248 | productName = "Luban-iOSUITests";
249 | productReference = BC6206371F1F3A3B00FCDC9E /* Luban-iOSUITests.xctest */;
250 | productType = "com.apple.product-type.bundle.ui-testing";
251 | };
252 | /* End PBXNativeTarget section */
253 |
254 | /* Begin PBXProject section */
255 | BC62060B1F1F3A3B00FCDC9E /* Project object */ = {
256 | isa = PBXProject;
257 | attributes = {
258 | LastUpgradeCheck = 0830;
259 | ORGANIZATIONNAME = guo;
260 | TargetAttributes = {
261 | BC6206121F1F3A3B00FCDC9E = {
262 | CreatedOnToolsVersion = 8.3.2;
263 | DevelopmentTeam = D95RMHATXP;
264 | ProvisioningStyle = Automatic;
265 | };
266 | BC62062B1F1F3A3B00FCDC9E = {
267 | CreatedOnToolsVersion = 8.3.2;
268 | DevelopmentTeam = 8JAJ87K5LP;
269 | ProvisioningStyle = Automatic;
270 | TestTargetID = BC6206121F1F3A3B00FCDC9E;
271 | };
272 | BC6206361F1F3A3B00FCDC9E = {
273 | CreatedOnToolsVersion = 8.3.2;
274 | DevelopmentTeam = 8JAJ87K5LP;
275 | ProvisioningStyle = Automatic;
276 | TestTargetID = BC6206121F1F3A3B00FCDC9E;
277 | };
278 | };
279 | };
280 | buildConfigurationList = BC62060E1F1F3A3B00FCDC9E /* Build configuration list for PBXProject "Luban-iOS" */;
281 | compatibilityVersion = "Xcode 3.2";
282 | developmentRegion = English;
283 | hasScannedForEncodings = 0;
284 | knownRegions = (
285 | en,
286 | Base,
287 | );
288 | mainGroup = BC62060A1F1F3A3B00FCDC9E;
289 | productRefGroup = BC6206141F1F3A3B00FCDC9E /* Products */;
290 | projectDirPath = "";
291 | projectRoot = "";
292 | targets = (
293 | BC6206121F1F3A3B00FCDC9E /* Luban-iOS */,
294 | BC62062B1F1F3A3B00FCDC9E /* Luban-iOSTests */,
295 | BC6206361F1F3A3B00FCDC9E /* Luban-iOSUITests */,
296 | );
297 | };
298 | /* End PBXProject section */
299 |
300 | /* Begin PBXResourcesBuildPhase section */
301 | BC6206111F1F3A3B00FCDC9E /* Resources */ = {
302 | isa = PBXResourcesBuildPhase;
303 | buildActionMask = 2147483647;
304 | files = (
305 | BC62067A1F25C82900FCDC9E /* Info.plist in Resources */,
306 | BC6206811F25C8A300FCDC9E /* Main.storyboard in Resources */,
307 | BC6206801F25C8A300FCDC9E /* LaunchScreen.storyboard in Resources */,
308 | BC62067D1F25C87D00FCDC9E /* Assets.xcassets in Resources */,
309 | BC6206751F25C78800FCDC9E /* IMG_1998.JPG in Resources */,
310 | );
311 | runOnlyForDeploymentPostprocessing = 0;
312 | };
313 | BC62062A1F1F3A3B00FCDC9E /* Resources */ = {
314 | isa = PBXResourcesBuildPhase;
315 | buildActionMask = 2147483647;
316 | files = (
317 | );
318 | runOnlyForDeploymentPostprocessing = 0;
319 | };
320 | BC6206351F1F3A3B00FCDC9E /* Resources */ = {
321 | isa = PBXResourcesBuildPhase;
322 | buildActionMask = 2147483647;
323 | files = (
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | };
327 | /* End PBXResourcesBuildPhase section */
328 |
329 | /* Begin PBXSourcesBuildPhase section */
330 | BC62060F1F1F3A3B00FCDC9E /* Sources */ = {
331 | isa = PBXSourcesBuildPhase;
332 | buildActionMask = 2147483647;
333 | files = (
334 | BC6206741F25C78800FCDC9E /* ViewController.m in Sources */,
335 | BC6206761F25C78800FCDC9E /* ModalTransitionAnimator.m in Sources */,
336 | BC62067B1F25C82900FCDC9E /* main.m in Sources */,
337 | BC62068C1F25C95100FCDC9E /* UIImage+Luban_iOS_Extension_h.m in Sources */,
338 | BC6206731F25C78800FCDC9E /* PhotoBrowserViewController.m in Sources */,
339 | BC6206841F25C8C000FCDC9E /* AppDelegate.m in Sources */,
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | };
343 | BC6206281F1F3A3B00FCDC9E /* Sources */ = {
344 | isa = PBXSourcesBuildPhase;
345 | buildActionMask = 2147483647;
346 | files = (
347 | BC6206311F1F3A3B00FCDC9E /* Luban_iOSTests.m in Sources */,
348 | );
349 | runOnlyForDeploymentPostprocessing = 0;
350 | };
351 | BC6206331F1F3A3B00FCDC9E /* Sources */ = {
352 | isa = PBXSourcesBuildPhase;
353 | buildActionMask = 2147483647;
354 | files = (
355 | BC62063C1F1F3A3B00FCDC9E /* Luban_iOSUITests.m in Sources */,
356 | );
357 | runOnlyForDeploymentPostprocessing = 0;
358 | };
359 | /* End PBXSourcesBuildPhase section */
360 |
361 | /* Begin PBXTargetDependency section */
362 | BC62062E1F1F3A3B00FCDC9E /* PBXTargetDependency */ = {
363 | isa = PBXTargetDependency;
364 | target = BC6206121F1F3A3B00FCDC9E /* Luban-iOS */;
365 | targetProxy = BC62062D1F1F3A3B00FCDC9E /* PBXContainerItemProxy */;
366 | };
367 | BC6206391F1F3A3B00FCDC9E /* PBXTargetDependency */ = {
368 | isa = PBXTargetDependency;
369 | target = BC6206121F1F3A3B00FCDC9E /* Luban-iOS */;
370 | targetProxy = BC6206381F1F3A3B00FCDC9E /* PBXContainerItemProxy */;
371 | };
372 | /* End PBXTargetDependency section */
373 |
374 | /* Begin XCBuildConfiguration section */
375 | BC62063E1F1F3A3B00FCDC9E /* Debug */ = {
376 | isa = XCBuildConfiguration;
377 | buildSettings = {
378 | ALWAYS_SEARCH_USER_PATHS = NO;
379 | CLANG_ANALYZER_NONNULL = YES;
380 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
382 | CLANG_CXX_LIBRARY = "libc++";
383 | CLANG_ENABLE_MODULES = YES;
384 | CLANG_ENABLE_OBJC_ARC = YES;
385 | CLANG_WARN_BOOL_CONVERSION = YES;
386 | CLANG_WARN_CONSTANT_CONVERSION = YES;
387 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
388 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
389 | CLANG_WARN_EMPTY_BODY = YES;
390 | CLANG_WARN_ENUM_CONVERSION = YES;
391 | CLANG_WARN_INFINITE_RECURSION = YES;
392 | CLANG_WARN_INT_CONVERSION = YES;
393 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
394 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
395 | CLANG_WARN_UNREACHABLE_CODE = YES;
396 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
397 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
398 | COPY_PHASE_STRIP = NO;
399 | DEBUG_INFORMATION_FORMAT = dwarf;
400 | ENABLE_STRICT_OBJC_MSGSEND = YES;
401 | ENABLE_TESTABILITY = YES;
402 | GCC_C_LANGUAGE_STANDARD = gnu99;
403 | GCC_DYNAMIC_NO_PIC = NO;
404 | GCC_NO_COMMON_BLOCKS = YES;
405 | GCC_OPTIMIZATION_LEVEL = 0;
406 | GCC_PREPROCESSOR_DEFINITIONS = (
407 | "DEBUG=1",
408 | "$(inherited)",
409 | );
410 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
411 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
412 | GCC_WARN_UNDECLARED_SELECTOR = YES;
413 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
414 | GCC_WARN_UNUSED_FUNCTION = YES;
415 | GCC_WARN_UNUSED_VARIABLE = YES;
416 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
417 | MTL_ENABLE_DEBUG_INFO = YES;
418 | ONLY_ACTIVE_ARCH = YES;
419 | SDKROOT = iphoneos;
420 | TARGETED_DEVICE_FAMILY = "1,2";
421 | };
422 | name = Debug;
423 | };
424 | BC62063F1F1F3A3B00FCDC9E /* Release */ = {
425 | isa = XCBuildConfiguration;
426 | buildSettings = {
427 | ALWAYS_SEARCH_USER_PATHS = NO;
428 | CLANG_ANALYZER_NONNULL = YES;
429 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
430 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
431 | CLANG_CXX_LIBRARY = "libc++";
432 | CLANG_ENABLE_MODULES = YES;
433 | CLANG_ENABLE_OBJC_ARC = YES;
434 | CLANG_WARN_BOOL_CONVERSION = YES;
435 | CLANG_WARN_CONSTANT_CONVERSION = YES;
436 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
437 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
438 | CLANG_WARN_EMPTY_BODY = YES;
439 | CLANG_WARN_ENUM_CONVERSION = YES;
440 | CLANG_WARN_INFINITE_RECURSION = YES;
441 | CLANG_WARN_INT_CONVERSION = YES;
442 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
443 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
444 | CLANG_WARN_UNREACHABLE_CODE = YES;
445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
446 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
447 | COPY_PHASE_STRIP = NO;
448 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
449 | ENABLE_NS_ASSERTIONS = NO;
450 | ENABLE_STRICT_OBJC_MSGSEND = YES;
451 | GCC_C_LANGUAGE_STANDARD = gnu99;
452 | GCC_NO_COMMON_BLOCKS = YES;
453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
455 | GCC_WARN_UNDECLARED_SELECTOR = YES;
456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
457 | GCC_WARN_UNUSED_FUNCTION = YES;
458 | GCC_WARN_UNUSED_VARIABLE = YES;
459 | IPHONEOS_DEPLOYMENT_TARGET = 8.3;
460 | MTL_ENABLE_DEBUG_INFO = NO;
461 | SDKROOT = iphoneos;
462 | TARGETED_DEVICE_FAMILY = "1,2";
463 | VALIDATE_PRODUCT = YES;
464 | };
465 | name = Release;
466 | };
467 | BC6206411F1F3A3B00FCDC9E /* Debug */ = {
468 | isa = XCBuildConfiguration;
469 | buildSettings = {
470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
471 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
472 | DEVELOPMENT_TEAM = D95RMHATXP;
473 | INFOPLIST_FILE = "Luban-iOS/Info.plist";
474 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
475 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOS";
476 | PRODUCT_NAME = "$(TARGET_NAME)";
477 | PROVISIONING_PROFILE_SPECIFIER = "";
478 | };
479 | name = Debug;
480 | };
481 | BC6206421F1F3A3B00FCDC9E /* Release */ = {
482 | isa = XCBuildConfiguration;
483 | buildSettings = {
484 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
485 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
486 | DEVELOPMENT_TEAM = D95RMHATXP;
487 | INFOPLIST_FILE = "Luban-iOS/Info.plist";
488 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
489 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOS";
490 | PRODUCT_NAME = "$(TARGET_NAME)";
491 | PROVISIONING_PROFILE_SPECIFIER = "";
492 | };
493 | name = Release;
494 | };
495 | BC6206441F1F3A3B00FCDC9E /* Debug */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | BUNDLE_LOADER = "$(TEST_HOST)";
499 | DEVELOPMENT_TEAM = 8JAJ87K5LP;
500 | INFOPLIST_FILE = "Luban-iOSTests/Info.plist";
501 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
502 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOSTests";
503 | PRODUCT_NAME = "$(TARGET_NAME)";
504 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Luban-iOS.app/Luban-iOS";
505 | };
506 | name = Debug;
507 | };
508 | BC6206451F1F3A3B00FCDC9E /* Release */ = {
509 | isa = XCBuildConfiguration;
510 | buildSettings = {
511 | BUNDLE_LOADER = "$(TEST_HOST)";
512 | DEVELOPMENT_TEAM = 8JAJ87K5LP;
513 | INFOPLIST_FILE = "Luban-iOSTests/Info.plist";
514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
515 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOSTests";
516 | PRODUCT_NAME = "$(TARGET_NAME)";
517 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Luban-iOS.app/Luban-iOS";
518 | };
519 | name = Release;
520 | };
521 | BC6206471F1F3A3B00FCDC9E /* Debug */ = {
522 | isa = XCBuildConfiguration;
523 | buildSettings = {
524 | DEVELOPMENT_TEAM = 8JAJ87K5LP;
525 | INFOPLIST_FILE = "Luban-iOSUITests/Info.plist";
526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
527 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOSUITests";
528 | PRODUCT_NAME = "$(TARGET_NAME)";
529 | TEST_TARGET_NAME = "Luban-iOS";
530 | };
531 | name = Debug;
532 | };
533 | BC6206481F1F3A3B00FCDC9E /* Release */ = {
534 | isa = XCBuildConfiguration;
535 | buildSettings = {
536 | DEVELOPMENT_TEAM = 8JAJ87K5LP;
537 | INFOPLIST_FILE = "Luban-iOSUITests/Info.plist";
538 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
539 | PRODUCT_BUNDLE_IDENTIFIER = "lianjia.Luban-iOSUITests";
540 | PRODUCT_NAME = "$(TARGET_NAME)";
541 | TEST_TARGET_NAME = "Luban-iOS";
542 | };
543 | name = Release;
544 | };
545 | /* End XCBuildConfiguration section */
546 |
547 | /* Begin XCConfigurationList section */
548 | BC62060E1F1F3A3B00FCDC9E /* Build configuration list for PBXProject "Luban-iOS" */ = {
549 | isa = XCConfigurationList;
550 | buildConfigurations = (
551 | BC62063E1F1F3A3B00FCDC9E /* Debug */,
552 | BC62063F1F1F3A3B00FCDC9E /* Release */,
553 | );
554 | defaultConfigurationIsVisible = 0;
555 | defaultConfigurationName = Release;
556 | };
557 | BC6206401F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOS" */ = {
558 | isa = XCConfigurationList;
559 | buildConfigurations = (
560 | BC6206411F1F3A3B00FCDC9E /* Debug */,
561 | BC6206421F1F3A3B00FCDC9E /* Release */,
562 | );
563 | defaultConfigurationIsVisible = 0;
564 | defaultConfigurationName = Release;
565 | };
566 | BC6206431F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOSTests" */ = {
567 | isa = XCConfigurationList;
568 | buildConfigurations = (
569 | BC6206441F1F3A3B00FCDC9E /* Debug */,
570 | BC6206451F1F3A3B00FCDC9E /* Release */,
571 | );
572 | defaultConfigurationIsVisible = 0;
573 | defaultConfigurationName = Release;
574 | };
575 | BC6206461F1F3A3B00FCDC9E /* Build configuration list for PBXNativeTarget "Luban-iOSUITests" */ = {
576 | isa = XCConfigurationList;
577 | buildConfigurations = (
578 | BC6206471F1F3A3B00FCDC9E /* Debug */,
579 | BC6206481F1F3A3B00FCDC9E /* Release */,
580 | );
581 | defaultConfigurationIsVisible = 0;
582 | defaultConfigurationName = Release;
583 | };
584 | /* End XCConfigurationList section */
585 | };
586 | rootObject = BC62060B1F1F3A3B00FCDC9E /* Project object */;
587 | }
588 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 |
24 | - (void)applicationWillResignActive:(UIApplication *)application {
25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
27 | }
28 |
29 |
30 | - (void)applicationDidEnterBackground:(UIApplication *)application {
31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 |
36 | - (void)applicationWillEnterForeground:(UIApplication *)application {
37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
38 | }
39 |
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 |
46 | - (void)applicationWillTerminate:(UIApplication *)application {
47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48 | }
49 |
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (Luban_iOS_Extension_h)
12 |
13 | + (NSData *)lubanCompressImage:(UIImage *)image;
14 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName;
15 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UIImage+Luban_iOS_Extension_h.h"
11 |
12 | @implementation UIImage (Luban_iOS_Extension_h)
13 |
14 | static char isCustomImage;
15 | static char customImageName;
16 |
17 | + (NSData *)lubanCompressImage:(UIImage *)image {
18 | return [self lubanCompressImage:image withMask:nil];
19 | }
20 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName {
21 |
22 | double size;
23 | NSData *imageData = UIImageJPEGRepresentation(image, 1);
24 |
25 | NSLog(@"Luban-iOS image data size before compressed == %f Kb",imageData.length/1024.0);
26 |
27 | int fixelW = (int)image.size.width;
28 | int fixelH = (int)image.size.height;
29 | int thumbW = fixelW % 2 == 1 ? fixelW + 1 : fixelW;
30 | int thumbH = fixelH % 2 == 1 ? fixelH + 1 : fixelH;
31 |
32 | double scale = ((double)fixelW/(double)fixelH);
33 |
34 | if (scale <= 1 && scale > 0.5625) {
35 |
36 | if (fixelH < 1664) {
37 | if (imageData.length/1024.0 < 150) {
38 | return imageData;
39 | }
40 | size = (fixelW * fixelH) / pow(1664, 2) * 150;
41 | size = size < 60 ? 60 : size;
42 | }
43 | else if (fixelH >= 1664 && fixelH < 4990) {
44 | thumbW = fixelW / 2;
45 | thumbH = fixelH / 2;
46 | size = (thumbH * thumbW) / pow(2495, 2) * 300;
47 | size = size < 60 ? 60 : size;
48 | }
49 | else if (fixelH >= 4990 && fixelH < 10240) {
50 | thumbW = fixelW / 4;
51 | thumbH = fixelH / 4;
52 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
53 | size = size < 100 ? 100 : size;
54 | }
55 | else {
56 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
57 | thumbW = fixelW / multiple;
58 | thumbH = fixelH / multiple;
59 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
60 | size = size < 100 ? 100 : size;
61 | }
62 | }
63 | else if (scale <= 0.5625 && scale > 0.5) {
64 |
65 | if (fixelH < 1280 && imageData.length/1024 < 200) {
66 |
67 | return imageData;
68 | }
69 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
70 | thumbW = fixelW / multiple;
71 | thumbH = fixelH / multiple;
72 | size = (thumbW * thumbH) / (1440.0 * 2560.0) * 400;
73 | size = size < 100 ? 100 : size;
74 | }
75 | else {
76 | int multiple = (int)ceil(fixelH / (1280.0 / scale));
77 | thumbW = fixelW / multiple;
78 | thumbH = fixelH / multiple;
79 | size = ((thumbW * thumbH) / (1280.0 * (1280 / scale))) * 500;
80 | size = size < 100 ? 100 : size;
81 | }
82 | return [self compressWithImage:image thumbW:thumbW thumbH:thumbH size:size withMask:maskName];
83 | }
84 |
85 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName {
86 |
87 | if (imageName) {
88 | objc_setAssociatedObject(self, &isCustomImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
89 | objc_setAssociatedObject(self, &customImageName, imageName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
90 | }
91 | return [self lubanCompressImage:image withMask:nil];
92 | }
93 |
94 | + (NSData *)compressWithImage:(UIImage *)image thumbW:(int)width thumbH:(int)height size:(double)size withMask:(NSString *)maskName {
95 |
96 | UIImage *thumbImage = [image fixOrientation];
97 | thumbImage = [thumbImage resizeImage:image thumbWidth:width thumbHeight:height withMask:maskName];
98 |
99 | float qualityCompress = 0.0;
100 | NSData *imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
101 |
102 | NSUInteger lenght = imageData.length;
103 | while (lenght / 1024 > size && qualityCompress <= (1-0.06)) {
104 |
105 | qualityCompress += 0.06 ;
106 | int intCommpress = (int)(qualityCompress*100);
107 | qualityCompress = intCommpress/100.0;
108 | imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
109 | lenght = imageData.length;
110 | thumbImage = [UIImage imageWithData:imageData];
111 | }
112 | NSLog(@"Luban-iOS image data size after compressed ==%f kb",imageData.length/1024.0);
113 | return imageData;
114 | }
115 |
116 | // specify the size
117 | - (UIImage *)resizeImage:(UIImage *)image thumbWidth:(int)width thumbHeight:(int)height withMask:(NSString *)maskName {
118 |
119 | int outW = (int)image.size.width;
120 | int outH = (int)image.size.height;
121 |
122 | int inSampleSize = 1;
123 |
124 | if (outW > width || outH > height) {
125 | int halfW = outW / 2;
126 | int halfH = outH / 2;
127 |
128 | while ((halfH / inSampleSize) > height && (halfW / inSampleSize) > width) {
129 | inSampleSize *= 2;
130 | }
131 | }
132 |
133 | // keep one decimal
134 | int outWith = (int)((outW / (float) width)*10);
135 | int outHeiht = (int)((outH / (float) height)*10);
136 | float heightRatio = outHeiht/10.0;
137 | float widthRatio = outWith/10.0;
138 |
139 | if (heightRatio > 1 || widthRatio > 1) {
140 |
141 | inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
142 | }
143 | CGSize thumbSize = CGSizeMake((NSUInteger)((CGFloat)(outW/inSampleSize)), (NSUInteger)((CGFloat)(outH/inSampleSize)));
144 |
145 | UIGraphicsBeginImageContext(thumbSize);
146 |
147 | CGContextRef context = UIGraphicsGetCurrentContext();
148 |
149 | [image drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
150 | if (maskName) {
151 |
152 | CGContextTranslateCTM (context, thumbSize.width / 2, thumbSize.height / 2);
153 | CGContextScaleCTM (context, 1, -1);
154 |
155 | [self drawMaskWithString:maskName context:context radius:0 angle:0 colour:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5] font:[UIFont systemFontOfSize:38.0] slantAngle:(CGFloat)(M_PI/6) size:thumbSize];
156 | }
157 | else {
158 | NSNumber *iscustom = objc_getAssociatedObject(self, &isCustomImage);
159 | BOOL isCustom = [iscustom boolValue];
160 | if (isCustom) {
161 | NSString *imageName = objc_getAssociatedObject(self, &customImageName);
162 | UIImage *imageMask = [UIImage imageNamed:imageName];
163 | if (imageMask) {
164 | [imageMask drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
165 | }
166 | }
167 | }
168 | UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
169 | UIGraphicsEndImageContext();
170 |
171 | objc_setAssociatedObject(self, &isCustomImage, @(NO), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
172 |
173 | return resultImage;
174 | }
175 |
176 | - (UIImage *)fixOrientation {
177 |
178 | // No-op if the orientation is already correct
179 | if (self.imageOrientation == UIImageOrientationUp) return self;
180 |
181 | // We need to calculate the proper transformation to make the image upright.
182 | // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
183 | CGAffineTransform transform = CGAffineTransformIdentity;
184 |
185 | switch (self.imageOrientation) {
186 | case UIImageOrientationDown:
187 | case UIImageOrientationDownMirrored:
188 | transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
189 | transform = CGAffineTransformRotate(transform, M_PI);
190 | break;
191 |
192 | case UIImageOrientationLeft:
193 | case UIImageOrientationLeftMirrored:
194 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
195 | transform = CGAffineTransformRotate(transform, M_PI_2);
196 | break;
197 |
198 | case UIImageOrientationRight:
199 | case UIImageOrientationRightMirrored:
200 | transform = CGAffineTransformTranslate(transform, 0, self.size.height);
201 | transform = CGAffineTransformRotate(transform, -M_PI_2);
202 | break;
203 | case UIImageOrientationUp:
204 | case UIImageOrientationUpMirrored:
205 | break;
206 | }
207 |
208 | switch (self.imageOrientation) {
209 | case UIImageOrientationUpMirrored:
210 | case UIImageOrientationDownMirrored:
211 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
212 | transform = CGAffineTransformScale(transform, -1, 1);
213 | break;
214 |
215 | case UIImageOrientationLeftMirrored:
216 | case UIImageOrientationRightMirrored:
217 | transform = CGAffineTransformTranslate(transform, self.size.height, 0);
218 | transform = CGAffineTransformScale(transform, -1, 1);
219 | break;
220 | case UIImageOrientationUp:
221 | case UIImageOrientationDown:
222 | case UIImageOrientationLeft:
223 | case UIImageOrientationRight:
224 | break;
225 | }
226 |
227 | // Now we draw the underlying CGImage into a new context, applying the transform
228 | // calculated above.
229 | CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
230 | CGImageGetBitsPerComponent(self.CGImage), 0,
231 | CGImageGetColorSpace(self.CGImage),
232 | CGImageGetBitmapInfo(self.CGImage));
233 | CGContextConcatCTM(ctx, transform);
234 | switch (self.imageOrientation) {
235 | case UIImageOrientationLeft:
236 | case UIImageOrientationLeftMirrored:
237 | case UIImageOrientationRight:
238 | case UIImageOrientationRightMirrored:
239 | // Grr...
240 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
241 | break;
242 |
243 | default:
244 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
245 | break;
246 | }
247 |
248 | // And now we just create a new UIImage from the drawing context
249 | CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
250 | UIImage *img = [UIImage imageWithCGImage:cgimg];
251 | CGContextRelease(ctx);
252 | CGImageRelease(cgimg);
253 | return img;
254 | }
255 |
256 | - (void) drawMaskWithString:(NSString *)str context:(CGContextRef)context radius:(CGFloat)radius angle:(CGFloat)angle colour:(UIColor *)colour font:(UIFont *)font slantAngle:(CGFloat)slantAngle size:(CGSize)size{
257 | // *******************************************************
258 | // This draws the String str centred at the position
259 | // specified by the polar coordinates (r, theta)
260 | // i.e. the x= r * cos(theta) y= r * sin(theta)
261 | // and rotated by the angle slantAngle
262 | // *******************************************************
263 |
264 | // Set the text attributes
265 | NSDictionary *attributes = @{NSForegroundColorAttributeName:colour,
266 | NSFontAttributeName:font};
267 | // Save the context
268 | CGContextSaveGState(context);
269 | // Undo the inversion of the Y-axis (or the text goes backwards!)
270 | CGContextScaleCTM(context, 1, -1);
271 | // Move the origin to the centre of the text (negating the y-axis manually)
272 | CGContextTranslateCTM(context, radius * cos(angle), -(radius * sin(angle)));
273 | // Rotate the coordinate system
274 | CGContextRotateCTM(context, -slantAngle);
275 | // Calculate the width of the text
276 | CGSize offset = [str sizeWithAttributes:attributes];
277 | // Move the origin by half the size of the text
278 | CGContextTranslateCTM (context, -offset.width / 2, -offset.height / 2); // Move the origin to the centre of the text (negating the y-axis manually)
279 | // Draw the text
280 |
281 | NSInteger width = ceil(cos(slantAngle)*offset.width);
282 | NSInteger height = ceil(sin(slantAngle)*offset.width);
283 |
284 | NSInteger row = size.height/(height+100.0);
285 | NSInteger coloum = size.width/(width+100.0)>6?:6;
286 | CGFloat xPoint = 0;
287 | CGFloat yPoint = 0;
288 | for (NSInteger index = 0; index < row*coloum; index++) {
289 |
290 | xPoint = (index%coloum) *(width+100.0)-[UIScreen mainScreen].bounds.size.width;
291 | yPoint = (index/coloum) *(height+100.0);
292 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
293 | xPoint += -[UIScreen mainScreen].bounds.size.width;
294 | yPoint += -[UIScreen mainScreen].bounds.size.height;
295 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
296 | }
297 |
298 | // Restore the context
299 | CGContextRestoreGState(context);
300 | }
301 |
302 | @end
303 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/PhotoBrowserViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoBrowserViewController.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PhotoBrowserViewController : UIViewController
12 |
13 | @property (nonatomic, strong) UIImage *imgBrowse;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/PhotoBrowserViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoBrowserViewController.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import "PhotoBrowserViewController.h"
10 |
11 | @interface PhotoBrowserViewController ()
12 |
13 | @property (weak, nonatomic) IBOutlet UIImageView *imgView;
14 |
15 | @end
16 |
17 | @implementation PhotoBrowserViewController
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 |
22 | [self initSubViews];
23 | }
24 |
25 | - (void)initSubViews {
26 |
27 | [self.imgView setImage:self.imgBrowse];
28 | }
29 |
30 | - (IBAction)tapView:(UITapGestureRecognizer *)sender {
31 |
32 | [self dismissViewControllerAnimated:YES completion:nil];
33 | }
34 |
35 | - (void)setImgBrowse:(UIImage *)imgBrowse {
36 |
37 | _imgBrowse = imgBrowse;
38 |
39 | if (imgBrowse) {
40 | self.view.backgroundColor = [UIColor blackColor];
41 | }
42 | else {
43 | self.view.backgroundColor = [UIColor colorWithRed:128.0/255.0 green:216.0/255.0 blue:255.0/255.0 alpha:1.0];
44 | }
45 | }
46 |
47 | - (void)didReceiveMemoryWarning {
48 | [super didReceiveMemoryWarning];
49 | // Dispose of any resources that can be recreated.
50 | }
51 |
52 | /*
53 | #pragma mark - Navigation
54 |
55 | // In a storyboard-based application, you will often want to do a little preparation before navigation
56 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
57 | // Get the new view controller using [segue destinationViewController].
58 | // Pass the selected object to the new view controller.
59 | }
60 | */
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 | #import "MacroFile.h"
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Controller/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 | #import "ViewController.h"
9 | #import "ModalTransitionAnimator.h"
10 | #import
11 | #import "PhotoBrowserViewController.h"
12 | #import "UIImage+Luban_iOS_Extension_h.h"
13 |
14 | @interface ViewController ()
15 |
16 |
17 | @property (nonatomic, strong) UIImage *imgCompressed;
18 | @property (nonatomic, strong) UIImagePickerController *cameraController;
19 | @property (nonatomic, strong) IBOutlet UIImageView *img_brower;
20 |
21 | @end
22 |
23 | @implementation ViewController
24 |
25 | - (void)viewDidLoad {
26 | [super viewDidLoad];
27 | [self initDataSource];
28 | #if TARGET_IPHONE_SIMULATOR
29 | #define SIMULATOR 1
30 | #elif TARGET_OS_IPHONE
31 | #define SIMULATOR 0
32 | #endif
33 | }
34 |
35 | - (void)initDataSource {
36 | NSData *imgData = [UIImage lubanCompressImage:[UIImage imageNamed:@"IMG_1998.JPG"] withMask:@"Luban_iOS"];
37 | self.imgCompressed = [UIImage imageWithData:imgData];
38 | self.img_brower.image = _imgCompressed;
39 | }
40 |
41 | - (IBAction)btnClick:(UIButton *)sender {
42 |
43 | if (SIMULATOR) {
44 | UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"提示" message:SIMULATOR_WARING preferredStyle:UIAlertControllerStyleAlert];
45 | UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
46 | [alertView addAction:doneAction];
47 | [self presentViewController:alertView animated:YES completion:nil];
48 | return;
49 | }
50 |
51 | AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
52 | if (status == AVAuthorizationStatusDenied) {
53 | UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"提示" message:SETTING_ALERT preferredStyle:UIAlertControllerStyleAlert];
54 | UIAlertAction *doneAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
55 | [alertView addAction:doneAction];
56 | [self presentViewController:alertView animated:YES completion:nil];
57 | }
58 | else {
59 |
60 | [self presentViewController:self.cameraController animated:YES completion:nil];
61 | }
62 | }
63 | - (IBAction)tapView:(UITapGestureRecognizer *)sender {
64 |
65 | PhotoBrowserViewController *photoBrowseVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"PhotoBrowserViewController"];
66 | photoBrowseVC.imgBrowse = self.imgCompressed;
67 | photoBrowseVC.transitioningDelegate = self;
68 | [self presentViewController:photoBrowseVC animated:YES completion:nil];
69 | }
70 |
71 | #pragma mark - UIImagePickerControllerDelegate
72 |
73 | - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary *)editingInfo {
74 |
75 | NSData *imgData = [UIImage lubanCompressImage:image];
76 | self.imgCompressed = [UIImage imageWithData:imgData];
77 | self.img_brower.image = _imgCompressed;
78 | [picker dismissViewControllerAnimated:YES completion:nil];
79 | }
80 | - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
81 | [picker dismissViewControllerAnimated:YES completion:nil];
82 | }
83 |
84 | #pragma mark - UIViewControllerTransitioningDelegate
85 |
86 | - (nullable id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
87 | return [self transitionAnimatorWithPresentProperty:YES];
88 | }
89 |
90 | - (nullable id )animationControllerForDismissedController:(UIViewController *)dismissed {
91 | return [self transitionAnimatorWithPresentProperty:NO];
92 | }
93 |
94 | #pragma mark - Private
95 |
96 | - (ModalTransitionAnimator *)transitionAnimatorWithPresentProperty:(BOOL)isPresented {
97 |
98 | ModalTransitionAnimator *transitionAnimator = [ModalTransitionAnimator new];
99 | transitionAnimator.m_isPresented = isPresented;
100 | transitionAnimator.m_originRect = [self.view convertRect:self.img_brower.frame toView:nil];
101 | return transitionAnimator;
102 | }
103 |
104 | #pragma mark - Getter & Setter
105 |
106 | - (UIImagePickerController *)cameraController {
107 |
108 | if (!_cameraController) {
109 | _cameraController = [[UIImagePickerController alloc] init];
110 | _cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
111 | _cameraController.delegate = self;
112 | _cameraController.modalPresentationStyle = UIModalPresentationFullScreen;
113 | }
114 | return _cameraController;
115 | }
116 |
117 | - (void)setImgCompressed:(UIImage *)imgCompressed {
118 |
119 | _imgCompressed = imgCompressed;
120 |
121 | if (imgCompressed) {
122 | _img_brower.backgroundColor = [UIColor blackColor];
123 | }
124 | else {
125 | _img_brower.backgroundColor = [UIColor colorWithRed:128.0/255.0 green:216.0/255.0 blue:255.0/255.0 alpha:1.0];
126 | }
127 | }
128 |
129 | - (void)didReceiveMemoryWarning {
130 | [super didReceiveMemoryWarning];
131 | // Dispose of any resources that can be recreated.
132 | }
133 |
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSCameraUsageDescription
6 | 使用相机拍摄照片
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/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 |
27 |
28 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/MacroFile.h:
--------------------------------------------------------------------------------
1 | //
2 | // MacroFile.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/21.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #ifndef MacroFile_h
10 | #define MacroFile_h
11 |
12 | #define SIMULATOR_WARING @"模拟器不支持拍照,想测试拍照,请在真机上运行,项目里已经内置了一张名字为 IMG_1998.JPG 的图片,所展示的也是此图的压缩图,点击可以查看压缩后的大图,控制台输出了压缩前后图片的大小"
13 | #define SETTING_ALERT @"请前往手机 设置->找到Luban-iOS->打开相机权限"
14 |
15 |
16 | #endif /* MacroFile_h */
17 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/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 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | }
88 | ],
89 | "info" : {
90 | "version" : 1,
91 | "author" : "xcode"
92 | }
93 | }
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_scqszj_sy.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "ic_scqszj_sy.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 | }
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_scqszj_sy.imageset/ic_scqszj_sy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuoZhiQiang/Luban_iOS/4554b92c20af3d87be7f6bd237adf6ce86c89a4f/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_scqszj_sy.imageset/ic_scqszj_sy.png
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_wd_jyfk_tj.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "ic_wd_jyfk_tj@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "ic_wd_jyfk_tj@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_wd_jyfk_tj.imageset/ic_wd_jyfk_tj@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuoZhiQiang/Luban_iOS/4554b92c20af3d87be7f6bd237adf6ce86c89a4f/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_wd_jyfk_tj.imageset/ic_wd_jyfk_tj@2x.png
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_wd_jyfk_tj.imageset/ic_wd_jyfk_tj@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuoZhiQiang/Luban_iOS/4554b92c20af3d87be7f6bd237adf6ce86c89a4f/Luban-iOSDemo/Luban-iOS/Resource/Assets.xcassets/ic_wd_jyfk_tj.imageset/ic_wd_jyfk_tj@3x.png
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Resource/IMG_1998.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GuoZhiQiang/Luban_iOS/4554b92c20af3d87be7f6bd237adf6ce86c89a4f/Luban-iOSDemo/Luban-iOS/Resource/IMG_1998.JPG
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Transition/ModalTransitionAnimator.h:
--------------------------------------------------------------------------------
1 | //
2 | // ModalTransitionAnimator.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/21.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import
11 |
12 | @interface ModalTransitionAnimator : NSObject
13 |
14 | // default value is 0.3s
15 | @property (nonatomic, assign) CGFloat m_duration;
16 | // default value is CGRectZero
17 | @property (nonatomic, assign) CGRect m_originRect;
18 | // default value is YES
19 | @property (nonatomic, assign) BOOL m_isPresented;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/Transition/ModalTransitionAnimator.m:
--------------------------------------------------------------------------------
1 | //
2 | // ModalTransitionAnimator.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/21.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 | #import
9 | #import "ModalTransitionAnimator.h"
10 |
11 | @implementation ModalTransitionAnimator
12 |
13 | - (instancetype)init {
14 | self = [super init];
15 | return self;
16 | }
17 |
18 | - (NSTimeInterval)transitionDuration:(id)transitionContext {
19 | return self.m_duration;
20 | }
21 |
22 | - (void)animateTransition:(id)transitionContext {
23 |
24 | UIView *transToView ;
25 | UIView *transFromView ;
26 | CGPoint endAnimationCenter ;
27 | CGPoint startAnimationCenter ;
28 | CGAffineTransform transformEnd ;
29 | CGAffineTransform transformStart ;
30 |
31 | if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
32 | transToView = [transitionContext viewForKey:UITransitionContextToViewKey];
33 | transFromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
34 | }
35 | else {
36 | // lower ios7
37 | transToView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
38 | transFromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;
39 | }
40 | UIView *animationView = self.m_isPresented ? transToView : transFromView;
41 |
42 | CGFloat scaleX = CGRectGetWidth(animationView.frame) ? CGRectGetWidth(self.m_originRect) / CGRectGetWidth(animationView.frame) : 0.0;
43 | CGFloat scaleY = CGRectGetHeight(animationView.frame) ? CGRectGetHeight(self.m_originRect) / CGRectGetHeight(animationView.frame) : 0.0;
44 |
45 | CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
46 |
47 | CGPoint originCenter = CGPointMake(CGRectGetMidX(self.m_originRect), CGRectGetMidY(self.m_originRect));
48 | CGPoint animationCenter = CGPointMake(CGRectGetMidX(animationView.frame), CGRectGetMidY(animationView.frame));
49 |
50 | if (self.m_isPresented) {
51 | transformEnd = CGAffineTransformIdentity;
52 | transformStart = transform;
53 | endAnimationCenter = animationCenter;
54 | startAnimationCenter = originCenter;
55 | }
56 | else {
57 | transformEnd = transform;
58 | transformStart = CGAffineTransformIdentity;
59 | endAnimationCenter = originCenter;
60 | startAnimationCenter = animationCenter;
61 | }
62 | UIView *contrainer = [transitionContext containerView];
63 | [contrainer addSubview:transToView];
64 | [contrainer bringSubviewToFront:animationView];
65 |
66 | animationView.transform = transformStart;
67 | animationView.center = startAnimationCenter;
68 |
69 | [UIView animateWithDuration:self.m_duration animations:^{
70 |
71 | animationView.transform = transformEnd;
72 | animationView.center = endAnimationCenter;
73 | } completion:^(BOOL finished) {
74 | BOOL transitionWasCancelled = [transitionContext transitionWasCancelled];
75 | [transitionContext completeTransition:!transitionWasCancelled];
76 | }];
77 | }
78 |
79 | - (CGFloat)m_duration {
80 |
81 | NSNumber *duration = objc_getAssociatedObject(self, _cmd);
82 | if (duration) {
83 | return [duration floatValue];
84 | }
85 | self.m_duration = 0.3;
86 | return 0.3;
87 | }
88 |
89 | - (void)setM_duration:(CGFloat)m_duration {
90 |
91 | SEL key = @selector(m_duration);
92 | objc_setAssociatedObject(self, key, @(m_duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
93 | }
94 |
95 | - (CGRect)m_originRect {
96 | NSValue *rect = objc_getAssociatedObject(self, _cmd);
97 | if (rect) {
98 | return [rect CGRectValue];
99 | }
100 | self.m_originRect = CGRectZero;
101 | return CGRectZero;
102 | }
103 |
104 | - (void)setM_originRect:(CGRect)m_originRect {
105 |
106 | SEL key = @selector(m_originRect);
107 | objc_setAssociatedObject(self, key, [NSValue valueWithCGRect:m_originRect], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
108 | }
109 |
110 | - (BOOL)m_isPresented {
111 |
112 | NSNumber *present = objc_getAssociatedObject(self, _cmd);
113 | if (present) {
114 | return [present boolValue];
115 | }
116 | self.m_isPresented = YES;
117 | return YES;
118 | }
119 |
120 | - (void)setM_isPresented:(BOOL)m_isPresented {
121 |
122 | SEL key = @selector(m_isPresented);
123 | objc_setAssociatedObject(self, key, @(m_isPresented), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
124 | }
125 |
126 | @end
127 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOS/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOSTests/Luban_iOSTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // Luban_iOSTests.m
3 | // Luban-iOSTests
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface Luban_iOSTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation Luban_iOSTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOSUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban-iOSUITests/Luban_iOSUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // Luban_iOSUITests.m
3 | // Luban-iOSUITests
4 | //
5 | // Created by guo on 2017/7/19.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface Luban_iOSUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation Luban_iOSUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (Luban_iOS_Extension_h)
12 |
13 | + (NSData *)lubanCompressImage:(UIImage *)image;
14 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName;
15 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Luban-iOSDemo/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UIImage+Luban_iOS_Extension_h.h"
11 |
12 | @implementation UIImage (Luban_iOS_Extension_h)
13 |
14 | static char isCustomImage;
15 | static char customImageName;
16 |
17 | + (NSData *)lubanCompressImage:(UIImage *)image {
18 | return [self lubanCompressImage:image withMask:nil];
19 | }
20 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName {
21 |
22 | double size;
23 | NSData *imageData = UIImageJPEGRepresentation(image, 1);
24 |
25 | NSLog(@"Luban-iOS image data size before compressed == %f Kb",imageData.length/1024.0);
26 |
27 | int fixelW = (int)image.size.width;
28 | int fixelH = (int)image.size.height;
29 | int thumbW = fixelW % 2 == 1 ? fixelW + 1 : fixelW;
30 | int thumbH = fixelH % 2 == 1 ? fixelH + 1 : fixelH;
31 |
32 | double scale = ((double)fixelW/fixelH);
33 |
34 | if (scale <= 1 && scale > 0.5625) {
35 |
36 | if (fixelH < 1664) {
37 | if (imageData.length/1024.0 < 150) {
38 | return imageData;
39 | }
40 | size = (fixelW * fixelH) / pow(1664, 2) * 150;
41 | size = size < 60 ? 60 : size;
42 | }
43 | else if (fixelH >= 1664 && fixelH < 4990) {
44 | thumbW = fixelW / 2;
45 | thumbH = fixelH / 2;
46 | size = (thumbH * thumbW) / pow(2495, 2) * 300;
47 | size = size < 60 ? 60 : size;
48 | }
49 | else if (fixelH >= 4990 && fixelH < 10240) {
50 | thumbW = fixelW / 4;
51 | thumbH = fixelH / 4;
52 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
53 | size = size < 100 ? 100 : size;
54 | }
55 | else {
56 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
57 | thumbW = fixelW / multiple;
58 | thumbH = fixelH / multiple;
59 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
60 | size = size < 100 ? 100 : size;
61 | }
62 | }
63 | else if (scale <= 0.5625 && scale > 0.5) {
64 |
65 | if (fixelH < 1280 && imageData.length/1024 < 200) {
66 |
67 | return imageData;
68 | }
69 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
70 | thumbW = fixelW / multiple;
71 | thumbH = fixelH / multiple;
72 | size = (thumbW * thumbH) / (1440.0 * 2560.0) * 400;
73 | size = size < 100 ? 100 : size;
74 | }
75 | else {
76 | int multiple = (int)ceil(fixelH / (1280.0 / scale));
77 | thumbW = fixelW / multiple;
78 | thumbH = fixelH / multiple;
79 | size = ((thumbW * thumbH) / (1280.0 * (1280 / scale))) * 500;
80 | size = size < 100 ? 100 : size;
81 | }
82 | return [self compressWithImage:image thumbW:thumbW thumbH:thumbH size:size withMask:maskName];
83 | }
84 |
85 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName {
86 |
87 | if (imageName) {
88 | objc_setAssociatedObject(self, &isCustomImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
89 | objc_setAssociatedObject(self, &customImageName, imageName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
90 | }
91 | return [self lubanCompressImage:image withMask:nil];
92 | }
93 |
94 | + (NSData *)compressWithImage:(UIImage *)image thumbW:(int)width thumbH:(int)height size:(double)size withMask:(NSString *)maskName {
95 |
96 | UIImage *thumbImage = [image fixOrientation];
97 | thumbImage = [thumbImage resizeImage:image thumbWidth:width thumbHeight:height withMask:maskName];
98 |
99 | float qualityCompress = 0.0;
100 | NSData *imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
101 |
102 | NSUInteger lenght = imageData.length;
103 | while (lenght / 1024 > size && qualityCompress <= (1-0.06)) {
104 |
105 | qualityCompress += 0.06 ;
106 | int intCommpress = (int)(qualityCompress*100);
107 | qualityCompress = intCommpress/100.0;
108 | imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
109 | lenght = imageData.length;
110 | thumbImage = [UIImage imageWithData:imageData];
111 | }
112 | NSLog(@"Luban-iOS image data size after compressed ==%f kb",imageData.length/1024.0);
113 | return imageData;
114 | }
115 |
116 | // specify the size
117 | - (UIImage *)resizeImage:(UIImage *)image thumbWidth:(int)width thumbHeight:(int)height withMask:(NSString *)maskName {
118 |
119 | int outW = (int)image.size.width;
120 | int outH = (int)image.size.height;
121 |
122 | int inSampleSize = 1;
123 |
124 | if (outW > width || outH > height) {
125 | int halfW = outW / 2;
126 | int halfH = outH / 2;
127 |
128 | while ((halfH / inSampleSize) > height && (halfW / inSampleSize) > width) {
129 | inSampleSize *= 2;
130 | }
131 | }
132 | // keep one decimal
133 | int outWith = (int)((outW / (float) width)*10);
134 | int outHeiht = (int)((outH / (float) height)*10);
135 | float heightRatio = outHeiht/10.0;
136 | float widthRatio = outWith/10.0;
137 |
138 | if (heightRatio > 1 || widthRatio > 1) {
139 |
140 | inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
141 | }
142 | CGSize thumbSize = CGSizeMake((NSUInteger)((CGFloat)(outW/inSampleSize)), (NSUInteger)((CGFloat)(outH/inSampleSize)));
143 |
144 | UIGraphicsBeginImageContext(thumbSize);
145 |
146 | CGContextRef context = UIGraphicsGetCurrentContext();
147 |
148 | [image drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
149 | if (maskName) {
150 |
151 | CGContextTranslateCTM (context, thumbSize.width / 2, thumbSize.height / 2);
152 | CGContextScaleCTM (context, 1, -1);
153 |
154 | [self drawMaskWithString:maskName context:context radius:0 angle:0 colour:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5] font:[UIFont systemFontOfSize:38.0] slantAngle:(CGFloat)(M_PI/6) size:thumbSize];
155 | }
156 | else {
157 | NSNumber *iscustom = objc_getAssociatedObject(self, &isCustomImage);
158 | BOOL isCustom = [iscustom boolValue];
159 | if (isCustom) {
160 | NSString *imageName = objc_getAssociatedObject(self, &customImageName);
161 | UIImage *imageMask = [UIImage imageNamed:imageName];
162 | if (imageMask) {
163 | [imageMask drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
164 | }
165 | }
166 | }
167 | UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
168 | UIGraphicsEndImageContext();
169 |
170 | objc_setAssociatedObject(self, &isCustomImage, @(NO), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
171 |
172 | return resultImage;
173 | }
174 |
175 | - (UIImage *)fixOrientation {
176 |
177 | // No-op if the orientation is already correct
178 | if (self.imageOrientation == UIImageOrientationUp) return self;
179 |
180 | // We need to calculate the proper transformation to make the image upright.
181 | // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
182 | CGAffineTransform transform = CGAffineTransformIdentity;
183 |
184 | switch (self.imageOrientation) {
185 | case UIImageOrientationDown:
186 | case UIImageOrientationDownMirrored:
187 | transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
188 | transform = CGAffineTransformRotate(transform, M_PI);
189 | break;
190 |
191 | case UIImageOrientationLeft:
192 | case UIImageOrientationLeftMirrored:
193 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
194 | transform = CGAffineTransformRotate(transform, M_PI_2);
195 | break;
196 |
197 | case UIImageOrientationRight:
198 | case UIImageOrientationRightMirrored:
199 | transform = CGAffineTransformTranslate(transform, 0, self.size.height);
200 | transform = CGAffineTransformRotate(transform, -M_PI_2);
201 | break;
202 | case UIImageOrientationUp:
203 | case UIImageOrientationUpMirrored:
204 | break;
205 | }
206 |
207 | switch (self.imageOrientation) {
208 | case UIImageOrientationUpMirrored:
209 | case UIImageOrientationDownMirrored:
210 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
211 | transform = CGAffineTransformScale(transform, -1, 1);
212 | break;
213 |
214 | case UIImageOrientationLeftMirrored:
215 | case UIImageOrientationRightMirrored:
216 | transform = CGAffineTransformTranslate(transform, self.size.height, 0);
217 | transform = CGAffineTransformScale(transform, -1, 1);
218 | break;
219 | case UIImageOrientationUp:
220 | case UIImageOrientationDown:
221 | case UIImageOrientationLeft:
222 | case UIImageOrientationRight:
223 | break;
224 | }
225 |
226 | // Now we draw the underlying CGImage into a new context, applying the transform
227 | // calculated above.
228 | CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
229 | CGImageGetBitsPerComponent(self.CGImage), 0,
230 | CGImageGetColorSpace(self.CGImage),
231 | CGImageGetBitmapInfo(self.CGImage));
232 | CGContextConcatCTM(ctx, transform);
233 | switch (self.imageOrientation) {
234 | case UIImageOrientationLeft:
235 | case UIImageOrientationLeftMirrored:
236 | case UIImageOrientationRight:
237 | case UIImageOrientationRightMirrored:
238 | // Grr...
239 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
240 | break;
241 |
242 | default:
243 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
244 | break;
245 | }
246 |
247 | // And now we just create a new UIImage from the drawing context
248 | CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
249 | UIImage *img = [UIImage imageWithCGImage:cgimg];
250 | CGContextRelease(ctx);
251 | CGImageRelease(cgimg);
252 | return img;
253 | }
254 |
255 | - (void) drawMaskWithString:(NSString *)str context:(CGContextRef)context radius:(CGFloat)radius angle:(CGFloat)angle colour:(UIColor *)colour font:(UIFont *)font slantAngle:(CGFloat)slantAngle size:(CGSize)size{
256 | // *******************************************************
257 | // This draws the String str centred at the position
258 | // specified by the polar coordinates (r, theta)
259 | // i.e. the x= r * cos(theta) y= r * sin(theta)
260 | // and rotated by the angle slantAngle
261 | // *******************************************************
262 |
263 | // Set the text attributes
264 | NSDictionary *attributes = @{NSForegroundColorAttributeName:colour,
265 | NSFontAttributeName:font};
266 | // Save the context
267 | CGContextSaveGState(context);
268 | // Undo the inversion of the Y-axis (or the text goes backwards!)
269 | CGContextScaleCTM(context, 1, -1);
270 | // Move the origin to the centre of the text (negating the y-axis manually)
271 | CGContextTranslateCTM(context, radius * cos(angle), -(radius * sin(angle)));
272 | // Rotate the coordinate system
273 | CGContextRotateCTM(context, -slantAngle);
274 | // Calculate the width of the text
275 | CGSize offset = [str sizeWithAttributes:attributes];
276 | // Move the origin by half the size of the text
277 | CGContextTranslateCTM (context, -offset.width / 2, -offset.height / 2); // Move the origin to the centre of the text (negating the y-axis manually)
278 | // Draw the text
279 |
280 | NSInteger width = ceil(cos(slantAngle)*offset.width);
281 | NSInteger height = ceil(sin(slantAngle)*offset.width);
282 |
283 | NSInteger row = size.height/(height+100.0);
284 | NSInteger coloum = size.width/(width+100.0)>6?:6;
285 | CGFloat xPoint = 0;
286 | CGFloat yPoint = 0;
287 | for (NSInteger index = 0; index < row*coloum; index++) {
288 |
289 | xPoint = (index%coloum) *(width+100.0)-[UIScreen mainScreen].bounds.size.width;
290 | yPoint = (index/coloum) *(height+100.0);
291 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
292 | xPoint += -[UIScreen mainScreen].bounds.size.width;
293 | yPoint += -[UIScreen mainScreen].bounds.size.height;
294 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
295 | }
296 |
297 | // Restore the context
298 | CGContextRestoreGState(context);
299 | }
300 |
301 | @end
302 |
--------------------------------------------------------------------------------
/Luban_iOS.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod spec lint Luban_iOS.podspec' to ensure this is a
3 | # valid spec and to remove all comments including this before submitting the spec.
4 | #
5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7 | #
8 |
9 | Pod::Spec.new do |s|
10 |
11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
12 | s.name = "Luban_iOS"
13 | s.version = "1.0.6"
14 | s.summary = "An UIImage's category to compress data almost without distortion ,Thanks to Android LuBan library"
15 | s.description = <<-DESC
16 | An UIImage's category to compress data almost without distortion ,Thanks to Android LuBan library. Just pod in 2 files and no need for any setups
17 | DESC
18 | s.homepage = "https://github.com/GuoZhiQiang/Luban_iOS"
19 |
20 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
21 |
22 | s.license = { :type => "MIT", :file => "LICENSE" }
23 |
24 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
25 |
26 | s.author = { "cook" => "http://www.jianshu.com/p/eb786aefdlle" }
27 | s.social_media_url = "http://weibo.com/2639447231/profile"
28 |
29 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
30 |
31 | s.platform = :ios, "8.0"
32 |
33 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
34 |
35 | s.source = { :git => "https://github.com/GuoZhiQiang/Luban_iOS.git", :tag => "1.0.6" }
36 |
37 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
38 |
39 | s.source_files = "Luban_iOS_Extension_h/*.{h,m}"
40 |
41 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
42 |
43 | s.requires_arc = true
44 |
45 | end
46 |
--------------------------------------------------------------------------------
/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.h
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIImage (Luban_iOS_Extension_h)
12 |
13 | + (NSData *)lubanCompressImage:(UIImage *)image;
14 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName;
15 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Luban_iOS_Extension_h/UIImage+Luban_iOS_Extension_h.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIImage+Luban_iOS_Extension_h.m
3 | // Luban-iOS
4 | //
5 | // Created by guo on 2017/7/20.
6 | // Copyright © 2017年 guo. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "UIImage+Luban_iOS_Extension_h.h"
11 |
12 | @implementation UIImage (Luban_iOS_Extension_h)
13 |
14 | static char isCustomImage;
15 | static char customImageName;
16 |
17 | + (NSData *)lubanCompressImage:(UIImage *)image {
18 | return [self lubanCompressImage:image withMask:nil];
19 | }
20 | + (NSData *)lubanCompressImage:(UIImage *)image withMask:(NSString *)maskName {
21 |
22 | double size;
23 | NSData *imageData = UIImageJPEGRepresentation(image, 1);
24 |
25 | NSLog(@"Luban-iOS image data size before compressed == %f Kb",imageData.length/1024.0);
26 |
27 | int fixelW = (int)image.size.width;
28 | int fixelH = (int)image.size.height;
29 | int thumbW = fixelW % 2 == 1 ? fixelW + 1 : fixelW;
30 | int thumbH = fixelH % 2 == 1 ? fixelH + 1 : fixelH;
31 |
32 | double scale = ((double)fixelW/fixelH);
33 |
34 | if (scale <= 1 && scale > 0.5625) {
35 |
36 | if (fixelH < 1664) {
37 | if (imageData.length/1024.0 < 150) {
38 | return imageData;
39 | }
40 | size = (fixelW * fixelH) / pow(1664, 2) * 150;
41 | size = size < 60 ? 60 : size;
42 | }
43 | else if (fixelH >= 1664 && fixelH < 4990) {
44 | thumbW = fixelW / 2;
45 | thumbH = fixelH / 2;
46 | size = (thumbH * thumbW) / pow(2495, 2) * 300;
47 | size = size < 60 ? 60 : size;
48 | }
49 | else if (fixelH >= 4990 && fixelH < 10240) {
50 | thumbW = fixelW / 4;
51 | thumbH = fixelH / 4;
52 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
53 | size = size < 100 ? 100 : size;
54 | }
55 | else {
56 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
57 | thumbW = fixelW / multiple;
58 | thumbH = fixelH / multiple;
59 | size = (thumbW * thumbH) / pow(2560, 2) * 300;
60 | size = size < 100 ? 100 : size;
61 | }
62 | }
63 | else if (scale <= 0.5625 && scale > 0.5) {
64 |
65 | if (fixelH < 1280 && imageData.length/1024 < 200) {
66 |
67 | return imageData;
68 | }
69 | int multiple = fixelH / 1280 == 0 ? 1 : fixelH / 1280;
70 | thumbW = fixelW / multiple;
71 | thumbH = fixelH / multiple;
72 | size = (thumbW * thumbH) / (1440.0 * 2560.0) * 400;
73 | size = size < 100 ? 100 : size;
74 | }
75 | else {
76 | int multiple = (int)ceil(fixelH / (1280.0 / scale));
77 | thumbW = fixelW / multiple;
78 | thumbH = fixelH / multiple;
79 | size = ((thumbW * thumbH) / (1280.0 * (1280 / scale))) * 500;
80 | size = size < 100 ? 100 : size;
81 | }
82 | return [self compressWithImage:image thumbW:thumbW thumbH:thumbH size:size withMask:maskName];
83 | }
84 |
85 | + (NSData *)lubanCompressImage:(UIImage *)image withCustomImage:(NSString *)imageName {
86 |
87 | if (imageName) {
88 | objc_setAssociatedObject(self, &isCustomImage, @(1), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
89 | objc_setAssociatedObject(self, &customImageName, imageName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
90 | }
91 | return [self lubanCompressImage:image withMask:nil];
92 | }
93 |
94 | + (NSData *)compressWithImage:(UIImage *)image thumbW:(int)width thumbH:(int)height size:(double)size withMask:(NSString *)maskName {
95 |
96 | UIImage *thumbImage = [image fixOrientation];
97 | thumbImage = [thumbImage resizeImage:image thumbWidth:width thumbHeight:height withMask:maskName];
98 |
99 | float qualityCompress = 0.0;
100 | NSData *imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
101 |
102 | NSUInteger lenght = imageData.length;
103 | while (lenght / 1024 > size && qualityCompress <= (1-0.06)) {
104 |
105 | qualityCompress += 0.06 ;
106 | int intCommpress = (int)(qualityCompress*100);
107 | qualityCompress = intCommpress/100.0;
108 | imageData = UIImageJPEGRepresentation(thumbImage, qualityCompress);
109 | lenght = imageData.length;
110 | thumbImage = [UIImage imageWithData:imageData];
111 | }
112 | NSLog(@"Luban-iOS image data size after compressed ==%f kb",imageData.length/1024.0);
113 | return imageData;
114 | }
115 |
116 | // specify the size
117 | - (UIImage *)resizeImage:(UIImage *)image thumbWidth:(int)width thumbHeight:(int)height withMask:(NSString *)maskName {
118 |
119 | int outW = (int)image.size.width;
120 | int outH = (int)image.size.height;
121 |
122 | int inSampleSize = 1;
123 |
124 | if (outW > width || outH > height) {
125 | int halfW = outW / 2;
126 | int halfH = outH / 2;
127 |
128 | while ((halfH / inSampleSize) > height && (halfW / inSampleSize) > width) {
129 | inSampleSize *= 2;
130 | }
131 | }
132 | // keep one decimal
133 | int outWith = (int)((outW / (float) width)*10);
134 | int outHeiht = (int)((outH / (float) height)*10);
135 | float heightRatio = outHeiht/10.0;
136 | float widthRatio = outWith/10.0;
137 |
138 | if (heightRatio > 1 || widthRatio > 1) {
139 |
140 | inSampleSize = heightRatio > widthRatio ? heightRatio : widthRatio;
141 | }
142 | CGSize thumbSize = CGSizeMake((NSUInteger)((CGFloat)(outW/inSampleSize)), (NSUInteger)((CGFloat)(outH/inSampleSize)));
143 |
144 | UIGraphicsBeginImageContext(thumbSize);
145 |
146 | CGContextRef context = UIGraphicsGetCurrentContext();
147 |
148 | [image drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
149 | if (maskName) {
150 |
151 | CGContextTranslateCTM (context, thumbSize.width / 2, thumbSize.height / 2);
152 | CGContextScaleCTM (context, 1, -1);
153 |
154 | [self drawMaskWithString:maskName context:context radius:0 angle:0 colour:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5] font:[UIFont systemFontOfSize:38.0] slantAngle:(CGFloat)(M_PI/6) size:thumbSize];
155 | }
156 | else {
157 | NSNumber *iscustom = objc_getAssociatedObject(self, &isCustomImage);
158 | BOOL isCustom = [iscustom boolValue];
159 | if (isCustom) {
160 | NSString *imageName = objc_getAssociatedObject(self, &customImageName);
161 | UIImage *imageMask = [UIImage imageNamed:imageName];
162 | if (imageMask) {
163 | [imageMask drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
164 | }
165 | }
166 | }
167 | UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
168 | UIGraphicsEndImageContext();
169 |
170 | objc_setAssociatedObject(self, &isCustomImage, @(NO), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
171 |
172 | return resultImage;
173 | }
174 |
175 | - (UIImage *)fixOrientation {
176 |
177 | // No-op if the orientation is already correct
178 | if (self.imageOrientation == UIImageOrientationUp) return self;
179 |
180 | // We need to calculate the proper transformation to make the image upright.
181 | // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
182 | CGAffineTransform transform = CGAffineTransformIdentity;
183 |
184 | switch (self.imageOrientation) {
185 | case UIImageOrientationDown:
186 | case UIImageOrientationDownMirrored:
187 | transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
188 | transform = CGAffineTransformRotate(transform, M_PI);
189 | break;
190 |
191 | case UIImageOrientationLeft:
192 | case UIImageOrientationLeftMirrored:
193 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
194 | transform = CGAffineTransformRotate(transform, M_PI_2);
195 | break;
196 |
197 | case UIImageOrientationRight:
198 | case UIImageOrientationRightMirrored:
199 | transform = CGAffineTransformTranslate(transform, 0, self.size.height);
200 | transform = CGAffineTransformRotate(transform, -M_PI_2);
201 | break;
202 | case UIImageOrientationUp:
203 | case UIImageOrientationUpMirrored:
204 | break;
205 | }
206 |
207 | switch (self.imageOrientation) {
208 | case UIImageOrientationUpMirrored:
209 | case UIImageOrientationDownMirrored:
210 | transform = CGAffineTransformTranslate(transform, self.size.width, 0);
211 | transform = CGAffineTransformScale(transform, -1, 1);
212 | break;
213 |
214 | case UIImageOrientationLeftMirrored:
215 | case UIImageOrientationRightMirrored:
216 | transform = CGAffineTransformTranslate(transform, self.size.height, 0);
217 | transform = CGAffineTransformScale(transform, -1, 1);
218 | break;
219 | case UIImageOrientationUp:
220 | case UIImageOrientationDown:
221 | case UIImageOrientationLeft:
222 | case UIImageOrientationRight:
223 | break;
224 | }
225 |
226 | // Now we draw the underlying CGImage into a new context, applying the transform
227 | // calculated above.
228 | CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height,
229 | CGImageGetBitsPerComponent(self.CGImage), 0,
230 | CGImageGetColorSpace(self.CGImage),
231 | CGImageGetBitmapInfo(self.CGImage));
232 | CGContextConcatCTM(ctx, transform);
233 | switch (self.imageOrientation) {
234 | case UIImageOrientationLeft:
235 | case UIImageOrientationLeftMirrored:
236 | case UIImageOrientationRight:
237 | case UIImageOrientationRightMirrored:
238 | // Grr...
239 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
240 | break;
241 |
242 | default:
243 | CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
244 | break;
245 | }
246 |
247 | // And now we just create a new UIImage from the drawing context
248 | CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
249 | UIImage *img = [UIImage imageWithCGImage:cgimg];
250 | CGContextRelease(ctx);
251 | CGImageRelease(cgimg);
252 | return img;
253 | }
254 |
255 | - (void) drawMaskWithString:(NSString *)str context:(CGContextRef)context radius:(CGFloat)radius angle:(CGFloat)angle colour:(UIColor *)colour font:(UIFont *)font slantAngle:(CGFloat)slantAngle size:(CGSize)size{
256 | // *******************************************************
257 | // This draws the String str centred at the position
258 | // specified by the polar coordinates (r, theta)
259 | // i.e. the x= r * cos(theta) y= r * sin(theta)
260 | // and rotated by the angle slantAngle
261 | // *******************************************************
262 |
263 | // Set the text attributes
264 | NSDictionary *attributes = @{NSForegroundColorAttributeName:colour,
265 | NSFontAttributeName:font};
266 | // Save the context
267 | CGContextSaveGState(context);
268 | // Undo the inversion of the Y-axis (or the text goes backwards!)
269 | CGContextScaleCTM(context, 1, -1);
270 | // Move the origin to the centre of the text (negating the y-axis manually)
271 | CGContextTranslateCTM(context, radius * cos(angle), -(radius * sin(angle)));
272 | // Rotate the coordinate system
273 | CGContextRotateCTM(context, -slantAngle);
274 | // Calculate the width of the text
275 | CGSize offset = [str sizeWithAttributes:attributes];
276 | // Move the origin by half the size of the text
277 | CGContextTranslateCTM (context, -offset.width / 2, -offset.height / 2); // Move the origin to the centre of the text (negating the y-axis manually)
278 | // Draw the text
279 |
280 | NSInteger width = ceil(cos(slantAngle)*offset.width);
281 | NSInteger height = ceil(sin(slantAngle)*offset.width);
282 |
283 | NSInteger row = size.height/(height+100.0);
284 | NSInteger coloum = size.width/(width+100.0)>6?:6;
285 | CGFloat xPoint = 0;
286 | CGFloat yPoint = 0;
287 | for (NSInteger index = 0; index < row*coloum; index++) {
288 |
289 | xPoint = (index%coloum) *(width+100.0)-[UIScreen mainScreen].bounds.size.width;
290 | yPoint = (index/coloum) *(height+100.0);
291 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
292 | xPoint += -[UIScreen mainScreen].bounds.size.width;
293 | yPoint += -[UIScreen mainScreen].bounds.size.height;
294 | [str drawAtPoint:CGPointMake(xPoint, yPoint) withAttributes:attributes];
295 | }
296 |
297 | // Restore the context
298 | CGContextRestoreGState(context);
299 | }
300 |
301 | @end
302 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # [Wiki](https://github.com/GuoZhiQiang/Luban_iOS/wiki)
3 | - 带有演示效果图 `gif`,请查看 [图文并茂](http://www.jianshu.com/p/7bb78eed7826)
4 |
5 | # 更新.Update
6 | - 现在可以添加自定义文字 **水印** 了 | Add custom text as an watermark to your image
7 | - 对应的调用方法:`[UIImage lubanCompressImage:image withMask:maskName]`
8 |
9 | # Luban-iOS
10 | - 借鉴 [Android 鲁班](https://github.com/Curzibn/Luban)压缩库,生成的 iOS 版 压缩代码
11 |
12 | ## 压缩比如下表.Compare:
13 |
14 | | 机型 | 照片获取途径 | 原图大小.before | 压缩后大小.after |
15 | |:------------- |:--------------- | :-------------| :------------- |
16 | | 6s | 拍照(竖屏) | 5.19 Mb | 86.8 Kb
17 | | 6s | 拍照(横屏) | 5.26 Mb | 29.2 Kb
18 | | 7plus | 拍照(竖屏) | 8.05 Mb | 229.1 Kb
19 | | 7plus | 拍照(横屏) | 6.34 Mb | 39.6 Kb
20 | | 6s | 截屏 | 1.05 Mb | 53.56 Kb
21 | | 7plus | 截屏 |234.7 Kb | 37.5 Kb
22 |
23 | ## 安装.Install
24 |
25 | ### Via CocoaPods
26 | - 在 `Podfile` 文件里添加`pod 'Luban_iOS'`
27 |
28 | 然后在终端运行 `pod install`
29 |
30 | >注意:如果使用 `pod search Luban_iOS` or `pod search Luban-iOS` 搜不到,那么,你需要
31 | ```
32 | pod setup
33 | rm -rf ~/Library/Caches/Cocoapods
34 | ```
35 |
36 | ### 使用.Usage
37 | - 下载 Demo 试玩一下,看一下输出,点一下图片看压缩后的效果大图
38 | - 导入 Category 头文件:
39 |
40 | `#import `
41 |
42 | - 方法调用
43 |
44 | `[UIImage lubanCompressImage:image]` **or**
45 |
46 | `[UIImage lubanCompressImage:image withMask:maskName]` **or**
47 |
48 | `[UIImage lubanCompressImage:image withCustomImage:imageName]`
49 |
50 | - 参数说明
51 |
52 | ```
53 | /*
54 | image: UIImage 对象
55 | withMask: 添加水印名字 (NSString)
56 | withCustomImage: 水印图片名称
57 | */
58 | ```
59 | - 注意:
60 | 想使用自定义文字水印的请使用方法:`[UIImage lubanCompressImage:image withMask:maskName]`
61 | 添加水印时,想使用自定义图片水印的请使用方法:`[UIImage lubanCompressImage:image withCustomImage:imageName]`
62 |
63 | ### 后续添加的功能.Further
64 | - 可以自定义水印旋转角度
65 | - 可以根据一个本地路径,进行压缩并存储
66 |
--------------------------------------------------------------------------------