Skip to content

Commit

Permalink
Added a crop filter.
Browse files Browse the repository at this point in the history
  • Loading branch information
BradLarson committed Mar 7, 2012
1 parent 248b817 commit 0bdd101
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Expand Up @@ -78,6 +78,9 @@ For example, an application that takes in live video from the camera, converts t

- **GPUImageRotationFilter**: This lets you rotate an image left or right by 90 degrees, or flip it horizontally or vertically

- **GPUImageCropFilter**: This crops an image to a specific region, then passes only that region on to the next stage in the filter
- *cropRegion*: A rectangular area to crop out of the image, normalized to coordinates from 0.0 - 1.0. The (0.0, 0.0) position is in the upper left of the image.

- **GPUImageSharpenFilter**: Sharpens the image
- *sharpness*: The sharpness adjustment to apply (-4.0 - 4.0, with 0.0 as the default)

Expand Down
Expand Up @@ -67,6 +67,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
case GPUIMAGE_EXPOSURE: cell.textLabel.text = @"Exposure"; break;
case GPUIMAGE_SHARPEN: cell.textLabel.text = @"Sharpen"; break;
case GPUIMAGE_GAMMA: cell.textLabel.text = @"Gamma"; break;
case GPUIMAGE_CROP: cell.textLabel.text = @"Crop"; break;
case GPUIMAGE_COLORINVERT: cell.textLabel.text = @"Color invert"; break;
case GPUIMAGE_SEPIA: cell.textLabel.text = @"Sepia tone"; break;
case GPUIMAGE_PIXELLATE: cell.textLabel.text = @"Pixellate"; break;
Expand Down
@@ -1,7 +1,7 @@
#import <UIKit/UIKit.h>
#import "GPUImage.h"

typedef enum { GPUIMAGE_SATURATION, GPUIMAGE_CONTRAST, GPUIMAGE_BRIGHTNESS, GPUIMAGE_EXPOSURE, GPUIMAGE_SHARPEN, GPUIMAGE_GAMMA, GPUIMAGE_SEPIA, GPUIMAGE_COLORINVERT, GPUIMAGE_PIXELLATE, GPUIMAGE_SOBELEDGEDETECTION, GPUIMAGE_SKETCH, GPUIMAGE_TOON, GPUIMAGE_KUWAHARA, GPUIMAGE_VIGNETTE, GPUIMAGE_GAUSSIAN, GPUIMAGE_GAUSSIAN_SELECTIVE, GPUIMAGE_FASTBLUR, GPUIMAGE_SWIRL, GPUIMAGE_DISSOLVE, GPUIMAGE_MULTIPLY, GPUIMAGE_OVERLAY, GPUIMAGE_LIGHTEN, GPUIMAGE_DARKEN, GPUIMAGE_COLORBURN, GPUIMAGE_COLORDODGE, GPUIMAGE_SCREENBLEND, GPUIMAGE_DIFFERENCEBLEND, GPUIMAGE_EXCLUSIONBLEND, GPUIMAGE_HARDLIGHTBLEND, GPUIMAGE_SOFTLIGHTBLEND, GPUIMAGE_CUSTOM, GPUIMAGE_FILECONFIG, GPUIMAGE_NUMFILTERS} GPUImageShowcaseFilterType;
typedef enum { GPUIMAGE_SATURATION, GPUIMAGE_CONTRAST, GPUIMAGE_BRIGHTNESS, GPUIMAGE_EXPOSURE, GPUIMAGE_SHARPEN, GPUIMAGE_CROP, GPUIMAGE_GAMMA, GPUIMAGE_SEPIA, GPUIMAGE_COLORINVERT, GPUIMAGE_PIXELLATE, GPUIMAGE_SOBELEDGEDETECTION, GPUIMAGE_SKETCH, GPUIMAGE_TOON, GPUIMAGE_KUWAHARA, GPUIMAGE_VIGNETTE, GPUIMAGE_GAUSSIAN, GPUIMAGE_GAUSSIAN_SELECTIVE, GPUIMAGE_FASTBLUR, GPUIMAGE_SWIRL, GPUIMAGE_DISSOLVE, GPUIMAGE_MULTIPLY, GPUIMAGE_OVERLAY, GPUIMAGE_LIGHTEN, GPUIMAGE_DARKEN, GPUIMAGE_COLORBURN, GPUIMAGE_COLORDODGE, GPUIMAGE_SCREENBLEND, GPUIMAGE_DIFFERENCEBLEND, GPUIMAGE_EXCLUSIONBLEND, GPUIMAGE_HARDLIGHTBLEND, GPUIMAGE_SOFTLIGHTBLEND, GPUIMAGE_CUSTOM, GPUIMAGE_FILECONFIG, GPUIMAGE_NUMFILTERS} GPUImageShowcaseFilterType;

