Skip to content

Commit 598f813

Browse files
committed
Added an image buffet filter that delays frames, allowing for comparative processing of sequential frames. There are some slight issues with timing on the blends that I still need to fix.
1 parent 6619cd2 commit 598f813

File tree

12 files changed

+233
-21
lines changed

12 files changed

+233
-21
lines changed

examples/FilterShowcase/FilterShowcase/ShowcaseFilterListController.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
9292
case GPUIMAGE_HARRISCORNERDETECTION: cell.textLabel.text = @"Harris corner detection"; break;
9393
case GPUIMAGE_NOBLECORNERDETECTION: cell.textLabel.text = @"Noble corner detection"; break;
9494
case GPUIMAGE_SHITOMASIFEATUREDETECTION: cell.textLabel.text = @"Shi-Tomasi feature detection"; break;
95+
case GPUIMAGE_BUFFER: cell.textLabel.text = @"Image buffer"; break;
9596
case GPUIMAGE_SKETCH: cell.textLabel.text = @"Sketch"; break;
9697
case GPUIMAGE_TOON: cell.textLabel.text = @"Toon"; break;
9798
case GPUIMAGE_SMOOTHTOON: cell.textLabel.text = @"Smooth toon"; break;

examples/FilterShowcase/FilterShowcase/ShowcaseFilterViewController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ typedef enum {
3333
GPUIMAGE_HARRISCORNERDETECTION,
3434
GPUIMAGE_NOBLECORNERDETECTION,
3535
GPUIMAGE_SHITOMASIFEATUREDETECTION,
36+
GPUIMAGE_BUFFER,
3637
GPUIMAGE_SKETCH,
3738
GPUIMAGE_TOON,
3839
GPUIMAGE_SMOOTHTOON,

examples/FilterShowcase/FilterShowcase/ShowcaseFilterViewController.m

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,13 @@ - (void)setupFilter;
398398

399399
filter = [[GPUImageCannyEdgeDetectionFilter alloc] init];
400400
}; break;
401-
401+
case GPUIMAGE_BUFFER:
402+
{
403+
self.title = @"Image Buffer";
404+
self.filterSettingsSlider.hidden = YES;
405+
406+
filter = [[GPUImageBuffer alloc] init];
407+
}; break;
402408
case GPUIMAGE_SKETCH:
403409
{
404410
self.title = @"Sketch";
@@ -982,6 +988,25 @@ - (void)setupFilter;
982988
[weakUIElementInput update];
983989
}];
984990
}
991+
else if (filterType == GPUIMAGE_BUFFER)
992+
{
993+
994+
GPUImageDifferenceBlendFilter *blendFilter = [[GPUImageDifferenceBlendFilter alloc] init];
995+
[blendFilter forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
996+
997+
// [filter addTarget:filterView];
998+
[videoCamera removeTarget:filter];
999+
1000+
GPUImageGammaFilter *gammaFilter = [[GPUImageGammaFilter alloc] init];
1001+
[videoCamera addTarget:gammaFilter];
1002+
[gammaFilter addTarget:blendFilter];
1003+
gammaFilter.targetToIgnoreForUpdates = blendFilter;
1004+
[videoCamera addTarget:filter];
1005+
1006+
[filter addTarget:blendFilter];
1007+
1008+
[blendFilter addTarget:filterView];
1009+
}
9851010
else
9861011
{
9871012
[filter addTarget:filterView];

framework/GPUImage.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@
190190
BCB6B9051507CA8D0041703B /* GPUImageCropFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCB6B9031507CA8C0041703B /* GPUImageCropFilter.m */; };
191191
BCBCE9991595021B00E0ED33 /* GPUImageMonochromeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBCE9971595021B00E0ED33 /* GPUImageMonochromeFilter.h */; };
192192
BCBCE99A1595021B00E0ED33 /* GPUImageMonochromeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBCE9981595021B00E0ED33 /* GPUImageMonochromeFilter.m */; };
193+
BCBCE9D5159944AC00E0ED33 /* GPUImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBCE9D3159944AB00E0ED33 /* GPUImageBuffer.h */; };
194+
BCBCE9D6159944AC00E0ED33 /* GPUImageBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = BCBCE9D4159944AB00E0ED33 /* GPUImageBuffer.m */; };
193195
BCC11D72154B44DC0044F5A0 /* GPUImageHistogramGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC11D70154B44DC0044F5A0 /* GPUImageHistogramGenerator.h */; };
194196
BCC11D73154B44DC0044F5A0 /* GPUImageHistogramGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = BCC11D71154B44DC0044F5A0 /* GPUImageHistogramGenerator.m */; };
195197
BCC1E5A8151E74B20006EFA5 /* GPUImagePosterizeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC1E5A6151E74B20006EFA5 /* GPUImagePosterizeFilter.h */; };
@@ -440,6 +442,8 @@
440442
BCB6B9031507CA8C0041703B /* GPUImageCropFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageCropFilter.m; path = Source/GPUImageCropFilter.m; sourceTree = SOURCE_ROOT; };
441443
BCBCE9971595021B00E0ED33 /* GPUImageMonochromeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageMonochromeFilter.h; path = Source/GPUImageMonochromeFilter.h; sourceTree = SOURCE_ROOT; };
442444
BCBCE9981595021B00E0ED33 /* GPUImageMonochromeFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageMonochromeFilter.m; path = Source/GPUImageMonochromeFilter.m; sourceTree = SOURCE_ROOT; };
445+
BCBCE9D3159944AB00E0ED33 /* GPUImageBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageBuffer.h; path = Source/GPUImageBuffer.h; sourceTree = SOURCE_ROOT; };
446+
BCBCE9D4159944AB00E0ED33 /* GPUImageBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageBuffer.m; path = Source/GPUImageBuffer.m; sourceTree = SOURCE_ROOT; };
443447
BCC11D70154B44DC0044F5A0 /* GPUImageHistogramGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageHistogramGenerator.h; path = Source/GPUImageHistogramGenerator.h; sourceTree = SOURCE_ROOT; };
444448
BCC11D71154B44DC0044F5A0 /* GPUImageHistogramGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageHistogramGenerator.m; path = Source/GPUImageHistogramGenerator.m; sourceTree = SOURCE_ROOT; };
445449
BCC1E5A6151E74B20006EFA5 /* GPUImagePosterizeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImagePosterizeFilter.h; path = Source/GPUImagePosterizeFilter.h; sourceTree = SOURCE_ROOT; };
@@ -684,6 +688,8 @@
684688
BCC1E5B7151E83700006EFA5 /* GPUImageFilterGroup.m */,
685689
BC01E830155CA5E1004C75C3 /* GPUImage3x3TextureSamplingFilter.h */,
686690
BC01E831155CA5E1004C75C3 /* GPUImage3x3TextureSamplingFilter.m */,
691+
BCBCE9D3159944AB00E0ED33 /* GPUImageBuffer.h */,
692+
BCBCE9D4159944AB00E0ED33 /* GPUImageBuffer.m */,
687693
BC1B715D14F4AFFF00ACA2AB /* Color processing */,
688694
BCC93A5215031B1700958B26 /* Image processing */,
689695
BC1B715E14F4B04800ACA2AB /* Blends */,
@@ -1005,6 +1011,7 @@
10051011
BC0690F7157C5075009274F9 /* GPUImageColorPackingFilter.h in Headers */,
10061012
BC76CE9B15813818008B45D3 /* GPUImageSphereRefractionFilter.h in Headers */,
10071013
BCBCE9991595021B00E0ED33 /* GPUImageMonochromeFilter.h in Headers */,
1014+
BCBCE9D5159944AC00E0ED33 /* GPUImageBuffer.h in Headers */,
10081015
);
10091016
runOnlyForDeploymentPostprocessing = 0;
10101017
};
@@ -1230,6 +1237,7 @@
12301237
BC0690F8157C5075009274F9 /* GPUImageColorPackingFilter.m in Sources */,
12311238
BC76CE9C15813818008B45D3 /* GPUImageSphereRefractionFilter.m in Sources */,
12321239
BCBCE99A1595021B00E0ED33 /* GPUImageMonochromeFilter.m in Sources */,
1240+
BCBCE9D6159944AC00E0ED33 /* GPUImageBuffer.m in Sources */,
12331241
);
12341242
runOnlyForDeploymentPostprocessing = 0;
12351243
};

