Skip to content

Commit

Permalink
Merge pull request #37 from matej/fixes
Browse files Browse the repository at this point in the history
Added the ability to specify the image resolution and various other fixes an enhancements
  • Loading branch information
dmitric committed Sep 14, 2013
2 parents 9c5ab46 + 81c4be8 commit e69ad62
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 94 deletions.
4 changes: 2 additions & 2 deletions Classes/BlurOverlayView.h → Classes/DLCBlurOverlayView.h
@@ -1,5 +1,5 @@
//
// BlurOverlayView.h
// DLCBlurOverlayView.h
// Backspaces
//
// Created by Dmitri Cherniak on 11/18/12.
Expand All @@ -8,7 +8,7 @@

#import <UIKit/UIKit.h>

@interface BlurOverlayView : UIView
@interface DLCBlurOverlayView : UIView

@property (nonatomic, assign) CGFloat radius;
@property (nonatomic, assign) CGPoint circleCenter;
Expand Down
6 changes: 3 additions & 3 deletions Classes/BlurOverlayView.m → Classes/DLCBlurOverlayView.m
@@ -1,14 +1,14 @@
//
// BlurOverlayView.m
// DLCBlurOverlayView.m
// Backspaces
//
// Created by Dmitri Cherniak on 11/18/12.
// Copyright (c) 2012 DLC Inc. All rights reserved.
//

#import "BlurOverlayView.h"
#import "DLCBlurOverlayView.h"