@interface ShowcaseFilterViewController : UIViewController
{
Expand Down
Expand Up @@ -150,6 +150,17 @@ - (void)setupFilter;

filter = [[GPUImageGammaFilter alloc] init];
}; break;
case GPUIMAGE_CROP:
{
self.title = @"Crop";
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setMinimumValue:0.3];
[self.filterSettingsSlider setMaximumValue:1.0];
[self.filterSettingsSlider setValue:0.5];

filter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.0, 0.0, 0.5, 0.5)];
}; break;
case GPUIMAGE_SOBELEDGEDETECTION:
{
self.title = @"Edge Detection";
Expand Down Expand Up @@ -382,6 +393,7 @@ - (IBAction)updateFilterFromSlider:(id)sender;
case GPUIMAGE_GAUSSIAN: [(GPUImageGaussianBlurFilter *)filter setBlurSize:[(UISlider*)sender value]]; break;
case GPUIMAGE_FASTBLUR: [(GPUImageFastBlurFilter *)filter setBlurPasses:round([(UISlider*)sender value])]; break;
case GPUIMAGE_GAUSSIAN_SELECTIVE: [(GPUImageGaussianSelectiveBlurFilter *)filter setExcludeCircleRadius:[(UISlider*)sender value]]; break;
case GPUIMAGE_CROP: [(GPUImageCropFilter *)filter setCropRegion:CGRectMake(0.0, 0.0, [(UISlider*)sender value], [(UISlider*)sender value])]; break;
default: break;
}
}
Expand Down
Expand Up @@ -62,8 +62,13 @@ - (void)setupImageFilteringToDisk;
UIImage *inputImage = [UIImage imageNamed:@"Lambeau.jpg"];

GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:inputImage];
// GPUImageSepiaFilter *stillImageFilter = [[GPUImageSepiaFilter alloc] init];
GPUImageSketchFilter *stillImageFilter = [[GPUImageSketchFilter alloc] init];
GPUImageSepiaFilter *stillImageFilter = [[GPUImageSepiaFilter alloc] init];
// GPUImageSketchFilter *stillImageFilter = [[GPUImageSketchFilter alloc] init];

// There's a problem with the Kuwahara filter where it doesn't finish rendering before the image is extracted from it.
// It looks like it only gets through certain tiles before glReadPixels() is called. Odd.
// GPUImageKuwaharaFilter *stillImageFilter = [[GPUImageKuwaharaFilter alloc] init];
// stillImageFilter.radius = 9;