framework/Source/GPUImage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#import "GPUImageFilterGroup.h"
1717
#import "GPUImageTextureInput.h"
1818
#import "GPUImageUIElement.h"
19+
#import "GPUImageBuffer.h"
1920

2021
// Filters
2122
#import "GPUImageFilter.h"

framework/Source/GPUImageBuffer.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#import "GPUImageFilter.h"
2+
3+
@interface GPUImageBuffer : GPUImageFilter
4+
{
5+
NSMutableArray *bufferedTextures;
6+
}
7+
8+
@property(readwrite, nonatomic) NSUInteger bufferSize;
9+
10+
@end

framework/Source/GPUImageBuffer.m

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#import "GPUImageBuffer.h"
2+
3+
@implementation GPUImageBuffer
4+
5+
@synthesize bufferSize = _bufferSize;
6+
7+
#pragma mark -
8+
#pragma mark Initialization and teardown
9+
10+
- (id)init;
11+
{
12+
if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString]))
13+
{
14+
return nil;
15+
}
16+
17+
bufferedTextures = [[NSMutableArray alloc] init];
18+
[bufferedTextures addObject:[NSNumber numberWithInt:outputTexture]];
19+
_bufferSize = 1;
20+
21+
return self;
22+
}
23+
24+
- (void)dealloc
25+
{
26+
for (NSNumber *currentTextureName in bufferedTextures)
27+
{
28+
[self removeTexture:[currentTextureName intValue]];
29+
}
30+
}
31+
32+
#pragma mark -
33+
#pragma mark GPUImageInput
34+
35+
- (void)newFrameReadyAtTime:(CMTime)frameTime;
36+
{
37+
static const GLfloat imageVertices[] = {
38+
-1.0f, -1.0f,
39+
1.0f, -1.0f,
40+
-1.0f, 1.0f,
41+
1.0f, 1.0f,
42+
};
43+
44+
// Let the downstream video elements see the previous frame from the buffer before rendering a new one into place
45+
[self informTargetsAboutNewFrameAtTime:frameTime];
46+
47+
// Move the last frame to the back of the buffer, if needed
48+
if (_bufferSize > 1)
49+
{
50+
NSNumber *lastTextureName = [bufferedTextures objectAtIndex:0];
51+
[bufferedTextures removeObjectAtIndex:0];
52+
[bufferedTextures addObject:lastTextureName];
53+
}
54+
else
55+
{
56+
// Make sure the previous rendering has finished before enqueuing the current frame when simply delaying by one frame
57+
glFinish();
58+
}
59+
60+
// Render the new frame to the back of the buffer
61+
[self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation] sourceTexture:filterSourceTexture];
62+
}
63+
64+
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates sourceTexture:(GLuint)sourceTexture;
65+
{
66+
if (self.preventRendering)
67+
{
68+
return;
69+
}
70+
71+
[GPUImageOpenGLESContext useImageProcessingContext];
72+
[self setFilterFBO];
73+
74+
glBindTexture(GL_TEXTURE_2D, [[bufferedTextures lastObject] intValue]);
75+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, [[bufferedTextures lastObject] intValue], 0);
76+
77+
[filterProgram use];
78+
79+
glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha);
80+
glClear(GL_COLOR_BUFFER_BIT);
81+
82+
glActiveTexture(GL_TEXTURE2);
83+
glBindTexture(GL_TEXTURE_2D, sourceTexture);
84+
85+
glUniform1i(filterInputTextureUniform, 2);
86+
87+
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
88+
glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
89+
90+
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
91+
}
92+
93+
- (void)prepareForImageCapture;
94+
{
95+
// Disable this for now, until I figure out how to integrate the texture caches with a buffer like this
96+
}
97+
98+
#pragma mark -
99+
#pragma mark Managing targets
100+
101+
- (void)setInputTextureForTarget:(id<GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex;
102+
{
103+
[target setInputTexture:[[bufferedTextures objectAtIndex:0] intValue] atIndex:inputTextureIndex];
104+
}
105+
106+
107+
#pragma mark -
108+
#pragma mark Texture management
109+
110+
- (GLuint)generateTexture;
111+
{
112+
GLuint newTextureName = 0;
113+
glActiveTexture(GL_TEXTURE0);
114+
glGenTextures(1, &newTextureName);
115+
glBindTexture(GL_TEXTURE_2D, newTextureName);
116+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
117+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118+
// This is necessary for non-power-of-two textures
119+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
120+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
121+
122+
CGSize currentFBOSize = [self sizeOfFBO];
123+
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)currentFBOSize.width, (int)currentFBOSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
124+
glBindTexture(GL_TEXTURE_2D, 0);
125+
126+
return newTextureName;
127+
}
128+
129+
- (void)removeTexture:(GLuint)textureToRemove;
130+
{
131+
glDeleteTextures(1, &textureToRemove);
132+
}
133+
134+
#pragma mark -
135+
#pragma mark Accessors
136+
137+
- (void)setBufferSize:(NSUInteger)newValue;
138+
{
139+
if ( (newValue == _bufferSize) || (newValue < 1) )
140+
{
141+
return;
142+
}
143+
144+
if (newValue > _bufferSize)
145+
{
146+
NSUInteger texturesToAdd = newValue - _bufferSize;
147+
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToAdd; currentTextureIndex++)
148+
{
149+
[bufferedTextures addObject:[NSNumber numberWithInt:[self generateTexture]]];
150+
}
151+
}
152+
else
153+
{
154+
NSUInteger texturesToRemove = _bufferSize - newValue;
155+
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToRemove; currentTextureIndex++)
156+
{
157+
NSNumber *lastTextureName = [bufferedTextures lastObject];
158+
[bufferedTextures removeObjectAtIndex:([bufferedTextures count] - 1)];
159+
[self removeTexture:[lastTextureName intValue]];
160+
}
161+
}
162+
}
163+
164+
@end

framework/Source/GPUImageMovie.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ - (id)initWithURL:(NSURL *)url;
4848
return self;
4949
}
5050

51+
- (void)dealloc
52+
{
53+
if ([GPUImageOpenGLESContext supportsFastTextureUpload])
54+
{
55+
CFRelease(coreVideoTextureCache);
56+
}
57+
}
58+
5159
#pragma mark -
5260
#pragma mark Movie processing
5361

framework/Source/GPUImageMovieWriter.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ - (void)renderAtInternalSize;
401401

402402
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
403403

404-
glFlush();
404+
glFinish();
405405
}
406406

407407
#pragma mark -

framework/Source/GPUImagePicture.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
@interface GPUImagePicture : GPUImageOutput
66
{
7-
UIImage *imageSource;
7+
CGSize pixelSizeOfImage;
88
}
99

1010
// Initialization and teardown

0 commit comments

Comments
 (0)