Skip to content

Commit

Permalink
Added a raw data output type for reading image bytes and textures. Ad…
Browse files Browse the repository at this point in the history
…ded a sketch effect filter.
  • Loading branch information
BradLarson committed Feb 22, 2012
1 parent a051287 commit fe84406
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
case GPUIMAGE_SEPIA: cell.textLabel.text = @"Sepia tone"; break;
case GPUIMAGE_PIXELLATE: cell.textLabel.text = @"Pixellate"; break;
case GPUIMAGE_SOBELEDGEDETECTION: cell.textLabel.text = @"Sobel edge detection"; break;
case GPUIMAGE_SKETCH: cell.textLabel.text = @"Sketch"; break;
case GPUIMAGE_TOON: cell.textLabel.text = @"Toon"; break;
case GPUIMAGE_DISSOLVE: cell.textLabel.text = @"Dissolve blend"; break;
case GPUIMAGE_MULTIPLY: cell.textLabel.text = @"Multiply blend"; break;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import <UIKit/UIKit.h>
#import "GPUImage.h"

typedef enum { GPUIMAGE_SATURATION, GPUIMAGE_CONTRAST, GPUIMAGE_BRIGHTNESS, GPUIMAGE_GAMMA, GPUIMAGE_SEPIA, GPUIMAGE_COLORINVERT, GPUIMAGE_PIXELLATE, GPUIMAGE_SOBELEDGEDETECTION, GPUIMAGE_TOON, GPUIMAGE_KUWAHARA, GPUIMAGE_DISSOLVE, GPUIMAGE_MULTIPLY, GPUIMAGE_OVERLAY, GPUIMAGE_LIGHTEN, GPUIMAGE_DARKEN, GPUIMAGE_CUSTOM, GPUIMAGE_NUMFILTERS} GPUImageShowcaseFilterType;
typedef enum { GPUIMAGE_SATURATION, GPUIMAGE_CONTRAST, GPUIMAGE_BRIGHTNESS, GPUIMAGE_GAMMA, GPUIMAGE_SEPIA, GPUIMAGE_COLORINVERT, GPUIMAGE_PIXELLATE, GPUIMAGE_SOBELEDGEDETECTION, GPUIMAGE_SKETCH, GPUIMAGE_TOON, GPUIMAGE_KUWAHARA, GPUIMAGE_DISSOLVE, GPUIMAGE_MULTIPLY, GPUIMAGE_OVERLAY, GPUIMAGE_LIGHTEN, GPUIMAGE_DARKEN, GPUIMAGE_CUSTOM, GPUIMAGE_NUMFILTERS} GPUImageShowcaseFilterType;

@interface ShowcaseFilterViewController : UIViewController
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ - (void)setupFilter;

filter = [[GPUImageSobelEdgeDetectionFilter alloc] init]; break;
}; break;
case GPUIMAGE_SKETCH:
{
self.title = @"Sketch";
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setMinimumValue:0.0];
[self.filterSettingsSlider setMaximumValue:1.0];
[self.filterSettingsSlider setValue:1.0];

