├── LICENSE
├── PrismaSimpleImagePicker.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── roylee.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
└── xcuserdata
│ └── roylee.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ ├── PrismaSimpleImagePicker.xcscheme
│ └── xcschememanagement.plist
├── PrismaSimpleImagePicker
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── AppIcon29x29@2x.png
│ │ ├── AppIcon29x29@3x.png
│ │ ├── AppIcon40x40@2x.png
│ │ ├── AppIcon40x40@3x.png
│ │ ├── AppIcon60x60@2x.png
│ │ ├── AppIcon60x60@3x.png
│ │ └── Contents.json
│ ├── Contents.json
│ ├── Oval.imageset
│ │ ├── Contents.json
│ │ ├── Oval@2x.png
│ │ └── Oval@3x.png
│ ├── StyleSelected.imageset
│ │ ├── Contents.json
│ │ ├── StyleSelected.png
│ │ ├── StyleSelected@2x.png
│ │ └── StyleSelected@3x.png
│ ├── albums-arrow.imageset
│ │ ├── Contents.json
│ │ ├── albums-arrow@2x.png
│ │ └── albums-arrow@3x.png
│ ├── arrows.imageset
│ │ ├── Contents.json
│ │ ├── arrows@2x.png
│ │ └── arrows@3x.png
│ ├── back.imageset
│ │ ├── Contents.json
│ │ ├── back@2x.png
│ │ └── back@3x.png
│ ├── cross.imageset
│ │ ├── Contents.json
│ │ ├── cross@2x.png
│ │ └── cross@3x.png
│ ├── facebook-small.imageset
│ │ ├── Contents.json
│ │ └── facebook-small@2x.png
│ ├── facebook.imageset
│ │ ├── Contents.json
│ │ ├── facebook@2x.png
│ │ └── facebook@3x.png
│ ├── flash-auto.imageset
│ │ ├── Contents.json
│ │ ├── flash-auto@2x.png
│ │ └── flash-auto@3x.png
│ ├── flash-on.imageset
│ │ ├── Contents.json
│ │ ├── flash-on@2x.png
│ │ └── flash-on@3x.png
│ ├── flash.imageset
│ │ ├── Contents.json
│ │ ├── flash@2x.png
│ │ └── flash@3x.png
│ ├── flip.imageset
│ │ ├── Contents.json
│ │ ├── flip@2x.png
│ │ └── flip@3x.png
│ ├── instagram-small.imageset
│ │ ├── Contents.json
│ │ └── instagram-small@2x.png
│ ├── instagram.imageset
│ │ ├── Contents.json
│ │ ├── instagram@2x.png
│ │ └── instagram@3x.png
│ ├── nocamera.imageset
│ │ ├── Contents.json
│ │ ├── nocamera@2x.png
│ │ └── nocamera@3x.png
│ ├── ok.imageset
│ │ ├── Contents.json
│ │ ├── ok@2x.png
│ │ └── ok@3x.png
│ ├── photos.imageset
│ │ ├── Contents.json
│ │ ├── photos@2x.png
│ │ └── photos@3x.png
│ ├── rotate-left.imageset
│ │ ├── Contents.json
│ │ ├── rotate-left@2x.png
│ │ └── rotate-left@3x.png
│ ├── rotate-right.imageset
│ │ ├── Contents.json
│ │ ├── rotate-right@2x.png
│ │ └── rotate-right@3x.png
│ ├── save-small.imageset
│ │ ├── Contents.json
│ │ └── save-small@2x.png
│ ├── save.imageset
│ │ ├── Contents.json
│ │ ├── save@2x.png
│ │ └── save@3x.png
│ ├── settings.imageset
│ │ ├── Contents.json
│ │ ├── settings@2x.png
│ │ └── settings@3x.png
│ ├── share-small.imageset
│ │ ├── Contents.json
│ │ └── share-small@2x.png
│ ├── share.imageset
│ │ ├── Contents.json
│ │ ├── share@2x.png
│ │ └── share@3x.png
│ ├── vk-small.imageset
│ │ ├── Contents.json
│ │ └── vk-small@2x.png
│ ├── vk.imageset
│ │ ├── Contents.json
│ │ ├── vk@2x.png
│ │ └── vk@3x.png
│ ├── watermark.imageset
│ │ ├── Contents.json
│ │ └── watermark@2x.png
│ ├── weibo-small.imageset
│ │ ├── Contents.json
│ │ └── weibo-small@2x.png
│ ├── weibo.imageset
│ │ ├── Contents.json
│ │ ├── weibo@2x.png
│ │ └── weibo@3x.png
│ ├── weсhat-small.imageset
│ │ ├── Contents.json
│ │ └── weсhat-small@2x.png
│ └── weсhat.imageset
│ │ ├── Contents.json
│ │ ├── weсhat@2x.png
│ │ └── weсhat@3x.png
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Info.plist
├── PrismaImagePicker
│ ├── PickerController
│ │ ├── PMImageGroupController.swift
│ │ ├── PMImageGroupController.xib
│ │ ├── PMImagePickerController.swift
│ │ ├── PMImageViewController.swift
│ │ └── PMImageViewController.xib
│ ├── PickerHelper
│ │ ├── PMDeviceOrientation.swift
│ │ └── PMImageManger.swift
│ ├── PickerModel
│ │ └── PMGroupModel.swift
│ └── PickerView
│ │ ├── PMImageGroupCell.swift
│ │ ├── PMImageGroupCell.xib
│ │ ├── PMPhotoGridView.swift
│ │ ├── PMPhotoHeaderItem.swift
│ │ ├── PMPhotoHeaderView.swift
│ │ └── PMPickerTitleButton.swift
├── PrismaPhotoCapture
│ ├── PMImageEditController.swift
│ ├── PMImageProcessController.swift
│ ├── PMImageProtocol.swift
│ ├── PMImageSettingController.swift
│ ├── PMImageSettingController.xib
│ ├── PMNavigationController.swift
│ ├── PMRootViewController.swift
│ └── PNImageCaptureController.swift
├── PrismaViews
│ ├── PMCaptureButtom.swift
│ ├── PMStyleCell.swift
│ └── PMStyleHeaderView.swift
├── PrismaWebImage
│ ├── PMImageCache.swift
│ ├── PMImageDownloader.swift
│ └── PMImageSession.swift
├── ViewController.swift
└── styles.json
├── PrismaSimpleImagePickerTests
├── Info.plist
└── PrismaSimpleImagePickerTests.swift
├── README.md
└── ScreenShots
├── cropimage.png
├── frameworks.png
├── logo.png
├── possion.png
├── prismanib.png
├── screenshot1.gif
├── screenshot2.gif
└── screenshot3.gif
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Roy lee.
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 |
23 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker.xcodeproj/project.xcworkspace/xcuserdata/roylee.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker.xcodeproj/project.xcworkspace/xcuserdata/roylee.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker.xcodeproj/xcuserdata/roylee.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker.xcodeproj/xcuserdata/roylee.xcuserdatad/xcschemes/PrismaSimpleImagePicker.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
53 |
54 |
64 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
83 |
85 |
91 |
92 |
93 |
94 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker.xcodeproj/xcuserdata/roylee.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | PrismaSimpleImagePicker.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 7D56B5DD1D449BA1009224A5
16 |
17 | primary
18 |
19 |
20 | 7D56B5F11D449BA1009224A5
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(application: UIApplication) {
23 | // 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.
24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(application: UIApplication) {
28 | // 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.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(application: UIApplication) {
33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
34 | }
35 |
36 | func applicationDidBecomeActive(application: UIApplication) {
37 | // 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.
38 | }
39 |
40 | func applicationWillTerminate(application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon29x29@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon40x40@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/AppIcon60x60@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "AppIcon29x29@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "AppIcon29x29@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "AppIcon40x40@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "AppIcon40x40@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "AppIcon60x60@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "AppIcon60x60@3x.png",
37 | "scale" : "3x"
38 | },
39 | ],
40 | "info" : {
41 | "version" : 1,
42 | "author" : "xcode"
43 | }
44 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/Oval.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "Oval@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "Oval@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/Oval.imageset/Oval@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/Oval.imageset/Oval@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/Oval.imageset/Oval@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/Oval.imageset/Oval@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "StyleSelected.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "StyleSelected@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "StyleSelected@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/StyleSelected.imageset/StyleSelected@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/albums-arrow.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "albums-arrow@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "albums-arrow@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/albums-arrow.imageset/albums-arrow@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/albums-arrow.imageset/albums-arrow@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/albums-arrow.imageset/albums-arrow@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/albums-arrow.imageset/albums-arrow@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/arrows.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "arrows@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "arrows@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/arrows.imageset/arrows@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/arrows.imageset/arrows@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/arrows.imageset/arrows@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/arrows.imageset/arrows@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/back.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "back@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "back@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/back.imageset/back@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/back.imageset/back@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/back.imageset/back@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/back.imageset/back@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/cross.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "cross@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "cross@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/cross.imageset/cross@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/cross.imageset/cross@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/cross.imageset/cross@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/cross.imageset/cross@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/facebook-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "facebook-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/facebook-small.imageset/facebook-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/facebook-small.imageset/facebook-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/facebook.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "facebook@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "facebook@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/facebook.imageset/facebook@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/facebook.imageset/facebook@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/facebook.imageset/facebook@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/facebook.imageset/facebook@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-auto.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "flash-auto@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "flash-auto@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-auto.imageset/flash-auto@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash-auto.imageset/flash-auto@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-auto.imageset/flash-auto@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash-auto.imageset/flash-auto@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-on.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "flash-on@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "flash-on@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-on.imageset/flash-on@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash-on.imageset/flash-on@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash-on.imageset/flash-on@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash-on.imageset/flash-on@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "flash@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "flash@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash.imageset/flash@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash.imageset/flash@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flash.imageset/flash@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flash.imageset/flash@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flip.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "flip@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "flip@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flip.imageset/flip@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flip.imageset/flip@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/flip.imageset/flip@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/flip.imageset/flip@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/instagram-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "instagram-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/instagram-small.imageset/instagram-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/instagram-small.imageset/instagram-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/instagram.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "instagram@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "instagram@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/instagram.imageset/instagram@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/instagram.imageset/instagram@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/instagram.imageset/instagram@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/instagram.imageset/instagram@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/nocamera.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "nocamera@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "nocamera@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/nocamera.imageset/nocamera@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/nocamera.imageset/nocamera@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/nocamera.imageset/nocamera@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/nocamera.imageset/nocamera@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/ok.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "ok@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "ok@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/ok.imageset/ok@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/ok.imageset/ok@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/ok.imageset/ok@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/ok.imageset/ok@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/photos.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "photos@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "photos@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/photos.imageset/photos@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/photos.imageset/photos@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/photos.imageset/photos@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/photos.imageset/photos@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-left.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "rotate-left@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "rotate-left@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-left.imageset/rotate-left@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/rotate-left.imageset/rotate-left@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-left.imageset/rotate-left@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/rotate-left.imageset/rotate-left@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-right.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "rotate-right@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "rotate-right@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-right.imageset/rotate-right@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/rotate-right.imageset/rotate-right@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/rotate-right.imageset/rotate-right@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/rotate-right.imageset/rotate-right@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/save-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "save-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/save-small.imageset/save-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/save-small.imageset/save-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/save.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "save@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "save@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/save.imageset/save@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/save.imageset/save@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/save.imageset/save@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/save.imageset/save@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/settings.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "settings@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "settings@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | },
22 | "properties" : {
23 | "template-rendering-intent" : "original"
24 | }
25 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/settings.imageset/settings@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/settings.imageset/settings@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/settings.imageset/settings@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/settings.imageset/settings@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/share-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "share-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/share-small.imageset/share-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/share-small.imageset/share-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/share.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "share@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "share@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/share.imageset/share@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/share.imageset/share@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/share.imageset/share@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/share.imageset/share@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/vk-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "vk-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/vk-small.imageset/vk-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/vk-small.imageset/vk-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/vk.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "vk@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "vk@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/vk.imageset/vk@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/vk.imageset/vk@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/vk.imageset/vk@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/vk.imageset/vk@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/watermark.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "watermark@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/watermark.imageset/watermark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/watermark.imageset/watermark@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weibo-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "weibo-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weibo-small.imageset/weibo-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weibo-small.imageset/weibo-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weibo.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "weibo@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "weibo@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weibo.imageset/weibo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weibo.imageset/weibo@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weibo.imageset/weibo@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weibo.imageset/weibo@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weсhat-small.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "weсhat-small@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weсhat-small.imageset/weсhat-small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weсhat-small.imageset/weсhat-small@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weсhat.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "weсhat@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "weсhat@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weсhat.imageset/weсhat@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weсhat.imageset/weсhat@2x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/Assets.xcassets/weсhat.imageset/weсhat@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/PrismaSimpleImagePicker/Assets.xcassets/weсhat.imageset/weсhat@3x.png
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
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 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/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 | Prisma
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIRequiresFullScreen
34 |
35 | UIStatusBarHidden
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerController/PMImageGroupController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageGroupController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/25.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Photos
11 |
12 | class PMImageGroupController: UIViewController, UITableViewDelegate, UITableViewDataSource {
13 |
14 |
15 | @IBOutlet weak var tableView: UITableView!
16 | let topLine: CALayer = CALayer.init()
17 | var groups: [PMGroupModel] = [PMGroupModel]()
18 | var photoGroups: [PHAssetCollection]? = [PHAssetCollection]()
19 | var didSelectGroupAction: ((Int)-> Void)?
20 |
21 |
22 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
23 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
24 | }
25 |
26 | convenience init() {
27 | var nibNameOrNil = String?("PMImageGroupController")
28 | if NSBundle.mainBundle().pathForResource(nibNameOrNil, ofType: "xib") == nil {
29 | nibNameOrNil = nil
30 | }
31 | self.init(nibName: nibNameOrNil, bundle: nil)
32 | }
33 |
34 | required init?(coder aDecoder: NSCoder) {
35 | fatalError("init(coder:) has not been implemented")
36 | }
37 |
38 | override func viewDidLoad() {
39 | super.viewDidLoad()
40 |
41 | edgesForExtendedLayout = .None
42 | automaticallyAdjustsScrollViewInsets = false
43 |
44 | tableView.registerNib(UINib.init(nibName: "PMImageGroupCell", bundle: nil), forCellReuseIdentifier: "kGroupCellIdfy")
45 | var contentInset = tableView.contentInset
46 | contentInset.bottom = 44
47 | tableView.contentInset = contentInset
48 |
49 | // Top line
50 | let mainScreen: UIScreen = UIScreen.mainScreen()
51 | let frame = CGRectMake(0, -1/mainScreen.scale, mainScreen.bounds.size.width, 1/mainScreen.scale)
52 | topLine.frame = frame
53 | topLine.backgroundColor = UIColor.whiteColor().CGColor
54 | topLine.shadowOffset = CGSizeMake(0, frame.size.height)
55 | topLine.shadowRadius = 1
56 | topLine.shadowOpacity = 1
57 | topLine.shadowColor = UIColor.lightGrayColor().CGColor
58 |
59 | view.layer.masksToBounds = true
60 | view.layer.addSublayer(topLine)
61 |
62 | // PHAssetCollection to Model
63 | for collection in photoGroups! {
64 | let groupModel = PMGroupModel.groupModelFromPHAssetCollection(collection)
65 | groups.append(groupModel)
66 | }
67 | }
68 |
69 | override func viewDidLayoutSubviews() {
70 | topLine.removeFromSuperlayer()
71 | view.layer.addSublayer(topLine)
72 | }
73 |
74 |
75 | // MARK: UITableView M
76 |
77 | func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
78 | return UIScreen.mainScreen().bounds.size.width/320 * 80
79 | }
80 |
81 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
82 | return groups.count
83 | }
84 |
85 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
86 | let cell = tableView.dequeueReusableCellWithIdentifier("kGroupCellIdfy", forIndexPath: indexPath) as! PMImageGroupCell
87 |
88 | let groupModel = groups[indexPath.item]
89 | cell.configGroupCell(groupModel)
90 |
91 | return cell
92 | }
93 |
94 | func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
95 | if let doneAction = didSelectGroupAction {
96 | doneAction(indexPath.item)
97 | }
98 | }
99 |
100 | override func prefersStatusBarHidden() -> Bool {
101 | return true
102 | }
103 |
104 | override func didReceiveMemoryWarning() {
105 | super.didReceiveMemoryWarning()
106 | // Dispose of any resources that can be recreated.
107 | }
108 |
109 |
110 | /*
111 | // MARK: - Navigation
112 |
113 | // In a storyboard-based application, you will often want to do a little preparation before navigation
114 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
115 | // Get the new view controller using segue.destinationViewController.
116 | // Pass the selected object to the new view controller.
117 | }
118 | */
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerController/PMImageGroupController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerController/PMImagePickerController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImagePickerController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Photos
11 |
12 | @objc protocol PMImagePickerControllerDelegate: NSObjectProtocol {
13 | /**
14 | Call when tap `Use` button of the picker view controller
15 |
16 | - parameter picker: The view controller of class PMImagePickerController
17 | - parameter image: An cropped image which displayed in the top header after edit
18 | */
19 | optional func imagePickerController(picker: PMImagePickerController, didFinishPickingImage image: UIImage)
20 |
21 | /**
22 | Call when tap `Use` button of the picker view controller
23 |
24 | - parameter picker: The view controller of class PMImagePickerController
25 | - parameter originalImage: An original image which displayed in the top header
26 | - parameter selectedRect: A rect displayed of the header
27 | - parameter zoomScale: ZoomScale of the image
28 | */
29 | optional func imagePickerController(picker: PMImagePickerController, didFinishPickingImage originalImage: UIImage, selectedRect: CGRect, zoomScale:CGFloat)
30 |
31 | /**
32 | Call when tap `Cancel` button of the picker view controller
33 |
34 | - parameter picker: The view controller of class PMImagePickerController
35 | */
36 | optional func imagePickerControllerDidCancel(picker: PMImagePickerController)
37 | }
38 |
39 | class PMImagePickerController: UINavigationController {
40 |
41 | private var _photoGroups: [PHAssetCollection]? = [PHAssetCollection]()
42 | private var _photoAssets: [PHAsset]? = [PHAsset]()
43 | weak var pmDelegate: PMImagePickerControllerDelegate?
44 | var photoGroups: [PHAssetCollection] {
45 | set {
46 | _photoGroups = newValue
47 | let rootVC = viewControllers[0] as? PMImageViewController
48 | rootVC?.photoGroups = newValue
49 | }
50 | get {
51 | return _photoGroups!
52 | }
53 | }
54 | var photoAssets: [PHAsset] {
55 | set {
56 | _photoAssets = newValue
57 | let rootVC = viewControllers[0] as? PMImageViewController
58 | rootVC?.photoAssets = newValue
59 | }
60 | get {
61 | return _photoAssets!
62 | }
63 | }
64 |
65 | init() {
66 | let rootVC = PMImageViewController(nibName: "PMImageViewController", bundle: nil)
67 | super.init(rootViewController: rootVC)
68 | }
69 |
70 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
71 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
72 | }
73 |
74 | required init?(coder aDecoder: NSCoder) {
75 | super.init(coder: aDecoder)
76 | fatalError("init(coder:) has not been implemented")
77 | }
78 |
79 | override func viewDidLoad() {
80 | super.viewDidLoad()
81 |
82 | // Init navigation bar
83 | let bgImage = UIImage.imageWithColor(UIColor.whiteColor(), size: CGSizeMake(UIScreen.mainScreen().bounds.size.width, 44))
84 | navigationBar.tintColor = UIColor.blackColor()
85 | navigationBar.setBackgroundImage(bgImage, forBarPosition: UIBarPosition.Top, barMetrics: UIBarMetrics.Default)
86 | navigationBar.shadowImage = UIImage.init()
87 | }
88 |
89 | override func didReceiveMemoryWarning() {
90 | super.didReceiveMemoryWarning()
91 | }
92 | /*
93 | // MARK: - Navigation
94 |
95 | // In a storyboard-based application, you will often want to do a little preparation before navigation
96 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
97 | // Get the new view controller using segue.destinationViewController.
98 | // Pass the selected object to the new view controller.
99 | }
100 | */
101 |
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerController/PMImageViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
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 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerHelper/PMDeviceOrientation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMDeviceOrientation.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/29.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import CoreMotion
11 | import AVFoundation
12 |
13 | class PMDeviceOrientation: NSObject {
14 |
15 | var motionManager: CMMotionManager = CMMotionManager()
16 |
17 | override init() {
18 | super.init()
19 | setupMotionManger()
20 | }
21 |
22 | // MARK: Actual orientation
23 | func orientation() -> UIDeviceOrientation {
24 | return actualDeviceOrientationFromAccelerometer()
25 | }
26 |
27 | func deviceOrientationMatchesInterfaceOrientation() -> Bool {
28 | return orientation() == UIDevice.currentDevice().orientation
29 | }
30 |
31 | /// Change UIDeviceOrientation to AVCaptureVideoOrientation
32 | class func avOrientationFromDeviceOrientation(deviceOrientation: UIDeviceOrientation) -> AVCaptureVideoOrientation {
33 | var result = AVCaptureVideoOrientation.Portrait
34 | if deviceOrientation == UIDeviceOrientation.LandscapeLeft {
35 | result = .LandscapeRight
36 | }else if deviceOrientation == UIDeviceOrientation.LandscapeRight {
37 | result = .LandscapeLeft
38 | }else if deviceOrientation == UIDeviceOrientation.PortraitUpsideDown {
39 | result = .PortraitUpsideDown
40 | }
41 | return result
42 | }
43 |
44 | // MARK: Privatte
45 | private func setupMotionManger() {
46 | UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
47 | motionManager.accelerometerUpdateInterval = 0.005
48 | motionManager.startAccelerometerUpdates()
49 | }
50 |
51 | private func teardownMotionManager() {
52 | UIDevice.currentDevice().endGeneratingDeviceOrientationNotifications()
53 | motionManager.stopAccelerometerUpdates()
54 | }
55 |
56 | private func actualDeviceOrientationFromAccelerometer() -> UIDeviceOrientation {
57 | let acceleration = motionManager.accelerometerData!.acceleration
58 | if acceleration.z < -0.75 {
59 | return UIDeviceOrientation.FaceUp
60 | }
61 |
62 | if acceleration.z > 0.75 {
63 | return UIDeviceOrientation.FaceDown
64 | }
65 |
66 | let scaling = 1.0 / (fabs(acceleration.x) + fabs(acceleration.y))
67 |
68 | let x = acceleration.x * scaling
69 | let y = acceleration.y * scaling
70 |
71 | if x < -0.5 {
72 | return UIDeviceOrientation.LandscapeLeft
73 | }
74 |
75 | if x > 0.5 {
76 | return UIDeviceOrientation.LandscapeRight
77 | }
78 |
79 | if y > 0.5 {
80 | return UIDeviceOrientation.PortraitUpsideDown
81 | }
82 |
83 | return UIDeviceOrientation.Portrait
84 | }
85 |
86 | deinit {
87 | teardownMotionManager()
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerHelper/PMImageManger.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageManger.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/29.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 | import AssetsLibrary
12 | import Photos
13 | import CoreImage
14 | import Accelerate
15 |
16 |
17 | public enum RotateOrientation : Int {
18 |
19 | case Up // default orientation
20 | case Down // 180 deg rotation
21 | case Left // 90 deg CCW
22 | case Right // 90 deg CW
23 | case UpMirrored // as above but image mirrored along other axis. horizontal flip
24 | case DownMirrored // horizontal flip
25 | case LeftMirrored // vertical flip
26 | case RightMirrored // vertical flip
27 | }
28 |
29 | class PMImageManger: NSObject {
30 | /// Camera about
31 |
32 | // MARK: Authorizations
33 | /// Capture authorization
34 | class func captureAuthorization(shouldCapture: ((Bool)-> Void)!) {
35 |
36 | let captureStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
37 | switch captureStatus {
38 | case.NotDetermined:
39 | AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
40 | runOnMainQuene({ () -> Void in
41 | shouldCapture(granted)
42 | })
43 | })
44 | break
45 | case.Authorized:
46 | shouldCapture(true)
47 | break
48 | default:
49 | shouldCapture(false)
50 | break
51 | }
52 | }
53 |
54 | // Run on main quene
55 | class func runOnMainQuene(callBack: (()->Void)?) {
56 | if NSThread.currentThread().isMainThread {
57 | if let call = callBack {
58 | call()
59 | }
60 | }else {
61 | dispatch_async(dispatch_get_main_queue(), {
62 | if let call = callBack {
63 | call()
64 | }
65 | })
66 | }
67 | }
68 |
69 | /// Crop the image to target size, default crop in the middle
70 | class func cropImageAffterCapture(originImage: UIImage, toSize: CGSize) -> UIImage {
71 |
72 | let ratio = toSize.height/toSize.width
73 | let width = originImage.size.width
74 | let height = width * ratio
75 | let x = CGFloat(0)
76 | let y = (originImage.size.height - height)/2
77 |
78 | let finalRect = CGRectMake(x, y, width, height)
79 | let croppedImage = UIImage.init(CGImage: CGImageCreateWithImageInRect(originImage.CGImage!, finalRect)!, scale: originImage.scale, orientation: originImage.imageOrientation)
80 |
81 | return croppedImage
82 | }
83 |
84 | /// Crop the image to target rect
85 | class func cropImageToRect(originImage: UIImage, toRect: CGRect) -> UIImage {
86 |
87 | let croppedImage = UIImage.init(CGImage: CGImageCreateWithImageInRect(originImage.CGImage!, toRect)!, scale: originImage.scale, orientation: originImage.imageOrientation)
88 |
89 | return croppedImage
90 | }
91 |
92 | /// Photolibrary authorization
93 | class func photoAuthorization(canGoAssets: ((Bool)-> Void)!) {
94 |
95 | let PhotoStatus: PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
96 | switch (PhotoStatus) {
97 | case .NotDetermined:
98 | PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in
99 | dispatch_async(dispatch_get_main_queue(), {
100 | switch (status) {
101 | case .Authorized:
102 | canGoAssets(true)
103 | break
104 | default:
105 | canGoAssets(false)
106 | break
107 | }
108 | })
109 | }
110 | break
111 | case .Authorized:
112 | canGoAssets(true)
113 | break
114 | default:
115 | canGoAssets(false)
116 | break
117 | }
118 | }
119 |
120 | // MARK: Photo libiary
121 | /// Get photo albums
122 | class func photoLibrarys() -> [PHAssetCollection] {
123 | var photoGroups:[PHAssetCollection] = [PHAssetCollection]()
124 |
125 | // Camera
126 | let cameraRoll: PHAssetCollection = (PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumUserLibrary, options: nil).lastObject as? PHAssetCollection)!
127 | if cameraRoll.photosCount > 0 {
128 | photoGroups.append(cameraRoll)
129 | }
130 |
131 | // Favorites
132 | let favorites: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumFavorites, options: nil)
133 | favorites.enumerateObjectsWithOptions(.Reverse) { (obj, index: Int, stop: UnsafeMutablePointer) in
134 | let collection = obj as! PHAssetCollection
135 | guard collection.photosCount > 0 else {
136 | return
137 | }
138 | photoGroups.append(collection)
139 | }
140 |
141 | // ScreenShots
142 | if #available(iOS 9.0, *) {
143 | let screenShots: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumScreenshots, options: nil)
144 | screenShots.enumerateObjectsWithOptions(.Reverse) { (obj, index: Int, stop: UnsafeMutablePointer) in
145 | let collection = obj as! PHAssetCollection
146 | guard collection.photosCount > 0 else {
147 | return
148 | }
149 | photoGroups.append(collection)
150 | }
151 | }
152 |
153 | // User photos
154 | let assetCollections: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: nil)
155 | assetCollections.enumerateObjectsWithOptions(.Reverse) { (obj, index: Int, stop: UnsafeMutablePointer) in
156 | let collection = obj as! PHAssetCollection
157 | guard collection.photosCount > 0 else {
158 | return
159 | }
160 | photoGroups.append(collection)
161 | }
162 |
163 | return photoGroups
164 | }
165 |
166 | /// Get photos from an album
167 | class func photoAssetsForAlbum(collection: PHAssetCollection) -> [PHAsset] {
168 | var photoAssets:[PHAsset] = [PHAsset]()
169 |
170 | let asstes: PHFetchResult = PHAsset.fetchAssetsInAssetCollection(collection, options: nil)
171 | asstes.enumerateObjectsWithOptions(NSEnumerationOptions.Reverse) { (obj, index: Int, stop: UnsafeMutablePointer) in
172 | photoAssets.append(obj as! PHAsset)
173 | }
174 | return photoAssets
175 | }
176 |
177 | // Get image from a PHAsset
178 | class func imageFromAsset(asset: PHAsset, isOriginal original: Bool, toSize: CGSize?, resultHandler: (UIImage?)->Void) {
179 | let options = PHImageRequestOptions()
180 | options.synchronous = true
181 | options.resizeMode = .Fast
182 | options.deliveryMode = .FastFormat
183 |
184 | var size = CGSizeMake(100, 100)
185 | if original {
186 | size = CGSizeMake(CGFloat(asset.pixelWidth), CGFloat(asset.pixelHeight))
187 | }else if let _toSize = toSize {
188 | size = _toSize
189 | }
190 | PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: size, contentMode: PHImageContentMode.AspectFill, options: options) { (image: UIImage?, info: [NSObject : AnyObject]?) in
191 | resultHandler(image)
192 | }
193 | }
194 |
195 | // Translate degress to image orientation
196 | class func imageOrientationFromDegress(angle: CGFloat) -> UIImageOrientation {
197 | var orientation = UIImageOrientation.Up
198 | let ratio = (angle/CGFloat(M_PI/2))%4
199 | switch ratio {
200 | case 0:
201 | orientation = .Up
202 | break
203 | case 1, -3:
204 | orientation = .Right
205 | break
206 | case 2, -2:
207 | orientation = .Down
208 | break
209 | case 3, -1:
210 | orientation = .Left
211 | break
212 | default:
213 | orientation = .Up
214 | break
215 | }
216 | return orientation
217 | }
218 |
219 | }
220 |
221 | // MARK: UIImage ectension
222 | extension UIImage {
223 | // Get a image with color
224 | func imageWithColor(color: UIColor) -> UIImage {
225 | UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
226 | let context = UIGraphicsGetCurrentContext()
227 | CGContextTranslateCTM(context!, 0, self.size.height)
228 | CGContextScaleCTM(context!, 1.0, -1.0)
229 | CGContextSetBlendMode(context!, CGBlendMode.Normal)
230 | let rect = CGRectMake(0, 0, self.size.width, self.size.height)
231 | CGContextClipToMask(context!, rect, self.CGImage!)
232 | color.setFill()
233 | CGContextFillRect(context!, rect)
234 | let newImage = UIGraphicsGetImageFromCurrentImageContext()
235 | UIGraphicsEndImageContext()
236 | return newImage!
237 | }
238 |
239 | // Get a image with color & size
240 | class func imageWithColor(color: UIColor, size: CGSize) -> UIImage {
241 | let rect = CGRectMake(0, 0, size.width, size.height)
242 | UIGraphicsBeginImageContext(rect.size)
243 | let context = UIGraphicsGetCurrentContext()
244 | CGContextSetFillColorWithColor(context!, color.CGColor)
245 | CGContextFillRect(context!, rect)
246 | let image = UIGraphicsGetImageFromCurrentImageContext()
247 | UIGraphicsEndImageContext()
248 | return image!
249 | }
250 |
251 | /**
252 | Method to fix the orientation of an image.(The orientation of an image is just the orientation for the possion when take a photo)
253 | An image after capture, the orientation is not the correct possion(roated 90 degress), owing to the position of sensor. And the default possion of iPhone is landscape & home button on the right.
254 | AVPreviewLayer has fixed the possion of the image, so it display a correct image. But when we handle the image, the image is just original(not on the corrent possion).
255 | So, if we make a capture portrait, Actually the image landscape left and the orientation is right.
256 | e.g.
257 |
258 | | _ | __________
259 | | |_ | --> |
260 | | | | --> |__|___ | So, the image is `|_|__`
261 | | __ | __________| And orientation is right(the sensor orientation when take a photo)
262 |
263 | - returns: An image has been fixed oriention
264 | */
265 | func fixOrientation() -> UIImage {
266 | return fixOrientation(imageOrientation)
267 | }
268 |
269 | /**
270 | Rotate image to the target orientation.
271 |
272 | - parameter rotateOrientation: target orientation
273 |
274 | - returns: An image has been changed to the target orientaion
275 | */
276 | func rotateImageTo(rotateOrientation: RotateOrientation) -> UIImage {
277 |
278 | var imageOrientation = UIImageOrientation.Up
279 | switch rotateOrientation {
280 | case .Up:
281 | imageOrientation = .Up
282 | break
283 | case .UpMirrored:
284 | imageOrientation = .UpMirrored
285 | break
286 | case .Left:
287 | imageOrientation = .Right
288 | break
289 | case .LeftMirrored:
290 | imageOrientation = .RightMirrored
291 | break
292 | case .Right:
293 | imageOrientation = .Left
294 | break
295 | case .RightMirrored:
296 | imageOrientation = .LeftMirrored
297 | break
298 | case .Down:
299 | imageOrientation = .Down
300 | break
301 | case .DownMirrored:
302 | imageOrientation = .DownMirrored
303 | break
304 | }
305 |
306 | return fixOrientation(imageOrientation)
307 | }
308 |
309 | func rotateImageFromInterfaceOrientation(orientation: UIDeviceOrientation) -> UIImage {
310 | var rotateOrientation = RotateOrientation.Up
311 | switch orientation {
312 | case .Portrait:
313 | rotateOrientation = .Up
314 | break
315 | case .LandscapeLeft:
316 | rotateOrientation = .Right
317 | break
318 | case .LandscapeRight:
319 | rotateOrientation = .Left
320 | break
321 | case .PortraitUpsideDown:
322 | rotateOrientation = .Down
323 | break
324 | default:
325 | rotateOrientation = .Up
326 | break
327 | }
328 | return rotateImageTo(rotateOrientation)
329 | }
330 |
331 | func fixOrientation(imageOrientation: UIImageOrientation) -> UIImage {
332 | if imageOrientation == UIImageOrientation.Up {
333 | return self
334 | }
335 |
336 | var transform: CGAffineTransform = CGAffineTransformIdentity
337 |
338 | switch imageOrientation {
339 | case UIImageOrientation.Down, UIImageOrientation.DownMirrored:
340 | transform = CGAffineTransformTranslate(transform, size.width, size.height)
341 | transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
342 | break
343 | case UIImageOrientation.Left, UIImageOrientation.LeftMirrored:
344 | transform = CGAffineTransformTranslate(transform, size.width, 0)
345 | transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
346 | break
347 | case UIImageOrientation.Right, UIImageOrientation.RightMirrored:
348 | transform = CGAffineTransformTranslate(transform, 0, size.height)
349 | transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
350 | break
351 | case UIImageOrientation.Up, UIImageOrientation.UpMirrored:
352 | break
353 | }
354 |
355 | switch imageOrientation {
356 | case UIImageOrientation.UpMirrored, UIImageOrientation.DownMirrored:
357 | CGAffineTransformTranslate(transform, size.width, 0)
358 | CGAffineTransformScale(transform, -1, 1)
359 | break
360 | case UIImageOrientation.LeftMirrored, UIImageOrientation.RightMirrored:
361 | CGAffineTransformTranslate(transform, size.height, 0)
362 | CGAffineTransformScale(transform, -1, 1)
363 | case UIImageOrientation.Up, UIImageOrientation.Down, UIImageOrientation.Left, UIImageOrientation.Right:
364 | break
365 | }
366 |
367 | let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(size.width), Int(size.height), CGImageGetBitsPerComponent(CGImage!), 0, CGImageGetColorSpace(CGImage!)!, CGImageAlphaInfo.PremultipliedLast.rawValue)!
368 |
369 | CGContextConcatCTM(ctx, transform)
370 |
371 | switch imageOrientation {
372 | case UIImageOrientation.Left, UIImageOrientation.LeftMirrored, UIImageOrientation.Right, UIImageOrientation.RightMirrored:
373 | CGContextDrawImage(ctx, CGRectMake(0, 0, size.height, size.width), CGImage!)
374 | break
375 | default:
376 | CGContextDrawImage(ctx, CGRectMake(0, 0, size.width, size.height), CGImage!)
377 | break
378 | }
379 |
380 | let cgImage: CGImageRef = CGBitmapContextCreateImage(ctx)!
381 |
382 | return UIImage(CGImage: cgImage)
383 | }
384 | }
385 |
386 |
387 | // MARK: UIColor ectension
388 | extension UIColor {
389 |
390 | class func RGBColor(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor {
391 | return RGBAlphaColor(red, green: green, blue: blue, alpha: 1)
392 | }
393 |
394 | class func RGBAlphaColor(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> UIColor {
395 | return UIColor.init(red: red/255.0, green: green/255.0, blue: blue/255.0, alpha: alpha)
396 | }
397 |
398 | }
399 |
400 |
401 | // MARK: UIDevice orientation
402 | extension UIDevice {
403 |
404 | }
405 |
406 |
407 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerModel/PMGroupModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMGroupModel.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/25.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Photos
11 |
12 | class PMGroupModel: NSObject {
13 |
14 | var image: UIImage?
15 | var title: String?
16 | var content: String?
17 |
18 | override init() {
19 | super.init()
20 | }
21 |
22 | convenience init(image: UIImage?, title: String?, content: String?) {
23 | self.init()
24 | self.image = image
25 | self.title = title
26 | self.content = content
27 | }
28 |
29 | class func groupModelFromPHAssetCollection(collection: PHAssetCollection) -> PMGroupModel {
30 |
31 | var image: UIImage? = nil
32 | let title = collection.localizedTitle
33 | let content = collection.photosCount
34 |
35 | let assets: PHFetchResult = PHAsset.fetchAssetsInAssetCollection(collection, options: nil)
36 | let asset = assets.firstObject as? PHAsset
37 |
38 | let options = PHImageRequestOptions()
39 | options.synchronous = true
40 | options.resizeMode = .Fast
41 | options.deliveryMode = .FastFormat
42 |
43 | if let _asset = asset {
44 | let size: CGSize = CGSizeMake(150, 150)
45 | PHImageManager.defaultManager().requestImageForAsset(_asset, targetSize: size, contentMode: PHImageContentMode.AspectFill, options: options) { (_image: UIImage?, info: [NSObject : AnyObject]?) in
46 | image = _image
47 | }
48 | }
49 |
50 | let model = PMGroupModel.init(image: image, title: title, content: String(content))
51 | return model
52 | }
53 | }
54 |
55 |
56 | extension PHAssetCollection {
57 | var photosCount: Int {
58 | let fetchOptions = PHFetchOptions()
59 | fetchOptions.predicate = NSPredicate(format: "mediaType == %d", PHAssetMediaType.Image.rawValue)
60 | let result = PHAsset.fetchAssetsInAssetCollection(self, options: fetchOptions)
61 | return result.count
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMImageGroupCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageGroupCell.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/25.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Photos
11 |
12 | class PMImageGroupCell: UITableViewCell {
13 |
14 |
15 | @IBOutlet weak var groupCover: UIImageView!
16 | @IBOutlet weak var groupTitle: UILabel!
17 | @IBOutlet weak var groupContent: UILabel!
18 |
19 |
20 | override func awakeFromNib() {
21 | super.awakeFromNib()
22 | // Initialization code
23 | selectedBackgroundView = UIView.init(frame: self.bounds)
24 | selectedBackgroundView!.backgroundColor = UIColor.init(white: 0.85, alpha: 1)
25 | }
26 |
27 | func configGroupCell(group : PMGroupModel) {
28 | groupCover.image = group.image
29 | groupTitle.text = group.title
30 | groupContent.text = group.content
31 | }
32 |
33 |
34 | override func setSelected(selected: Bool, animated: Bool) {
35 | super.setSelected(selected, animated: animated)
36 |
37 | // Configure the view for the selected state
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMImageGroupCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
40 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
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 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMPhotoGridView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMPhotoGridView.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/26.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMPhotoGridView: UIView {
12 |
13 | var lineWidth: CGFloat = 1.0/UIScreen.mainScreen().scale
14 | var lineOffset: CGFloat = (1.0/UIScreen.mainScreen().scale)/2
15 | let screenScale: CGFloat = UIScreen.mainScreen().scale
16 | var lineBgWidth: CGFloat = 5
17 | var lineColor: UIColor = UIColor.init(white: 1.0, alpha: 0.45)
18 | var lineBgColor: UIColor = UIColor.init(white: 0.65, alpha: 0.07)
19 |
20 |
21 | override var frame: CGRect {
22 | didSet {
23 | setNeedsDisplay()
24 | }
25 | }
26 |
27 | override init(frame: CGRect) {
28 | super.init(frame: frame)
29 | backgroundColor = UIColor.clearColor()
30 | }
31 |
32 | required init?(coder aDecoder: NSCoder) {
33 | fatalError("init(coder:) has not been implemented")
34 | }
35 |
36 | // Only override drawRect: if you perform custom drawing.
37 | // An empty implementation adversely affects performance during animation.
38 | override func drawRect(rect: CGRect) {
39 |
40 | let context = UIGraphicsGetCurrentContext()
41 |
42 | drawLine(context!, color: lineBgColor, width: lineBgWidth)
43 | CGContextSaveGState(context!)
44 | drawLine(context!, color: lineColor, width: lineWidth)
45 | }
46 |
47 | func drawLine(context: CGContext, color: UIColor, width: CGFloat) {
48 | let width1 = CGFloatPixelRound(bounds.size.width/3)
49 | let width2 = CGFloatPixelRound(bounds.size.width/3 * 2)
50 | let height1 = CGFloatPixelRound(bounds.size.height/3)
51 | let height2 = CGFloatPixelRound(bounds.size.height/3 * 2)
52 |
53 | // H line 1
54 | CGContextSetStrokeColorWithColor(context, color.CGColor)
55 | CGContextMoveToPoint(context, 0, height1 + lineOffset)
56 | CGContextAddLineToPoint(context, bounds.size.width, height1 + lineOffset)
57 | CGContextSetLineWidth(context, width)
58 | CGContextStrokePath(context)
59 |
60 | CGContextSaveGState(context)
61 |
62 | // H line 2
63 | CGContextSetStrokeColorWithColor(context, color.CGColor)
64 | CGContextMoveToPoint(context, 0, height2 + lineOffset)
65 | CGContextAddLineToPoint(context, bounds.size.width, height2 + lineOffset)
66 | CGContextSetLineWidth(context, width)
67 | CGContextStrokePath(context)
68 |
69 | CGContextRestoreGState(context)
70 | CGContextSaveGState(context)
71 |
72 |
73 | // V line 1
74 | CGContextSetStrokeColorWithColor(context, color.CGColor)
75 | CGContextMoveToPoint(context, width1 + lineOffset, 0)
76 | CGContextAddLineToPoint(context, width1 + lineOffset, bounds.size.height)
77 | CGContextSetLineWidth(context, width)
78 | CGContextStrokePath(context)
79 |
80 | CGContextRestoreGState(context)
81 | CGContextSaveGState(context)
82 |
83 | // V line 2
84 | CGContextSetStrokeColorWithColor(context, color.CGColor)
85 | CGContextMoveToPoint(context, width2 + lineOffset, 0)
86 | CGContextAddLineToPoint(context, width2 + lineOffset, bounds.size.height)
87 | CGContextSetLineWidth(context, width)
88 | CGContextStrokePath(context)
89 | }
90 |
91 | func CGFloatPixelRound(value: CGFloat) -> CGFloat {
92 | let scale = screenScale
93 | return round(value * scale) / scale
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMPhotoHeaderItem.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMPhotoHeaderItem.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/26.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 |
12 | class PMPhotoHeaderItem: UIScrollView, UIScrollViewDelegate {
13 |
14 | var imageContainerView: UIView = UIView.init()
15 | var imageView: UIImageView = UIImageView.init()
16 | var selectedRect: CGRect = CGRectZero
17 | var targetZoomScale: CGFloat = 1.0
18 |
19 | override var frame: CGRect {
20 | didSet {
21 | bounds.origin = CGPointZero // reset zero origin to fit the adjust effect of scroll view
22 | imageContainerView.frame = bounds
23 | imageView.frame = imageContainerView.bounds
24 | resetSubViews()
25 | }
26 | }
27 | var scrollViewDidZoom: ((scrollView: UIScrollView)->Void)?
28 | var scrollViewBeganDragging: ((scrollView: UIScrollView)->Void)?
29 | var scrollViewEndDragging: ((scrollView: UIScrollView)->Void)?
30 |
31 |
32 | override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | configSubviews()
35 | }
36 |
37 | required init?(coder aDecoder: NSCoder) {
38 | fatalError("init(coder:) has not been implemented")
39 | }
40 |
41 | func configSubviews() {
42 |
43 | delegate = self
44 | bouncesZoom = true
45 | maximumZoomScale = 3
46 | multipleTouchEnabled = true
47 | bounces = true
48 | alwaysBounceVertical = true
49 | alwaysBounceHorizontal = true
50 | showsVerticalScrollIndicator = false
51 | showsHorizontalScrollIndicator = false
52 |
53 | imageContainerView.frame = bounds
54 | imageContainerView.clipsToBounds = true
55 | imageContainerView.backgroundColor = UIColor.whiteColor()
56 | imageView.clipsToBounds = true
57 | imageContainerView.addSubview(imageView)
58 | addSubview(imageContainerView)
59 |
60 | let doubleTap = UITapGestureRecognizer.init(target: self, action: #selector(PMPhotoHeaderItem.doubleTap(_:)))
61 | doubleTap.numberOfTapsRequired = 2
62 | addGestureRecognizer(doubleTap)
63 | }
64 |
65 | /**
66 | Set the image of content image view. And scroll to target rect.
67 | If parameter zoomScale is not 1, the target rect `scrollToRect` should be the rect with image coordinate
68 |
69 | - parameter image: An image set to display
70 | - parameter scrollToRect: Target rect to show the image view
71 | - parameter zoomScale: Target zoomScale
72 | */
73 | func setImage(image: UIImage, scrollToRect: CGRect, zoomScale: CGFloat) {
74 | imageView.image = image
75 | selectedRect = scrollToRect
76 | targetZoomScale = zoomScale
77 | // Reset contentSize
78 | resetSubViews()
79 | }
80 |
81 | // MARK: Private
82 |
83 | @objc private func doubleTap(tap: UITapGestureRecognizer) {
84 | zoomOutView(tap)
85 | // zoomInView(tap)
86 | }
87 |
88 | private func zoomInView(tap: UITapGestureRecognizer) {
89 | if zoomScale > 1 {
90 | setZoomScale(1, animated: true)
91 | } else {
92 | let touchPoint = tap.locationInView(imageView)
93 | let newZoomScale = maximumZoomScale
94 | let xsize = bounds.size.width / newZoomScale
95 | let ysize = bounds.size.height / newZoomScale
96 |
97 | zoomToRect(CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize), animated: true)
98 | }
99 | }
100 |
101 | private func zoomOutView(tap: UITapGestureRecognizer) {
102 | guard zoomScale > 1 else {
103 | return
104 | }
105 | zoomScale = 1
106 | resetSubViews()
107 | }
108 |
109 | private func resetSubViews() {
110 | if let image = imageView.image {
111 | let ratio = image.size.width/image.size.height
112 | let const = bounds.size.width/bounds.size.height
113 | if ratio > const {
114 | contentSize = CGSizeMake(ratio * bounds.size.height, bounds.size.height)
115 | }else {
116 | contentSize = CGSizeMake(bounds.size.width, bounds.size.width/ratio)
117 | }
118 | var frame = imageContainerView.frame
119 | frame.size = contentSize
120 | imageContainerView.frame = frame
121 | imageView.frame = imageContainerView.bounds
122 |
123 | // scroll to target rect
124 | var fitRect = CGRectMake((contentSize.width - bounds.size.width)/2, (contentSize.height - bounds.size.height)/2, bounds.size.width, bounds.size.height)
125 | if !CGRectEqualToRect(selectedRect, CGRectZero) {
126 | fitRect = selectedRect
127 | }
128 |
129 | // zoom if need
130 | if targetZoomScale != 1 {
131 | let contentSize = CGSizeApplyAffineTransform(self.contentSize, CGAffineTransformMakeScale(targetZoomScale, targetZoomScale))
132 | fitRect.origin.x = fitRect.origin.x * (contentSize.width/image.size.width)
133 | fitRect.origin.y = fitRect.origin.y * (contentSize.height/image.size.height)
134 |
135 | fitRect = CGRectApplyAffineTransform(fitRect, CGAffineTransformMakeScale(1.0/targetZoomScale, 1.0/targetZoomScale))
136 | zoomToRect(fitRect, animated: false)
137 | }else {
138 | scrollRectToVisible(fitRect, animated: false)
139 | }
140 | }
141 | }
142 |
143 | // MARK: Zoom
144 | func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
145 | return imageContainerView
146 | }
147 |
148 | func scrollViewDidZoom(scrollView: UIScrollView) {
149 | let subView = imageContainerView
150 |
151 | var offsetX = CGFloat(0)
152 | if scrollView.bounds.size.width > scrollView.contentSize.width {
153 | offsetX = (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5
154 | }
155 |
156 | var offsetY = CGFloat(0)
157 | if scrollView.bounds.size.height > scrollView.contentSize.height {
158 | offsetY = (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5
159 | }
160 |
161 | subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
162 | scrollView.contentSize.height * 0.5 + offsetY)
163 |
164 | if let action = scrollViewDidZoom {
165 | action(scrollView: scrollView)
166 | }
167 | }
168 |
169 |
170 | // MARK: UIScrollView M
171 |
172 | func scrollViewWillBeginDragging(scrollView: UIScrollView) {
173 | if let drag = scrollViewBeganDragging {
174 | drag(scrollView: self)
175 | }
176 | }
177 |
178 | func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
179 | if let endDrag = scrollViewEndDragging {
180 | endDrag(scrollView: self)
181 | }
182 | }
183 |
184 |
185 | /*
186 | // Only override drawRect: if you perform custom drawing.
187 | // An empty implementation adversely affects performance during animation.
188 | override func drawRect(rect: CGRect) {
189 | // Drawing code
190 | }
191 | */
192 |
193 | }
194 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMPhotoHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMPhotoHeaderView.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/25.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | private var kContentOffsetContext = 0
12 |
13 | class PMPhotoHeaderView: UIView {
14 |
15 | var imageView: PMPhotoHeaderItem = PMPhotoHeaderItem.init()
16 | var tapAction: ((view: PMPhotoHeaderView)->Void)?
17 | var gridMask: PMPhotoGridView = PMPhotoGridView()
18 | var alwaysShowGrid: Bool = false
19 | var currentAngle = CGFloat(0)
20 | private var _editEnabled: Bool = true
21 | var editEnabled: Bool {
22 | set {
23 | _editEnabled = newValue
24 | gridMask.hidden = !newValue
25 | imageView.scrollEnabled = newValue
26 | }
27 | get {
28 | return _editEnabled
29 | }
30 | }
31 |
32 | var image: UIImage {
33 | get {
34 | if let image = imageView.imageView.image {
35 | return image
36 | }
37 | return UIImage()
38 | }
39 | }
40 |
41 | override init(frame: CGRect) {
42 | super.init(frame: frame)
43 | configSubviews()
44 | }
45 |
46 | required init?(coder aDecoder: NSCoder) {
47 | super.init(coder: aDecoder)
48 | configSubviews()
49 | }
50 |
51 | func configSubviews() {
52 |
53 | imageView.frame = bounds
54 | addSubview(imageView)
55 |
56 | // Grid
57 | gridMask.frame = bounds
58 | gridMask.alpha = alwaysShowGrid ?1:0
59 | gridMask.userInteractionEnabled = false
60 | addSubview(gridMask)
61 | imageView.addObserver(self, forKeyPath: "contentOffset", options: .New, context: &kContentOffsetContext)
62 |
63 | // Tap
64 | let tap = UITapGestureRecognizer.init(target: self, action: #selector(PMPhotoHeaderView.tap(_:)))
65 | tap.numberOfTapsRequired = 1
66 | addGestureRecognizer(tap)
67 |
68 | // Zoom action
69 | imageView.scrollViewDidZoom = { (scrollView: UIScrollView) in
70 | self.scrollViewDidZoom(scrollView)
71 | }
72 | imageView.scrollViewBeganDragging = { (scrollView: UIScrollView) in
73 | if self.alwaysShowGrid {
74 | return
75 | }
76 | self.showGrid(true)
77 | }
78 | imageView.scrollViewEndDragging = { (scrollView: UIScrollView) in
79 | if self.alwaysShowGrid {
80 | return
81 | }
82 | self.showGrid(false)
83 | }
84 | }
85 |
86 | override func layoutSubviews() {
87 | if imageView.bounds.size.width != bounds.size.width {
88 | imageView.frame = bounds
89 | gridMask.frame = bounds
90 | }
91 | if alwaysShowGrid {
92 | gridMask.alpha = 1
93 | }
94 | }
95 |
96 | func setImage(image: UIImage, scrollToRect: CGRect, zoomScale: CGFloat) {
97 | imageView.setImage(image, scrollToRect: scrollToRect, zoomScale: zoomScale)
98 | }
99 |
100 | func tap(tap: UITapGestureRecognizer) {
101 | if let tap = tapAction {
102 | tap(view: self)
103 | }
104 | }
105 |
106 | func rotate(angle: CGFloat, closeWise: Bool) {
107 | currentAngle = angle
108 | UIView.animateWithDuration(0.12, animations: {
109 | self.transform = CGAffineTransformMakeRotation(angle)
110 | }) { (com: Bool) in
111 |
112 | }
113 | }
114 |
115 | func cropImageAffterEdit() -> UIImage {
116 | // Get the rect
117 | var imageRect = CGRectZero
118 | let ratio = image.size.width/imageView.contentSize.width
119 | var x = fmax(imageView.contentOffset.x, 0)
120 | var y = fmax(imageView.contentOffset.y, 0)
121 | x = x/imageView.contentSize.width * image.size.width
122 | y = y/imageView.contentSize.height * image.size.height
123 | imageRect = CGRectMake(x, y, bounds.size.width * ratio, bounds.size.height * ratio)
124 |
125 | // Crop
126 | var croppedImage = PMImageManger.cropImageToRect(self.image, toRect: imageRect)
127 | // Rotate
128 | let imageOrientation = PMImageManger.imageOrientationFromDegress(currentAngle)
129 | if imageOrientation != .Up {
130 | croppedImage = UIImage.init(CGImage: croppedImage.CGImage!, scale: croppedImage.scale, orientation: imageOrientation)
131 | }
132 | return croppedImage
133 | }
134 |
135 | func scrollViewDidZoom(scrollView: UIScrollView) {
136 | // Reset grid
137 | let imageContainerView = imageView.imageContainerView
138 | let containerFrame = convertRect(imageContainerView.frame, fromView: imageContainerView.superview)
139 |
140 | let x = fmax(0, containerFrame.origin.x)
141 | let y = fmax(0, containerFrame.origin.y)
142 |
143 | var width = CGFloat(0)
144 | if x > 0 {
145 | width = fmin(containerFrame.size.width, bounds.size.width - x)
146 | }else {
147 | width = fmin(containerFrame.size.width + containerFrame.origin.x, bounds.size.width)
148 | }
149 | var height = CGFloat(0)
150 | if y > 0 {
151 | height = fmin(containerFrame.size.height, bounds.size.height - y)
152 | }else {
153 | height = fmin(containerFrame.size.height + containerFrame.origin.y, bounds.size.height)
154 | }
155 |
156 | gridMask.frame = CGRectMake(x, y, width, height)
157 | }
158 |
159 | func showGrid(show: Bool) {
160 | if show {
161 | UIView.animateWithDuration(0.3, animations: {
162 | self.gridMask.alpha = 1
163 | })
164 | }else {
165 | UIView.animateWithDuration(0.35, animations: {
166 | self.gridMask.alpha = 0
167 | })
168 | }
169 | }
170 |
171 | // MARK: KVO
172 |
173 | override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
174 | if context == &kContentOffsetContext {
175 |
176 | if let scrollView = object as? UIScrollView {
177 | guard !scrollView.zooming && !scrollView.zoomBouncing else {
178 | return
179 | }
180 |
181 | let imageContainerView = imageView.imageContainerView
182 | let containerFrame = convertRect(imageContainerView.frame, fromView: imageContainerView.superview)
183 |
184 | let x = fmax(0, containerFrame.origin.x)
185 | let y = fmax(0, containerFrame.origin.y)
186 |
187 | var width = CGFloat(0)
188 | if x > 0 {
189 | width = fmin(containerFrame.size.width, bounds.size.width - x)
190 | }else {
191 | width = fmin(containerFrame.size.width + containerFrame.origin.x, bounds.size.width)
192 | }
193 | var height = CGFloat(0)
194 | if y > 0 {
195 | height = fmin(containerFrame.size.height, bounds.size.height - y)
196 | }else {
197 | height = fmin(containerFrame.size.height + containerFrame.origin.y, bounds.size.height)
198 | }
199 |
200 | gridMask.frame = CGRectMake(x, y, width, height)
201 | }
202 | }else {
203 | super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
204 | }
205 | }
206 |
207 | deinit {
208 | removeObserver(self, forKeyPath: "contentOffset", context: &kContentOffsetContext)
209 | }
210 |
211 |
212 | /*
213 | // Only override drawRect: if you perform custom drawing.
214 | // An empty implementation adversely affects performance during animation.
215 | override func drawRect(rect: CGRect) {
216 | // Drawing code
217 | }
218 | */
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaImagePicker/PickerView/PMPickerTitleButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMPickerTitleButton.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/25.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | enum ArrowStatus {
12 | case up
13 | case down
14 | }
15 |
16 | class PMPickerTitleButton: UIButton {
17 |
18 | var arrowStatus: ArrowStatus = .down
19 |
20 | override init(frame: CGRect) {
21 | super.init(frame: frame)
22 | }
23 |
24 | required init?(coder aDecoder: NSCoder) {
25 | fatalError("init(coder:) has not been implemented")
26 | }
27 |
28 | override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
29 | var rect = contentRect
30 | rect.size.width -= contentRect.size.height
31 | return rect
32 | }
33 |
34 | override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
35 | var rect = contentRect
36 | rect.size.width = contentRect.size.height
37 | rect.origin.x = CGRectGetWidth(contentRect) - CGRectGetWidth(rect)
38 | return rect
39 | }
40 |
41 | /*
42 | // Only override drawRect: if you perform custom drawing.
43 | // An empty implementation adversely affects performance during animation.
44 | override func drawRect(rect: CGRect) {
45 | // Drawing code
46 | }
47 | */
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMImageEditController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageEditController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMImageEditController: UIViewController {
12 |
13 | @IBOutlet weak var navigationBar: UINavigationBar!
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | navigationBar.setBackgroundImage(UIImage.init(), forBarPosition: UIBarPosition.Top, barMetrics: UIBarMetrics.Default)
19 | navigationBar.shadowImage = UIImage.init()
20 | }
21 |
22 | @IBAction func rotateRight(sender: AnyObject) {
23 | photoPisplayBoard?.rotateDisplayImage(true)
24 | }
25 |
26 | @IBAction func rotateLeft(sender: AnyObject) {
27 | photoPisplayBoard?.rotateDisplayImage(false)
28 | }
29 |
30 | @IBAction func next(sender: AnyObject) {
31 | let finalImage = photoPisplayBoard?.croppedImage()
32 | photoPisplayBoard?.setState(.SingleShow, image: finalImage, selectedRect: CGRectZero, zoomScale:1, animated: false)
33 |
34 | // Push to style vc
35 | let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
36 | let styleVC = storyBoard.instantiateViewControllerWithIdentifier("styleImageController") as? PMImageProcessController
37 | navigationController?.pushViewController(styleVC!, animated: true)
38 | }
39 |
40 | @IBAction func back(sender: AnyObject) {
41 | let navigationController = self.navigationController as? PMNavigationController
42 | navigationController?.popViewControllerAnimated(true, completion: { (isPush: Bool) in
43 | if !isPush {
44 | self.photoPisplayBoard?.setState(PMImageDisplayState.Preivew, image: nil, selectedRect: CGRectZero, zoomScale:1, animated: true)
45 | }
46 | })
47 | }
48 |
49 | override func viewDidDisappear(animated: Bool) {
50 | super.viewDidDisappear(animated)
51 | // Pop handle
52 | if navigationController == nil {
53 | self.photoPisplayBoard?.setState(PMImageDisplayState.Preivew, image: nil, selectedRect: CGRectZero, zoomScale:1, animated: true)
54 | }
55 | }
56 |
57 | override func didReceiveMemoryWarning() {
58 | super.didReceiveMemoryWarning()
59 | // Dispose of any resources that can be recreated.
60 | }
61 |
62 |
63 | /*
64 | // MARK: - Navigation
65 |
66 | // In a storyboard-based application, you will often want to do a little preparation before navigation
67 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
68 | // Get the new view controller using segue.destinationViewController.
69 | // Pass the selected object to the new view controller.
70 | }
71 | */
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMImageProcessController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageProcessController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMImageProcessController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
12 |
13 |
14 | @IBOutlet weak var navigationBar: UINavigationBar!
15 | @IBOutlet weak var stylesCollectionView: UICollectionView!
16 | var styles: [AnyObject]?
17 |
18 | var fromCapture: Bool = false
19 |
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 |
24 | navigationBar.setBackgroundImage(UIImage.init(), forBarPosition: UIBarPosition.Top, barMetrics: UIBarMetrics.Default)
25 | navigationBar.shadowImage = UIImage.init()
26 |
27 | let navigationController = self.navigationController as? PMNavigationController
28 | stylesCollectionView.panGestureRecognizer.requireGestureRecognizerToFail(navigationController!.panGestureRecognizer)
29 |
30 | styles = getStyles() as? [AnyObject]
31 | }
32 |
33 | func getStyles() -> AnyObject {
34 | let dataPath = NSBundle.mainBundle().pathForResource("", ofType: "json")
35 | let data = NSData.init(contentsOfFile: dataPath!)
36 | let dataDic: AnyObject = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
37 |
38 | let styles: AnyObject = dataDic.objectForKey("styles")!
39 | return styles
40 | }
41 |
42 | @IBAction func back(sender: AnyObject) {
43 | let navigationController = self.navigationController as? PMNavigationController
44 | navigationController?.popViewControllerAnimated(true, completion: { (isPush: Bool) in
45 | if !isPush {
46 | let state = self.fromCapture ?PMImageDisplayState.Preivew:PMImageDisplayState.EditImage
47 | self.photoPisplayBoard?.setState(state, image: nil, selectedRect: CGRectZero, zoomScale:1, animated: true)
48 | }
49 | })
50 | }
51 |
52 | // MARK: UICollectionView M
53 |
54 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
55 | return 10
56 | }
57 |
58 | func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
59 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("styleCell", forIndexPath: indexPath) as? PMStyleCell
60 |
61 | let style: AnyObject = styles![indexPath.row]
62 | cell?.loadImage(style)
63 |
64 | return cell!
65 | }
66 |
67 | func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
68 | print("click item at \(indexPath.item)")
69 | }
70 |
71 | override func viewDidDisappear(animated: Bool) {
72 | super.viewDidDisappear(animated)
73 | // Pop handle
74 | if navigationController == nil {
75 | let state = fromCapture ?PMImageDisplayState.Preivew:PMImageDisplayState.EditImage
76 | self.photoPisplayBoard?.setState(state, image: nil, selectedRect: CGRectZero, zoomScale:1, animated: true)
77 | }
78 | }
79 |
80 | override func didReceiveMemoryWarning() {
81 | super.didReceiveMemoryWarning()
82 | // Dispose of any resources that can be recreated.
83 | }
84 |
85 |
86 | /*
87 | // MARK: - Navigation
88 |
89 | // In a storyboard-based application, you will often want to do a little preparation before navigation
90 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
91 | // Get the new view controller using segue.destinationViewController.
92 | // Pass the selected object to the new view controller.
93 | }
94 | */
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMImageProtocol.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageProtocol.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/29.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | @objc enum PMImageOrientation : Int {
13 | case Up // Normal affter rotated
14 | case Down // Down affter rotated
15 | case Left // Left affter rotated
16 | case Right // Right after rotated
17 | }
18 |
19 | @objc enum PMImageDisplayState : Int {
20 | case Preivew // Display AVCapturePreviewLayer
21 | case EditImage // Edit image, such as rotate, scale.
22 | case SingleShow // Just display image to make art photo
23 | }
24 |
25 | @objc protocol PMImageProtocol {
26 | // Display image
27 | optional var displayImage: UIImage { get }
28 |
29 | // Display header view
30 | var displayHeaderView: UIView { get }
31 |
32 | // Image orienttation affter rotated
33 | var rotatedImageOrientation: PMImageOrientation { get }
34 |
35 | // Tap header to focus
36 | var singleTapHeaderAction: ((tap: UITapGestureRecognizer)->Void) { get set }
37 |
38 | // Set the AVCaptureVideoPreviewLayer
39 | func setAVCapturePreviewLayer(layer: AVCaptureVideoPreviewLayer)
40 |
41 | // Change state
42 | func setState(state: PMImageDisplayState, image: UIImage?, selectedRect: CGRect, zoomScale:CGFloat, animated: Bool)
43 |
44 | // Rotate image
45 | func rotateDisplayImage(clockwise: Bool)
46 |
47 | // Cropped image affter edit
48 | func croppedImage() -> UIImage
49 |
50 | }
51 |
52 | extension UIViewController {
53 | var photoPisplayBoard: PMImageProtocol? {
54 | get {
55 | let vc = UIApplication.sharedApplication().keyWindow?.rootViewController
56 | if let rootVC = vc as? PMRootViewController {
57 | return rootVC
58 | }
59 | return nil
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMImageSettingController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageSettingController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/2.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMImageSettingController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | // Do any additional setup after loading the view.
17 | }
18 |
19 | override func didReceiveMemoryWarning() {
20 | super.didReceiveMemoryWarning()
21 | // Dispose of any resources that can be recreated.
22 | }
23 |
24 |
25 | /*
26 | // MARK: - Navigation
27 |
28 | // In a storyboard-based application, you will often want to do a little preparation before navigation
29 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
30 | // Get the new view controller using segue.destinationViewController.
31 | // Pass the selected object to the new view controller.
32 | }
33 | */
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMImageSettingController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMNavigationController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMNavigationController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let kPushDuration = 0.32
12 |
13 | class PushAnimator: NSObject, UIViewControllerAnimatedTransitioning {
14 |
15 | var push: Bool = true
16 | var isInteractive: Bool = false
17 |
18 |
19 | override init() {
20 | super.init()
21 | }
22 |
23 | convenience init(isPush: Bool) {
24 | self.init()
25 | self.push = isPush
26 | }
27 |
28 | func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
29 | return kPushDuration
30 | }
31 |
32 | func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
33 |
34 | let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
35 | let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
36 | let containerView = transitionContext.containerView()
37 |
38 | containerView.addSubview(fromViewController!.view)
39 | containerView.addSubview(toViewController!.view)
40 | toViewController?.view.frame = fromViewController!.view.bounds
41 |
42 | var fromFrame = fromViewController?.view.frame
43 | var toFrame = toViewController?.view.frame
44 | let screenWidth = UIScreen.mainScreen().bounds.size.width
45 | var animationOption = UIViewAnimationOptions.CurveEaseInOut
46 |
47 | if isInteractive {
48 | animationOption = UIViewAnimationOptions.CurveLinear
49 | }
50 |
51 | if push {
52 | toFrame?.origin.x = screenWidth
53 | toViewController?.view.frame = toFrame!
54 | UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: animationOption, animations: {
55 | fromFrame?.origin.x = -screenWidth
56 | fromViewController?.view.frame = fromFrame!
57 | toFrame?.origin.x = 0
58 | toViewController?.view.frame = toFrame!
59 | }, completion: { (com: Bool) in
60 | let complete = !transitionContext.transitionWasCancelled()
61 | if complete {
62 | if let nav = fromViewController?.navigationController as? PMNavigationController {
63 | if let completion = nav.completionHandler {
64 | completion(isPush: true)
65 | }
66 | }
67 | }
68 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
69 | })
70 | }else {
71 | toFrame?.origin.x = -screenWidth
72 | toViewController?.view.frame = toFrame!
73 | UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: animationOption, animations: {
74 | fromFrame?.origin.x = screenWidth
75 | fromViewController?.view.frame = fromFrame!
76 | toFrame?.origin.x = 0
77 | toViewController?.view.frame = toFrame!
78 | }, completion: { (com: Bool) in
79 | let complete = !transitionContext.transitionWasCancelled()
80 | if complete {
81 | if let nav = toViewController?.navigationController as? PMNavigationController {
82 | if let completion = nav.completionHandler {
83 | completion(isPush: false)
84 | }
85 | }
86 | }
87 | transitionContext.completeTransition(complete)
88 | })
89 | }
90 |
91 | }
92 | }
93 |
94 |
95 |
96 | class PMNavigationController: UINavigationController, UIGestureRecognizerDelegate, UINavigationControllerDelegate {
97 |
98 | var panGestureRecognizer: UIPanGestureRecognizer = UIPanGestureRecognizer.init()
99 | var frameOrigin: CGPoint = CGPointZero
100 | var interactionController: UIPercentDrivenInteractiveTransition?
101 | var animator: PushAnimator?
102 | var isInteractive: Bool = false
103 | var popEdgeInset: CGFloat = 50
104 | var completionHandler: ((isPush: Bool)->Void)?
105 |
106 |
107 | override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
108 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
109 | }
110 |
111 | override init(rootViewController: UIViewController) {
112 | super.init(rootViewController: rootViewController)
113 | }
114 |
115 | required init?(coder aDecoder: NSCoder) {
116 | super.init(coder: aDecoder)
117 | }
118 |
119 | override func viewDidLoad() {
120 | super.viewDidLoad()
121 |
122 | interactivePopGestureRecognizer?.enabled = false
123 | delegate = self
124 |
125 | // Add new pan gesture replace the edge gesture
126 | panGestureRecognizer.addTarget(self, action: #selector(PMNavigationController.didPan(_:)))
127 | panGestureRecognizer.delegate = self
128 | view.addGestureRecognizer(panGestureRecognizer)
129 | }
130 |
131 | // MARK: Change the frame of the default view, under the capture view
132 | override func viewDidLayoutSubviews() {
133 | var frame = view.frame
134 | frame.origin.y = frameOrigin.y
135 | frame.size.height = UIScreen.mainScreen().bounds.size.height - frame.origin.y
136 | view.frame = frame
137 | }
138 |
139 | override func pushViewController(viewController: UIViewController, animated: Bool) {
140 | super.pushViewController(viewController, animated: animated)
141 | if !animated {
142 | if let completion = completionHandler {
143 | completion(isPush: true)
144 | }
145 | }
146 | }
147 |
148 | override func popViewControllerAnimated(animated: Bool) -> UIViewController? {
149 | if !animated {
150 | if let completion = completionHandler {
151 | completion(isPush: false)
152 | }
153 | }
154 | return super.popViewControllerAnimated(animated)
155 | }
156 |
157 | func pushViewController(viewController: UIViewController, animated: Bool, completion:((isPush: Bool)->Void)?) {
158 | completionHandler = completion
159 | self.pushViewController(viewController, animated: animated)
160 | }
161 |
162 |
163 | func popViewControllerAnimated(animated: Bool, completion:((isPush: Bool)->Void)?) -> UIViewController? {
164 | completionHandler = completion
165 | return self.popViewControllerAnimated(animated)
166 | }
167 |
168 | // MARK: Transition animation
169 |
170 | func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
171 | if animator == nil {
172 | animator = PushAnimator.init(isPush: operation == UINavigationControllerOperation.Push)
173 | }
174 | animator?.isInteractive = isInteractive
175 | animator?.push = operation == UINavigationControllerOperation.Push
176 | return animator!
177 | }
178 |
179 | func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
180 | return interactionController
181 | }
182 |
183 | func didPan(panGestureRecognizer: UIPanGestureRecognizer) {
184 |
185 | if panGestureRecognizer.state == .Began {
186 |
187 | isInteractive = true
188 | animator?.isInteractive = true
189 | interactionController = UIPercentDrivenInteractiveTransition()
190 | popViewControllerAnimated(true)
191 | }else if panGestureRecognizer.state == .Changed {
192 |
193 | let translaton = panGestureRecognizer.translationInView(view)
194 | let percent = translaton.x / CGRectGetWidth(view!.bounds)
195 | interactionController!.updateInteractiveTransition(percent)
196 | }else if panGestureRecognizer.state == .Ended {
197 |
198 | if panGestureRecognizer.velocityInView(view).x > 100 {
199 | interactionController!.finishInteractiveTransition()
200 | }else {
201 | interactionController!.cancelInteractiveTransition()
202 | }
203 | interactionController = nil
204 | animator?.isInteractive = false
205 | }
206 | }
207 |
208 | // MARK: UIGestureRecognizerDelegate
209 |
210 | func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
211 | let location = gestureRecognizer.locationInView(view)
212 | if location.y < 64 || location.x > popEdgeInset {
213 | return false
214 | }
215 | return true
216 | }
217 |
218 | override func didReceiveMemoryWarning() {
219 | super.didReceiveMemoryWarning()
220 | // Dispose of any resources that can be recreated.
221 | }
222 |
223 |
224 | /*
225 | // MARK: - Navigation
226 |
227 | // In a storyboard-based application, you will often want to do a little preparation before navigation
228 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
229 | // Get the new view controller using segue.destinationViewController.
230 | // Pass the selected object to the new view controller.
231 | }
232 | */
233 |
234 | }
235 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PMRootViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMRootViewController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | class PMRootViewController: UIViewController, PMImageProtocol {
13 |
14 |
15 | @IBOutlet weak var captureHeaderView: UIView!
16 | var previewLayer: AVCaptureVideoPreviewLayer?
17 | var photoHeaderView: PMPhotoHeaderView?
18 | var styleHeaderView: PMStyleHeaderView?
19 | var state: PMImageDisplayState = PMImageDisplayState.Preivew
20 | var imageAngle: CGFloat = 0
21 |
22 |
23 | override func viewDidLoad() {
24 | super.viewDidLoad()
25 |
26 | captureHeaderView.backgroundColor = UIColor.blackColor()
27 | captureHeaderView.layer.masksToBounds = true
28 |
29 | // Add navigation
30 | let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
31 | let baseNav = storyBoard.instantiateViewControllerWithIdentifier("mainNavigationController") as? PMNavigationController
32 | baseNav!.frameOrigin = CGPointMake(0, UIScreen.mainScreen().bounds.size.width)
33 | self.addChildViewController(baseNav!)
34 | view.addSubview(baseNav!.view)
35 |
36 | // Tap gesture to focus
37 | let tap = UITapGestureRecognizer.init(target: self, action: #selector(PMRootViewController.tapHeader))
38 | tap.numberOfTapsRequired = 1
39 | captureHeaderView.addGestureRecognizer(tap)
40 | }
41 |
42 | override func viewDidAppear(animated: Bool) {
43 | // Preview
44 | if let layer = previewLayer {
45 | CATransaction.begin()
46 | CATransaction.setDisableActions(true)
47 | layer.frame = captureHeaderView.bounds
48 | CATransaction.commit()
49 | }
50 | }
51 |
52 | // Tap header to focus
53 | func tapHeader(tap: UITapGestureRecognizer) {
54 | guard state == .Preivew else {
55 | return
56 | }
57 | singleTapHeaderAction(tap: tap)
58 | }
59 |
60 |
61 | // MARK: PMImageProtocol
62 |
63 | // Display header view
64 | var displayHeaderView: UIView {
65 | return captureHeaderView
66 | }
67 |
68 | // Display image
69 | var displayImage: UIImage {
70 | get {
71 | if let style = styleHeaderView {
72 | return style.imageView.image!
73 | }
74 | return (photoHeaderView?.image)!
75 | }
76 | }
77 |
78 | // Tap header to focus
79 | private var _singleTapHeaderAction: ((tap: UITapGestureRecognizer)->Void) = {(tap: UITapGestureRecognizer) in}
80 | var singleTapHeaderAction: ((tap: UITapGestureRecognizer)->Void) {
81 | set {
82 | _singleTapHeaderAction = newValue
83 | }
84 | get {
85 | return _singleTapHeaderAction
86 | }
87 | }
88 |
89 | // Image orienttation affter rotated
90 | private var _rotatedImageOrientation: PMImageOrientation = .Up
91 | var rotatedImageOrientation: PMImageOrientation {
92 | get {
93 | return _rotatedImageOrientation
94 | }
95 | set {
96 | _rotatedImageOrientation = newValue
97 | }
98 | }
99 |
100 | // Set the AVCaptureVideoPreviewLayer
101 | func setAVCapturePreviewLayer(previewLayer: AVCaptureVideoPreviewLayer) {
102 | self.previewLayer = previewLayer
103 | captureHeaderView.layer.insertSublayer(previewLayer, atIndex: 0)
104 | }
105 |
106 | // Change state
107 | func setState(state: PMImageDisplayState, image: UIImage?, selectedRect: CGRect, zoomScale:CGFloat, animated: Bool) {
108 | guard self.state != state else {
109 | return
110 | }
111 | let duration = animated ?0.25:0.0
112 | switch state {
113 | case .Preivew:
114 | captureHeaderView.backgroundColor = UIColor.blackColor()
115 |
116 | // Reset the angle
117 | imageAngle = 0
118 | // Hidden other header
119 | UIView.animateWithDuration(0.25, animations: {
120 | if let editHeader = self.photoHeaderView {
121 | editHeader.alpha = 0
122 | }
123 | if let styleHeader = self.styleHeaderView {
124 | styleHeader.alpha = 0
125 | }
126 | self.previewLayer?.opacity = 1
127 | }, completion: { (com: Bool) in
128 | if com {
129 | self.photoHeaderView?.removeFromSuperview()
130 | self.photoHeaderView = nil
131 | self.styleHeaderView?.removeFromSuperview()
132 | self.styleHeaderView = nil
133 | }
134 | })
135 | break
136 | case .EditImage:
137 | captureHeaderView.backgroundColor = UIColor.whiteColor()
138 |
139 | if self.state == .Preivew {
140 | // Go edit vc and add edit header
141 | let photoHeaderView = PMPhotoHeaderView.init(frame: captureHeaderView.bounds)
142 | photoHeaderView.backgroundColor = UIColor.whiteColor()
143 | photoHeaderView.alpha = 0
144 | photoHeaderView.alwaysShowGrid = true
145 | captureHeaderView.addSubview(photoHeaderView)
146 | // config the image rect
147 | var toRect = selectedRect
148 | if zoomScale == 1 {
149 | toRect.origin.x = toRect.origin.x * (photoHeaderView.imageView.contentSize.width/(image?.size.width)!)
150 | toRect.origin.y = toRect.origin.y * (photoHeaderView.imageView.contentSize.height/(image?.size.height)!)
151 | }
152 |
153 | toRect.size = photoHeaderView.bounds.size
154 | photoHeaderView.setImage(image!, scrollToRect: toRect, zoomScale:zoomScale)
155 |
156 | UIView.animateWithDuration(duration, animations: {
157 | photoHeaderView.alpha = 1
158 | self.previewLayer?.opacity = 0
159 | }, completion: { (com: Bool) in
160 |
161 | })
162 | self.photoHeaderView = photoHeaderView
163 | }else if self.state == .SingleShow {
164 | UIView.animateWithDuration(duration, animations: {
165 | self.styleHeaderView?.alpha = 0
166 | }, completion: { (com: Bool) in
167 | self.styleHeaderView?.removeFromSuperview()
168 | self.styleHeaderView = nil
169 | })
170 | }
171 | break
172 | case .SingleShow:
173 | // Go style vc
174 | let styleHeaderView = PMStyleHeaderView.init(frame: captureHeaderView.bounds)
175 | styleHeaderView.setImage(image!)
176 | styleHeaderView.alpha = 0
177 | captureHeaderView.addSubview(styleHeaderView)
178 |
179 | UIView.animateWithDuration(duration, animations: {
180 | styleHeaderView.alpha = 1
181 | self.previewLayer?.opacity = 0
182 | }, completion: { (com: Bool) in
183 |
184 | })
185 | self.styleHeaderView = styleHeaderView
186 |
187 | break
188 | }
189 | self.state = state
190 | }
191 |
192 | // Rotate image
193 | func rotateDisplayImage(clockwise: Bool) {
194 |
195 | if clockwise {
196 | imageAngle += CGFloat(M_PI/2)
197 | }else {
198 | imageAngle -= CGFloat(M_PI/2)
199 | }
200 | photoHeaderView?.rotate(imageAngle, closeWise: clockwise)
201 | }
202 |
203 | // Cropped image affter edit
204 | func croppedImage() -> UIImage {
205 | let image = photoHeaderView?.cropImageAffterEdit()
206 | return image!
207 | }
208 |
209 | override func prefersStatusBarHidden() -> Bool {
210 | return true
211 | }
212 |
213 | override func didReceiveMemoryWarning() {
214 | super.didReceiveMemoryWarning()
215 | // Dispose of any resources that can be recreated.
216 | }
217 |
218 |
219 | /*
220 | // MARK: - Navigation
221 |
222 | // In a storyboard-based application, you will often want to do a little preparation before navigation
223 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
224 | // Get the new view controller using segue.destinationViewController.
225 | // Pass the selected object to the new view controller.
226 | }
227 | */
228 |
229 | }
230 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaPhotoCapture/PNImageCaptureController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PNImageCaptureController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 | import AssetsLibrary
12 | import Photos
13 | import CoreImage
14 |
15 | class PNImageCaptureController: UIViewController, PMImagePickerControllerDelegate {
16 |
17 |
18 | @IBOutlet weak var captureButton: PMCaptureButton!
19 | @IBOutlet weak var navigationBar: UINavigationBar!
20 | @IBOutlet weak var flashBarItem: UIBarButtonItem!
21 | @IBOutlet weak var selectPhotoButton: UIButton!
22 | var session: AVCaptureSession! = AVCaptureSession()
23 | var deviceIntput: AVCaptureDeviceInput?
24 | var stillImageOutPut: AVCaptureStillImageOutput?
25 | var previewLayer: AVCaptureVideoPreviewLayer?
26 | var photoGroups = [PHAssetCollection]()
27 | var photoAssets = [PHAsset]()
28 | var isUsingFrontFacingCamera: Bool = false
29 | var currentFlashMode: AVCaptureFlashMode = .Off
30 | let screenSize = ScreenSize()
31 | let orientationManger: PMDeviceOrientation = PMDeviceOrientation()
32 |
33 |
34 | override func viewDidLoad() {
35 | super.viewDidLoad()
36 |
37 | // Init view
38 | initNavigationBar()
39 |
40 | // Auth
41 | PMImageManger.captureAuthorization { (canCapture: Bool) in
42 | if canCapture {
43 | self.initAVCapture()
44 | self.session.startRunning()
45 | }else {
46 | self.session.stopRunning()
47 | }
48 | }
49 |
50 | PMImageManger.photoAuthorization { (canAssets: Bool) in
51 | if canAssets {
52 | self.photoGroups = PMImageManger.photoLibrarys()
53 | self.photoAssets = PMImageManger.photoAssetsForAlbum(self.photoGroups.first!)
54 | PMImageManger.imageFromAsset(self.photoAssets.first!, isOriginal: false, toSize: CGSizeMake(150, 150), resultHandler: { (image: UIImage?) in
55 | self.selectPhotoButton.setBackgroundImage(image, forState: .Normal)
56 | })
57 | }
58 | }
59 |
60 | // Tap header to change focus
61 | photoPisplayBoard?.singleTapHeaderAction = { (tap: UITapGestureRecognizer) in
62 | self.tapToChangeFocus(tap)
63 | }
64 | }
65 |
66 | func initNavigationBar() {
67 | // Navigation bar
68 | navigationBar.setBackgroundImage(UIImage.init(), forBarPosition: UIBarPosition.Top, barMetrics: UIBarMetrics.Default)
69 | navigationBar.shadowImage = UIImage.init()
70 |
71 | let navigationItem = navigationBar.topItem
72 |
73 | // Flash button
74 | let letButton = UIButton.init(type: UIButtonType.System)
75 | letButton.frame = CGRectMake(-10, 0, 44, 44)
76 | letButton.setImage(UIImage.init(named: "flash"), forState: UIControlState.Normal)
77 | letButton.addTarget(self, action: #selector(self.changeFlash(_:)), forControlEvents: UIControlEvents.TouchUpInside)
78 | let letBarItem = UIBarButtonItem.init(customView: letButton)
79 | letButton.imageEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 10)
80 | navigationItem!.leftBarButtonItem = letBarItem
81 |
82 | // Camera possion
83 | let image = UIImage.init(named: "flip")
84 | let hImage = image?.imageWithColor(UIColor.lightGrayColor())
85 | let titleButton = UIButton.init(type: UIButtonType.Custom)
86 | titleButton.setImage(image, forState: UIControlState.Normal)
87 | titleButton.setImage(hImage, forState: UIControlState.Selected)
88 | titleButton.setImage(hImage, forState: UIControlState.Highlighted)
89 | titleButton.sizeToFit()
90 | titleButton.addTarget(self, action: #selector(self.changeCameraPossion), forControlEvents: UIControlEvents.TouchUpInside)
91 | navigationItem!.titleView = titleButton
92 | }
93 |
94 | func initAVCapture() {
95 | // Device
96 | let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
97 |
98 | try! device.lockForConfiguration()
99 | if device.hasFlash {
100 | device.flashMode = AVCaptureFlashMode.Off
101 | }
102 | if device.isFocusModeSupported(.AutoFocus) {
103 | device.focusMode = .AutoFocus
104 | }
105 | if device.isWhiteBalanceModeSupported(.AutoWhiteBalance) {
106 | device.whiteBalanceMode = .AutoWhiteBalance
107 | }
108 | if device.exposurePointOfInterestSupported {
109 | device.exposureMode = .ContinuousAutoExposure
110 | }
111 | device.unlockForConfiguration()
112 |
113 | // Input & Output
114 | // When init AVCaptureDeviceInput first, system will show alert to confirm the authentication from user.
115 | // But the best way is send the acces request manual. see `requestAccessForMediaType`
116 | deviceIntput = try! AVCaptureDeviceInput(device: device)
117 | stillImageOutPut = AVCaptureStillImageOutput()
118 |
119 | // Output settings
120 | stillImageOutPut?.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG, AVVideoScalingModeKey:AVVideoScalingModeResize]
121 |
122 | if session.canAddInput(deviceIntput) {
123 | session.addInput(deviceIntput)
124 | }
125 | if session.canAddOutput(stillImageOutPut) {
126 | session.addOutput(stillImageOutPut)
127 | }
128 |
129 | session.sessionPreset = AVCaptureSessionPresetPhoto
130 | // Preview
131 | previewLayer = AVCaptureVideoPreviewLayer.init(session: session)
132 | previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
133 |
134 | // Set root vc avcapture preview layer
135 | photoPisplayBoard?.setAVCapturePreviewLayer(previewLayer!)
136 | }
137 |
138 | // MARK: Capture action
139 |
140 | @IBAction func capturePhoto(sender: AnyObject) {
141 |
142 | // Disable the capture button
143 | captureButton.enabled = false
144 |
145 | let stillImageConnection = stillImageOutPut?.connectionWithMediaType(AVMediaTypeVideo)
146 | // let curDeviceOrientation = UIDevice.currentDevice().orientation
147 | // let avCaptureOrientation = PMDeviceOrientation.avOrientationFromDeviceOrientation(curDeviceOrientation)
148 | let avCaptureOrientation = AVCaptureVideoOrientation(rawValue: UIDevice.currentDevice().orientation.rawValue)!
149 | if stillImageConnection!.supportsVideoOrientation {
150 | stillImageConnection!.videoOrientation = avCaptureOrientation
151 | }
152 | stillImageConnection!.videoScaleAndCropFactor = 1
153 |
154 | stillImageOutPut?.captureStillImageAsynchronouslyFromConnection(stillImageConnection, completionHandler: { (imageDataSampleBuffer: CMSampleBufferRef!, error: NSError!) in
155 | let jpegData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
156 |
157 | if var image = UIImage(data: jpegData) {
158 |
159 | // Fix orientation & crop image
160 | image = image.fixOrientation()
161 | image = PMImageManger.cropImageAffterCapture(image,toSize: self.previewLayer!.frame.size)
162 |
163 | // Fix interface orientation
164 | if !self.orientationManger.deviceOrientationMatchesInterfaceOrientation() {
165 | let interfaceOrientation = self.orientationManger.orientation()
166 | image = image.rotateImageFromInterfaceOrientation(interfaceOrientation)
167 | }
168 |
169 | // Mirror the image
170 | if self.isUsingFrontFacingCamera {
171 | image = UIImage.init(CGImage: image.CGImage!, scale: image.scale, orientation: UIImageOrientation.UpMirrored)
172 | }
173 |
174 | // Save photo
175 | let authorStatus = ALAssetsLibrary.authorizationStatus()
176 | if authorStatus == ALAuthorizationStatus.Restricted || authorStatus == ALAuthorizationStatus.Denied {
177 | return
178 | }
179 |
180 | let library = ALAssetsLibrary()
181 | if self.isUsingFrontFacingCamera {
182 | library.writeImageToSavedPhotosAlbum(image.CGImage, orientation: ALAssetOrientation.UpMirrored, completionBlock: { (url: NSURL!, error: NSError!) in
183 |
184 | })
185 | }else {
186 | let attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault,imageDataSampleBuffer,kCMAttachmentMode_ShouldPropagate)
187 | // let attachments = CMGetAttachment(imageDataSampleBuffer, kCGImagePropertyExifDictionary, nil)
188 | library.writeImageToSavedPhotosAlbum(image.CGImage!, metadata: attachments as? [NSObject:AnyObject] , completionBlock: { (url: NSURL!, error: NSError!) in
189 |
190 | })
191 | }
192 |
193 | // Go to style vc
194 | self.photoPisplayBoard?.setState(.SingleShow, image: image, selectedRect: CGRectZero, zoomScale:1, animated: false)
195 | let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
196 | let styleVC = storyBoard.instantiateViewControllerWithIdentifier("styleImageController") as? PMImageProcessController
197 | styleVC?.fromCapture = true
198 | self.navigationController?.pushViewController(styleVC!, animated: true)
199 | }
200 |
201 | // Stop session
202 | self.session.stopRunning()
203 | })
204 | }
205 |
206 | func changeCameraPossion() {
207 |
208 | var desiredPosition : AVCaptureDevicePosition?
209 | let navigationItem = navigationBar.topItem
210 |
211 | if (isUsingFrontFacingCamera){
212 | desiredPosition = AVCaptureDevicePosition.Back
213 | navigationItem!.leftBarButtonItem!.customView?.userInteractionEnabled = true
214 | navigationItem!.leftBarButtonItem!.highlighted = false
215 | }else{
216 | desiredPosition = AVCaptureDevicePosition.Front
217 | navigationItem!.leftBarButtonItem!.customView?.userInteractionEnabled = false
218 | navigationItem!.leftBarButtonItem!.highlighted = true
219 | }
220 |
221 | for device in AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) {
222 | let device = device as! AVCaptureDevice
223 | if device.position == desiredPosition {
224 | // Config device
225 | try! device.lockForConfiguration()
226 | if device.hasFlash {
227 | device.flashMode = currentFlashMode
228 | }
229 | if device.isFocusModeSupported(.AutoFocus) {
230 | device.focusMode = .ContinuousAutoFocus
231 | }
232 | if device.isWhiteBalanceModeSupported(.AutoWhiteBalance) {
233 | device.whiteBalanceMode = .AutoWhiteBalance
234 | }
235 | if device.exposurePointOfInterestSupported {
236 | device.exposureMode = .ContinuousAutoExposure
237 | }
238 | device.unlockForConfiguration()
239 | // Add device
240 | let input = try! AVCaptureDeviceInput(device: device)
241 | session.removeInput(deviceIntput)
242 | session.addInput(input)
243 | deviceIntput = input
244 | break;
245 | }
246 | }
247 |
248 | isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
249 | }
250 |
251 | // Tap header to focus
252 | func tapToChangeFocus(tap: UITapGestureRecognizer) {
253 | guard !isUsingFrontFacingCamera else {
254 | return
255 | }
256 | // Location
257 | let point = tap.locationInView(photoPisplayBoard?.displayHeaderView)
258 |
259 | // Show square
260 | showSquareBox(point)
261 |
262 | // Change focus
263 | // let pointInCamera = convertToPointOfInterestFromViewCoordinates(point)
264 | let pointInCamera = previewLayer!.captureDevicePointOfInterestForPoint(point)
265 | let device = deviceIntput?.device
266 | try! device!.lockForConfiguration()
267 |
268 | if device!.focusPointOfInterestSupported {
269 | device!.focusPointOfInterest = pointInCamera
270 | }
271 | if device!.isFocusModeSupported(.ContinuousAutoFocus) {
272 | device!.focusMode = .ContinuousAutoFocus
273 | }
274 | if device!.exposurePointOfInterestSupported {
275 | device?.exposureMode = .ContinuousAutoExposure
276 | device?.exposurePointOfInterest = pointInCamera
277 | }
278 | device?.subjectAreaChangeMonitoringEnabled = true
279 | device!.focusPointOfInterest = pointInCamera
280 |
281 | device!.unlockForConfiguration()
282 | }
283 |
284 | @IBAction func selectPhoto(sender: AnyObject) {
285 | let nav = PMImagePickerController.init()
286 | nav.pmDelegate = self
287 | nav.photoGroups = photoGroups
288 | nav.photoAssets = photoAssets
289 | weak var weakSelf = self
290 | self.presentViewController(nav, animated: true) {
291 | weakSelf!.session.stopRunning()
292 | }
293 | }
294 |
295 | @IBAction func changeFlash(sender: AnyObject) {
296 | var image: UIImage? = nil
297 |
298 | let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
299 | try! device.lockForConfiguration()
300 | if device.hasFlash {
301 | switch device.flashMode {
302 | case .Off:
303 | device.flashMode = .On
304 | currentFlashMode = .On
305 | image = UIImage.init(named: "flash-on")
306 | break
307 | case .On:
308 | device.flashMode = .Auto
309 | currentFlashMode = .Auto
310 | image = UIImage.init(named: "flash-auto")
311 | break
312 | case .Auto:
313 | device.flashMode = .Off
314 | currentFlashMode = .Off
315 | image = UIImage.init(named: "flash")
316 | break
317 | }
318 | // Flash baritem
319 | let letButton = navigationBar.topItem!.leftBarButtonItem?.customView as? UIButton
320 | letButton?.setImage(image, forState: UIControlState.Normal)
321 | }
322 | device.unlockForConfiguration()
323 | }
324 |
325 | @IBAction func setting(sender: AnyObject) {
326 |
327 | }
328 |
329 | // Show focus square box
330 | private func showSquareBox(point: CGPoint) {
331 | // remove box
332 | guard let header = photoPisplayBoard?.displayHeaderView else {
333 | return
334 | }
335 | for layer in header.layer.sublayers!{
336 | if layer.name == "box" {
337 | layer.removeFromSuperlayer()
338 | }
339 | }
340 | // create a box layer
341 | let width = CGFloat(60)
342 | let box = CAShapeLayer.init()
343 | box.frame = CGRectMake(point.x - width/2, point.y - width/2, width, width)
344 | box.borderWidth = 1
345 | box.borderColor = UIColor.whiteColor().CGColor
346 | box.name = "box"
347 | header.layer.addSublayer(box)
348 |
349 | // animation
350 | let alphaAnimation = CABasicAnimation.init(keyPath: "opacity")
351 | alphaAnimation.fromValue = 1
352 | alphaAnimation.toValue = 0
353 | alphaAnimation.duration = 0.01
354 | alphaAnimation.beginTime = CACurrentMediaTime()
355 |
356 | let scaleAnimation = CABasicAnimation.init(keyPath: "transform.scale")
357 | scaleAnimation.fromValue = 1.2
358 | scaleAnimation.toValue = 1
359 | scaleAnimation.duration = 0.35
360 | scaleAnimation.beginTime = CACurrentMediaTime()
361 |
362 | box.addAnimation(alphaAnimation, forKey: nil)
363 | box.addAnimation(scaleAnimation, forKey: nil)
364 |
365 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64((0.35 + 0.2) * Double(NSEC_PER_SEC)))
366 | dispatch_after(time, dispatch_get_main_queue()) {
367 | box.removeFromSuperlayer()
368 | }
369 | }
370 |
371 | // Convert the touch point to focus point of interest. The focus point of interest is from [0, 0] to [1, 1].
372 | private func convertToPointOfInterestFromViewCoordinates(point: CGPoint) -> CGPoint {
373 | var interestPoint = CGPointMake(0.5, 0.5)
374 | for _port in deviceIntput!.ports {
375 | if let port = _port as? AVCaptureInputPort {
376 | let cleanAperture = CMVideoFormatDescriptionGetCleanAperture(port.formatDescription, true)
377 | let apertureSize = cleanAperture.size
378 | let frameSize = previewLayer?.bounds.size
379 | let apertureRatio = apertureSize.height / apertureSize.width;
380 | let viewRatio = frameSize!.width / frameSize!.height;
381 | var xc = CGFloat(0.5)
382 | var yc = CGFloat(0.5)
383 |
384 | // Just calculate videoGravity of AVLayerVideoGravityResizeAspectFill mode
385 | if viewRatio > apertureRatio {
386 | let y2 = apertureSize.width * (frameSize!.width / apertureSize.height)
387 | xc = (point.y + ((y2 - frameSize!.height) / 2)) / y2
388 | yc = (frameSize!.width - point.x) / frameSize!.width
389 | } else {
390 | let x2 = apertureSize.height * (frameSize!.height / apertureSize.width)
391 | yc = 1.0 - ((point.x + ((x2 - frameSize!.width) / 2)) / x2)
392 | xc = point.y / frameSize!.height
393 | }
394 | interestPoint = CGPointMake(xc, yc)
395 | break
396 | }
397 | }
398 | return interestPoint
399 | }
400 |
401 | // MARK: PMImagePickerControllerDelegate
402 |
403 | func imagePickerController(picker: PMImagePickerController, didFinishPickingImage originalImage: UIImage, selectedRect: CGRect, zoomScale:CGFloat) {
404 | photoPisplayBoard?.setState(PMImageDisplayState.EditImage, image: originalImage, selectedRect: selectedRect, zoomScale:zoomScale, animated: false)
405 |
406 | let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
407 | let editVC = storyBoard.instantiateViewControllerWithIdentifier("imageEditController") as? PMImageEditController
408 | navigationController?.pushViewController(editVC!, animated: false)
409 | }
410 |
411 | func imagePickerController(picker: PMImagePickerController, didFinishPickingImage image: UIImage) {}
412 |
413 | func imagePickerControllerDidCancel(picker: PMImagePickerController) {
414 | session.startRunning()
415 | }
416 |
417 | override func viewWillAppear(animated: Bool) {
418 | session.startRunning()
419 | captureButton.enabled = true
420 | }
421 |
422 | override func didReceiveMemoryWarning() {
423 | super.didReceiveMemoryWarning()
424 | // Dispose of any resources that can be recreated.
425 | }
426 |
427 |
428 | /*
429 | // MARK: - Navigation
430 |
431 | // In a storyboard-based application, you will often want to do a little preparation before navigation
432 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
433 | // Get the new view controller using segue.destinationViewController.
434 | // Pass the selected object to the new view controller.
435 | }
436 | */
437 |
438 | }
439 |
440 | extension UIBarButtonItem {
441 |
442 | var highlighted: Bool {
443 | set {
444 | if let button = customView as? UIButton {
445 | button.highlighted = newValue
446 | }
447 | }
448 | get {
449 | if let button = customView as? UIButton {
450 | return button.highlighted
451 | }
452 | return false
453 | }
454 | }
455 | }
456 |
457 |
458 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaViews/PMCaptureButtom.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMCaptureButtom.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/28.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | let touchUpDuration = 0.4
12 |
13 | class PMTarget: NSObject {
14 | var target: AnyObject?
15 | var action: Selector?
16 | var touchAction: Selector = #selector(PMTarget.touch(_:))
17 |
18 | override init() {
19 | super.init()
20 | }
21 |
22 | convenience init(target: AnyObject, action: Selector) {
23 | self.init()
24 | self.target = target
25 | self.action = action
26 | }
27 |
28 | func touch(sender: UIButton) {
29 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(touchUpDuration * Double(NSEC_PER_SEC)))
30 | dispatch_after(time, dispatch_get_main_queue()) {
31 | if let target = self.target as? NSObject{
32 | target.performSelector(self.action!, withObject: sender)
33 | }
34 | }
35 | }
36 | }
37 |
38 |
39 | class PMCaptureButton: UIButton {
40 |
41 | var lineWidth: CGFloat = 1
42 | var lineColor: UIColor = UIColor.RGBColor(78, green: 78, blue: 78)
43 | var fillColor: UIColor = UIColor.RGBColor(245, green: 245, blue: 245)
44 | var enabledColor: UIColor = UIColor.init(white: 0.98, alpha: 0.75)
45 | let content = PMCaptureButtonContent.init()
46 | var shouldLayout = true
47 | var targets: [AnyObject] = [AnyObject]()
48 |
49 |
50 | override var enabled: Bool {
51 | didSet {
52 | content.enabled = enabled
53 | }
54 | }
55 |
56 |
57 | override init(frame: CGRect) {
58 | super.init(frame: frame)
59 | backgroundColor = UIColor.clearColor()
60 | configViews()
61 | }
62 |
63 | required init?(coder aDecoder: NSCoder) {
64 | super.init(coder: aDecoder)
65 | backgroundColor = UIColor.clearColor()
66 | configViews()
67 | }
68 |
69 | func configViews() {
70 | content.backgroundColor = UIColor.clearColor()
71 | content.frame = bounds
72 | content.lineColor = lineColor
73 | content.lineWidth = lineWidth
74 | content.fillColor = fillColor
75 | content.enabledColor = enabledColor
76 | content.userInteractionEnabled = false
77 | addSubview(content)
78 |
79 | addTarget(self, action: #selector(PMCaptureButton.touchDown), forControlEvents: UIControlEvents.TouchDown)
80 | super.addTarget(self, action: #selector(PMCaptureButton.touchUpInside), forControlEvents: UIControlEvents.TouchUpInside)
81 | addTarget(self, action: #selector(PMCaptureButton.touchDragExit), forControlEvents: UIControlEvents.TouchDragExit)
82 | addTarget(self, action: #selector(PMCaptureButton.touchDragEnter), forControlEvents: UIControlEvents.TouchDragEnter)
83 | }
84 |
85 | override func layoutSubviews() {
86 | guard shouldLayout else {
87 | return
88 | }
89 | content.frame = bounds
90 | }
91 |
92 | override func addTarget(target: AnyObject?, action: Selector, forControlEvents controlEvents: UIControlEvents) {
93 | if controlEvents == .TouchUpInside {
94 | if let tar = target {
95 | let pmTarget = PMTarget.init(target: tar, action: action)
96 | super.addTarget(pmTarget, action: #selector(PMTarget.touch(_:)), forControlEvents: controlEvents)
97 | targets.append(pmTarget) // retain ARC, also could associate `pmTarget` property to `target`, and write an extension of NSObject to add a dealloc call back metohod(remove the association).
98 | }
99 | }else {
100 | super.addTarget(target, action: action, forControlEvents: controlEvents)
101 | }
102 | }
103 |
104 |
105 | func touchDown() {
106 | setSelectedState(true)
107 | }
108 |
109 | func touchUpInside() {
110 | setSelectedState(false)
111 | }
112 |
113 | func touchDragExit() {
114 | setSelectedState(false)
115 | }
116 |
117 | func touchDragEnter() {
118 | setSelectedState(true)
119 | }
120 |
121 | func setSelectedState(selected: Bool) {
122 | if selected {
123 | shouldLayout = false
124 | UIView.animateWithDuration(0.05, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: {
125 | self.content.transform = CGAffineTransformMakeScale(0.86, 0.86)
126 | }, completion: { (com: Bool) in
127 | self.shouldLayout = true
128 | })
129 | }else {
130 | shouldLayout = false
131 | UIView.animateWithDuration(touchUpDuration, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
132 | self.content.transform = CGAffineTransformIdentity
133 | }, completion: { (com: Bool) in
134 | self.shouldLayout = true
135 | })
136 | }
137 | }
138 | }
139 |
140 | class PMCaptureButtonContent: UIView {
141 |
142 | var lineWidth: CGFloat = 1
143 | var lineColor: UIColor = UIColor.blackColor()
144 | var fillColor: UIColor = UIColor.grayColor()
145 | var enabledColor: UIColor = UIColor.lightGrayColor()
146 | let screenScale: CGFloat = UIScreen.mainScreen().scale
147 | var centerOffset: CGFloat = (1.0/UIScreen.mainScreen().scale)/2
148 | private var _enabled: Bool = true
149 | var enabled: Bool {
150 | set {
151 | _enabled = newValue
152 | setNeedsDisplay()
153 | }
154 | get {
155 | return _enabled
156 | }
157 | }
158 |
159 |
160 | override func drawRect(rect: CGRect) {
161 | // Draw circle
162 | let edgeInset: CGFloat = 2
163 | let centerX = CGFloatPixelRound(bounds.size.width/2)
164 | let centerY = CGFloatPixelRound(bounds.size.height/2)
165 | let radius = CGFloatPixelRound(bounds.size.width/2 - 2 * edgeInset)
166 | if (lineWidth * screenScale)/2 == 0 {
167 | centerOffset = 0
168 | }
169 |
170 | let context = UIGraphicsGetCurrentContext()
171 | CGContextSetStrokeColorWithColor(context!, lineColor.CGColor)
172 | CGContextSetLineWidth(context!, lineWidth)
173 | CGContextSetFillColorWithColor(context!, fillColor.CGColor)
174 | CGContextAddArc(context!, centerX + centerOffset, centerY + centerOffset, radius, 0, CGFloat(M_PI) * 2, 0)
175 | CGContextDrawPath(context!, CGPathDrawingMode.FillStroke)
176 |
177 | if enabled == false {
178 | CGContextSaveGState(context!)
179 | CGContextSetFillColorWithColor(context!, enabledColor.CGColor)
180 | CGContextAddArc(context!, centerX + centerOffset, centerY + centerOffset, radius + lineWidth, 0, CGFloat(M_PI) * 2, 0)
181 | CGContextDrawPath(context!, CGPathDrawingMode.Fill)
182 | }
183 | }
184 |
185 | func CGFloatPixelRound(value: CGFloat) -> CGFloat {
186 | let scale = screenScale
187 | return round(value * scale) / scale
188 | }
189 | }
190 |
191 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaViews/PMStyleCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMStyleCell.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/1.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMStyleCell: UICollectionViewCell {
12 |
13 | @IBOutlet weak var styleImageView: UIImageView!
14 | @IBOutlet weak var styleNameLabel: UILabel!
15 | @IBOutlet weak var view: UIView!
16 | @IBOutlet weak var indicator: UIActivityIndicatorView!
17 |
18 |
19 | override func layoutSubviews() {
20 | super.layoutSubviews()
21 | view.frame = bounds
22 | }
23 |
24 | func loadImage(data: AnyObject) {
25 | // Loading
26 | indicator.hidden = false
27 | indicator.startAnimating()
28 |
29 | // Ttile
30 | let title: String = data.objectForKey("artwork")! as! String
31 | self.styleNameLabel.text = title
32 |
33 | // Download image
34 | let URL: NSURL = NSURL.init(string: data.objectForKey("image_url")! as! String)!
35 | styleImageView.pm_setImageWithURL(URL) { (image: UIImage?, error: NSError?) in
36 | self.indicator.stopAnimating()
37 | self.indicator.hidden = true
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaViews/PMStyleHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMStyleHeaderView.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/1.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMStyleHeaderView: UIView {
12 |
13 | var imageView = UIImageView.init()
14 |
15 | override init(frame: CGRect) {
16 | super.init(frame: frame)
17 | configSubviews()
18 | }
19 |
20 | func configSubviews() {
21 | imageView.backgroundColor = UIColor.whiteColor()
22 | imageView.frame = bounds
23 | addSubview(imageView)
24 | }
25 |
26 | override func layoutSubviews() {
27 | super.layoutSubviews()
28 | imageView.frame = bounds
29 | }
30 |
31 | func setImage(image: UIImage) {
32 | imageView.image = image
33 | }
34 |
35 | required init?(coder aDecoder: NSCoder) {
36 | fatalError("init(coder:) has not been implemented")
37 | }
38 |
39 | /*
40 | // Only override drawRect: if you perform custom drawing.
41 | // An empty implementation adversely affects performance during animation.
42 | override func drawRect(rect: CGRect) {
43 | // Drawing code
44 | }
45 | */
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaWebImage/PMImageCache.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageCache.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/5.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import Compression
11 |
12 | class PMImageCache: NSObject {
13 |
14 | let imageCache: NSCache = NSCache.init()
15 | var diskPath: String?
16 | let fileManager: NSFileManager = NSFileManager.defaultManager()
17 |
18 | override init() {
19 | super.init()
20 | self.diskPath = defaultDiskPath()
21 | }
22 |
23 | func storeImage(image: UIImage, forKey: String) {
24 | let path = defaultCachePathForKey(forKey)
25 | if !fileManager.isExecutableFileAtPath(diskPath!) {
26 | try! fileManager.createDirectoryAtPath(diskPath!, withIntermediateDirectories: true, attributes: nil)
27 | }
28 |
29 | imageCache.setObject(image, forKey: forKey, cost: Int(image.size.height * image.size.width * image.scale * image.scale))
30 | fileManager.createFileAtPath(path, contents: UIImageJPEGRepresentation(image, 1.0), attributes: nil)
31 | }
32 |
33 | func queryImageFromCache(key: String, doneBlock: ((image: UIImage?)->Void)?) {
34 |
35 | var image: UIImage?
36 |
37 | if let cacheImage = self.imageCache.objectForKey(key) {
38 | image = cacheImage as? UIImage
39 | if let done = doneBlock {
40 | done(image: image)
41 | }
42 | }else {
43 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
44 | let path = self.defaultCachePathForKey(key)
45 | if self.fileManager.isExecutableFileAtPath(path) {
46 | let data = NSData.init(contentsOfFile: path)
47 | image = UIImage.init(data: data!)
48 | }
49 |
50 | if let done = doneBlock {
51 | dispatch_async(dispatch_get_main_queue(), {
52 | done(image: image)
53 | })
54 | }
55 | }
56 |
57 | }
58 | }
59 |
60 | func defaultDiskPath() -> String {
61 | var path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory, .UserDomainMask, true)
62 | let diskDir: NSString = path[0]
63 | let diskPath = diskDir.stringByAppendingPathComponent("com.PMImageSimplePicker.PMImageCache")
64 | return diskPath
65 | }
66 |
67 | func defaultCachePathForKey(key: String) -> String {
68 | let path = (diskPath! as NSString).stringByAppendingPathComponent(key)
69 | return path
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaWebImage/PMImageDownloader.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageDownloader.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/5.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class PMSessionDelegate: NSObject {
12 | var completionHandler: ((NSData?, NSURL?, NSError?) -> Void)?
13 | var task: NSURLSessionDataTask?
14 | var mutableData: NSMutableData = NSMutableData.init()
15 |
16 | override init() {
17 | super.init()
18 | }
19 |
20 | convenience init(completionHandler: ((NSData?, NSURL?, NSError?) -> Void)?) {
21 | self.init()
22 | self.completionHandler = completionHandler
23 | }
24 | }
25 |
26 | class PMImageDownloader: NSObject, NSURLSessionDelegate, NSURLSessionDataDelegate {
27 |
28 | var session: NSURLSession?
29 | var imageCache: PMImageCache = PMImageCache.init()
30 | var taskDelegates: [String:PMSessionDelegate] = [String:PMSessionDelegate]()
31 |
32 |
33 | override init() {
34 | super.init()
35 | session = NSURLSession.init(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: self, delegateQueue: NSOperationQueue.init())
36 | }
37 |
38 | class func sharedDownloader() -> PMImageDownloader {
39 | struct Static {
40 | static var token: dispatch_once_t = 0
41 | static var downloader: PMImageDownloader?
42 | }
43 |
44 | dispatch_once(&Static.token) {
45 | Static.downloader = PMImageDownloader.init()
46 | }
47 |
48 | return Static.downloader!
49 | }
50 |
51 | func downloadImage(url: NSURL, completionHandler: ((image: UIImage?, URL: NSURL?, error: NSError?)->Void)) {
52 | let urlKey = url.absoluteString
53 |
54 | // Check disk
55 | weak var weakSelf = self
56 | imageCache.queryImageFromCache(urlKey!) { (image: UIImage?) in
57 | if let img: UIImage = image {
58 | if let com: ((image: UIImage?, URL: NSURL?, error: NSError?)->Void) = completionHandler {
59 | com(image: img, URL: url, error: nil)
60 | }
61 | }
62 |
63 | // Down image
64 | else {
65 | let dataTask = weakSelf!.pmDataTaskWithURL(url) { (data: NSData?, _URL: NSURL?, error: NSError?) in
66 | var image: UIImage?
67 | var error: NSError?
68 | if let err = error {
69 | error = err
70 | print("down error \(err)")
71 | }else {
72 | if data?.length > 0 {
73 | image = UIImage.init(data: data!)
74 | // Stroe image
75 | weakSelf!.imageCache.storeImage(image!, forKey: urlKey!)
76 | }
77 | }
78 |
79 | if let com: ((image: UIImage?, URL: NSURL? ,error: NSError?)->Void) = completionHandler {
80 | com(image: image, URL: _URL, error: error)
81 | }
82 | }
83 |
84 | dataTask.resume()
85 | }
86 | }
87 |
88 | }
89 |
90 |
91 | func pmDataTaskWithURL(url: NSURL, completionHandler: (NSData?, NSURL?, NSError?) -> Void) -> NSURLSessionDataTask {
92 |
93 | if let delegate = taskDelegates[url.absoluteString!] {
94 | delegate.completionHandler = completionHandler
95 | let task = delegate.task!
96 | return task
97 | }
98 |
99 | let task = self.session!.dataTaskWithURL(url)
100 | let delegate = PMSessionDelegate.init(completionHandler: completionHandler)
101 | delegate.task = task
102 | taskDelegates[url.absoluteString!] = delegate
103 |
104 | return task
105 | }
106 |
107 | // MARK: Delegate
108 |
109 | func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
110 | let delegate = taskDelegates[(dataTask.originalRequest?.URL?.absoluteString)!]
111 | delegate?.mutableData.appendData(data)
112 | }
113 |
114 | func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
115 | let delegate = taskDelegates[(task.originalRequest?.URL?.absoluteString)!]
116 | if let callBack = delegate?.completionHandler {
117 | dispatch_async(dispatch_get_main_queue(), {
118 | callBack(delegate?.mutableData, task.originalRequest?.URL, error)
119 | })
120 | }
121 | }
122 |
123 | }
124 |
125 | var kAssociatedUrl: UInt8 = 0
126 |
127 | extension UIImageView {
128 |
129 | var currentUrl: String {
130 | set {
131 | objc_setAssociatedObject(self, &kAssociatedUrl, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
132 | }
133 | get {
134 | if let url = objc_getAssociatedObject(self, &kAssociatedUrl) {
135 | return url as! String
136 | }
137 | return "current_orginal_url"
138 | }
139 | }
140 |
141 | func pm_setImageWithURL(URL: NSURL, completionHandler:((image: UIImage?, error: NSError?)->Void)?) {
142 | self.image = nil
143 | currentUrl = URL.absoluteString!
144 | let downloader = PMImageDownloader.sharedDownloader()
145 | downloader.downloadImage(URL) { (image: UIImage?, _URL: NSURL?, error: NSError?) in
146 |
147 | guard _URL?.absoluteString == self.currentUrl else {
148 | return
149 | }
150 |
151 | if let img = image {
152 | self.image = img
153 | self.setNeedsLayout()
154 | }
155 |
156 | if let callBack = completionHandler {
157 | callBack(image: image,error: error)
158 | }
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/PrismaWebImage/PMImageSession.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PMImageSession.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/8/6.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // PrismaSimpleImagePicker
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 | // Do any additional setup after loading the view, typically from a nib.
16 | }
17 |
18 | override func didReceiveMemoryWarning() {
19 | super.didReceiveMemoryWarning()
20 | // Dispose of any resources that can be recreated.
21 | }
22 |
23 |
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePicker/styles.json:
--------------------------------------------------------------------------------
1 | {"styles":[{"artist":"","artwork":"Femme","image_url":"https:\/\/cdn.neuralprisma.com\/images\/1507_k15.jpg","model":"1507_k15"},{"artist":"","artwork":"Udnie","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet11_na.jpg","model":"resNet11_na"},{"artist":"","artwork":"Tears","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet10_nd.jpg","model":"resNet10_nd"},{"artist":"","artwork":"#GettUrban","image_url":"https:\/\/cdn.neuralprisma.com\/images\/kd.jpg","model":"kd"},{"artist":"","artwork":"Marcus D - Lone Wolf","image_url":"https:\/\/cdn.neuralprisma.com\/images\/k11.jpg","model":"k11"},{"artist":"","artwork":"Dreams","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet9_n1_1.jpg","model":"resNet9_n1"},{"artist":"","artwork":"Running in the storm","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet11_m9_1.jpg","model":"resNet11_m9"},{"artist":"","artwork":"Curtain","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet10_m7_1.jpg","model":"resNet10_m7"},{"artist":"","artwork":"Impression","image_url":"https:\/\/cdn.neuralprisma.com\/images\/palmolive02.jpg","model":"k3"},{"artist":"","artwork":"Flame flower","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet10_m2.jpg","model":"resNet10_m2"},{"artist":"","artwork":"Mondrian","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet11_nb.jpg","model":"resNet11_nb"},{"artist":"","artwork":"Paper art","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet9_n2.jpg","model":"resNet9_n2"},{"artist":"","artwork":"Roland","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet9_n3.jpg","model":"resNet9_n3"},{"artist":"","artwork":"Red head","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet9_n7.jpg","model":"resNet9_n7"},{"artist":"","artwork":"Composition","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_final5.jpg","model":"resNetFinal_final5"},{"artist":"","artwork":"Light summer reading","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_14.jpg","model":"resNetFinal_14"},{"artist":"","artwork":"Coloured sky","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet9_n5_1.jpg","model":"resNet9_n5"},{"artist":"","artwork":"Roy","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet4_6.jpg","model":"resNet4_6"},{"artist":"","artwork":"Candy","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet7_4.jpg","model":"resNet7_4"},{"artist":"","artwork":"Transverse Line","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet8_1.jpg","model":"resNet8_1"},{"artist":"","artwork":"Mosaic","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet8_6.jpg","model":"resNet8_6"},{"artist":"","artwork":"Heisenberg","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_4.jpg","model":"resNetFinal_4"},{"artist":"","artwork":"Illegal Beauty","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNet7_5.jpg","model":"resNet7_5"},{"artist":"","artwork":"Mononoke","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_8.jpg","model":"resNetFinal_8"},{"artist":"","artwork":"Urban","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_9.jpg","model":"resNetFinal_9"},{"artist":"","artwork":"Tokyo","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_13.jpg","model":"resNetFinal_13"},{"artist":"","artwork":"Curly Hair","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_final0.jpg","model":"resNetFinal_final0"},{"artist":"","artwork":"Wave","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_final1.jpg","model":"resNetFinal_final1"},{"artist":"","artwork":"Gothic","image_url":"https:\/\/cdn.neuralprisma.com\/images\/resNetFinal_final3.jpg","model":"resNetFinal_final3"}],"version":59}
--------------------------------------------------------------------------------
/PrismaSimpleImagePickerTests/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 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/PrismaSimpleImagePickerTests/PrismaSimpleImagePickerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PrismaSimpleImagePickerTests.swift
3 | // PrismaSimpleImagePickerTests
4 | //
5 | // Created by Roy lee on 16/7/24.
6 | // Copyright © 2016年 Roy lee. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import PrismaSimpleImagePicker
11 |
12 | class PrismaSimpleImagePickerTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measureBlock {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PrismaSimpleImagePicker
2 |
3 |
4 | 
5 |
6 |
7 | Custom camera, image picker ,image editor and the interface just like Prisma's style.
8 |
9 |
10 | # Overview
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | # Introduction
19 |
20 | ### This is just a client function copy of Prisma, not a pod solution
21 |
22 | Prisma is a sucessful APP of photo editing, but it's success is more than just art. And the details of the Prisma is also very good. So, I try to reproduce the client function of Prisma use Swift, and the result is this project.
23 |
24 | This is build with Storyboard and xib, just because the Prisma is also used Storyboard and xib. The follow is the struct:
25 |
26 | 
27 |
28 |
29 | ### What is the use of this project?
30 |
31 | **Firstly**, we can learn how to custom camera use framework AVFoundation.
32 |
33 | > * **AVCaptureSession** A session to manage camera, responsible for the video image management function
34 | > * **AVCaptureDeviceInput** Do the image acquisition
35 | > * **AVCaptureStillImageOutput** Function for image stream output
36 | > * **AVCaptureVideoPreviewLayer** Video preview layer, used to display the scene of the camera in real time
37 |
38 | There is one thing we need to pay attention when we custom a camera, it's the image's orientation. Because the normal orientation of iPhone camera is lanscape left(Home button on the right), so the image orientation is different from our expected result. Below is a comparison.
39 |
40 | 
41 |
42 |
43 | **Secondly**, from this project we can learn about some kowledge of system photo album. Because just support iOS8 above, so I use framework Photos to complete photo select, not the AssetsLibrary frmawork Prisma used. And below is the frameworks Prisma used.
44 |
45 | 
46 |
47 |
48 | **Finally**, we could just use the image picker in foder `PrismaImagePicker`, this is an independent function for developer jsut want to have a image picker with Prisma's syle.
49 |
50 | **More details, please view my [blog](http://error408.com/2016/08/03/Prisma-%E6%88%90%E5%8A%9F%E7%9A%84%E4%B8%8D%E5%8F%AA%E6%98%AF%E8%89%BA%E6%9C%AF/)(*Only Chinese supported*)**
51 |
52 |
53 |
54 | ### How to use PrismaImagePicker?
55 |
56 | * Create an object of class `PMImagePickerController`, and just present it from your own view controller.
57 | * If you just have the data source before, you can set the data source of `PMImagePickerController`, so it can be fast because without read the photo album.
58 | * Conform to protocol `PMImagePickerControllerDelegate`, and implement the delegate used.
59 |
60 | The PMImagePickerControllerDelegate
61 |
62 | ```swift
63 | @objc protocol PMImagePickerControllerDelegate: NSObjectProtocol {
64 | /**
65 | Call when tap `Use` button of the picker view controller
66 |
67 | - parameter picker: The view controller of class PMImagePickerController
68 | - parameter image: An cropped image which displayed in the top header after edit
69 | */
70 | optional func imagePickerController(picker: PMImagePickerController, didFinishPickingImage image: UIImage)
71 |
72 | /**
73 | Call when tap `Use` button of the picker view controller
74 |
75 | - parameter picker: The view controller of class PMImagePickerController
76 | - parameter originalImage: An original image which displayed in the top header
77 | - parameter selectedRect: A rect displayed of the header
78 | - parameter zoomScale: ZoomScale of the image
79 | */
80 | optional func imagePickerController(picker: PMImagePickerController, didFinishPickingImage originalImage: UIImage, selectedRect: CGRect, zoomScale:CGFloat)
81 |
82 | /**
83 | Call when tap `Cancel` button of the picker view controller
84 |
85 | - parameter picker: The view controller of class PMImagePickerController
86 | */
87 | optional func imagePickerControllerDidCancel(picker: PMImagePickerController)
88 | }
89 | ```
90 |
91 |
92 | Create and use the iamge picker
93 |
94 | ```swift
95 | // Create image picker
96 | @IBAction func selectPhoto(sender: AnyObject) {
97 | let nav = PMImagePickerController.init()
98 | nav.pmDelegate = self
99 | nav.photoGroups = photoGroups
100 | nav.photoAssets = photoAssets
101 | weak var weakSelf = self
102 | self.presentViewController(nav, animated: true) {
103 | weakSelf!.session.stopRunning()
104 | }
105 | }
106 |
107 |
108 | // PMImagePickerControllerDelegate
109 | func imagePickerController(picker: PMImagePickerController, didFinishPickingImage originalImage: UIImage, selectedRect: CGRect, zoomScale:CGFloat) {
110 | // Do something with the original image
111 | ...
112 | }
113 |
114 | func imagePickerController(picker: PMImagePickerController, didFinishPickingImage image: UIImage) {
115 | // Dow something with the cropped image
116 | ...
117 | }
118 |
119 | func imagePickerControllerDidCancel(picker: PMImagePickerController) {
120 | session.startRunning()
121 | }
122 | ```
123 |
124 | **Custom your own album kind**
125 |
126 | The default album is `Camera`、`Favorites`、`ScreenShots` and `User photos`, and all the operations of image is in `PMImageManger.swift`.
127 |
128 | If you want change the kind of album, you could change the parameters `PHAssetCollectionType` and `PHAssetCollectionSubtype` in function `class func photoLibrarys() -> [PHAssetCollection]`
129 |
130 |
131 | # License
132 |
133 | PrismaSimpleImagePicker is available under the MIT license. See the LICENSE file for more info.
134 |
--------------------------------------------------------------------------------
/ScreenShots/cropimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/cropimage.png
--------------------------------------------------------------------------------
/ScreenShots/frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/frameworks.png
--------------------------------------------------------------------------------
/ScreenShots/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/logo.png
--------------------------------------------------------------------------------
/ScreenShots/possion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/possion.png
--------------------------------------------------------------------------------
/ScreenShots/prismanib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/prismanib.png
--------------------------------------------------------------------------------
/ScreenShots/screenshot1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/screenshot1.gif
--------------------------------------------------------------------------------
/ScreenShots/screenshot2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/screenshot2.gif
--------------------------------------------------------------------------------
/ScreenShots/screenshot3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liangdrime/PrismaSimpleImagePicker/4c33274fa2cceec436b42aa8205d42a393a27c13/ScreenShots/screenshot3.gif
--------------------------------------------------------------------------------