@implementation BlurOverlayView {
@implementation DLCBlurOverlayView {
CGRect holeRect;
}

Expand Down
Expand Up @@ -4,7 +4,7 @@ extern NSString *const kGrayscaleContrastFragmentShaderString;

/** Converts an image to grayscale (a slightly faster implementation of the saturation filter, without the ability to vary the color contribution)
*/
@interface GrayscaleContrastFilter : GPUImageFilter
@interface DLCGrayscaleContrastFilter : GPUImageFilter
{
GLint intensityUniform;
GLint slopeUniform;
Expand Down
@@ -1,6 +1,6 @@
#import "GrayscaleContrastFilter.h"
#import "DLCGrayscaleContrastFilter.h"

@implementation GrayscaleContrastFilter
@implementation DLCGrayscaleContrastFilter

NSString *const kGrayscaleContrastFragmentShaderString = SHADER_STRING
(
Expand Down
15 changes: 4 additions & 11 deletions Classes/DLCImagePickerController.h
Expand Up @@ -8,7 +8,7 @@

#import <Foundation/Foundation.h>
#import "GPUImage.h"
#import "BlurOverlayView.h"
#import "DLCBlurOverlayView.h"

@class DLCImagePickerController;

Expand All @@ -18,15 +18,7 @@
- (void)imagePickerControllerDidCancel:(DLCImagePickerController *)picker;
@end

@interface DLCImagePickerController : UIViewController <UINavigationControllerDelegate,UIImagePickerControllerDelegate> {
GPUImageStillCamera *stillCamera;
GPUImageOutput<GPUImageInput> *filter;
GPUImageOutput<GPUImageInput> *blurFilter;
GPUImageCropFilter *cropFilter;
GPUImagePicture *staticPicture;
UIImageOrientation staticPictureOriginalOrientation;

}
@interface DLCImagePickerController : UIViewController <UINavigationControllerDelegate,UIImagePickerControllerDelegate>

@property (nonatomic, weak) IBOutlet GPUImageView *imageView;
@property (nonatomic, weak) id <DLCImagePickerDelegate> delegate;
Expand All @@ -44,9 +36,10 @@
@property (nonatomic, weak) IBOutlet UIImageView *filtersBackgroundImageView;
@property (nonatomic, weak) IBOutlet UIView *photoBar;
@property (nonatomic, weak) IBOutlet UIView *topBar;
@property (nonatomic, strong) BlurOverlayView *blurOverlayView;
@property (nonatomic, strong) DLCBlurOverlayView *blurOverlayView;
@property (nonatomic, strong) UIImageView *focusView;

@property (nonatomic, assign) CGFloat outputJPEGQuality;
@property (nonatomic, assign) CGSize requestedImageSize;

@end
149 changes: 106 additions & 43 deletions Classes/DLCImagePickerController.m
Expand Up @@ -7,14 +7,21 @@
//

#import "DLCImagePickerController.h"
#import "GrayscaleContrastFilter.h"
#import "DLCGrayscaleContrastFilter.h"

#define kStaticBlurSize 2.0f

@implementation DLCImagePickerController {
GPUImageStillCamera *stillCamera;
GPUImageOutput<GPUImageInput> *filter;
GPUImageOutput<GPUImageInput> *blurFilter;
GPUImageCropFilter *cropFilter;
GPUImagePicture *staticPicture;
UIImageOrientation staticPictureOriginalOrientation;
BOOL isStatic;
BOOL hasBlur;
int selectedFilter;
dispatch_once_t showLibraryOnceToken;
}

@synthesize delegate,
Expand All @@ -32,20 +39,36 @@ @implementation DLCImagePickerController {
photoBar,
topBar,
blurOverlayView,
outputJPEGQuality;
outputJPEGQuality,
requestedImageSize;

-(id) init {
self = [super initWithNibName:@"DLCImagePicker" bundle:nil];

-(void) sharedInit {
outputJPEGQuality = 1.0;
requestedImageSize = CGSizeZero;
}

-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.outputJPEGQuality = 1.0;
[self sharedInit];
}

return self;
}

- (void)viewDidLoad
{
-(id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self sharedInit];
}
return self;
}

-(id) init {
return [self initWithNibName:@"DLCImagePicker" bundle:nil];
}

-(void)viewDidLoad {

[super viewDidLoad];
self.wantsFullScreenLayout = YES;
//set background color
Expand All @@ -67,9 +90,10 @@ - (void)viewDidLoad
self.focusView.alpha = 0;


self.blurOverlayView = [[BlurOverlayView alloc] initWithFrame:CGRectMake(0, 0,
self.imageView.frame.size.width,
self.imageView.frame.size.height)];
self.blurOverlayView = [[DLCBlurOverlayView alloc] initWithFrame:CGRectMake(0, 0,
self.imageView.frame.size.width,
self.imageView.frame.size.height)];
self.blurOverlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.blurOverlayView.alpha = 0;
[self.imageView addSubview:self.blurOverlayView];

Expand All @@ -92,6 +116,15 @@ -(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}

-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (![UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
dispatch_once(&showLibraryOnceToken, ^{
[self switchToLibrary:nil];
});
}
}

-(void) loadFilters {
for(int i = 0; i < 10; i++) {
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
Expand Down Expand Up @@ -144,9 +177,14 @@ -(void) setUpCamera {
[self prepareFilter];
});
} else {
// No camera
NSLog(@"No camera");
runOnMainQueueWithoutDeadlocking(^{
// No camera awailable, hide camera related buttons and show the image picker
self.cameraToggleButton.hidden = YES;
self.photoCaptureButton.hidden = YES;
self.flashToggleButton.hidden = YES;
// Show the library picker
// [self switchToLibrary:nil];
// [self performSelector:@selector(switchToLibrary:) withObject:nil afterDelay:0.5];
[self prepareFilter];
});
}
Expand Down Expand Up @@ -182,7 +220,7 @@ -(void) setFilter:(int) index {
filter = [[GPUImageToneCurveFilter alloc] initWithACV:@"02"];
} break;
case 4: {
filter = [[GrayscaleContrastFilter alloc] init];
filter = [[DLCGrayscaleContrastFilter alloc] init];
} break;
case 5: {
filter = [[GPUImageToneCurveFilter alloc] initWithACV:@"17"];
Expand Down Expand Up @@ -236,11 +274,6 @@ -(void) prepareLiveFilter {

-(void) prepareStaticFilter {

if (!staticPicture) {
// TODO: fix this hack
[self performSelector:@selector(switchToLibrary:) withObject:nil afterDelay:0.5];
}

[staticPicture addTarget:filter];

// blur is terminal filter
Expand Down Expand Up @@ -272,7 +305,7 @@ -(void) prepareStaticFilter {
[self.imageView setInputRotation:imageViewRotationMode atIndex:0];


[staticPicture processImage];
[staticPicture processImage];
}

-(void) removeAllTargets {
Expand Down Expand Up @@ -324,6 +357,9 @@ -(IBAction) toggleBlur:(UIButton*)blurButton {
[(GPUImageGaussianSelectiveBlurFilter*)blurFilter setAspectRatio:1.0f];
}
hasBlur = YES;
CGPoint excludePoint = [(GPUImageGaussianSelectiveBlurFilter*)blurFilter excludeCirclePoint];
CGSize frameSize = self.blurOverlayView.frame.size;
self.blurOverlayView.circleCenter = CGPointMake(excludePoint.x * frameSize.width, excludePoint.y * frameSize.height);
[self.blurToggleButton setSelected:YES];
[self flashBlurOverlay];
}
Expand Down Expand Up @@ -362,23 +398,53 @@ -(void) prepareForCapture {


-(void)captureImage {
UIImage *img = [cropFilter imageFromCurrentlyProcessedOutput];
[stillCamera.inputCamera unlockForConfiguration];
[stillCamera stopCameraCapture];
[self removeAllTargets];

staticPicture = [[GPUImagePicture alloc] initWithImage:img
smoothlyScaleOutput:YES];
void (^completion)(UIImage *, NSError *) = ^(UIImage *img, NSError *error) {

[stillCamera.inputCamera unlockForConfiguration];
[stillCamera stopCameraCapture];
[self removeAllTargets];

staticPicture = [[GPUImagePicture alloc] initWithImage:img smoothlyScaleOutput:NO];
staticPictureOriginalOrientation = img.imageOrientation;

[self prepareFilter];
[self.retakeButton setHidden:NO];
[self.photoCaptureButton setTitle:@"Done" forState:UIControlStateNormal];
[self.photoCaptureButton setImage:nil forState:UIControlStateNormal];
[self.photoCaptureButton setEnabled:YES];
if(![self.filtersToggleButton isSelected]){
[self showFilters];
}
};

staticPictureOriginalOrientation = img.imageOrientation;

[self prepareFilter];
[self.retakeButton setHidden:NO];
[self.photoCaptureButton setTitle:@"Done" forState:UIControlStateNormal];
[self.photoCaptureButton setImage:nil forState:UIControlStateNormal];
[self.photoCaptureButton setEnabled:YES];
if(![self.filtersToggleButton isSelected]){
[self showFilters];
AVCaptureDevicePosition currentCameraPosition = stillCamera.inputCamera.position;
Class contextClass = NSClassFromString(@"GPUImageContext") ?: NSClassFromString(@"GPUImageOpenGLESContext");
if ((currentCameraPosition != AVCaptureDevicePositionFront) || (![contextClass supportsFastTextureUpload])) {
// Image full-resolution capture is currently possible just on the final (destination filter), so
// create a new paralel chain, that crops and resizes our image
[self removeAllTargets];

GPUImageCropFilter *captureCrop = [[GPUImageCropFilter alloc] initWithCropRegion:cropFilter.cropRegion];
[stillCamera addTarget:captureCrop];
GPUImageFilter *finalFilter = captureCrop;

if (!CGSizeEqualToSize(requestedImageSize, CGSizeZero)) {
GPUImageFilter *captureResize = [[GPUImageFilter alloc] init];
[captureResize forceProcessingAtSize:requestedImageSize];
[captureCrop addTarget:captureResize];
finalFilter = captureResize;
}

[finalFilter prepareForImageCapture];

[stillCamera capturePhotoAsImageProcessedUpToFilter:finalFilter withCompletionHandler:completion];
} else {
// A workaround inside capturePhotoProcessedUpToFilter:withImageOnGPUHandler: would cause the above method to fail,
// so we just grap the current crop filter output as an aproximation (the size won't match trough)
UIImage *img = [cropFilter imageFromCurrentlyProcessedOutput];
completion(img, nil);
}
}

Expand Down Expand Up @@ -560,7 +626,7 @@ -(void) showFilters {
self.filtersBackgroundImageView.hidden = NO;
[UIView animateWithDuration:0.10
delay:0.05
options: UIViewAnimationCurveEaseOut
options: UIViewAnimationOptionCurveEaseOut
animations:^{
self.imageView.frame = imageRect;
self.filterScrollView.frame = sliderScrollFrame;
Expand All @@ -583,7 +649,7 @@ -(void) hideFilters {

[UIView animateWithDuration:0.10
delay:0.05
options: UIViewAnimationCurveEaseOut
options: UIViewAnimationOptionCurveEaseOut
animations:^{
self.imageView.frame = imageRect;
self.filterScrollView.frame = sliderScrollFrame;
Expand Down Expand Up @@ -670,6 +736,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
[self.cameraToggleButton setEnabled:NO];
[self.flashToggleButton setEnabled:NO];
[self prepareStaticFilter];
[self.photoCaptureButton setHidden:NO];
[self.photoCaptureButton setTitle:@"Done" forState:UIControlStateNormal];
[self.photoCaptureButton setImage:nil forState:UIControlStateNormal];
[self.photoCaptureButton setEnabled:YES];
Expand All @@ -681,12 +748,8 @@ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPicking
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
if (isStatic) {
// TODO: fix this hack
[self dismissViewControllerAnimated:NO completion:nil];
[self.delegate imagePickerControllerDidCancel:self];
} else {
[self dismissViewControllerAnimated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
if (!isStatic) {
[self retakePhoto:nil];
}
}
Expand Down
34 changes: 34 additions & 0 deletions DLCImagePickerController.podspec
@@ -0,0 +1,34 @@
Pod::Spec.new do |s|
s.name = "DLCImagePickerController"
s.version = "0.0.1"
s.summary = "ImagePickerController with live filters, radial blur and more. Brought to you by the fine ladies and gents at Backspaces."
s.description = <<-DESC
DLCImagePickerController is a fast, beautiful and fun way to filter and capture your photos with OpenGL and your iPhone.
The majority of the praise should be directed towards BradLarson for his GPUImage library.
DESC
s.homepage = "www.backspac.es"
s.license = 'BSD'
s.author = { "Dmitri Cherniak" => "dmitric@gmail.com" }
s.source = { :git => "https://github.com/gobackspaces/DLCImagePickerController.git", :tag => "0.0.1" }
s.platform = :ios, '5.0'
s.requires_arc = true
s.framework = 'AssetsLibrary'

s.subspec 'Core' do |sp|
sp.source_files = 'Classes'
sp.resources = "Images/{UI,Overlays}/*.png"
sp.dependency 'GPUImage'
end

s.subspec 'Filters' do |sp|
sp.resources = "Resources/Filters/*.acv"
end

s.subspec 'UI' do |sp|
sp.resources = "Resources/*.xib"
end

s.subspec 'FilterSamples' do |sp|
sp.resources = "Images/FilterSamples/*.jpg"
end
end

0 comments on commit e69ad62

Please sign in to comment.