filter = [[GPUImageSketchFilter alloc] init]; break;
}; break;
case GPUIMAGE_TOON:
{
self.title = @"Toon";
Expand Down Expand Up @@ -235,6 +246,7 @@ - (IBAction)updateFilterFromSlider:(id)sender;
case GPUIMAGE_BRIGHTNESS: [(GPUImageBrightnessFilter *)filter setBrightness:[(UISlider *)sender value]]; break;
case GPUIMAGE_GAMMA: [(GPUImageGammaFilter *)filter setGamma:[(UISlider *)sender value]]; break;
case GPUIMAGE_SOBELEDGEDETECTION: [(GPUImageSobelEdgeDetectionFilter *)filter setIntensity:[(UISlider *)sender value]]; break;
case GPUIMAGE_SKETCH: [(GPUImageSketchFilter *)filter setIntensity:[(UISlider *)sender value]]; break;
case GPUIMAGE_DISSOLVE: [(GPUImageDissolveBlendFilter *)filter setMix:[(UISlider *)sender value]]; break;
case GPUIMAGE_KUWAHARA: [(GPUImageKuwaharaFilter *)filter setRadius:round([(UISlider *)sender value])]; break;
default: break;
Expand Down
70 changes: 55 additions & 15 deletions framework/GPUImage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
/* Begin PBXBuildFile section */
B81521A214F1BA6A00F105F8 /* GPUImageColorMatrixFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = B81521A014F1BA6A00F105F8 /* GPUImageColorMatrixFilter.h */; };
B81521A314F1BA6A00F105F8 /* GPUImageColorMatrixFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B81521A114F1BA6A00F105F8 /* GPUImageColorMatrixFilter.m */; };
BC1B715714F49DAA00ACA2AB /* GPUImageRawData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1B715514F49DAA00ACA2AB /* GPUImageRawData.h */; };
BC1B715814F49DAA00ACA2AB /* GPUImageRawData.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1B715614F49DAA00ACA2AB /* GPUImageRawData.m */; };
BC1B717C14F566E200ACA2AB /* GPUImageSketchFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1B717A14F566E200ACA2AB /* GPUImageSketchFilter.h */; };
BC1B717D14F566E200ACA2AB /* GPUImageSketchFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1B717B14F566E200ACA2AB /* GPUImageSketchFilter.m */; };
BC245DC114DDBCF5009FE7EB /* GPUImage.h in Headers */ = {isa = PBXBuildFile; fileRef = BC245DBF14DDBCF5009FE7EB /* GPUImage.h */; };
BC245DCA14DDBED7009FE7EB /* GPUImageFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC245DC814DDBED7009FE7EB /* GPUImageFilter.h */; };
BC245DCB14DDBED7009FE7EB /* GPUImageFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC245DC914DDBED7009FE7EB /* GPUImageFilter.m */; };
Expand Down Expand Up @@ -85,6 +89,10 @@
/* Begin PBXFileReference section */
B81521A014F1BA6A00F105F8 /* GPUImageColorMatrixFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageColorMatrixFilter.h; path = Source/GPUImageColorMatrixFilter.h; sourceTree = SOURCE_ROOT; };
B81521A114F1BA6A00F105F8 /* GPUImageColorMatrixFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageColorMatrixFilter.m; path = Source/GPUImageColorMatrixFilter.m; sourceTree = SOURCE_ROOT; };
BC1B715514F49DAA00ACA2AB /* GPUImageRawData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageRawData.h; path = Source/GPUImageRawData.h; sourceTree = SOURCE_ROOT; };
BC1B715614F49DAA00ACA2AB /* GPUImageRawData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageRawData.m; path = Source/GPUImageRawData.m; sourceTree = SOURCE_ROOT; };
BC1B717A14F566E200ACA2AB /* GPUImageSketchFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageSketchFilter.h; path = Source/GPUImageSketchFilter.h; sourceTree = SOURCE_ROOT; };
BC1B717B14F566E200ACA2AB /* GPUImageSketchFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageSketchFilter.m; path = Source/GPUImageSketchFilter.m; sourceTree = SOURCE_ROOT; };
BC245DBF14DDBCF5009FE7EB /* GPUImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImage.h; path = Source/GPUImage.h; sourceTree = SOURCE_ROOT; };
BC245DC814DDBED7009FE7EB /* GPUImageFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageFilter.h; path = Source/GPUImageFilter.h; sourceTree = SOURCE_ROOT; };
BC245DC914DDBED7009FE7EB /* GPUImageFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageFilter.m; path = Source/GPUImageFilter.m; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -179,27 +187,30 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
BC245DC314DDBE6B009FE7EB /* Filters */ = {
BC1B715D14F4AFFF00ACA2AB /* Color processing */ = {
isa = PBXGroup;
children = (
BC245DC814DDBED7009FE7EB /* GPUImageFilter.h */,
BC245DC914DDBED7009FE7EB /* GPUImageFilter.m */,
BCB5E85314E63BBB00701302 /* GPUImageRotationFilter.h */,
BCB5E85414E63BBB00701302 /* GPUImageRotationFilter.m */,
BCB5E7C014E4B6D400701302 /* GPUImageSepiaFilter.h */,
BCB5E7C114E4B6D400701302 /* GPUImageSepiaFilter.m */,
B81521A014F1BA6A00F105F8 /* GPUImageColorMatrixFilter.h */,
B81521A114F1BA6A00F105F8 /* GPUImageColorMatrixFilter.m */,
BC982B4F14F07F790001FF6F /* GPUImageColorInvertFilter.h */,
BC982B5014F07F790001FF6F /* GPUImageColorInvertFilter.m */,
BC982B5114F07F790001FF6F /* GPUImageSaturationFilter.h */,
BC982B5214F07F790001FF6F /* GPUImageSaturationFilter.m */,
BC982B6514F092EF0001FF6F /* GPUImageContrastFilter.h */,
BC982B6614F092EF0001FF6F /* GPUImageContrastFilter.m */,
BC982B7714F098CC0001FF6F /* GPUImageBrightnessFilter.h */,
BC982B7814F098CC0001FF6F /* GPUImageBrightnessFilter.m */,
BC982B6514F092EF0001FF6F /* GPUImageContrastFilter.h */,
BC982B6614F092EF0001FF6F /* GPUImageContrastFilter.m */,
BC982B5114F07F790001FF6F /* GPUImageSaturationFilter.h */,
BC982B5214F07F790001FF6F /* GPUImageSaturationFilter.m */,
BC982B7C14F09F980001FF6F /* GPUImageGammaFilter.h */,
BC982B7D14F09F980001FF6F /* GPUImageGammaFilter.m */,
B81521A014F1BA6A00F105F8 /* GPUImageColorMatrixFilter.h */,
B81521A114F1BA6A00F105F8 /* GPUImageColorMatrixFilter.m */,
BCB5E7C014E4B6D400701302 /* GPUImageSepiaFilter.h */,
BCB5E7C114E4B6D400701302 /* GPUImageSepiaFilter.m */,
BC982B4F14F07F790001FF6F /* GPUImageColorInvertFilter.h */,
BC982B5014F07F790001FF6F /* GPUImageColorInvertFilter.m */,
);
name = "Color processing";
sourceTree = "<group>";
};
BC1B715E14F4B04800ACA2AB /* Blends */ = {
isa = PBXGroup;
children = (
BC982BE714F1CE600001FF6F /* GPUImageDissolveBlendFilter.h */,
BC982BE814F1CE600001FF6F /* GPUImageDissolveBlendFilter.m */,
BC982BE914F1CE600001FF6F /* GPUImageMultiplyBlendFilter.h */,
Expand All @@ -210,15 +221,38 @@
BC982C7E14F34F0B0001FF6F /* GPUImageDarkenBlendFilter.m */,
BC982C7F14F34F0C0001FF6F /* GPUImageLightenBlendFilter.h */,
BC982C8014F34F0C0001FF6F /* GPUImageLightenBlendFilter.m */,
);
name = Blends;
sourceTree = "<group>";
};
BC1B715F14F4B06600ACA2AB /* Effects */ = {
isa = PBXGroup;
children = (
BCB5DE0B14E87F32000AF3C2 /* GPUImagePixellateFilter.h */,
BCB5DE0C14E87F32000AF3C2 /* GPUImagePixellateFilter.m */,
BC982B9714F0B34E0001FF6F /* GPUImageSobelEdgeDetectionFilter.h */,
BC982B9814F0B34E0001FF6F /* GPUImageSobelEdgeDetectionFilter.m */,
BC1B717A14F566E200ACA2AB /* GPUImageSketchFilter.h */,
BC1B717B14F566E200ACA2AB /* GPUImageSketchFilter.m */,
BC982C9D14F35C2D0001FF6F /* GPUImageToonFilter.h */,
BC982C9E14F35C2D0001FF6F /* GPUImageToonFilter.m */,
BC982C4514F29E580001FF6F /* GPUImageKuwaharaFilter.h */,
BC982C4614F29E580001FF6F /* GPUImageKuwaharaFilter.m */,
);
name = Effects;
sourceTree = "<group>";
};
BC245DC314DDBE6B009FE7EB /* Filters */ = {
isa = PBXGroup;
children = (
BC245DC814DDBED7009FE7EB /* GPUImageFilter.h */,
BC245DC914DDBED7009FE7EB /* GPUImageFilter.m */,
BCB5E85314E63BBB00701302 /* GPUImageRotationFilter.h */,
BCB5E85414E63BBB00701302 /* GPUImageRotationFilter.m */,
BC1B715D14F4AFFF00ACA2AB /* Color processing */,
BC1B715E14F4B04800ACA2AB /* Blends */,
BC1B715F14F4B06600ACA2AB /* Effects */,
);
name = Filters;
sourceTree = "<group>";
};
Expand All @@ -240,6 +274,8 @@
children = (
BCB5E75A14E2086300701302 /* GPUImageView.h */,
BCB5E75B14E2086300701302 /* GPUImageView.m */,
BC1B715514F49DAA00ACA2AB /* GPUImageRawData.h */,
BC1B715614F49DAA00ACA2AB /* GPUImageRawData.m */,
);
name = Display;
sourceTree = "<group>";
Expand Down Expand Up @@ -356,6 +392,8 @@
BC982C8114F34F0C0001FF6F /* GPUImageDarkenBlendFilter.h in Headers */,
BC982C8314F34F0C0001FF6F /* GPUImageLightenBlendFilter.h in Headers */,
BC982C9F14F35C2D0001FF6F /* GPUImageToonFilter.h in Headers */,
BC1B715714F49DAA00ACA2AB /* GPUImageRawData.h in Headers */,
BC1B717C14F566E200ACA2AB /* GPUImageSketchFilter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -482,6 +520,8 @@
BC982C8214F34F0C0001FF6F /* GPUImageDarkenBlendFilter.m in Sources */,
BC982C8414F34F0C0001FF6F /* GPUImageLightenBlendFilter.m in Sources */,
BC982CA014F35C2D0001FF6F /* GPUImageToonFilter.m in Sources */,
BC1B715814F49DAA00ACA2AB /* GPUImageRawData.m in Sources */,
BC1B717D14F566E200ACA2AB /* GPUImageSketchFilter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 2 additions & 0 deletions framework/Source/GPUImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#import "GPUImageVideoCamera.h"
#import "GPUImageMovie.h"
#import "GPUImagePicture.h"
#import "GPUImageRawData.h"

// Filters
#import "GPUImageFilter.h"
Expand All @@ -19,6 +20,7 @@
#import "GPUImageBrightnessFilter.h"
#import "GPUImageGammaFilter.h"
#import "GPUImageSobelEdgeDetectionFilter.h"
#import "GPUImageSketchFilter.h"
#import "GPUImageToonFilter.h"
#import "GPUImageMultiplyBlendFilter.h"
#import "GPUImageDissolveBlendFilter.h"
Expand Down
30 changes: 30 additions & 0 deletions framework/Source/GPUImageRawData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#import <Foundation/Foundation.h>
#import "GPUImageOpenGLESContext.h"

struct GPUByteColorVector {
GLubyte red;
GLubyte green;
GLubyte blue;
GLubyte alphe;
};
typedef struct GPUByteColorVector GPUByteColorVector;

@protocol GPUImageRawDataProcessor;

@interface GPUImageRawData : NSObject <GPUImageInput>

@property(readwrite, unsafe_unretained, nonatomic) id<GPUImageRawDataProcessor> delegate;
@property(readonly) GLubyte *rawBytesForImage;
@property(readonly) GLint openGLTexture;

// Initialization and teardown
- (id)initWithImageSize:(CGSize)newImageSize;

// Data access
- (GPUByteColorVector)colorAtLocation:(CGPoint)locationInImage;

@end

@protocol GPUImageRawDataProcessor
- (void)newImageFrameAvailableFromDataSource:(GPUImageRawData *)rawDataSource;
@end
108 changes: 108 additions & 0 deletions framework/Source/GPUImageRawData.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#import "GPUImageRawData.h"

@interface GPUImageRawData ()
{
CGSize imageSize;
BOOL hasReadFromTheCurrentFrame;
}
@end

@implementation GPUImageRawData

#pragma mark -
#pragma mark Initialization and teardown

- (id)initWithImageSize:(CGSize)newImageSize;
{
if (!(self = [super init]))
{
return nil;
}

imageSize = newImageSize;

hasReadFromTheCurrentFrame = NO;
_rawBytesForImage = NULL;

return self;
}

- (void)dealloc
{
if (_rawBytesForImage != NULL)
{
free(_rawBytesForImage);
_rawBytesForImage = NULL;
}
}

#pragma mark -
#pragma mark Data access

- (GPUByteColorVector)colorAtLocation:(CGPoint)locationInImage;
{
GPUByteColorVector *imageColorBytes = (GPUByteColorVector *)self.rawBytesForImage;

CGPoint locationToPickFrom = CGPointZero;
locationToPickFrom.x = MIN(MAX(locationInImage.x, 0.0), (imageSize.width - 1.0));
locationToPickFrom.y = MIN(MAX(locationInImage.y, 0.0), (imageSize.height - 1.0));

return imageColorBytes[(int)(round(locationToPickFrom.x * locationToPickFrom.y))];
}

#pragma mark -
#pragma mark GPUImageInput protocol

- (void)newFrameReady;
{
hasReadFromTheCurrentFrame = NO;

[self.delegate newImageFrameAvailableFromDataSource:self];
}

- (void)setInputTexture:(GLuint)newInputTexture;
{
_openGLTexture = newInputTexture;
}

- (void)setInputSize:(CGSize)newSize;
{

}

- (CGSize)maximumOutputSize;
{
return imageSize;
}

#pragma mark -
#pragma mark Accessors

@synthesize rawBytesForImage = _rawBytesForImage;
@synthesize openGLTexture = _openGLTexture;
@synthesize delegate = _delegate;

- (GLubyte *)rawBytesForImage;
{
if (_rawBytesForImage == NULL)
{
_rawBytesForImage = (GLubyte *) calloc(imageSize.width * imageSize.height * 4, sizeof(GLubyte));
hasReadFromTheCurrentFrame = NO;
}

if (hasReadFromTheCurrentFrame)
{
return _rawBytesForImage;
}
else
{
[GPUImageOpenGLESContext useImageProcessingContext];
// This might require a re-rendering of the previous frame in order for the reading of the pixels to work
glReadPixels(0, 0, imageSize.width, imageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, _rawBytesForImage);

return _rawBytesForImage;
}

}

@end
14 changes: 14 additions & 0 deletions framework/Source/GPUImageSketchFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#import "GPUImageFilter.h"

@interface GPUImageSketchFilter : GPUImageFilter
{
GLint intensityUniform, imageWidthFactorUniform, imageHeightFactorUniform;
}

// Intensity is the degree to which the edges are overlaid on the image. 1.0 is the default, and is complete visibility for them
@property(readwrite, nonatomic) CGFloat intensity;
// The image width and height factors tweak the appearance of the edges. Normally, they are close to the image size in pixels
@property(readwrite, nonatomic) CGFloat imageWidthFactor;
@property(readwrite, nonatomic) CGFloat imageHeightFactor;

@end
Loading

0 comments on commit fe84406

Please sign in to comment.