diff --git a/ALCameraViewController.xcodeproj/project.pbxproj b/ALCameraViewController.xcodeproj/project.pbxproj index a7a71cde..f34e57ed 100644 --- a/ALCameraViewController.xcodeproj/project.pbxproj +++ b/ALCameraViewController.xcodeproj/project.pbxproj @@ -7,6 +7,17 @@ objects = { /* Begin PBXBuildFile section */ + B2357AB11FA50D51003F9ACF /* FilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B2357AAF1FA50D51003F9ACF /* FilterViewController.xib */; }; + B2357AB21FA50D51003F9ACF /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB01FA50D51003F9ACF /* FilterViewController.swift */; }; + B2357AB31FA50E13003F9ACF /* FilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB01FA50D51003F9ACF /* FilterViewController.swift */; }; + B2357AB41FA50E13003F9ACF /* FilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B2357AAF1FA50D51003F9ACF /* FilterViewController.xib */; }; + B2357AB91FA51156003F9ACF /* UIImageView+Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB61FA51155003F9ACF /* UIImageView+Filter.m */; }; + B2357ABA1FA51156003F9ACF /* UIImage+Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB71FA51156003F9ACF /* UIImage+Filter.m */; }; + B2357ABB1FA5115C003F9ACF /* UIImage+Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = B2357AB81FA51156003F9ACF /* UIImage+Filter.h */; }; + B2357ABC1FA5115C003F9ACF /* UIImage+Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB71FA51156003F9ACF /* UIImage+Filter.m */; }; + B2357ABD1FA5115C003F9ACF /* UIImageView+Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = B2357AB51FA51155003F9ACF /* UIImageView+Filter.h */; }; + B2357ABE1FA5115C003F9ACF /* UIImageView+Filter.m in Sources */ = {isa = PBXBuildFile; fileRef = B2357AB61FA51155003F9ACF /* UIImageView+Filter.m */; }; + B2357ABF1FA511DC003F9ACF /* CameraViewController-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = E33BE72F1F54955E005842DC /* CameraViewController-Bridging-Header.h */; }; BF5861F31F613FB800B406F6 /* CropViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF5861F61F613FB800B406F6 /* CropViewController.xib */; }; BF5861F41F613FB800B406F6 /* CropViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF5861F61F613FB800B406F6 /* CropViewController.xib */; }; BF5861F81F61404C00B406F6 /* ConfirmViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF5861FB1F61404C00B406F6 /* ConfirmViewController.xib */; }; @@ -74,6 +85,12 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + B2357AAF1FA50D51003F9ACF /* FilterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FilterViewController.xib; sourceTree = ""; }; + B2357AB01FA50D51003F9ACF /* FilterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterViewController.swift; sourceTree = ""; }; + B2357AB51FA51155003F9ACF /* UIImageView+Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+Filter.h"; sourceTree = ""; }; + B2357AB61FA51155003F9ACF /* UIImageView+Filter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+Filter.m"; sourceTree = ""; }; + B2357AB71FA51156003F9ACF /* UIImage+Filter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Filter.m"; sourceTree = ""; }; + B2357AB81FA51156003F9ACF /* UIImage+Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Filter.h"; sourceTree = ""; }; BF5862001F625D0F00B406F6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/CameraView.strings; sourceTree = ""; }; BF5862021F625D1200B406F6 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/CameraView.strings"; sourceTree = ""; }; C40665431C73A47C00EB9751 /* SingleImageSaver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleImageSaver.swift; sourceTree = ""; }; @@ -157,6 +174,8 @@ E3669CC41F96848D00CCDD01 /* CameraViewController.xib */, FA7E6B9A1B429012000E1B14 /* CropViewController.swift */, BF5861F61F613FB800B406F6 /* CropViewController.xib */, + B2357AB01FA50D51003F9ACF /* FilterViewController.swift */, + B2357AAF1FA50D51003F9ACF /* FilterViewController.xib */, E35A240E1F50B49A001047FD /* ConfirmViewController.swift */, BF5861FB1F61404C00B406F6 /* ConfirmViewController.xib */, ); @@ -180,6 +199,10 @@ children = ( E33BE71B1F5134C1005842DC /* CIImage+Utilities.m */, E33BE71C1F5134C1005842DC /* CIImage+Utilities.h */, + B2357AB81FA51156003F9ACF /* UIImage+Filter.h */, + B2357AB71FA51156003F9ACF /* UIImage+Filter.m */, + B2357AB51FA51155003F9ACF /* UIImageView+Filter.h */, + B2357AB61FA51155003F9ACF /* UIImageView+Filter.m */, FAB50BF01B413E8C009905B9 /* ImageFetcher.swift */, C40665431C73A47C00EB9751 /* SingleImageSaver.swift */, C40665471C73B72D00EB9751 /* SingleImageFetcher.swift */, @@ -257,9 +280,12 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + B2357ABB1FA5115C003F9ACF /* UIImage+Filter.h in Headers */, E33BE7271F546920005842DC /* IRLRectangleFeature+Extensions.h in Headers */, E33BE71F1F5134C1005842DC /* CIImage+Utilities.h in Headers */, + B2357ABF1FA511DC003F9ACF /* CameraViewController-Bridging-Header.h in Headers */, E33BE72E1F5494EC005842DC /* CameraViewController.h in Headers */, + B2357ABD1FA5115C003F9ACF /* UIImageView+Filter.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -353,6 +379,7 @@ E3669CC21F96848D00CCDD01 /* CameraViewController.xib in Resources */, BF5861F91F61404C00B406F6 /* ConfirmViewController.xib in Resources */, C482A0151CAEB1B100541D08 /* CameraViewAssets.xcassets in Resources */, + B2357AB41FA50E13003F9ACF /* FilterViewController.xib in Resources */, BF5861F41F613FB800B406F6 /* CropViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -368,6 +395,7 @@ FAF0584C1B31618D008E5592 /* Images.xcassets in Resources */, FA778A411B8319D8005807E7 /* image.jpg in Resources */, BF5861F31F613FB800B406F6 /* CropViewController.xib in Resources */, + B2357AB11FA50D51003F9ACF /* FilterViewController.xib in Resources */, BF5861F81F61404C00B406F6 /* ConfirmViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -390,6 +418,7 @@ E35A240A1F509FBD001047FD /* CGRectExtensions.swift in Sources */, E33BE7291F546920005842DC /* IRLRectangleFeature+Extensions.m in Sources */, C482A0081CAEB18D00541D08 /* CameraGlobals.swift in Sources */, + B2357ABC1FA5115C003F9ACF /* UIImage+Filter.m in Sources */, C482A0091CAEB18D00541D08 /* VolumeControl.swift in Sources */, C482A00A1CAEB18D00541D08 /* PhotoLibraryAuthorizer.swift in Sources */, E35A24071F509CDC001047FD /* OverlayView.swift in Sources */, @@ -397,8 +426,10 @@ C482A00B1CAEB18D00541D08 /* UIButtonExtensions.swift in Sources */, C482A00C1CAEB18D00541D08 /* PhotoLibraryViewController.swift in Sources */, C482A00D1CAEB18D00541D08 /* CameraViewController.swift in Sources */, + B2357AB31FA50E13003F9ACF /* FilterViewController.swift in Sources */, C482A00E1CAEB18D00541D08 /* CropViewController.swift in Sources */, C482A00F1CAEB18D00541D08 /* ImageCell.swift in Sources */, + B2357ABE1FA5115C003F9ACF /* UIImageView+Filter.m in Sources */, C482A0101CAEB18D00541D08 /* PermissionsView.swift in Sources */, C482A0111CAEB18D00541D08 /* CameraView.swift in Sources */, C482A0121CAEB18D00541D08 /* CropOverlay.swift in Sources */, @@ -414,10 +445,12 @@ E35A240F1F50B49A001047FD /* ConfirmViewController.swift in Sources */, FA5FA3431B3AFA2B00497C62 /* PermissionsView.swift in Sources */, FAB50BFC1B413E8C009905B9 /* ImageFetcher.swift in Sources */, + B2357ABA1FA51156003F9ACF /* UIImage+Filter.m in Sources */, E35A24091F509FBD001047FD /* CGRectExtensions.swift in Sources */, FA82313A1B3C296C00A837BE /* Utilities.swift in Sources */, FAB50C001B413E8C009905B9 /* PhotoLibraryViewController.swift in Sources */, E33BE7281F546920005842DC /* IRLRectangleFeature+Extensions.m in Sources */, + B2357AB91FA51156003F9ACF /* UIImageView+Filter.m in Sources */, FAF0586A1B317894008E5592 /* CameraShot.swift in Sources */, E35A240C1F509FFC001047FD /* CGPointExtensions.swift in Sources */, FAF058661B316695008E5592 /* CameraViewController.swift in Sources */, @@ -429,6 +462,7 @@ FAF058471B31618D008E5592 /* ViewController.swift in Sources */, FAF058681B3175C5008E5592 /* CameraView.swift in Sources */, C4D9BA471CA73163004F70F7 /* UIButtonExtensions.swift in Sources */, + B2357AB21FA50D51003F9ACF /* FilterViewController.swift in Sources */, C40665461C73A94100EB9751 /* CameraGlobals.swift in Sources */, FAF058451B31618D008E5592 /* AppDelegate.swift in Sources */, C40665441C73A47C00EB9751 /* SingleImageSaver.swift in Sources */, diff --git a/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Contents.json new file mode 100644 index 00000000..466a19fe --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Line.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Line.pdf b/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Line.pdf new file mode 100644 index 00000000..72e0398b Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/Line.imageset/Line.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/Contents.json new file mode 100644 index 00000000..cb72ff4c --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bwFilterHighlight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/bwFilterHighlight.pdf b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/bwFilterHighlight.pdf new file mode 100644 index 00000000..c1808348 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterHighlight.imageset/bwFilterHighlight.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/Contents.json new file mode 100644 index 00000000..ee1b44a5 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bwFilterNormal.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/bwFilterNormal.pdf b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/bwFilterNormal.pdf new file mode 100644 index 00000000..3787d9df Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/bwFilterNormal.imageset/bwFilterNormal.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/Contents.json new file mode 100644 index 00000000..db990789 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "colorFilterHighlight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/colorFilterHighlight.pdf b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/colorFilterHighlight.pdf new file mode 100644 index 00000000..c7086502 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterHighlight.imageset/colorFilterHighlight.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/Contents.json new file mode 100644 index 00000000..3d9f66d1 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "colorFilterNormal.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/colorFilterNormal.pdf b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/colorFilterNormal.pdf new file mode 100644 index 00000000..833ee342 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/colorFilterNormal.imageset/colorFilterNormal.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/Contents.json new file mode 100644 index 00000000..7236b7bb --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "exposureFilterHighlight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/exposureFilterHighlight.pdf b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/exposureFilterHighlight.pdf new file mode 100644 index 00000000..f8bcb778 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterHighlight.imageset/exposureFilterHighlight.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/Contents.json new file mode 100644 index 00000000..c0836b1c --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "exposureFilterNormal.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/exposureFilterNormal.pdf b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/exposureFilterNormal.pdf new file mode 100644 index 00000000..f81e16cb Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/exposureFilterNormal.imageset/exposureFilterNormal.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/Contents.json new file mode 100644 index 00000000..6e430e87 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "grayFilterHighlight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/grayFilterHighlight.pdf b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/grayFilterHighlight.pdf new file mode 100644 index 00000000..91c0ed1e Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterHighlight.imageset/grayFilterHighlight.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/Contents.json new file mode 100644 index 00000000..fe30d28f --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "grayFilterNormal.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/grayFilterNormal.pdf b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/grayFilterNormal.pdf new file mode 100644 index 00000000..9eeda26e Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/grayFilterNormal.imageset/grayFilterNormal.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/Contents.json new file mode 100644 index 00000000..dc0cae75 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "originalFilterHighlight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/originalFilterHighlight.pdf b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/originalFilterHighlight.pdf new file mode 100644 index 00000000..a842f531 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterHighlight.imageset/originalFilterHighlight.pdf differ diff --git a/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/Contents.json b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/Contents.json new file mode 100644 index 00000000..19119a71 --- /dev/null +++ b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "originalFilterNormal.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/originalFilterNormal.pdf b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/originalFilterNormal.pdf new file mode 100644 index 00000000..247b5054 Binary files /dev/null and b/ALCameraViewController/CameraViewAssets.xcassets/originalFilterNormal.imageset/originalFilterNormal.pdf differ diff --git a/ALCameraViewController/Utilities/UIImage+Filter.h b/ALCameraViewController/Utilities/UIImage+Filter.h new file mode 100755 index 00000000..0da00061 --- /dev/null +++ b/ALCameraViewController/Utilities/UIImage+Filter.h @@ -0,0 +1,45 @@ +// +// UIImage+Filter.h +// Updates +// +// Created by Nebojsa Petrovic on 4/16/13. +// Copyright (c) 2013 Nebojsa Petrovic. All rights reserved. +// + +#import + +typedef enum { + ImageFilterPresetOriginal = 0, + ImageFilterPresetBlackAndWhite, + ImageFilterPresetEnhanceColor, + ImageFilterPresetEnhanceExposure, + ImageFilterPresetGrayScale +} ImageFilterPreset; + +@interface UIImage (Filter) + +/* + Asynchronously applies 'filter' to the target image and + returns the filtered image in the block. + The target image remains unchanged. + */ +- (void)applyFilter:(CIFilter *)filter + completion:(void (^)(UIImage *filteredImage))completionBlock; + +/* + Returns a UIImage from the filter. + */ +- (UIImage *)imageWithFilter:(CIFilter *)filter; + +/* + Returns a UIImage from a filter preset + */ +- (UIImage *)imageWithFilterPreset:(ImageFilterPreset)preset intensity:(float)intensity; + +/* + Returns a filter using a common preset, and intensity value, ranging from 0 to 1 + */ +- (CIFilter *)filterWithPreset:(ImageFilterPreset)preset; +- (CIFilter *)filterWithPreset:(ImageFilterPreset)preset intensity:(float)intensity; + +@end diff --git a/ALCameraViewController/Utilities/UIImage+Filter.m b/ALCameraViewController/Utilities/UIImage+Filter.m new file mode 100755 index 00000000..094fe45f --- /dev/null +++ b/ALCameraViewController/Utilities/UIImage+Filter.m @@ -0,0 +1,241 @@ +// +// UIImage+Filter.m +// Updates +// +// Created by Nebojsa Petrovic on 4/16/13. +// Copyright (c) 2013 Nebojsa Petrovic. All rights reserved. +// + +#import "UIImage+Filter.h" + +@interface ValueRange : NSObject + +@property(nonatomic) float low; +@property(nonatomic) float high; + +- (id)initWithLow:(float)low high:(float)high; +- (NSNumber*)valueWithIntensity:(float)intensity; ++ (id)valueWithLow:(float)low high:(float)high; + +@end + + +@implementation ValueRange + ++ (id)valueWithLow:(float)low high:(float)high { + return [[self alloc] initWithLow:low high:high]; +} + +- (id)initWithLow:(float)low high:(float)high { + if ( self = [super init] ) { + self.low = low; + self.high = high; + } + + return self; +} + +- (NSNumber*)valueWithIntensity:(float)intensity { + return [NSNumber numberWithFloat:self.low + (self.high-self.low)*intensity]; +} +@end + + +@implementation UIImage (Filter) + +- (void)applyFilter:(CIFilter *)filter + completion:(void (^)(UIImage *filteredImage))completionBlock { + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + CIContext *context = [CIContext contextWithOptions:nil]; + CIImage *outputImage = filter.outputImage; + CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; + UIImage *newImg = [UIImage imageWithCGImage:cgimg]; + CGImageRelease(cgimg); + + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(newImg); + }); + }); + +} + +- (UIImage *)imageWithFilter:(CIFilter *)filter { + CIContext *context = [CIContext contextWithOptions:nil]; + CIImage *outputImage = filter.outputImage; + CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; + UIImage *newImg = [UIImage imageWithCGImage:cgimg]; + CGImageRelease(cgimg); + return newImg; +} + +- (UIImage *)imageWithFilterPreset:(ImageFilterPreset)preset { + return [self imageWithFilterPreset:preset intensity:0.3]; +} + +- (UIImage *)imageWithFilterPreset:(ImageFilterPreset)preset intensity:(float)intensity{ + if (preset == ImageFilterPresetOriginal) { + return self; + } + + return [self imageWithFilter:[self filterWithPreset:preset intensity:intensity]]; +} + +- (CIFilter *)filterWithPreset:(ImageFilterPreset)preset { + return [self filterWithPreset:preset intensity:0.3]; +} + +- (CIFilter *)filterWithPreset:(ImageFilterPreset)preset intensity:(float)intensity { + CIImage *image = [CIImage imageWithCGImage:self.CGImage]; + CIFilter *filter = nil; + + switch (preset) { + case ImageFilterPresetBlackAndWhite: { + CIFilter* colorControl = [CIFilter filterWithName:@"CIColorControls" + keysAndValues:kCIInputImageKey, image, nil]; + [self setValueForPreset:preset filter:colorControl intensity:intensity]; + + + CIFilter* sharpMask = [CIFilter filterWithName:@"CIUnsharpMask" + keysAndValues:kCIInputImageKey, colorControl.outputImage, nil]; + [self setValueForPreset:preset filter:sharpMask intensity:intensity]; + + filter = [CIFilter filterWithName:@"CIExposureAdjust" + keysAndValues:kCIInputImageKey, sharpMask.outputImage, nil]; + [self setValueForPreset:preset filter:filter intensity:intensity]; + + } + break; + case ImageFilterPresetGrayScale: { + CIFilter* unsharpMask = [CIFilter filterWithName:@"CIUnsharpMask" + keysAndValues:kCIInputImageKey, image, nil]; + [self setValueForPreset:preset filter:unsharpMask intensity:intensity]; + + filter = [CIFilter filterWithName:@"CIColorControls" + keysAndValues:kCIInputImageKey, unsharpMask.outputImage, nil]; + [self setValueForPreset:preset filter:filter intensity:intensity]; + + + } + break; + case ImageFilterPresetEnhanceColor: { + CIFilter* colorControl = [CIFilter filterWithName:@"CIColorControls" + keysAndValues:kCIInputImageKey, image, nil]; + [self setValueForPreset:preset filter:colorControl intensity:intensity]; + + + filter = [CIFilter filterWithName:@"CIUnsharpMask" + keysAndValues:kCIInputImageKey, colorControl.outputImage, nil]; + [self setValueForPreset:preset filter:filter intensity:intensity]; + + } + break; + case ImageFilterPresetEnhanceExposure: { + CIFilter* exposure = [CIFilter filterWithName:@"CIExposureAdjust" + keysAndValues:kCIInputImageKey, image, nil]; + [self setValueForPreset:preset filter:exposure intensity:intensity]; + + CIFilter* gamma = [CIFilter filterWithName:@"CIGammaAdjust" + keysAndValues:kCIInputImageKey, exposure.outputImage, nil]; + [self setValueForPreset:preset filter:gamma intensity:intensity]; + + + + CIFilter* noiseReduction = [CIFilter filterWithName:@"CINoiseReduction" + keysAndValues:kCIInputImageKey, gamma.outputImage, nil]; + [self setValueForPreset:preset filter:noiseReduction intensity:intensity]; + + + filter = [CIFilter filterWithName:@"CIColorControls" + keysAndValues:kCIInputImageKey, noiseReduction.outputImage, nil]; + [self setValueForPreset:preset filter:filter intensity:intensity]; + + } + break; + default: + break; + } + + return filter; +} + ++(NSDictionary*)presetParameters { + static NSDictionary *inst = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + inst = @{ + @(ImageFilterPresetEnhanceExposure): @{ @"CIExposureAdjust" : @{ + @"inputEV": [ValueRange valueWithLow:0 high:5] + }, + @"CIGammaAdjust": @{ + @"inputPower": [ValueRange valueWithLow:1 high:0.7] + } , + @"CINoiseReduction": @{ + @"inputNoiseLevel": [ValueRange valueWithLow:0 high:0.01], + @"inputSharpness": [ValueRange valueWithLow:0.3 high:1.1] + }, + @"CIColorControls": @{ + @"inputSaturation": [ValueRange valueWithLow:1 high:1], + @"inputBrightness": [ValueRange valueWithLow:0 high:0], + @"inputContrast": [ValueRange valueWithLow:1 high:1.3] + } + }, + @(ImageFilterPresetEnhanceColor): @{ @"CIColorControls" : @{ + @"inputSaturation": [ValueRange valueWithLow:1 high:1.9], + @"inputBrightness": [ValueRange valueWithLow:0 high:0.1], + @"inputContrast": [ValueRange valueWithLow:1 high:1.2] + }, + @"CIUnsharpMask": @{ + @"inputRadius": [ValueRange valueWithLow:0 high:2.5], + @"inputIntensity": [ValueRange valueWithLow:0 high:0.5] + } + }, + @(ImageFilterPresetGrayScale): @{ @"CIColorControls" : @{ + @"inputSaturation": [ValueRange valueWithLow:1 high:0], + @"inputBrightness": [ValueRange valueWithLow:0 high:0], + @"inputContrast": [ValueRange valueWithLow:1 high:1] + }, + @"CIUnsharpMask": @{ + @"inputRadius": [ValueRange valueWithLow:0 high:2.5], + @"inputIntensity": [ValueRange valueWithLow:0 high:0.15] + } + }, + @(ImageFilterPresetBlackAndWhite): @{ @"CIExposureAdjust" : @{ + @"inputEV": [ValueRange valueWithLow:0 high:2.3] + }, + @"CIUnsharpMask" : @{ + @"inputRadius": [ValueRange valueWithLow:0 high:75.0], + @"inputIntensity": [ValueRange valueWithLow:0 high:2.0] + }, + @"CIColorControls": @{ + @"inputSaturation": [ValueRange valueWithLow:1 high:0], + @"inputBrightness": [ValueRange valueWithLow:0 high:0.15], + @"inputContrast": [ValueRange valueWithLow:1 high:1.3] + } + } + }; + }); + return inst; +} + +-(void)setValueForPreset:(ImageFilterPreset)preset filter:(CIFilter*)filter intensity:(float)intensity{ + NSDictionary* presetDict = [[[self class] presetParameters] objectForKey:@(preset)]; + + NSDictionary *subDict = presetDict[[filter name]]; + + for (NSString* key in [subDict allKeys]) { + ValueRange *value = subDict[key]; + [filter setValue:[value valueWithIntensity:intensity] forKey:key]; + } + +} + +@end + + + + + + + + diff --git a/ALCameraViewController/Utilities/UIImageView+Filter.h b/ALCameraViewController/Utilities/UIImageView+Filter.h new file mode 100755 index 00000000..ec34f46a --- /dev/null +++ b/ALCameraViewController/Utilities/UIImageView+Filter.h @@ -0,0 +1,65 @@ +// +// UIImageView+Filter.h +// Updates +// +// Created by Nebojsa Petrovic on 4/14/13. +// Copyright (c) 2013 Nebojsa Petrovic. All rights reserved. +// + +#import +#import "UIImage+Filter.h" + +@interface UIImageView (Filter) + +/* + Apply 'filter' to the image view's image. + The filter application can be animated with custom duration + and options. + When the filter has finished being applied, the completionBlock is called. + */ +- (void)applyFilter:(CIFilter *)filter + animationDuration:(NSTimeInterval)animationDuration + animationOptions:(UIViewAnimationOptions)animationOptions + completion:(void (^)(void))completionBlock; +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + animationDuration:(NSTimeInterval)animationDuration + animationOptions:(UIViewAnimationOptions)animationOptions + completion:(void (^)(void))completionBlock; + +/* + Apply 'filter' to the image view's image. + If 'animated' is YES, the filter application is animated + with a cross-disolve effect for a duration of 0.3 seconds. + When the filter has finished being applied, the completionBlock is called. + */ +- (void)applyFilter:(CIFilter *)filter + animated:(BOOL)animated + completion:(void (^)(void))completionBlock; +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + animated:(BOOL)animated + completion:(void (^)(void))completionBlock; + +/* + Apply 'filter' to the image view's image without animation. + When the filter has finished being applied, the completionBlock is called. + */ +- (void)applyFilter:(CIFilter *)filter + completion:(void (^)(void))completionBlock; +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + completion:(void (^)(void))completionBlock; + +/* + Apply 'filter' to the image view's image without animation. + */ +- (void)applyFilter:(CIFilter *)filter; +- (void)applyFilterWithPreset:(ImageFilterPreset)preset intensity:(float)intensity; + +/* + Remove any filters applied. This bring back the original image. + */ +- (void)removeFilter; + +@end diff --git a/ALCameraViewController/Utilities/UIImageView+Filter.m b/ALCameraViewController/Utilities/UIImageView+Filter.m new file mode 100755 index 00000000..6c8655cb --- /dev/null +++ b/ALCameraViewController/Utilities/UIImageView+Filter.m @@ -0,0 +1,129 @@ +// +// UIImageView+Filter.m +// Updates +// +// Created by Nebojsa Petrovic on 4/14/13. +// Copyright (c) 2013 Nebojsa Petrovic. All rights reserved. +// + +#import "UIImageView+Filter.h" +#import + +// Arbitrary tag so that we can identify filtered images. +// Otherwise we risk removing a custom subview that isn't a filter. +#define IMAGE_FILTER_TAG 123454321 + +@implementation UIImageView (Filter) + +- (void)applyFilter:(CIFilter *)filter + animationDuration:(NSTimeInterval)animationDuration + animationOptions:(UIViewAnimationOptions)animationOptions + completion:(void (^)(void))completionBlock { + + [self.image applyFilter:filter completion:^(UIImage *filteredImage) { + // Remove any previous filters + [self removeFilter]; + + // Add the filtered image on top of the original image. + UIImageView *filteredImageView = [[UIImageView alloc] initWithFrame:self.bounds]; + filteredImageView.tag = IMAGE_FILTER_TAG; + filteredImageView.contentMode = self.contentMode; + [self addSubview:filteredImageView]; + + // No animation + if (animationDuration == 0.0f) { + filteredImageView.image = filteredImage; + if (completionBlock) { + completionBlock(); + } + return; + } + + // Animation + [UIView transitionWithView:self + duration:animationDuration + options:animationOptions + animations:^{ + filteredImageView.image = filteredImage; + } completion:^(BOOL finished) { + if (completionBlock) { + completionBlock(); + } + }]; + }]; +} + +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + animationDuration:(NSTimeInterval)animationDuration + animationOptions:(UIViewAnimationOptions)animationOptions + completion:(void (^)(void))completionBlock { + CIFilter *filter = [self.image filterWithPreset:preset]; + [self applyFilter:filter + animationDuration:animationDuration + animationOptions:animationOptions + completion:completionBlock]; +} + +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + animationDuration:(NSTimeInterval)animationDuration + animationOptions:(UIViewAnimationOptions)animationOptions + completion:(void (^)(void))completionBlock { + CIFilter *filter = [self.image filterWithPreset:preset intensity:intensity]; + [self applyFilter:filter + animationDuration:animationDuration + animationOptions:animationOptions + completion:completionBlock]; +} + +- (void)applyFilter:(CIFilter *)filter + animated:(BOOL)animated + completion:(void (^)(void))completionBlock { + [self applyFilter:filter + animationDuration:animated ? 0.3f : 0.0f + animationOptions:UIViewAnimationOptionTransitionCrossDissolve + completion:completionBlock]; +} + +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + animated:(BOOL)animated + completion:(void (^)(void))completionBlock { + CIFilter *filter = [self.image filterWithPreset:preset intensity:intensity]; + [self applyFilter:filter + animated:animated + completion:completionBlock]; +} + +- (void)applyFilter:(CIFilter *)filter + completion:(void (^)(void))completionBlock { + [self applyFilter:filter animated:NO completion:completionBlock]; +} + +- (void)applyFilterWithPreset:(ImageFilterPreset)preset + intensity:(float)intensity + completion:(void (^)(void))completionBlock { + CIFilter *filter = [self.image filterWithPreset:preset intensity:intensity]; + [self applyFilter:filter + completion:completionBlock]; +} + +- (void)applyFilter:(CIFilter *)filter { + [self applyFilter:filter completion:nil]; +} + +- (void)applyFilterWithPreset:(ImageFilterPreset)preset intensity:(float)intensity{ + CIFilter *filter = [self.image filterWithPreset:preset intensity:intensity]; + [self applyFilter:filter]; +} + +- (void)removeFilter { + for (UIView *subview in self.subviews) { + if ([subview isKindOfClass:[UIImageView class]] && + subview.tag == IMAGE_FILTER_TAG) { + [subview removeFromSuperview]; + } + } +} + +@end diff --git a/ALCameraViewController/ViewController/CropViewController.swift b/ALCameraViewController/ViewController/CropViewController.swift index 0b3855ff..57c0dbb8 100644 --- a/ALCameraViewController/ViewController/CropViewController.swift +++ b/ALCameraViewController/ViewController/CropViewController.swift @@ -395,17 +395,9 @@ public class CropViewController: UIViewController, UIScrollViewDelegate { private func startConfimController(uiImage: UIImage) { - let confirmController = ConfirmViewController(uiImage, asset) - confirmController.onComplete = { [weak self] image, asset in - guard let image = image else { - return - } - - self?.onComplete?(image, asset) - self?.onComplete = nil - } - - self.navigationController?.pushViewController(confirmController, animated: false) + let filterController = FilterViewController(uiImage, asset) + filterController.onComplete = onComplete + self.navigationController?.pushViewController(filterController, animated: false) } } diff --git a/ALCameraViewController/ViewController/FilterViewController.swift b/ALCameraViewController/ViewController/FilterViewController.swift new file mode 100644 index 00000000..3c573911 --- /dev/null +++ b/ALCameraViewController/ViewController/FilterViewController.swift @@ -0,0 +1,144 @@ +// +// FilterViewController.swift +// ALCameraViewController +// +// Created by Narek Simonyan on 10/28/17. +// Copyright © 2017 zero. All rights reserved. +// + +import UIKit +import Photos + +class FilterViewController: UIViewController { + + @IBOutlet var filterView: UIView! + + @IBOutlet var doneButton: UIButton! + @IBOutlet var backButton: UIButton! + @IBOutlet var imageView: UIImageView! + @IBOutlet var grayFilter: UIButton! + @IBOutlet var colorFilter: UIButton! + @IBOutlet var exposureFilter: UIButton! + @IBOutlet var bwFilter: UIButton! + @IBOutlet var filterIntensitySlider: UISlider! + + let image: UIImage? + let asset: PHAsset? + + var filterType:ImageFilterPreset? { + didSet { + apply() + } + } + var filterIntensity: Float = 0.3 { + didSet { + apply() + } + } + + public var onComplete: CameraViewCompletion? + + public override var prefersStatusBarHidden: Bool { + return true + } + + public override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { + return UIStatusBarAnimation.slide + } + + open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + return .portrait + } + + public init(_ image: UIImage?, _ asset: PHAsset?) { + self.image = image + self.asset = asset + super.init(nibName: "FilterViewController", bundle: CameraGlobals.shared.bundle) + } + + public required init?(coder aDecoder: NSCoder) { + image = nil + asset = nil + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + super.viewDidLoad() + + imageView.image = image + + setupButtonActions() + } + + internal func setupButtonActions() { + + backButton.action = {[weak self] in self?.navigationController?.popViewController(animated: false)} + doneButton.action = { [weak self] in self?.confirmPhoto() } + grayFilter.action = { [weak self] in + guard let strongSelf = self else {return} + strongSelf.applyFilter(sender: strongSelf.grayFilter) + } + colorFilter.action = { [weak self] in + guard let strongSelf = self else {return} + strongSelf.applyFilter(sender: strongSelf.colorFilter)} + exposureFilter.action = { [weak self] in + guard let strongSelf = self else {return} + strongSelf.applyFilter(sender: strongSelf.exposureFilter) + } + bwFilter.action = { [weak self] in + guard let strongSelf = self else {return} + strongSelf.applyFilter(sender: strongSelf.bwFilter) + } + } + + internal func confirmPhoto() { + + guard let image = imageView.image else { + return + } + let confirmController = ConfirmViewController(image, asset) + + confirmController.onComplete = { [weak self] image, asset in + guard let image = image else { + return + } + + self?.onComplete?(image, asset) + self?.onComplete = nil + } + + self.navigationController?.pushViewController(confirmController, animated: false) + } + + internal func applyFilter (sender: UIButton) { + + let dictionary = [grayFilter:ImageFilterPresetGrayScale, + bwFilter:ImageFilterPresetBlackAndWhite, + exposureFilter:ImageFilterPresetEnhanceExposure, + colorFilter:ImageFilterPresetEnhanceColor] + + guard let filter = dictionary[sender] else { + return + } + + _ = [grayFilter,colorFilter,exposureFilter,bwFilter].map({$0?.isSelected = false}) + sender.isSelected = true + filterType = filter + } + + internal func apply() { + + guard let filterType = filterType, let filter = imageView.image?.filter(with: filterType, intensity: filterIntensity) else { + return + } + imageView.image?.apply(filter, completion: { (image) in + DispatchQueue.main.async { [weak self] in + self?.imageView.image = image + } + }) + } + + @IBAction func filterIntensityChanged(_ sender: UISlider) { + filterIntensity = sender.value + } +} diff --git a/ALCameraViewController/ViewController/FilterViewController.xib b/ALCameraViewController/ViewController/FilterViewController.xib new file mode 100644 index 00000000..fc92acbb --- /dev/null +++ b/ALCameraViewController/ViewController/FilterViewController.xib @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CameraViewController/CameraViewController-Bridging-Header.h b/CameraViewController/CameraViewController-Bridging-Header.h index 3e5d816f..a3feef8d 100644 --- a/CameraViewController/CameraViewController-Bridging-Header.h +++ b/CameraViewController/CameraViewController-Bridging-Header.h @@ -2,6 +2,7 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // - +#import "UIImage+Filter.h" +#import "UIImageView+Filter.h" #import "CIImage+Utilities.h" #import "IRLRectangleFeature+Extensions.h"