[stillImageSource addTarget:stillImageFilter];
[stillImageSource processImage];
Expand Down
8 changes: 8 additions & 0 deletions framework/GPUImage.xcodeproj/project.pbxproj
Expand Up @@ -96,6 +96,8 @@
BCB6B8771504234A0041703B /* GPUImageSoftLightBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6B86F1504234A0041703B /* GPUImageSoftLightBlendFilter.m */; };
BCB6B8BB1505BF940041703B /* GPUImageTextureOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6B8B91505BF940041703B /* GPUImageTextureOutput.h */; };
BCB6B8BC1505BF940041703B /* GPUImageTextureOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6B8BA1505BF940041703B /* GPUImageTextureOutput.m */; };
BCB6B9041507CA8D0041703B /* GPUImageCropFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB6B9021507CA8C0041703B /* GPUImageCropFilter.h */; };
BCB6B9051507CA8D0041703B /* GPUImageCropFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6B9031507CA8C0041703B /* GPUImageCropFilter.m */; };
BCC93A0F1501D1BF00958B26 /* GPUImageFastBlurFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC93A0D1501D1BF00958B26 /* GPUImageFastBlurFilter.h */; };
BCC93A101501D1BF00958B26 /* GPUImageFastBlurFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC93A0E1501D1BF00958B26 /* GPUImageFastBlurFilter.m */; };
BCC93A1E1501E42F00958B26 /* GPUImageTwoPassFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC93A1C1501E42E00958B26 /* GPUImageTwoPassFilter.h */; };
Expand Down Expand Up @@ -216,6 +218,8 @@
BCB6B86F1504234A0041703B /* GPUImageSoftLightBlendFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageSoftLightBlendFilter.m; path = Source/GPUImageSoftLightBlendFilter.m; sourceTree = SOURCE_ROOT; };
BCB6B8B91505BF940041703B /* GPUImageTextureOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageTextureOutput.h; path = Source/GPUImageTextureOutput.h; sourceTree = SOURCE_ROOT; };
BCB6B8BA1505BF940041703B /* GPUImageTextureOutput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageTextureOutput.m; path = Source/GPUImageTextureOutput.m; sourceTree = SOURCE_ROOT; };
BCB6B9021507CA8C0041703B /* GPUImageCropFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageCropFilter.h; path = Source/GPUImageCropFilter.h; sourceTree = SOURCE_ROOT; };
BCB6B9031507CA8C0041703B /* GPUImageCropFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageCropFilter.m; path = Source/GPUImageCropFilter.m; sourceTree = SOURCE_ROOT; };
BCC93A0D1501D1BF00958B26 /* GPUImageFastBlurFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageFastBlurFilter.h; path = Source/GPUImageFastBlurFilter.h; sourceTree = SOURCE_ROOT; };
BCC93A0E1501D1BF00958B26 /* GPUImageFastBlurFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageFastBlurFilter.m; path = Source/GPUImageFastBlurFilter.m; sourceTree = SOURCE_ROOT; };
BCC93A1C1501E42E00958B26 /* GPUImageTwoPassFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageTwoPassFilter.h; path = Source/GPUImageTwoPassFilter.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -391,6 +395,8 @@
children = (
BCB5E85314E63BBB00701302 /* GPUImageRotationFilter.h */,
BCB5E85414E63BBB00701302 /* GPUImageRotationFilter.m */,
BCB6B9021507CA8C0041703B /* GPUImageCropFilter.h */,
BCB6B9031507CA8C0041703B /* GPUImageCropFilter.m */,
BCB6B835150400030041703B /* GPUImageSharpenFilter.h */,
BCB6B836150400030041703B /* GPUImageSharpenFilter.m */,
BCC93A0D1501D1BF00958B26 /* GPUImageFastBlurFilter.h */,
Expand Down Expand Up @@ -536,6 +542,7 @@
BCB6B8741504234A0041703B /* GPUImageHardLightBlendFilter.h in Headers */,
BCB6B8761504234A0041703B /* GPUImageSoftLightBlendFilter.h in Headers */,
BCB6B8BB1505BF940041703B /* GPUImageTextureOutput.h in Headers */,
BCB6B9041507CA8D0041703B /* GPUImageCropFilter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -682,6 +689,7 @@
BCB6B8751504234A0041703B /* GPUImageHardLightBlendFilter.m in Sources */,
BCB6B8771504234A0041703B /* GPUImageSoftLightBlendFilter.m in Sources */,
BCB6B8BC1505BF940041703B /* GPUImageTextureOutput.m in Sources */,
BCB6B9051507CA8D0041703B /* GPUImageCropFilter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
1 change: 1 addition & 0 deletions framework/Source/GPUImage.h
Expand Up @@ -45,3 +45,4 @@
#import "GPUImageDifferenceBlendFilter.h"
#import "GPUImageHardLightBlendFilter.h"
#import "GPUImageSoftLightBlendFilter.h"
#import "GPUImageCropFilter.h"
13 changes: 13 additions & 0 deletions framework/Source/GPUImageCropFilter.h
@@ -0,0 +1,13 @@
#import "GPUImageFilter.h"

@interface GPUImageCropFilter : GPUImageFilter
{
}

// The crop region is the rectangle within the image to crop. It is normalized to a coordinate space from 0.0 to 1.0, with 0.0, 0.0 being the upper left corner of the image
@property(readwrite, nonatomic) CGRect cropRegion;

// Initialization and teardown
- (id)initWithCropRegion:(CGRect)newCropRegion;

@end
77 changes: 77 additions & 0 deletions framework/Source/GPUImageCropFilter.m
@@ -0,0 +1,77 @@
#import "GPUImageCropFilter.h"

NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;

uniform sampler2D inputImageTexture;

void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);

@implementation GPUImageCropFilter

@synthesize cropRegion = _cropRegion;

#pragma mark -
#pragma mark Initialization and teardown

- (id)initWithCropRegion:(CGRect)newCropRegion;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCropFragmentShaderString]))
{
return nil;
}

self.cropRegion = newCropRegion;

return self;
}

- (id)init;
{
if (!(self = [self initWithCropRegion:CGRectMake(0.0, 0.0, 1.0, 1.0)]))
{
return nil;
}

return self;
}

#pragma mark -
#pragma mark GPUImageInput

//- (void)setInputSize:(CGSize)newSize;
//{
// CGSize croppedSize;
// croppedSize.width = newSize.width * _cropRegion.size.width;
// croppedSize.height = newSize.height * _cropRegion.size.height;
//
// inputTextureSize = croppedSize;
//}
//
- (void)newFrameReady;
{
static const GLfloat cropSquareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};

GLfloat cropTextureCoordinates[] = {
_cropRegion.origin.x, _cropRegion.origin.y,
CGRectGetMaxX(_cropRegion), _cropRegion.origin.y,
_cropRegion.origin.x, CGRectGetMaxY(_cropRegion),
CGRectGetMaxX(_cropRegion), CGRectGetMaxY(_cropRegion),
};

[self renderToTextureWithVertices:cropSquareVertices textureCoordinates:cropTextureCoordinates sourceTexture:filterSourceTexture];

[self informTargetsAboutNewFrame];
}

@end
2 changes: 1 addition & 1 deletion framework/Source/GPUImageFilter.m
Expand Up @@ -113,7 +113,7 @@ - (UIImage *)imageFromCurrentlyProcessedOutput;
{
[GPUImageOpenGLESContext useImageProcessingContext];
[self setOutputFBO];

CGSize currentFBOSize = [self sizeOfFBO];

NSUInteger totalBytesForImage = (int)currentFBOSize.width * (int)currentFBOSize.height * 4;
Expand Down
1 change: 0 additions & 1 deletion framework/Source/GPUImageSobelEdgeDetectionFilter.m
Expand Up @@ -138,7 +138,6 @@ - (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;

- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
NSLog(@"Setting up Sobel filter for size: %f, %f", filterFrameSize.width, filterFrameSize.height);
if (!hasOverriddenImageSizeFactor)
{
_imageWidthFactor = filterFrameSize.width;
Expand Down

0 comments on commit 0bdd101

Please sign in to comment.