Compare commits

...

19 Commits

Author SHA1 Message Date
chenliming 79ff5357ac update version 2016-12-21 09:55:42 +08:00
小歪~~~ 2989ffd911 Merge pull request #152 from linyehui/master
using NSMutableArray sortUsingFunction instead of NSArray sortedArray…
2016-12-20 15:58:37 +08:00
linyehui 0510aafead using NSMutableArray sortUsingFunction instead of NSArray sortedArrayUsingFunction
性能优化,同时也会修正多线程下使用LFStreamSocket推流的内存泄漏问题
2016-12-06 15:36:42 +08:00
chenliming f6feec3090 fix audioCapture crash 2016-11-17 10:26:56 +08:00
chenliming b3a8d96787 fix drop bug 2016-11-11 10:31:28 +08:00
chenliming ebc59bc4cf fix bug https://github.com/LaiFengiOS/LFLiveKit/issues/135 2016-11-10 18:19:53 +08:00
chenliming 565453fe9e support swift3 2016-11-09 17:13:19 +08:00
chenliming 3e44e0ebe7 update readme 2016-11-09 14:38:00 +08:00
小歪~~~ f255d10c94 Merge pull request #129 from Zeaa/master
优化更新LFLiveKit中的部分注释错误、添加LFDebug类的description方法
2016-11-09 14:05:16 +08:00
chenliming b683ddacab add carthage 2016-11-08 21:47:13 +08:00
chenliming 4fbf00bfea fix watermark bug 2016-11-08 21:35:50 +08:00
chenliming e64ba9da09 submit source code 2016-11-08 21:16:54 +08:00
ftao a8a160324e 优化更新LFLiveKit中的部分注释错误、添加LFDebug的description方法 2016-10-31 11:33:45 +08:00
chenliming c12a8a7bfa Revert "编译问题"
This reverts commit e1b8812b25.
2016-10-21 14:52:52 +08:00
chenliming e1b8812b25 编译问题 2016-10-21 14:44:53 +08:00
chenliming a130058c5d ... 2016-10-21 14:34:49 +08:00
chenliming 3f804634c5 添加build脚本 2016-10-21 14:26:54 +08:00
chenliming 8b39f68a48 update version 2016-10-20 21:16:49 +08:00
chenliming 1d7b1f7073 添加demo 2016-10-20 21:15:49 +08:00
477 changed files with 46935 additions and 299 deletions
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.4.2</string>
<string>2.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D8B4251D75778B00752B56"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -29,15 +29,6 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D8B4251D75778B00752B56"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
@@ -51,16 +42,15 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D8B4251D75778B00752B56"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -70,16 +60,15 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D8B4251D75778B00752B56"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.4.3</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
@@ -0,0 +1,26 @@
//
// LFLiveKitFramework.h
// LFLiveKitFramework
//
// Created by admin on 2016/10/20.
// Copyright © 2016年 admin. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for LFLiveKitFramework.
FOUNDATION_EXPORT double LFLiveKitFrameworkVersionNumber;
//! Project version string for LFLiveKitFramework.
FOUNDATION_EXPORT const unsigned char LFLiveKitFrameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <LFLiveKitFramework/PublicHeader.h>
#import <LFLiveKit/LFLiveSession.h>
#import <LFLiveKit/LFLiveAudioConfiguration.h>
#import <LFLiveKit/LFLiveVideoConfiguration.h>
#import <LFLiveKit/LFAudioFrame.h>
#import <LFLiveKit/LFFrame.h>
#import <LFLiveKit/LFLiveStreamInfo.h>
#import <LFLiveKit/LFVideoFrame.h>
#import <LFLiveKit/LFLiveDebug.h>
-7
View File
@@ -1,7 +0,0 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios,'7.0'
target “LFLiveKit” do
pod 'pili-librtmp', '~> 1.0.3.1'
pod 'LMGPUImage'
end
+1 -3
View File
@@ -2,7 +2,7 @@
Pod::Spec.new do |s|
s.name = "LFLiveKit"
s.version = "2.4.2"
s.version = "2.6"
s.summary = "LaiFeng ios Live. LFLiveKit."
s.homepage = "https://github.com/chenliming777"
s.license = { :type => "MIT", :file => "LICENSE" }
@@ -17,6 +17,4 @@ Pod::Spec.new do |s|
s.libraries = "c++", "z"
s.requires_arc = true
s.dependency 'LMGPUImage'
s.dependency 'pili-librtmp', '1.0.3.1'
end
+4 -10
View File
@@ -6,16 +6,9 @@
// Copyright © 2016年 LaiFeng All rights reserved.
//
#if __has_include(<LFLiveKit/LFLiveKit.h>)
#import <LFLiveKit/LFLiveSession.h>
#import <LFLiveKit/LFLiveAudioConfiguration.h>
#import <LFLiveKit/LFLiveVideoConfiguration.h>
#import <LFLiveKit/LFAudioFrame.h>
#import <LFLiveKit/LFFrame.h>
#import <LFLiveKit/LFLiveStreamInfo.h>
#import <LFLiveKit/LFVideoFrame.h>
#import <LFLiveKit/LFLiveDebug.h>
#else
#ifndef LFLiveKit_h
#define LFLiveKit_h
#import "LFLiveSession.h"
#import "LFLiveAudioConfiguration.h"
#import "LFLiveVideoConfiguration.h"
@@ -24,5 +17,6 @@
#import "LFLiveStreamInfo.h"
#import "LFVideoFrame.h"
#import "LFLiveDebug.h"
#endif
-10
View File
@@ -9,14 +9,6 @@
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#if __has_include(<LFLiveKit/LFLiveKit.h>)
#import <LFLiveKit/LFLiveStreamInfo.h>
#import <LFLiveKit/LFAudioFrame.h>
#import <LFLiveKit/LFVideoFrame.h>
#import <LFLiveKit/LFLiveAudioConfiguration.h>
#import <LFLiveKit/LFLiveVideoConfiguration.h>
#import <LFLiveKit/LFLiveDebug.h>
#else
#import "LFLiveStreamInfo.h"
#import "LFAudioFrame.h"
#import "LFVideoFrame.h"
@@ -24,8 +16,6 @@
#import "LFLiveVideoConfiguration.h"
#import "LFLiveDebug.h"
#endif
typedef NS_ENUM(NSInteger,LFLiveCaptureType) {
+42
View File
@@ -0,0 +1,42 @@
// This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book.
// A description of this can be found at his page on the topic:
// http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html
// I've extended this to be able to take programs as NSStrings in addition to files, for baked-in shaders
#import <Foundation/Foundation.h>
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#else
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#endif
@interface GLProgram : NSObject
{
NSMutableArray *attributes;
NSMutableArray *uniforms;
GLuint program,
vertShader,
fragShader;
}
@property(readwrite, nonatomic) BOOL initialized;
@property(readwrite, copy, nonatomic) NSString *vertexShaderLog;
@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog;
@property(readwrite, copy, nonatomic) NSString *programLog;
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderString:(NSString *)fShaderString;
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderFilename:(NSString *)fShaderFilename;
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
fragmentShaderFilename:(NSString *)fShaderFilename;
- (void)addAttribute:(NSString *)attributeName;
- (GLuint)attributeIndex:(NSString *)attributeName;
- (GLuint)uniformIndex:(NSString *)uniformName;
- (BOOL)link;
- (void)use;
- (void)validate;
@end
+236
View File
@@ -0,0 +1,236 @@
// This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book.
// A description of this can be found at his page on the topic:
// http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html
#import "GLProgram.h"
// START:typedefs
#pragma mark Function Pointer Definitions
typedef void (*GLInfoFunction)(GLuint program, GLenum pname, GLint* params);
typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
// END:typedefs
#pragma mark -
#pragma mark Private Extension Method Declaration
// START:extension
@interface GLProgram()
- (BOOL)compileShader:(GLuint *)shader
type:(GLenum)type
string:(NSString *)shaderString;
@end
// END:extension
#pragma mark -
@implementation GLProgram
// START:init
@synthesize initialized = _initialized;
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderString:(NSString *)fShaderString;
{
if ((self = [super init]))
{
_initialized = NO;
attributes = [[NSMutableArray alloc] init];
uniforms = [[NSMutableArray alloc] init];
program = glCreateProgram();
if (![self compileShader:&vertShader
type:GL_VERTEX_SHADER
string:vShaderString])
{
NSLog(@"Failed to compile vertex shader");
}
// Create and compile fragment shader
if (![self compileShader:&fragShader
type:GL_FRAGMENT_SHADER
string:fShaderString])
{
NSLog(@"Failed to compile fragment shader");
}
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
}
return self;
}
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderFilename:(NSString *)fShaderFilename;
{
NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString]))
{
}
return self;
}
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
fragmentShaderFilename:(NSString *)fShaderFilename;
{
NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"];
NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil];
NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]))
{
}
return self;
}
// END:init
// START:compile
- (BOOL)compileShader:(GLuint *)shader
type:(GLenum)type
string:(NSString *)shaderString
{
// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
GLint status;
const GLchar *source;
source =
(GLchar *)[shaderString UTF8String];
if (!source)
{
NSLog(@"Failed to load vertex shader");
return NO;
}
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &source, NULL);
glCompileShader(*shader);
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
if (shader == &vertShader)
{
self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
}
else
{
self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
}
free(log);
}
}
// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
// NSLog(@"Compiled in %f ms", linkTime * 1000.0);
return status == GL_TRUE;
}
// END:compile
#pragma mark -
// START:addattribute
- (void)addAttribute:(NSString *)attributeName
{
if (![attributes containsObject:attributeName])
{
[attributes addObject:attributeName];
glBindAttribLocation(program,
(GLuint)[attributes indexOfObject:attributeName],
[attributeName UTF8String]);
}
}
// END:addattribute
// START:indexmethods
- (GLuint)attributeIndex:(NSString *)attributeName
{
return (GLuint)[attributes indexOfObject:attributeName];
}
- (GLuint)uniformIndex:(NSString *)uniformName
{
return glGetUniformLocation(program, [uniformName UTF8String]);
}
// END:indexmethods
#pragma mark -
// START:link
- (BOOL)link
{
// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
GLint status;
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
return NO;
if (vertShader)
{
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader)
{
glDeleteShader(fragShader);
fragShader = 0;
}
self.initialized = YES;
// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
// NSLog(@"Linked in %f ms", linkTime * 1000.0);
return YES;
}
// END:link
// START:use
- (void)use
{
glUseProgram(program);
}
// END:use
#pragma mark -
- (void)validate;
{
GLint logLength;
glValidateProgram(program);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(program, logLength, &logLength, log);
self.programLog = [NSString stringWithFormat:@"%s", log];
free(log);
}
}
#pragma mark -
// START:dealloc
- (void)dealloc
{
if (vertShader)
glDeleteShader(vertShader);
if (fragShader)
glDeleteShader(fragShader);
if (program)
glDeleteProgram(program);
}
// END:dealloc
@end
+170
View File
@@ -0,0 +1,170 @@
#import "GLProgram.h"
// Base classes
#import "GPUImageContext.h"
#import "GPUImageOutput.h"
#import "GPUImageView.h"
#import "GPUImageVideoCamera.h"
#import "GPUImageStillCamera.h"
#import "GPUImageMovie.h"
#import "GPUImagePicture.h"
#import "GPUImageRawDataInput.h"
#import "GPUImageRawDataOutput.h"
#import "GPUImageMovieWriter.h"
#import "GPUImageFilterPipeline.h"
#import "GPUImageTextureOutput.h"
#import "GPUImageFilterGroup.h"
#import "GPUImageTextureInput.h"
#import "GPUImageUIElement.h"
#import "GPUImageBuffer.h"
#import "GPUImageFramebuffer.h"
#import "GPUImageFramebufferCache.h"
// Filters
#import "GPUImageFilter.h"
#import "GPUImageTwoInputFilter.h"
#import "GPUImagePixellateFilter.h"
#import "GPUImagePixellatePositionFilter.h"
#import "GPUImageSepiaFilter.h"
#import "GPUImageColorInvertFilter.h"
#import "GPUImageSaturationFilter.h"
#import "GPUImageContrastFilter.h"
#import "GPUImageExposureFilter.h"
#import "GPUImageBrightnessFilter.h"
#import "GPUImageLevelsFilter.h"
#import "GPUImageSharpenFilter.h"
#import "GPUImageGammaFilter.h"
#import "GPUImageSobelEdgeDetectionFilter.h"
#import "GPUImageSketchFilter.h"
#import "GPUImageToonFilter.h"
#import "GPUImageSmoothToonFilter.h"
#import "GPUImageMultiplyBlendFilter.h"
#import "GPUImageDissolveBlendFilter.h"
#import "GPUImageKuwaharaFilter.h"
#import "GPUImageKuwaharaRadius3Filter.h"
#import "GPUImageVignetteFilter.h"
#import "GPUImageGaussianBlurFilter.h"
#import "GPUImageGaussianBlurPositionFilter.h"
#import "GPUImageGaussianSelectiveBlurFilter.h"
#import "GPUImageOverlayBlendFilter.h"
#import "GPUImageDarkenBlendFilter.h"
#import "GPUImageLightenBlendFilter.h"
#import "GPUImageSwirlFilter.h"
#import "GPUImageSourceOverBlendFilter.h"
#import "GPUImageColorBurnBlendFilter.h"
#import "GPUImageColorDodgeBlendFilter.h"
#import "GPUImageScreenBlendFilter.h"
#import "GPUImageExclusionBlendFilter.h"
#import "GPUImageDifferenceBlendFilter.h"
#import "GPUImageSubtractBlendFilter.h"
#import "GPUImageHardLightBlendFilter.h"
#import "GPUImageSoftLightBlendFilter.h"
#import "GPUImageColorBlendFilter.h"
#import "GPUImageHueBlendFilter.h"
#import "GPUImageSaturationBlendFilter.h"
#import "GPUImageLuminosityBlendFilter.h"
#import "GPUImageCropFilter.h"
#import "GPUImageGrayscaleFilter.h"
#import "GPUImageTransformFilter.h"
#import "GPUImageChromaKeyBlendFilter.h"
#import "GPUImageHazeFilter.h"
#import "GPUImageLuminanceThresholdFilter.h"
#import "GPUImagePosterizeFilter.h"
#import "GPUImageBoxBlurFilter.h"
#import "GPUImageAdaptiveThresholdFilter.h"
#import "GPUImageSolarizeFilter.h"
#import "GPUImageUnsharpMaskFilter.h"
#import "GPUImageBulgeDistortionFilter.h"
#import "GPUImagePinchDistortionFilter.h"
#import "GPUImageCrosshatchFilter.h"
#import "GPUImageCGAColorspaceFilter.h"
#import "GPUImagePolarPixellateFilter.h"
#import "GPUImageStretchDistortionFilter.h"
#import "GPUImagePerlinNoiseFilter.h"
#import "GPUImageJFAVoronoiFilter.h"
#import "GPUImageVoronoiConsumerFilter.h"
#import "GPUImageMosaicFilter.h"
#import "GPUImageTiltShiftFilter.h"
#import "GPUImage3x3ConvolutionFilter.h"
#import "GPUImageEmbossFilter.h"
#import "GPUImageCannyEdgeDetectionFilter.h"
#import "GPUImageThresholdEdgeDetectionFilter.h"
#import "GPUImageMaskFilter.h"
#import "GPUImageHistogramFilter.h"
#import "GPUImageHistogramGenerator.h"
#import "GPUImageHistogramEqualizationFilter.h"
#import "GPUImagePrewittEdgeDetectionFilter.h"
#import "GPUImageXYDerivativeFilter.h"
#import "GPUImageHarrisCornerDetectionFilter.h"
#import "GPUImageAlphaBlendFilter.h"
#import "GPUImageNormalBlendFilter.h"
#import "GPUImageNonMaximumSuppressionFilter.h"
#import "GPUImageRGBFilter.h"
#import "GPUImageMedianFilter.h"
#import "GPUImageBilateralFilter.h"
#import "GPUImageCrosshairGenerator.h"
#import "GPUImageToneCurveFilter.h"
#import "GPUImageNobleCornerDetectionFilter.h"
#import "GPUImageShiTomasiFeatureDetectionFilter.h"
#import "GPUImageErosionFilter.h"
#import "GPUImageRGBErosionFilter.h"
#import "GPUImageDilationFilter.h"
#import "GPUImageRGBDilationFilter.h"
#import "GPUImageOpeningFilter.h"
#import "GPUImageRGBOpeningFilter.h"
#import "GPUImageClosingFilter.h"
#import "GPUImageRGBClosingFilter.h"
#import "GPUImageColorPackingFilter.h"
#import "GPUImageSphereRefractionFilter.h"
#import "GPUImageMonochromeFilter.h"
#import "GPUImageOpacityFilter.h"
#import "GPUImageHighlightShadowFilter.h"
#import "GPUImageFalseColorFilter.h"
#import "GPUImageHSBFilter.h"
#import "GPUImageHueFilter.h"
#import "GPUImageGlassSphereFilter.h"
#import "GPUImageLookupFilter.h"
#import "GPUImageAmatorkaFilter.h"
#import "GPUImageMissEtikateFilter.h"
#import "GPUImageSoftEleganceFilter.h"
#import "GPUImageAddBlendFilter.h"
#import "GPUImageDivideBlendFilter.h"
#import "GPUImagePolkaDotFilter.h"
#import "GPUImageLocalBinaryPatternFilter.h"
#import "GPUImageColorLocalBinaryPatternFilter.h"
#import "GPUImageLanczosResamplingFilter.h"
#import "GPUImageAverageColor.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageLuminosity.h"
#import "GPUImageAverageLuminanceThresholdFilter.h"
#import "GPUImageWhiteBalanceFilter.h"
#import "GPUImageChromaKeyFilter.h"
#import "GPUImageLowPassFilter.h"
#import "GPUImageHighPassFilter.h"
#import "GPUImageMotionDetector.h"
#import "GPUImageHalftoneFilter.h"
#import "GPUImageThresholdedNonMaximumSuppressionFilter.h"
#import "GPUImageHoughTransformLineDetector.h"
#import "GPUImageParallelCoordinateLineTransformFilter.h"
#import "GPUImageThresholdSketchFilter.h"
#import "GPUImageLineGenerator.h"
#import "GPUImageLinearBurnBlendFilter.h"
#import "GPUImageGaussianBlurPositionFilter.h"
#import "GPUImagePixellatePositionFilter.h"
#import "GPUImageTwoInputCrossTextureSamplingFilter.h"
#import "GPUImagePoissonBlendFilter.h"
#import "GPUImageMotionBlurFilter.h"
#import "GPUImageZoomBlurFilter.h"
#import "GPUImageLaplacianFilter.h"
#import "GPUImageiOSBlurFilter.h"
#import "GPUImageLuminanceRangeFilter.h"
#import "GPUImageDirectionalNonMaximumSuppressionFilter.h"
#import "GPUImageDirectionalSobelEdgeDetectionFilter.h"
#import "GPUImageSingleComponentGaussianBlurFilter.h"
#import "GPUImageThreeInputFilter.h"
#import "GPUImageFourInputFilter.h"
#import "GPUImageWeakPixelInclusionFilter.h"
#import "GPUImageColorConversion.h"
#import "GPUImageColourFASTFeatureDetector.h"
#import "GPUImageColourFASTSamplingOperation.h"
+18
View File
@@ -0,0 +1,18 @@
#import "GPUImage3x3TextureSamplingFilter.h"
/** Runs a 3x3 convolution kernel against the image
*/
@interface GPUImage3x3ConvolutionFilter : GPUImage3x3TextureSamplingFilter
{
GLint convolutionMatrixUniform;
}
/** Convolution kernel to run against the image
The convolution kernel is a 3x3 matrix of values to apply to the pixel and its 8 surrounding pixels.
The matrix is specified in row-major order, with the top left pixel being one.one and the bottom right three.three
If the values in the matrix don't add up to 1.0, the image could be brightened or darkened.
*/
@property(readwrite, nonatomic) GPUMatrix3x3 convolutionKernel;
@end
+128
View File
@@ -0,0 +1,128 @@
#import "GPUImage3x3ConvolutionFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING
(
precision highp float;
uniform sampler2D inputImageTexture;
uniform mediump mat3 convolutionMatrix;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
void main()
{
mediump vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
mediump vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
mediump vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
mediump vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
mediump vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
mediump vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
mediump vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
mediump vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
mediump vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
gl_FragColor = vec4(resultColor, centerColor.a);
}
);
#else
NSString *const kGPUImage3x3ConvolutionFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
uniform mat3 convolutionMatrix;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
void main()
{
vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
vec3 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
resultColor += leftColor * convolutionMatrix[1][0] + centerColor.rgb * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
gl_FragColor = vec4(resultColor, centerColor.a);
}
);
#endif
@implementation GPUImage3x3ConvolutionFilter
@synthesize convolutionKernel = _convolutionKernel;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [self initWithFragmentShaderFromString:kGPUImage3x3ConvolutionFragmentShaderString]))
{
return nil;
}
self.convolutionKernel = (GPUMatrix3x3){
{0.f, 0.f, 0.f},
{0.f, 1.f, 0.f},
{0.f, 0.f, 0.f}
};
return self;
}
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [super initWithFragmentShaderFromString:fragmentShaderString]))
{
return nil;
}
convolutionMatrixUniform = [filterProgram uniformIndex:@"convolutionMatrix"];
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setConvolutionKernel:(GPUMatrix3x3)newValue;
{
_convolutionKernel = newValue;
[self setMatrix3f:_convolutionKernel forUniform:convolutionMatrixUniform program:filterProgram];
}
@end
@@ -0,0 +1,18 @@
#import "GPUImageFilter.h"
extern NSString *const kGPUImageNearbyTexelSamplingVertexShaderString;
@interface GPUImage3x3TextureSamplingFilter : GPUImageFilter
{
GLint texelWidthUniform, texelHeightUniform;
CGFloat texelWidth, texelHeight;
BOOL hasOverriddenImageSizeFactor;
}
// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects.
@property(readwrite, nonatomic) CGFloat texelWidth;
@property(readwrite, nonatomic) CGFloat texelHeight;
@end
@@ -0,0 +1,121 @@
#import "GPUImage3x3TextureSamplingFilter.h"
// Override vertex shader to remove dependent texture reads
NSString *const kGPUImageNearbyTexelSamplingVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
uniform float texelWidth;
uniform float texelHeight;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
void main()
{
gl_Position = position;
vec2 widthStep = vec2(texelWidth, 0.0);
vec2 heightStep = vec2(0.0, texelHeight);
vec2 widthHeightStep = vec2(texelWidth, texelHeight);
vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);
textureCoordinate = inputTextureCoordinate.xy;
leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;
rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;
topTextureCoordinate = inputTextureCoordinate.xy - heightStep;
topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;
topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;
bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;
bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;
bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;
}
);
@implementation GPUImage3x3TextureSamplingFilter
@synthesize texelWidth = _texelWidth;
@synthesize texelHeight = _texelHeight;
#pragma mark -
#pragma mark Initialization and teardown
- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString]))
{
return nil;
}
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
return self;
}
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [self initWithVertexShaderFromString:kGPUImageNearbyTexelSamplingVertexShaderString fragmentShaderFromString:fragmentShaderString]))
{
return nil;
}
return self;
}
- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
if (!hasOverriddenImageSizeFactor)
{
_texelWidth = 1.0 / filterFrameSize.width;
_texelHeight = 1.0 / filterFrameSize.height;
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext setActiveShaderProgram:filterProgram];
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
{
glUniform1f(texelWidthUniform, _texelHeight);
glUniform1f(texelHeightUniform, _texelWidth);
}
else
{
glUniform1f(texelWidthUniform, _texelWidth);
glUniform1f(texelHeightUniform, _texelHeight);
}
});
}
}
#pragma mark -
#pragma mark Accessors
- (void)setTexelWidth:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelWidth = newValue;
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
}
- (void)setTexelHeight:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelHeight = newValue;
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
}
@end
+9
View File
@@ -0,0 +1,9 @@
#import "GPUImageFilterGroup.h"
@interface GPUImageAdaptiveThresholdFilter : GPUImageFilterGroup
/** A multiplier for the background averaging blur radius in pixels, with a default of 4
*/
@property(readwrite, nonatomic) CGFloat blurRadiusInPixels;
@end
+100
View File
@@ -0,0 +1,100 @@
#import "GPUImageAdaptiveThresholdFilter.h"
#import "GPUImageFilter.h"
#import "GPUImageTwoInputFilter.h"
#import "GPUImageGrayscaleFilter.h"
#import "GPUImageBoxBlurFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
highp float blurredInput = texture2D(inputImageTexture, textureCoordinate).r;
highp float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r;
highp float thresholdResult = step(blurredInput - 0.05, localLuminance);
gl_FragColor = vec4(vec3(thresholdResult), 1.0);
}
);
#else
NSString *const kGPUImageAdaptiveThresholdFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
float blurredInput = texture2D(inputImageTexture, textureCoordinate).r;
float localLuminance = texture2D(inputImageTexture2, textureCoordinate2).r;
float thresholdResult = step(blurredInput - 0.05, localLuminance);
gl_FragColor = vec4(vec3(thresholdResult), 1.0);
}
);
#endif
@interface GPUImageAdaptiveThresholdFilter()
{
GPUImageBoxBlurFilter *boxBlurFilter;
}
@end
@implementation GPUImageAdaptiveThresholdFilter
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
// First pass: reduce to luminance
GPUImageGrayscaleFilter *luminanceFilter = [[GPUImageGrayscaleFilter alloc] init];
[self addFilter:luminanceFilter];
// Second pass: perform a box blur
boxBlurFilter = [[GPUImageBoxBlurFilter alloc] init];
[self addFilter:boxBlurFilter];
// Third pass: compare the blurred background luminance to the local value
GPUImageFilter *adaptiveThresholdFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageAdaptiveThresholdFragmentShaderString];
[self addFilter:adaptiveThresholdFilter];
[luminanceFilter addTarget:boxBlurFilter];
[boxBlurFilter addTarget:adaptiveThresholdFilter];
// To prevent double updating of this filter, disable updates from the sharp luminance image side
[luminanceFilter addTarget:adaptiveThresholdFilter];
self.initialFilters = [NSArray arrayWithObject:luminanceFilter];
self.terminalFilter = adaptiveThresholdFilter;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
{
boxBlurFilter.blurRadiusInPixels = newValue;
}
- (CGFloat)blurRadiusInPixels;
{
return boxBlurFilter.blurRadiusInPixels;
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageAddBlendFilter : GPUImageTwoInputFilter
@end
+100
View File
@@ -0,0 +1,100 @@
#import "GPUImageAddBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
mediump float r;
if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) {
r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
} else {
r = overlay.r + base.r;
}
mediump float g;
if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) {
g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
} else {
g = overlay.g + base.g;
}
mediump float b;
if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) {
b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
} else {
b = overlay.b + base.b;
}
mediump float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(r, g, b, a);
}
);
#else
NSString *const kGPUImageAddBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
float r;
if (overlay.r * base.a + base.r * overlay.a >= overlay.a * base.a) {
r = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
} else {
r = overlay.r + base.r;
}
float g;
if (overlay.g * base.a + base.g * overlay.a >= overlay.a * base.a) {
g = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
} else {
g = overlay.g + base.g;
}
float b;
if (overlay.b * base.a + base.b * overlay.a >= overlay.a * base.a) {
b = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
} else {
b = overlay.b + base.b;
}
float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(r, g, b, a);
}
);
#endif
@implementation GPUImageAddBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageAddBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+11
View File
@@ -0,0 +1,11 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageAlphaBlendFilter : GPUImageTwoInputFilter
{
GLint mixUniform;
}
// Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 1.0 as the normal level
@property(readwrite, nonatomic) CGFloat mix;
@end
+72
View File
@@ -0,0 +1,72 @@
#import "GPUImageAlphaBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float mixturePercent;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a);
}
);
#else
NSString *const kGPUImageAlphaBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform float mixturePercent;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(mix(textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a);
}
);
#endif
@implementation GPUImageAlphaBlendFilter
@synthesize mix = _mix;
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageAlphaBlendFragmentShaderString]))
{
return nil;
}
mixUniform = [filterProgram uniformIndex:@"mixturePercent"];
self.mix = 0.5;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setMix:(CGFloat)newValue;
{
_mix = newValue;
[self setFloat:_mix forUniform:mixUniform program:filterProgram];
}
@end
+17
View File
@@ -0,0 +1,17 @@
#import "GPUImageFilterGroup.h"
@class GPUImagePicture;
/** A photo filter based on Photoshop action by Amatorka
http://amatorka.deviantart.com/art/Amatorka-Action-2-121069631
*/
// Note: If you want to use this effect you have to add lookup_amatorka.png
// from Resources folder to your application bundle.
@interface GPUImageAmatorkaFilter : GPUImageFilterGroup
{
GPUImagePicture *lookupImageSource;
}
@end
+38
View File
@@ -0,0 +1,38 @@
#import "GPUImageAmatorkaFilter.h"
#import "GPUImagePicture.h"
#import "GPUImageLookupFilter.h"
@implementation GPUImageAmatorkaFilter
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
UIImage *image = [UIImage imageNamed:@"lookup_amatorka.png"];
#else
NSImage *image = [NSImage imageNamed:@"lookup_amatorka.png"];
#endif
NSAssert(image, @"To use GPUImageAmatorkaFilter you need to add lookup_amatorka.png from GPUImage/framework/Resources to your application bundle.");
lookupImageSource = [[GPUImagePicture alloc] initWithImage:image];
GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init];
[self addFilter:lookupFilter];
[lookupImageSource addTarget:lookupFilter atTextureLocation:1];
[lookupImageSource processImage];
self.initialFilters = [NSArray arrayWithObjects:lookupFilter, nil];
self.terminalFilter = lookupFilter;
return self;
}
#pragma mark -
#pragma mark Accessors
@end
+20
View File
@@ -0,0 +1,20 @@
#import "GPUImageFilter.h"
extern NSString *const kGPUImageColorAveragingVertexShaderString;
@interface GPUImageAverageColor : GPUImageFilter
{
GLint texelWidthUniform, texelHeightUniform;
NSUInteger numberOfStages;
GLubyte *rawImagePixels;
CGSize finalStageSize;
}
// This block is called on the completion of color averaging for a frame
@property(nonatomic, copy) void(^colorAverageProcessingFinishedBlock)(CGFloat redComponent, CGFloat greenComponent, CGFloat blueComponent, CGFloat alphaComponent, CMTime frameTime);
- (void)extractAverageColorAtFrameTime:(CMTime)frameTime;
@end
+204
View File
@@ -0,0 +1,204 @@
#import "GPUImageAverageColor.h"
NSString *const kGPUImageColorAveragingVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
uniform float texelWidth;
uniform float texelHeight;
varying vec2 upperLeftInputTextureCoordinate;
varying vec2 upperRightInputTextureCoordinate;
varying vec2 lowerLeftInputTextureCoordinate;
varying vec2 lowerRightInputTextureCoordinate;
void main()
{
gl_Position = position;
upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight);
upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight);
lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight);
lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight);
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING
(
precision highp float;
uniform sampler2D inputImageTexture;
varying highp vec2 outputTextureCoordinate;
varying highp vec2 upperLeftInputTextureCoordinate;
varying highp vec2 upperRightInputTextureCoordinate;
varying highp vec2 lowerLeftInputTextureCoordinate;
varying highp vec2 lowerRightInputTextureCoordinate;
void main()
{
highp vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate);
highp vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate);
highp vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate);
highp vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate);
gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor);
}
);
#else
NSString *const kGPUImageColorAveragingFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
varying vec2 outputTextureCoordinate;
varying vec2 upperLeftInputTextureCoordinate;
varying vec2 upperRightInputTextureCoordinate;
varying vec2 lowerLeftInputTextureCoordinate;
varying vec2 lowerRightInputTextureCoordinate;
void main()
{
vec4 upperLeftColor = texture2D(inputImageTexture, upperLeftInputTextureCoordinate);
vec4 upperRightColor = texture2D(inputImageTexture, upperRightInputTextureCoordinate);
vec4 lowerLeftColor = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate);
vec4 lowerRightColor = texture2D(inputImageTexture, lowerRightInputTextureCoordinate);
gl_FragColor = 0.25 * (upperLeftColor + upperRightColor + lowerLeftColor + lowerRightColor);
}
);
#endif
@implementation GPUImageAverageColor
@synthesize colorAverageProcessingFinishedBlock = _colorAverageProcessingFinishedBlock;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithVertexShaderFromString:kGPUImageColorAveragingVertexShaderString fragmentShaderFromString:kGPUImageColorAveragingFragmentShaderString]))
{
return nil;
}
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
finalStageSize = CGSizeMake(1.0, 1.0);
__unsafe_unretained GPUImageAverageColor *weakSelf = self;
[self setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) {
[weakSelf extractAverageColorAtFrameTime:frameTime];
}];
return self;
}
- (void)dealloc;
{
if (rawImagePixels != NULL)
{
free(rawImagePixels);
}
}
#pragma mark -
#pragma mark Managing the display FBOs
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
{
if (self.preventRendering)
{
[firstInputFramebuffer unlock];
return;
}
outputFramebuffer = nil;
[GPUImageContext setActiveShaderProgram:filterProgram];
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
GLuint currentTexture = [firstInputFramebuffer texture];
NSUInteger numberOfReductionsInX = floor(log(inputTextureSize.width) / log(4.0));
NSUInteger numberOfReductionsInY = floor(log(inputTextureSize.height) / log(4.0));
NSUInteger reductionsToHitSideLimit = MIN(numberOfReductionsInX, numberOfReductionsInY);
for (NSUInteger currentReduction = 0; currentReduction < reductionsToHitSideLimit; currentReduction++)
{
CGSize currentStageSize = CGSizeMake(floor(inputTextureSize.width / pow(4.0, currentReduction + 1.0)), floor(inputTextureSize.height / pow(4.0, currentReduction + 1.0)));
[outputFramebuffer unlock];
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:currentStageSize textureOptions:self.outputTextureOptions onlyTexture:NO];
[outputFramebuffer activateFramebuffer];
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, currentTexture);
glUniform1i(filterInputTextureUniform, 2);
glUniform1f(texelWidthUniform, 0.25 / currentStageSize.width);
glUniform1f(texelHeightUniform, 0.25 / currentStageSize.height);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
currentTexture = [outputFramebuffer texture];
finalStageSize = currentStageSize;
}
[firstInputFramebuffer unlock];
}
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
{
inputRotation = kGPUImageNoRotation;
}
- (void)extractAverageColorAtFrameTime:(CMTime)frameTime;
{
runSynchronouslyOnVideoProcessingQueue(^{
// we need a normal color texture for averaging the color values
NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture internal format for this filter must be GL_RGBA.");
NSAssert(self.outputTextureOptions.type == GL_UNSIGNED_BYTE, @"The type of the output texture of this filter must be GL_UNSIGNED_BYTE.");
NSUInteger totalNumberOfPixels = round(finalStageSize.width * finalStageSize.height);
if (rawImagePixels == NULL)
{
rawImagePixels = (GLubyte *)malloc(totalNumberOfPixels * 4);
}
[GPUImageContext useImageProcessingContext];
[outputFramebuffer activateFramebuffer];
glReadPixels(0, 0, (int)finalStageSize.width, (int)finalStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels);
NSUInteger redTotal = 0, greenTotal = 0, blueTotal = 0, alphaTotal = 0;
NSUInteger byteIndex = 0;
for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
{
redTotal += rawImagePixels[byteIndex++];
greenTotal += rawImagePixels[byteIndex++];
blueTotal += rawImagePixels[byteIndex++];
alphaTotal += rawImagePixels[byteIndex++];
}
CGFloat normalizedRedTotal = (CGFloat)redTotal / (CGFloat)totalNumberOfPixels / 255.0;
CGFloat normalizedGreenTotal = (CGFloat)greenTotal / (CGFloat)totalNumberOfPixels / 255.0;
CGFloat normalizedBlueTotal = (CGFloat)blueTotal / (CGFloat)totalNumberOfPixels / 255.0;
CGFloat normalizedAlphaTotal = (CGFloat)alphaTotal / (CGFloat)totalNumberOfPixels / 255.0;
if (_colorAverageProcessingFinishedBlock != NULL)
{
_colorAverageProcessingFinishedBlock(normalizedRedTotal, normalizedGreenTotal, normalizedBlueTotal, normalizedAlphaTotal, frameTime);
}
});
}
@end
@@ -0,0 +1,8 @@
#import "GPUImageFilterGroup.h"
@interface GPUImageAverageLuminanceThresholdFilter : GPUImageFilterGroup
// This is multiplied by the continually calculated average image luminosity to arrive at the final threshold. Default is 1.0.
@property(readwrite, nonatomic) CGFloat thresholdMultiplier;
@end
@@ -0,0 +1,47 @@
#import "GPUImageAverageLuminanceThresholdFilter.h"
#import "GPUImageLuminosity.h"
#import "GPUImageLuminanceThresholdFilter.h"
@interface GPUImageAverageLuminanceThresholdFilter()
{
GPUImageLuminosity *luminosityFilter;
GPUImageLuminanceThresholdFilter *luminanceThresholdFilter;
}
@end
@implementation GPUImageAverageLuminanceThresholdFilter
@synthesize thresholdMultiplier = _thresholdMultiplier;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
self.thresholdMultiplier = 1.0;
luminosityFilter = [[GPUImageLuminosity alloc] init];
[self addFilter:luminosityFilter];
luminanceThresholdFilter = [[GPUImageLuminanceThresholdFilter alloc] init];
[self addFilter:luminanceThresholdFilter];
__unsafe_unretained GPUImageAverageLuminanceThresholdFilter *weakSelf = self;
__unsafe_unretained GPUImageLuminanceThresholdFilter *weakThreshold = luminanceThresholdFilter;
[luminosityFilter setLuminosityProcessingFinishedBlock:^(CGFloat luminosity, CMTime frameTime) {
weakThreshold.threshold = luminosity * weakSelf.thresholdMultiplier;
}];
self.initialFilters = [NSArray arrayWithObjects:luminosityFilter, luminanceThresholdFilter, nil];
self.terminalFilter = luminanceThresholdFilter;
return self;
}
@end
+10
View File
@@ -0,0 +1,10 @@
#import "GPUImageGaussianBlurFilter.h"
@interface GPUImageBilateralFilter : GPUImageGaussianBlurFilter
{
CGFloat firstDistanceNormalizationFactorUniform;
CGFloat secondDistanceNormalizationFactorUniform;
}
// A normalization factor for the distance between central color and sample color.
@property(nonatomic, readwrite) CGFloat distanceNormalizationFactor;
@end
+231
View File
@@ -0,0 +1,231 @@
#import "GPUImageBilateralFilter.h"
NSString *const kGPUImageBilateralBlurVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
const int GAUSSIAN_SAMPLES = 9;
uniform float texelWidthOffset;
uniform float texelHeightOffset;
varying vec2 textureCoordinate;
varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
// Calculate the positions for the blur
int multiplier = 0;
vec2 blurStep;
vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);
for (int i = 0; i < GAUSSIAN_SAMPLES; i++)
{
multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));
// Blur in x (horizontal)
blurStep = float(multiplier) * singleStepOffset;
blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;
}
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
const lowp int GAUSSIAN_SAMPLES = 9;
varying highp vec2 textureCoordinate;
varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];
uniform mediump float distanceNormalizationFactor;
void main()
{
lowp vec4 centralColor;
lowp float gaussianWeightTotal;
lowp vec4 sum;
lowp vec4 sampleColor;
lowp float distanceFromCentralColor;
lowp float gaussianWeight;
centralColor = texture2D(inputImageTexture, blurCoordinates[4]);
gaussianWeightTotal = 0.18;
sum = centralColor * 0.18;
sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
gl_FragColor = sum / gaussianWeightTotal;
}
);
#else
NSString *const kGPUImageBilateralFilterFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
const int GAUSSIAN_SAMPLES = 9;
varying vec2 textureCoordinate;
varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];
uniform float distanceNormalizationFactor;
void main()
{
vec4 centralColor;
float gaussianWeightTotal;
vec4 sum;
vec4 sampleColor;
float distanceFromCentralColor;
float gaussianWeight;
centralColor = texture2D(inputImageTexture, blurCoordinates[4]);
gaussianWeightTotal = 0.18;
sum = centralColor * 0.18;
sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
gaussianWeightTotal += gaussianWeight;
sum += sampleColor * gaussianWeight;
gl_FragColor = sum / gaussianWeightTotal;
}
);
#endif
@implementation GPUImageBilateralFilter
@synthesize distanceNormalizationFactor = _distanceNormalizationFactor;
- (id)init;
{
if (!(self = [super initWithFirstStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString
firstStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString
secondStageVertexShaderFromString:kGPUImageBilateralBlurVertexShaderString
secondStageFragmentShaderFromString:kGPUImageBilateralFilterFragmentShaderString])) {
return nil;
}
firstDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"];
secondDistanceNormalizationFactorUniform = [filterProgram uniformIndex:@"distanceNormalizationFactor"];
self.texelSpacingMultiplier = 4.0;
self.distanceNormalizationFactor = 8.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setDistanceNormalizationFactor:(CGFloat)newValue
{
_distanceNormalizationFactor = newValue;
[self setFloat:newValue
forUniform:firstDistanceNormalizationFactorUniform
program:filterProgram];
[self setFloat:newValue
forUniform:secondDistanceNormalizationFactorUniform
program:secondFilterProgram];
}
@end
+7
View File
@@ -0,0 +1,7 @@
#import "GPUImageGaussianBlurFilter.h"
/** A hardware-accelerated box blur of an image
*/
@interface GPUImageBoxBlurFilter : GPUImageGaussianBlurFilter
@end
+178
View File
@@ -0,0 +1,178 @@
#import "GPUImageBoxBlurFilter.h"
@implementation GPUImageBoxBlurFilter
+ (NSString *)vertexShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma;
{
if (blurRadius < 1)
{
return kGPUImageVertexShaderString;
}
// From these weights we calculate the offsets to read interpolated values from
NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7);
NSMutableString *shaderString = [[NSMutableString alloc] init];
// Header
[shaderString appendFormat:@"\
attribute vec4 position;\n\
attribute vec4 inputTextureCoordinate;\n\
\n\
uniform float texelWidthOffset;\n\
uniform float texelHeightOffset;\n\
\n\
varying vec2 blurCoordinates[%lu];\n\
\n\
void main()\n\
{\n\
gl_Position = position;\n\
\n\
vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2))];
// Inner offset loop
[shaderString appendString:@"blurCoordinates[0] = inputTextureCoordinate.xy;\n"];
for (NSUInteger currentOptimizedOffset = 0; currentOptimizedOffset < numberOfOptimizedOffsets; currentOptimizedOffset++)
{
GLfloat optimizedOffset = (GLfloat)(currentOptimizedOffset * 2) + 1.5;
[shaderString appendFormat:@"\
blurCoordinates[%lu] = inputTextureCoordinate.xy + singleStepOffset * %f;\n\
blurCoordinates[%lu] = inputTextureCoordinate.xy - singleStepOffset * %f;\n", (unsigned long)((currentOptimizedOffset * 2) + 1), optimizedOffset, (unsigned long)((currentOptimizedOffset * 2) + 2), optimizedOffset];
}
// Footer
[shaderString appendString:@"}\n"];
return shaderString;
}
+ (NSString *)fragmentShaderForOptimizedBlurOfRadius:(NSUInteger)blurRadius sigma:(CGFloat)sigma;
{
if (blurRadius < 1)
{
return kGPUImagePassthroughFragmentShaderString;
}
NSUInteger numberOfOptimizedOffsets = MIN(blurRadius / 2 + (blurRadius % 2), 7);
NSUInteger trueNumberOfOptimizedOffsets = blurRadius / 2 + (blurRadius % 2);
NSMutableString *shaderString = [[NSMutableString alloc] init];
// Header
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[shaderString appendFormat:@"\
uniform sampler2D inputImageTexture;\n\
uniform highp float texelWidthOffset;\n\
uniform highp float texelHeightOffset;\n\
\n\
varying highp vec2 blurCoordinates[%lu];\n\
\n\
void main()\n\
{\n\
lowp vec4 sum = vec4(0.0);\n", (unsigned long)(1 + (numberOfOptimizedOffsets * 2)) ];
#else
[shaderString appendFormat:@"\
uniform sampler2D inputImageTexture;\n\
uniform float texelWidthOffset;\n\
uniform float texelHeightOffset;\n\
\n\
varying vec2 blurCoordinates[%lu];\n\
\n\
void main()\n\
{\n\
vec4 sum = vec4(0.0);\n", 1 + (numberOfOptimizedOffsets * 2) ];
#endif
GLfloat boxWeight = 1.0 / (GLfloat)((blurRadius * 2) + 1);
// Inner texture loop
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0]) * %f;\n", boxWeight];
for (NSUInteger currentBlurCoordinateIndex = 0; currentBlurCoordinateIndex < numberOfOptimizedOffsets; currentBlurCoordinateIndex++)
{
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 1), boxWeight * 2.0];
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[%lu]) * %f;\n", (unsigned long)((currentBlurCoordinateIndex * 2) + 2), boxWeight * 2.0];
}
// If the number of required samples exceeds the amount we can pass in via varyings, we have to do dependent texture reads in the fragment shader
if (trueNumberOfOptimizedOffsets > numberOfOptimizedOffsets)
{
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
[shaderString appendString:@"highp vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"];
#else
[shaderString appendString:@"vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);\n"];
#endif
for (NSUInteger currentOverlowTextureRead = numberOfOptimizedOffsets; currentOverlowTextureRead < trueNumberOfOptimizedOffsets; currentOverlowTextureRead++)
{
GLfloat optimizedOffset = (GLfloat)(currentOverlowTextureRead * 2) + 1.5;
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] + singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0];
[shaderString appendFormat:@"sum += texture2D(inputImageTexture, blurCoordinates[0] - singleStepOffset * %f) * %f;\n", optimizedOffset, boxWeight * 2.0];
}
}
// Footer
[shaderString appendString:@"\
gl_FragColor = sum;\n\
}\n"];
return shaderString;
}
- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
[super setupFilterForSize:filterFrameSize];
if (shouldResizeBlurRadiusWithImageSize == YES)
{
}
}
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
// NSString *currentGaussianBlurVertexShader = [GPUImageGaussianBlurFilter vertexShaderForStandardGaussianOfRadius:4 sigma:2.0];
// NSString *currentGaussianBlurFragmentShader = [GPUImageGaussianBlurFilter fragmentShaderForStandardGaussianOfRadius:4 sigma:2.0];
NSString *currentBoxBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:4 sigma:0.0];
NSString *currentBoxBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:4 sigma:0.0];
if (!(self = [super initWithFirstStageVertexShaderFromString:currentBoxBlurVertexShader firstStageFragmentShaderFromString:currentBoxBlurFragmentShader secondStageVertexShaderFromString:currentBoxBlurVertexShader secondStageFragmentShaderFromString:currentBoxBlurFragmentShader]))
{
return nil;
}
_blurRadiusInPixels = 4.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
{
CGFloat newBlurRadius = round(round(newValue / 2.0) * 2.0); // For now, only do even radii
if (newBlurRadius != _blurRadiusInPixels)
{
_blurRadiusInPixels = newBlurRadius;
NSString *newGaussianBlurVertexShader = [[self class] vertexShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0];
NSString *newGaussianBlurFragmentShader = [[self class] fragmentShaderForOptimizedBlurOfRadius:_blurRadiusInPixels sigma:0.0];
// NSLog(@"Optimized vertex shader: \n%@", newGaussianBlurVertexShader);
// NSLog(@"Optimized fragment shader: \n%@", newGaussianBlurFragmentShader);
//
[self switchToVertexShader:newGaussianBlurVertexShader fragmentShader:newGaussianBlurFragmentShader];
}
shouldResizeBlurRadiusWithImageSize = NO;
}
@end
+11
View File
@@ -0,0 +1,11 @@
#import "GPUImageFilter.h"
@interface GPUImageBrightnessFilter : GPUImageFilter
{
GLint brightnessUniform;
}
// Brightness ranges from -1.0 to 1.0, with 0.0 as the normal level
@property(readwrite, nonatomic) CGFloat brightness;
@end
+66
View File
@@ -0,0 +1,66 @@
#import "GPUImageBrightnessFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float brightness;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
}
);
#else
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float brightness;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
}
);
#endif
@implementation GPUImageBrightnessFilter
@synthesize brightness = _brightness;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageBrightnessFragmentShaderString]))
{
return nil;
}
brightnessUniform = [filterProgram uniformIndex:@"brightness"];
self.brightness = 0.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setBrightness:(CGFloat)newValue;
{
_brightness = newValue;
[self setFloat:_brightness forUniform:brightnessUniform program:filterProgram];
}
@end
+10
View File
@@ -0,0 +1,10 @@
#import "GPUImageFilter.h"
@interface GPUImageBuffer : GPUImageFilter
{
NSMutableArray *bufferedFramebuffers;
}
@property(readwrite, nonatomic) NSUInteger bufferSize;
@end
+112
View File
@@ -0,0 +1,112 @@
#import "GPUImageBuffer.h"
@interface GPUImageBuffer()
@end
@implementation GPUImageBuffer
@synthesize bufferSize = _bufferSize;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [self initWithFragmentShaderFromString:kGPUImagePassthroughFragmentShaderString]))
{
return nil;
}
bufferedFramebuffers = [[NSMutableArray alloc] init];
// [bufferedTextures addObject:[NSNumber numberWithInt:outputTexture]];
_bufferSize = 1;
return self;
}
- (void)dealloc
{
for (GPUImageFramebuffer *currentFramebuffer in bufferedFramebuffers)
{
[currentFramebuffer unlock];
}
}
#pragma mark -
#pragma mark GPUImageInput
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
{
if ([bufferedFramebuffers count] >= _bufferSize)
{
outputFramebuffer = [bufferedFramebuffers objectAtIndex:0];
[bufferedFramebuffers removeObjectAtIndex:0];
}
else
{
// Nothing yet in the buffer, so don't process further until the buffer is full
outputFramebuffer = firstInputFramebuffer;
[firstInputFramebuffer lock];
}
[bufferedFramebuffers addObject:firstInputFramebuffer];
// Need to pass along rotation information, as we're just holding on to buffered framebuffers and not rotating them ourselves
for (id<GPUImageInput> currentTarget in targets)
{
if (currentTarget != self.targetToIgnoreForUpdates)
{
NSInteger indexOfObject = [targets indexOfObject:currentTarget];
NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
[currentTarget setInputRotation:inputRotation atIndex:textureIndex];
}
}
// Let the downstream video elements see the previous frame from the buffer before rendering a new one into place
[self informTargetsAboutNewFrameAtTime:frameTime];
// [self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]];
}
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
{
// No need to render to another texture anymore, since we'll be hanging on to the textures in our buffer
}
#pragma mark -
#pragma mark Accessors
- (void)setBufferSize:(NSUInteger)newValue;
{
if ( (newValue == _bufferSize) || (newValue < 1) )
{
return;
}
if (newValue > _bufferSize)
{
NSUInteger texturesToAdd = newValue - _bufferSize;
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToAdd; currentTextureIndex++)
{
// TODO: Deal with the growth of the size of the buffer by rotating framebuffers, no textures
}
}
else
{
NSUInteger texturesToRemove = _bufferSize - newValue;
for (NSUInteger currentTextureIndex = 0; currentTextureIndex < texturesToRemove; currentTextureIndex++)
{
GPUImageFramebuffer *lastFramebuffer = [bufferedFramebuffers lastObject];
[bufferedFramebuffers removeObjectAtIndex:([bufferedFramebuffers count] - 1)];
[lastFramebuffer unlock];
lastFramebuffer = nil;
}
}
_bufferSize = newValue;
}
@end
+16
View File
@@ -0,0 +1,16 @@
#import "GPUImageFilter.h"
/// Creates a bulge distortion on the image
@interface GPUImageBulgeDistortionFilter : GPUImageFilter
{
GLint aspectRatioUniform, radiusUniform, centerUniform, scaleUniform;
}
/// The center about which to apply the distortion, with a default of (0.5, 0.5)
@property(readwrite, nonatomic) CGPoint center;
/// The radius of the distortion, ranging from 0.0 to 1.0, with a default of 0.25
@property(readwrite, nonatomic) CGFloat radius;
/// The amount of distortion to apply, from -1.0 to 1.0, with a default of 0.5
@property(readwrite, nonatomic) CGFloat scale;
@end
+174
View File
@@ -0,0 +1,174 @@
#import "GPUImageBulgeDistortionFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp float aspectRatio;
uniform highp vec2 center;
uniform highp float radius;
uniform highp float scale;
void main()
{
highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, ((textureCoordinate.y - center.y) * aspectRatio) + center.y);
highp float dist = distance(center, textureCoordinateToUse);
textureCoordinateToUse = textureCoordinate;
if (dist < radius)
{
textureCoordinateToUse -= center;
highp float percent = 1.0 - ((radius - dist) / radius) * scale;
percent = percent * percent;
textureCoordinateToUse = textureCoordinateToUse * percent;
textureCoordinateToUse += center;
}
gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse );
}
);
#else
NSString *const kGPUImageBulgeDistortionFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float aspectRatio;
uniform vec2 center;
uniform float radius;
uniform float scale;
void main()
{
vec2 textureCoordinateToUse = vec2(textureCoordinate.x, ((textureCoordinate.y - center.y) * aspectRatio) + center.y);
float dist = distance(center, textureCoordinateToUse);
textureCoordinateToUse = textureCoordinate;
if (dist < radius)
{
textureCoordinateToUse -= center;
float percent = 1.0 - ((radius - dist) / radius) * scale;
percent = percent * percent;
textureCoordinateToUse = textureCoordinateToUse * percent;
textureCoordinateToUse += center;
}
gl_FragColor = texture2D(inputImageTexture, textureCoordinateToUse );
}
);
#endif
@interface GPUImageBulgeDistortionFilter ()
- (void)adjustAspectRatio;
@property (readwrite, nonatomic) CGFloat aspectRatio;
@end
@implementation GPUImageBulgeDistortionFilter
@synthesize aspectRatio = _aspectRatio;
@synthesize center = _center;
@synthesize radius = _radius;
@synthesize scale = _scale;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageBulgeDistortionFragmentShaderString]))
{
return nil;
}
aspectRatioUniform = [filterProgram uniformIndex:@"aspectRatio"];
radiusUniform = [filterProgram uniformIndex:@"radius"];
scaleUniform = [filterProgram uniformIndex:@"scale"];
centerUniform = [filterProgram uniformIndex:@"center"];
self.radius = 0.25;
self.scale = 0.5;
self.center = CGPointMake(0.5, 0.5);
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)adjustAspectRatio;
{
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
{
[self setAspectRatio:(inputTextureSize.width / inputTextureSize.height)];
}
else
{
[self setAspectRatio:(inputTextureSize.height / inputTextureSize.width)];
}
}
- (void)forceProcessingAtSize:(CGSize)frameSize;
{
[super forceProcessingAtSize:frameSize];
[self adjustAspectRatio];
}
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
{
CGSize oldInputSize = inputTextureSize;
[super setInputSize:newSize atIndex:textureIndex];
if ( (!CGSizeEqualToSize(oldInputSize, inputTextureSize)) && (!CGSizeEqualToSize(newSize, CGSizeZero)) )
{
[self adjustAspectRatio];
}
}
- (void)setAspectRatio:(CGFloat)newValue;
{
_aspectRatio = newValue;
[self setFloat:_aspectRatio forUniform:aspectRatioUniform program:filterProgram];
}
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
{
[super setInputRotation:newInputRotation atIndex:textureIndex];
[self setCenter:self.center];
[self adjustAspectRatio];
}
- (void)setRadius:(CGFloat)newValue;
{
_radius = newValue;
[self setFloat:_radius forUniform:radiusUniform program:filterProgram];
}
- (void)setScale:(CGFloat)newValue;
{
_scale = newValue;
[self setFloat:_scale forUniform:scaleUniform program:filterProgram];
}
- (void)setCenter:(CGPoint)newValue;
{
_center = newValue;
CGPoint rotatedPoint = [self rotatedPoint:_center forRotation:inputRotation];
[self setPoint:rotatedPoint forUniform:centerUniform program:filterProgram];
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import "GPUImageFilter.h"
@interface GPUImageCGAColorspaceFilter : GPUImageFilter
@end
+113
View File
@@ -0,0 +1,113 @@
//
// GPUImageCGAColorspaceFilter.m
//
#import "GPUImageCGAColorspaceFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
highp vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0);
//highp vec4 colorDivisor = vec4(colorDepth);
highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor);
highp vec4 color = texture2D(inputImageTexture, samplePos );
//gl_FragColor = texture2D(inputImageTexture, samplePos );
mediump vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0);
mediump vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0);
mediump vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0);
mediump vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0);
mediump vec4 endColor;
highp float blackDistance = distance(color, colorBlack);
highp float whiteDistance = distance(color, colorWhite);
highp float magentaDistance = distance(color, colorMagenta);
highp float cyanDistance = distance(color, colorCyan);
mediump vec4 finalColor;
highp float colorDistance = min(magentaDistance, cyanDistance);
colorDistance = min(colorDistance, whiteDistance);
colorDistance = min(colorDistance, blackDistance);
if (colorDistance == blackDistance) {
finalColor = colorBlack;
} else if (colorDistance == whiteDistance) {
finalColor = colorWhite;
} else if (colorDistance == cyanDistance) {
finalColor = colorCyan;
} else {
finalColor = colorMagenta;
}
gl_FragColor = finalColor;
}
);
#else
NSString *const kGPUImageCGAColorspaceFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
vec2 sampleDivisor = vec2(1.0 / 200.0, 1.0 / 320.0);
//highp vec4 colorDivisor = vec4(colorDepth);
vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor);
vec4 color = texture2D(inputImageTexture, samplePos );
//gl_FragColor = texture2D(inputImageTexture, samplePos );
vec4 colorCyan = vec4(85.0 / 255.0, 1.0, 1.0, 1.0);
vec4 colorMagenta = vec4(1.0, 85.0 / 255.0, 1.0, 1.0);
vec4 colorWhite = vec4(1.0, 1.0, 1.0, 1.0);
vec4 colorBlack = vec4(0.0, 0.0, 0.0, 1.0);
vec4 endColor;
float blackDistance = distance(color, colorBlack);
float whiteDistance = distance(color, colorWhite);
float magentaDistance = distance(color, colorMagenta);
float cyanDistance = distance(color, colorCyan);
vec4 finalColor;
float colorDistance = min(magentaDistance, cyanDistance);
colorDistance = min(colorDistance, whiteDistance);
colorDistance = min(colorDistance, blackDistance);
if (colorDistance == blackDistance) {
finalColor = colorBlack;
} else if (colorDistance == whiteDistance) {
finalColor = colorWhite;
} else if (colorDistance == cyanDistance) {
finalColor = colorCyan;
} else {
finalColor = colorMagenta;
}
gl_FragColor = finalColor;
}
);
#endif
@implementation GPUImageCGAColorspaceFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCGAColorspaceFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+62
View File
@@ -0,0 +1,62 @@
#import "GPUImageFilterGroup.h"
@class GPUImageGrayscaleFilter;
@class GPUImageSingleComponentGaussianBlurFilter;
@class GPUImageDirectionalSobelEdgeDetectionFilter;
@class GPUImageDirectionalNonMaximumSuppressionFilter;
@class GPUImageWeakPixelInclusionFilter;
/** This applies the edge detection process described by John Canny in
Canny, J., A Computational Approach To Edge Detection, IEEE Trans. Pattern Analysis and Machine Intelligence, 8(6):679698, 1986.
and implemented in OpenGL ES by
A. Ensor, S. Hall. GPU-based Image Analysis on Mobile Devices. Proceedings of Image and Vision Computing New Zealand 2011.
It starts with a conversion to luminance, followed by an accelerated 9-hit Gaussian blur. A Sobel operator is applied to obtain the overall
gradient strength in the blurred image, as well as the direction (in texture sampling steps) of the gradient. A non-maximum suppression filter
acts along the direction of the gradient, highlighting strong edges that pass the threshold and completely removing those that fail the lower
threshold. Finally, pixels from in-between these thresholds are either included in edges or rejected based on neighboring pixels.
*/
@interface GPUImageCannyEdgeDetectionFilter : GPUImageFilterGroup
{
GPUImageGrayscaleFilter *luminanceFilter;
GPUImageSingleComponentGaussianBlurFilter *blurFilter;
GPUImageDirectionalSobelEdgeDetectionFilter *edgeDetectionFilter;
GPUImageDirectionalNonMaximumSuppressionFilter *nonMaximumSuppressionFilter;
GPUImageWeakPixelInclusionFilter *weakPixelInclusionFilter;
}
/** The image width and height factors tweak the appearance of the edges.
These parameters affect the visibility of the detected edges
By default, they match the inverse of the filter size in pixels
*/
@property(readwrite, nonatomic) CGFloat texelWidth;
/** The image width and height factors tweak the appearance of the edges.
These parameters affect the visibility of the detected edges
By default, they match the inverse of the filter size in pixels
*/
@property(readwrite, nonatomic) CGFloat texelHeight;
/** The underlying blur radius for the Gaussian blur. Default is 2.0.
*/
@property (readwrite, nonatomic) CGFloat blurRadiusInPixels;
/** The underlying blur texel spacing multiplier. Default is 1.0.
*/
@property (readwrite, nonatomic) CGFloat blurTexelSpacingMultiplier;
/** Any edge with a gradient magnitude above this threshold will pass and show up in the final result.
*/
@property(readwrite, nonatomic) CGFloat upperThreshold;
/** Any edge with a gradient magnitude below this threshold will fail and be removed from the final result.
*/
@property(readwrite, nonatomic) CGFloat lowerThreshold;
@end
+125
View File
@@ -0,0 +1,125 @@
#import "GPUImageCannyEdgeDetectionFilter.h"
#import "GPUImageGrayscaleFilter.h"
#import "GPUImageDirectionalSobelEdgeDetectionFilter.h"
#import "GPUImageDirectionalNonMaximumSuppressionFilter.h"
#import "GPUImageWeakPixelInclusionFilter.h"
#import "GPUImageSingleComponentGaussianBlurFilter.h"
@implementation GPUImageCannyEdgeDetectionFilter
@synthesize upperThreshold;
@synthesize lowerThreshold;
@synthesize blurRadiusInPixels;
@synthesize blurTexelSpacingMultiplier;
@synthesize texelWidth;
@synthesize texelHeight;
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
// First pass: convert image to luminance
luminanceFilter = [[GPUImageGrayscaleFilter alloc] init];
[self addFilter:luminanceFilter];
// Second pass: apply a variable Gaussian blur
blurFilter = [[GPUImageSingleComponentGaussianBlurFilter alloc] init];
[self addFilter:blurFilter];
// Third pass: run the Sobel edge detection, with calculated gradient directions, on this blurred image
edgeDetectionFilter = [[GPUImageDirectionalSobelEdgeDetectionFilter alloc] init];
[self addFilter:edgeDetectionFilter];
// Fourth pass: apply non-maximum suppression
nonMaximumSuppressionFilter = [[GPUImageDirectionalNonMaximumSuppressionFilter alloc] init];
[self addFilter:nonMaximumSuppressionFilter];
// Fifth pass: include weak pixels to complete edges
weakPixelInclusionFilter = [[GPUImageWeakPixelInclusionFilter alloc] init];
[self addFilter:weakPixelInclusionFilter];
[luminanceFilter addTarget:blurFilter];
[blurFilter addTarget:edgeDetectionFilter];
[edgeDetectionFilter addTarget:nonMaximumSuppressionFilter];
[nonMaximumSuppressionFilter addTarget:weakPixelInclusionFilter];
self.initialFilters = [NSArray arrayWithObject:luminanceFilter];
// self.terminalFilter = nonMaximumSuppressionFilter;
self.terminalFilter = weakPixelInclusionFilter;
self.blurRadiusInPixels = 2.0;
self.blurTexelSpacingMultiplier = 1.0;
self.upperThreshold = 0.4;
self.lowerThreshold = 0.1;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
{
blurFilter.blurRadiusInPixels = newValue;
}
- (CGFloat)blurRadiusInPixels;
{
return blurFilter.blurRadiusInPixels;
}
- (void)setBlurTexelSpacingMultiplier:(CGFloat)newValue;
{
blurFilter.texelSpacingMultiplier = newValue;
}
- (CGFloat)blurTexelSpacingMultiplier;
{
return blurFilter.texelSpacingMultiplier;
}
- (void)setTexelWidth:(CGFloat)newValue;
{
edgeDetectionFilter.texelWidth = newValue;
}
- (CGFloat)texelWidth;
{
return edgeDetectionFilter.texelWidth;
}
- (void)setTexelHeight:(CGFloat)newValue;
{
edgeDetectionFilter.texelHeight = newValue;
}
- (CGFloat)texelHeight;
{
return edgeDetectionFilter.texelHeight;
}
- (void)setUpperThreshold:(CGFloat)newValue;
{
nonMaximumSuppressionFilter.upperThreshold = newValue;
}
- (CGFloat)upperThreshold;
{
return nonMaximumSuppressionFilter.upperThreshold;
}
- (void)setLowerThreshold:(CGFloat)newValue;
{
nonMaximumSuppressionFilter.lowerThreshold = newValue;
}
- (CGFloat)lowerThreshold;
{
return nonMaximumSuppressionFilter.lowerThreshold;
}
@end
+32
View File
@@ -0,0 +1,32 @@
#import "GPUImageTwoInputFilter.h"
/** Selectively replaces a color in the first image with the second image
*/
@interface GPUImageChromaKeyBlendFilter : GPUImageTwoInputFilter
{
GLint colorToReplaceUniform, thresholdSensitivityUniform, smoothingUniform;
}
/** The threshold sensitivity controls how similar pixels need to be colored to be replaced
The default value is 0.3
*/
@property(readwrite, nonatomic) CGFloat thresholdSensitivity;
/** The degree of smoothing controls how gradually similar colors are replaced in the image
The default value is 0.1
*/
@property(readwrite, nonatomic) CGFloat smoothing;
/** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0).
The default is green: (0.0, 1.0, 0.0).
@param redComponent Red component of color to be replaced
@param greenComponent Green component of color to be replaced
@param blueComponent Blue component of color to be replaced
*/
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
@end
+117
View File
@@ -0,0 +1,117 @@
#import "GPUImageChromaKeyBlendFilter.h"
// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING
(
precision highp float;
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform float thresholdSensitivity;
uniform float smoothing;
uniform vec3 colorToReplace;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
float maskCr = 0.7132 * (colorToReplace.r - maskY);
float maskCb = 0.5647 * (colorToReplace.b - maskY);
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
gl_FragColor = mix(textureColor, textureColor2, blendValue);
}
);
#else
NSString *const kGPUImageChromaKeyBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform float thresholdSensitivity;
uniform float smoothing;
uniform vec3 colorToReplace;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
float maskCr = 0.7132 * (colorToReplace.r - maskY);
float maskCb = 0.5647 * (colorToReplace.b - maskY);
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
float blendValue = 1.0 - smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
gl_FragColor = mix(textureColor, textureColor2, blendValue);
}
);
#endif
@implementation GPUImageChromaKeyBlendFilter
@synthesize thresholdSensitivity = _thresholdSensitivity;
@synthesize smoothing = _smoothing;
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyBlendFragmentShaderString]))
{
return nil;
}
thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"];
smoothingUniform = [filterProgram uniformIndex:@"smoothing"];
colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"];
self.thresholdSensitivity = 0.4;
self.smoothing = 0.1;
[self setColorToReplaceRed:0.0 green:1.0 blue:0.0];
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
{
GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent};
[self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram];
}
- (void)setThresholdSensitivity:(CGFloat)newValue;
{
_thresholdSensitivity = newValue;
[self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram];
}
- (void)setSmoothing:(CGFloat)newValue;
{
_smoothing = newValue;
[self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram];
}
@end
+30
View File
@@ -0,0 +1,30 @@
#import "GPUImageFilter.h"
@interface GPUImageChromaKeyFilter : GPUImageFilter
{
GLint colorToReplaceUniform, thresholdSensitivityUniform, smoothingUniform;
}
/** The threshold sensitivity controls how similar pixels need to be colored to be replaced
The default value is 0.3
*/
@property(readwrite, nonatomic) CGFloat thresholdSensitivity;
/** The degree of smoothing controls how gradually similar colors are replaced in the image
The default value is 0.1
*/
@property(readwrite, nonatomic) CGFloat smoothing;
/** The color to be replaced is specified using individual red, green, and blue components (normalized to 1.0).
The default is green: (0.0, 1.0, 0.0).
@param redComponent Red component of color to be replaced
@param greenComponent Green component of color to be replaced
@param blueComponent Blue component of color to be replaced
*/
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
@end
+113
View File
@@ -0,0 +1,113 @@
#import "GPUImageChromaKeyFilter.h"
// Shader code based on Apple's CIChromaKeyFilter example: https://developer.apple.com/library/mac/#samplecode/CIChromaKeyFilter/Introduction/Intro.html
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING
(
precision highp float;
varying highp vec2 textureCoordinate;
uniform float thresholdSensitivity;
uniform float smoothing;
uniform vec3 colorToReplace;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
float maskCr = 0.7132 * (colorToReplace.r - maskY);
float maskCb = 0.5647 * (colorToReplace.b - maskY);
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
}
);
#else
NSString *const kGPUImageChromaKeyFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform float thresholdSensitivity;
uniform float smoothing;
uniform vec3 colorToReplace;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
float maskCr = 0.7132 * (colorToReplace.r - maskY);
float maskCb = 0.5647 * (colorToReplace.b - maskY);
float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
float Cr = 0.7132 * (textureColor.r - Y);
float Cb = 0.5647 * (textureColor.b - Y);
// float blendValue = 1.0 - smoothstep(thresholdSensitivity - smoothing, thresholdSensitivity , abs(Cr - maskCr) + abs(Cb - maskCb));
float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));
gl_FragColor = vec4(textureColor.rgb, textureColor.a * blendValue);
}
);
#endif
@implementation GPUImageChromaKeyFilter
@synthesize thresholdSensitivity = _thresholdSensitivity;
@synthesize smoothing = _smoothing;
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageChromaKeyFragmentShaderString]))
{
return nil;
}
thresholdSensitivityUniform = [filterProgram uniformIndex:@"thresholdSensitivity"];
smoothingUniform = [filterProgram uniformIndex:@"smoothing"];
colorToReplaceUniform = [filterProgram uniformIndex:@"colorToReplace"];
self.thresholdSensitivity = 0.4;
self.smoothing = 0.1;
[self setColorToReplaceRed:0.0 green:1.0 blue:0.0];
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setColorToReplaceRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
{
GPUVector3 colorToReplace = {redComponent, greenComponent, blueComponent};
[self setVec3:colorToReplace forUniform:colorToReplaceUniform program:filterProgram];
}
- (void)setThresholdSensitivity:(CGFloat)newValue;
{
_thresholdSensitivity = newValue;
[self setFloat:(GLfloat)_thresholdSensitivity forUniform:thresholdSensitivityUniform program:filterProgram];
}
- (void)setSmoothing:(CGFloat)newValue;
{
_smoothing = newValue;
[self setFloat:(GLfloat)_smoothing forUniform:smoothingUniform program:filterProgram];
}
@end
+19
View File
@@ -0,0 +1,19 @@
#import "GPUImageFilterGroup.h"
@class GPUImageErosionFilter;
@class GPUImageDilationFilter;
// A filter that first performs a dilation on the red channel of an image, followed by an erosion of the same radius.
// This helps to filter out smaller dark elements.
@interface GPUImageClosingFilter : GPUImageFilterGroup
{
GPUImageErosionFilter *erosionFilter;
GPUImageDilationFilter *dilationFilter;
}
@property(readwrite, nonatomic) CGFloat verticalTexelSpacing, horizontalTexelSpacing;
- (id)initWithRadius:(NSUInteger)radius;
@end
+57
View File
@@ -0,0 +1,57 @@
#import "GPUImageClosingFilter.h"
#import "GPUImageErosionFilter.h"
#import "GPUImageDilationFilter.h"
@implementation GPUImageClosingFilter
@synthesize verticalTexelSpacing = _verticalTexelSpacing;
@synthesize horizontalTexelSpacing = _horizontalTexelSpacing;
- (id)init;
{
if (!(self = [self initWithRadius:1]))
{
return nil;
}
return self;
}
- (id)initWithRadius:(NSUInteger)radius;
{
if (!(self = [super init]))
{
return nil;
}
// First pass: dilation
dilationFilter = [[GPUImageDilationFilter alloc] initWithRadius:radius];
[self addFilter:dilationFilter];
// Second pass: erosion
erosionFilter = [[GPUImageErosionFilter alloc] initWithRadius:radius];
[self addFilter:erosionFilter];
[dilationFilter addTarget:erosionFilter];
self.initialFilters = [NSArray arrayWithObjects:dilationFilter, nil];
self.terminalFilter = erosionFilter;
return self;
}
- (void)setVerticalTexelSpacing:(CGFloat)newValue;
{
_verticalTexelSpacing = newValue;
erosionFilter.verticalTexelSpacing = newValue;
dilationFilter.verticalTexelSpacing = newValue;
}
- (void)setHorizontalTexelSpacing:(CGFloat)newValue;
{
_horizontalTexelSpacing = newValue;
erosionFilter.horizontalTexelSpacing = newValue;
dilationFilter.horizontalTexelSpacing = newValue;
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageColorBlendFilter : GPUImageTwoInputFilter
@end
+113
View File
@@ -0,0 +1,113 @@
#import "GPUImageColorBlendFilter.h"
/**
* Color blend mode based upon pseudo code from the PDF specification.
*/
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
highp float lum(lowp vec3 c) {
return dot(c, vec3(0.3, 0.59, 0.11));
}
lowp vec3 clipcolor(lowp vec3 c) {
highp float l = lum(c);
lowp float n = min(min(c.r, c.g), c.b);
lowp float x = max(max(c.r, c.g), c.b);
if (n < 0.0) {
c.r = l + ((c.r - l) * l) / (l - n);
c.g = l + ((c.g - l) * l) / (l - n);
c.b = l + ((c.b - l) * l) / (l - n);
}
if (x > 1.0) {
c.r = l + ((c.r - l) * (1.0 - l)) / (x - l);
c.g = l + ((c.g - l) * (1.0 - l)) / (x - l);
c.b = l + ((c.b - l) * (1.0 - l)) / (x - l);
}
return c;
}
lowp vec3 setlum(lowp vec3 c, highp float l) {
highp float d = l - lum(c);
c = c + vec3(d);
return clipcolor(c);
}
void main()
{
highp vec4 baseColor = texture2D(inputImageTexture, textureCoordinate);
highp vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a);
}
);
#else
NSString *const kGPUImageColorBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
float lum(vec3 c) {
return dot(c, vec3(0.3, 0.59, 0.11));
}
vec3 clipcolor(vec3 c) {
float l = lum(c);
float n = min(min(c.r, c.g), c.b);
float x = max(max(c.r, c.g), c.b);
if (n < 0.0) {
c.r = l + ((c.r - l) * l) / (l - n);
c.g = l + ((c.g - l) * l) / (l - n);
c.b = l + ((c.b - l) * l) / (l - n);
}
if (x > 1.0) {
c.r = l + ((c.r - l) * (1.0 - l)) / (x - l);
c.g = l + ((c.g - l) * (1.0 - l)) / (x - l);
c.b = l + ((c.b - l) * (1.0 - l)) / (x - l);
}
return c;
}
vec3 setlum(vec3 c, float l) {
float d = l - lum(c);
c = c + vec3(d);
return clipcolor(c);
}
void main()
{
vec4 baseColor = texture2D(inputImageTexture, textureCoordinate);
vec4 overlayColor = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(baseColor.rgb * (1.0 - overlayColor.a) + setlum(overlayColor.rgb, lum(baseColor.rgb)) * overlayColor.a, baseColor.a);
}
);
#endif
@implementation GPUImageColorBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+9
View File
@@ -0,0 +1,9 @@
#import "GPUImageTwoInputFilter.h"
/** Applies a color burn blend of two images
*/
@interface GPUImageColorBurnBlendFilter : GPUImageTwoInputFilter
{
}
@end
+52
View File
@@ -0,0 +1,52 @@
#import "GPUImageColorBurnBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
mediump vec4 whiteColor = vec4(1.0);
gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2;
}
);
#else
NSString *const kGPUImageColorBurnBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
vec4 whiteColor = vec4(1.0);
gl_FragColor = whiteColor - (whiteColor - textureColor) / textureColor2;
}
);
#endif
@implementation GPUImageColorBurnBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorBurnBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+12
View File
@@ -0,0 +1,12 @@
#ifndef GPUImageColorConversion_h
#define GPUImageColorConversion_h
extern GLfloat *kColorConversion601;
extern GLfloat *kColorConversion601FullRange;
extern GLfloat *kColorConversion709;
extern NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString;
extern NSString *const kGPUImageYUVFullRangeConversionForLAFragmentShaderString;
extern NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString;
#endif /* GPUImageColorConversion_h */
+159
View File
@@ -0,0 +1,159 @@
#import "GPUImageFilter.h"
// Color Conversion Constants (YUV to RGB) including adjustment from 16-235/16-240 (video range)
// BT.601, which is the standard for SDTV.
GLfloat kColorConversion601Default[] = {
1.164, 1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813, 0.0,
};
// BT.601 full range (ref: http://www.equasys.de/colorconversion.html)
GLfloat kColorConversion601FullRangeDefault[] = {
1.0, 1.0, 1.0,
0.0, -0.343, 1.765,
1.4, -0.711, 0.0,
};
// BT.709, which is the standard for HDTV.
GLfloat kColorConversion709Default[] = {
1.164, 1.164, 1.164,
0.0, -0.213, 2.112,
1.793, -0.533, 0.0,
};
GLfloat *kColorConversion601 = kColorConversion601Default;
GLfloat *kColorConversion601FullRange = kColorConversion601FullRangeDefault;
GLfloat *kColorConversion709 = kColorConversion709Default;
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
#else
NSString *const kGPUImageYUVVideoRangeConversionForRGFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
void main()
{
vec3 yuv;
vec3 rgb;
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).rg - vec2(0.5, 0.5);
// BT.601, which is the standard for SDTV is provided as a reference
/*
rgb = mat3( 1, 1, 1,
0, -.39465, 2.03211,
1.13983, -.58060, 0) * yuv;
*/
// Using BT.709 which is the standard for HDTV
rgb = mat3( 1, 1, 1,
0, -.21482, 2.12798,
1.28033, -.38059, 0) * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
#endif
NSString *const kGPUImageYUVFullRangeConversionForLAFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
uniform mediump mat3 colorConversionMatrix;
void main()
{
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = texture2D(luminanceTexture, textureCoordinate).r - (16.0/255.0);
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
#else
NSString *const kGPUImageYUVVideoRangeConversionForLAFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D luminanceTexture;
uniform sampler2D chrominanceTexture;
void main()
{
vec3 yuv;
vec3 rgb;
yuv.x = texture2D(luminanceTexture, textureCoordinate).r;
yuv.yz = texture2D(chrominanceTexture, textureCoordinate).ra - vec2(0.5, 0.5);
// BT.601, which is the standard for SDTV is provided as a reference
/*
rgb = mat3( 1, 1, 1,
0, -.39465, 2.03211,
1.13983, -.58060, 0) * yuv;
*/
// Using BT.709 which is the standard for HDTV
rgb = mat3( 1, 1, 1,
0, -.21482, 2.12798,
1.28033, -.38059, 0) * yuv;
gl_FragColor = vec4(rgb, 1);
}
);
#endif
+9
View File
@@ -0,0 +1,9 @@
#import "GPUImageTwoInputFilter.h"
/** Applies a color dodge blend of two images
*/
@interface GPUImageColorDodgeBlendFilter : GPUImageTwoInputFilter
{
}
@end
+75
View File
@@ -0,0 +1,75 @@
#import "GPUImageColorDodgeBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING
(
precision mediump float;
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a);
vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a);
vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct;
vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99);
vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct;
vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct);
gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0);
}
);
#else
NSString *const kGPUImageColorDodgeBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
vec3 baseOverlayAlphaProduct = vec3(overlay.a * base.a);
vec3 rightHandProduct = overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a);
vec3 firstBlendColor = baseOverlayAlphaProduct + rightHandProduct;
vec3 overlayRGB = clamp((overlay.rgb / clamp(overlay.a, 0.01, 1.0)) * step(0.0, overlay.a), 0.0, 0.99);
vec3 secondBlendColor = (base.rgb * overlay.a) / (1.0 - overlayRGB) + rightHandProduct;
vec3 colorChoice = step((overlay.rgb * base.a + base.rgb * overlay.a), baseOverlayAlphaProduct);
gl_FragColor = vec4(mix(firstBlendColor, secondBlendColor, colorChoice), 1.0);
}
);
#endif
@implementation GPUImageColorDodgeBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorDodgeBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+7
View File
@@ -0,0 +1,7 @@
#import "GPUImageFilter.h"
@interface GPUImageColorInvertFilter : GPUImageFilter
{
}
@end
+46
View File
@@ -0,0 +1,46 @@
#import "GPUImageColorInvertFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w);
}
);
#else
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.w);
}
);
#endif
@implementation GPUImageColorInvertFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString]))
{
return nil;
}
return self;
}
@end
@@ -0,0 +1,5 @@
#import "GPUImage3x3TextureSamplingFilter.h"
@interface GPUImageColorLocalBinaryPatternFilter : GPUImage3x3TextureSamplingFilter
@end
@@ -0,0 +1,159 @@
#import "GPUImageColorLocalBinaryPatternFilter.h"
// This is based on "Accelerating image recognition on mobile devices using GPGPU" by Miguel Bordallo Lopez, Henri Nykanen, Jari Hannuksela, Olli Silven and Markku Vehvilainen
// http://www.ee.oulu.fi/~jhannuks/publications/SPIE2011a.pdf
// Right pixel is the most significant bit, traveling clockwise to get to the upper right, which is the least significant
// If the external pixel is greater than or equal to the center, set to 1, otherwise 0
//
// 2 1 0
// 3 7
// 4 5 6
// 01101101
// 76543210
@implementation GPUImageColorLocalBinaryPatternFilter
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorLocalBinaryPatternFragmentShaderString = SHADER_STRING
(
precision highp float;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
lowp vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
lowp vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
lowp vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
lowp vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
lowp vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
lowp vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
lowp vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
lowp vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
lowp vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
lowp float redByteTally = 1.0 / 255.0 * step(centerColor.r, topRightColor.r);
redByteTally += 2.0 / 255.0 * step(centerColor.r, topColor.r);
redByteTally += 4.0 / 255.0 * step(centerColor.r, topLeftColor.r);
redByteTally += 8.0 / 255.0 * step(centerColor.r, leftColor.r);
redByteTally += 16.0 / 255.0 * step(centerColor.r, bottomLeftColor.r);
redByteTally += 32.0 / 255.0 * step(centerColor.r, bottomColor.r);
redByteTally += 64.0 / 255.0 * step(centerColor.r, bottomRightColor.r);
redByteTally += 128.0 / 255.0 * step(centerColor.r, rightColor.r);
lowp float blueByteTally = 1.0 / 255.0 * step(centerColor.b, topRightColor.b);
blueByteTally += 2.0 / 255.0 * step(centerColor.b, topColor.b);
blueByteTally += 4.0 / 255.0 * step(centerColor.b, topLeftColor.b);
blueByteTally += 8.0 / 255.0 * step(centerColor.b, leftColor.b);
blueByteTally += 16.0 / 255.0 * step(centerColor.b, bottomLeftColor.b);
blueByteTally += 32.0 / 255.0 * step(centerColor.b, bottomColor.b);
blueByteTally += 64.0 / 255.0 * step(centerColor.b, bottomRightColor.b);
blueByteTally += 128.0 / 255.0 * step(centerColor.b, rightColor.b);
lowp float greenByteTally = 1.0 / 255.0 * step(centerColor.g, topRightColor.g);
greenByteTally += 2.0 / 255.0 * step(centerColor.g, topColor.g);
greenByteTally += 4.0 / 255.0 * step(centerColor.g, topLeftColor.g);
greenByteTally += 8.0 / 255.0 * step(centerColor.g, leftColor.g);
greenByteTally += 16.0 / 255.0 * step(centerColor.g, bottomLeftColor.g);
greenByteTally += 32.0 / 255.0 * step(centerColor.g, bottomColor.g);
greenByteTally += 64.0 / 255.0 * step(centerColor.g, bottomRightColor.g);
greenByteTally += 128.0 / 255.0 * step(centerColor.g, rightColor.g);
// TODO: Replace the above with a dot product and two vec4s
// TODO: Apply step to a matrix, rather than individually
gl_FragColor = vec4(redByteTally, blueByteTally, greenByteTally, 1.0);
}
);
#else
NSString *const kGPUImageColorLocalBinaryPatternFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
vec3 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate).rgb;
vec3 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate).rgb;
vec3 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate).rgb;
vec3 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate).rgb;
vec3 leftColor = texture2D(inputImageTexture, leftTextureCoordinate).rgb;
vec3 rightColor = texture2D(inputImageTexture, rightTextureCoordinate).rgb;
vec3 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate).rgb;
vec3 topColor = texture2D(inputImageTexture, topTextureCoordinate).rgb;
float redByteTally = 1.0 / 255.0 * step(centerColor.r, topRightColor.r);
redByteTally += 2.0 / 255.0 * step(centerColor.r, topColor.r);
redByteTally += 4.0 / 255.0 * step(centerColor.r, topLeftColor.r);
redByteTally += 8.0 / 255.0 * step(centerColor.r, leftColor.r);
redByteTally += 16.0 / 255.0 * step(centerColor.r, bottomLeftColor.r);
redByteTally += 32.0 / 255.0 * step(centerColor.r, bottomColor.r);
redByteTally += 64.0 / 255.0 * step(centerColor.r, bottomRightColor.r);
redByteTally += 128.0 / 255.0 * step(centerColor.r, rightColor.r);
float blueByteTally = 1.0 / 255.0 * step(centerColor.b, topRightColor.b);
blueByteTally += 2.0 / 255.0 * step(centerColor.b, topColor.b);
blueByteTally += 4.0 / 255.0 * step(centerColor.b, topLeftColor.b);
blueByteTally += 8.0 / 255.0 * step(centerColor.b, leftColor.b);
blueByteTally += 16.0 / 255.0 * step(centerColor.b, bottomLeftColor.b);
blueByteTally += 32.0 / 255.0 * step(centerColor.b, bottomColor.b);
blueByteTally += 64.0 / 255.0 * step(centerColor.b, bottomRightColor.b);
blueByteTally += 128.0 / 255.0 * step(centerColor.b, rightColor.b);
float greenByteTally = 1.0 / 255.0 * step(centerColor.g, topRightColor.g);
greenByteTally += 2.0 / 255.0 * step(centerColor.g, topColor.g);
greenByteTally += 4.0 / 255.0 * step(centerColor.g, topLeftColor.g);
greenByteTally += 8.0 / 255.0 * step(centerColor.g, leftColor.g);
greenByteTally += 16.0 / 255.0 * step(centerColor.g, bottomLeftColor.g);
greenByteTally += 32.0 / 255.0 * step(centerColor.g, bottomColor.g);
greenByteTally += 64.0 / 255.0 * step(centerColor.g, bottomRightColor.g);
greenByteTally += 128.0 / 255.0 * step(centerColor.g, rightColor.g);
// TODO: Replace the above with a dot product and two vec4s
// TODO: Apply step to a matrix, rather than individually
gl_FragColor = vec4(redByteTally, blueByteTally, greenByteTally, 1.0);
}
);
#endif
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorLocalBinaryPatternFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+19
View File
@@ -0,0 +1,19 @@
#import "GPUImageFilter.h"
/** Transforms the colors of an image by applying a matrix to them
*/
@interface GPUImageColorMatrixFilter : GPUImageFilter
{
GLint colorMatrixUniform;
GLint intensityUniform;
}
/** A 4x4 matrix used to transform each color in an image
*/
@property(readwrite, nonatomic) GPUMatrix4x4 colorMatrix;
/** The degree to which the new transformed color replaces the original color for each pixel
*/
@property(readwrite, nonatomic) CGFloat intensity;
@end
+87
View File
@@ -0,0 +1,87 @@
#import "GPUImageColorMatrixFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp mat4 colorMatrix;
uniform lowp float intensity;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 outputColor = textureColor * colorMatrix;
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
}
);
#else
NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform mat4 colorMatrix;
uniform float intensity;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 outputColor = textureColor * colorMatrix;
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
}
);
#endif
@implementation GPUImageColorMatrixFilter
@synthesize intensity = _intensity;
@synthesize colorMatrix = _colorMatrix;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageColorMatrixFragmentShaderString]))
{
return nil;
}
colorMatrixUniform = [filterProgram uniformIndex:@"colorMatrix"];
intensityUniform = [filterProgram uniformIndex:@"intensity"];
self.intensity = 1.f;
self.colorMatrix = (GPUMatrix4x4){
{1.f, 0.f, 0.f, 0.f},
{0.f, 1.f, 0.f, 0.f},
{0.f, 0.f, 1.f, 0.f},
{0.f, 0.f, 0.f, 1.f}
};
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setIntensity:(CGFloat)newIntensity;
{
_intensity = newIntensity;
[self setFloat:_intensity forUniform:intensityUniform program:filterProgram];
}
- (void)setColorMatrix:(GPUMatrix4x4)newColorMatrix;
{
_colorMatrix = newColorMatrix;
[self setMatrix4f:_colorMatrix forUniform:colorMatrixUniform program:filterProgram];
}
@end
+10
View File
@@ -0,0 +1,10 @@
#import "GPUImageFilter.h"
@interface GPUImageColorPackingFilter : GPUImageFilter
{
GLint texelWidthUniform, texelHeightUniform;
CGFloat texelWidth, texelHeight;
}
@end
+139
View File
@@ -0,0 +1,139 @@
#import "GPUImageColorPackingFilter.h"
NSString *const kGPUImageColorPackingVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
uniform float texelWidth;
uniform float texelHeight;
varying vec2 upperLeftInputTextureCoordinate;
varying vec2 upperRightInputTextureCoordinate;
varying vec2 lowerLeftInputTextureCoordinate;
varying vec2 lowerRightInputTextureCoordinate;
void main()
{
gl_Position = position;
upperLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, -texelHeight);
upperRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, -texelHeight);
lowerLeftInputTextureCoordinate = inputTextureCoordinate.xy + vec2(-texelWidth, texelHeight);
lowerRightInputTextureCoordinate = inputTextureCoordinate.xy + vec2(texelWidth, texelHeight);
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING
(
precision lowp float;
uniform sampler2D inputImageTexture;
uniform mediump mat3 convolutionMatrix;
varying highp vec2 outputTextureCoordinate;
varying highp vec2 upperLeftInputTextureCoordinate;
varying highp vec2 upperRightInputTextureCoordinate;
varying highp vec2 lowerLeftInputTextureCoordinate;
varying highp vec2 lowerRightInputTextureCoordinate;
void main()
{
float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity);
}
);
#else
NSString *const kGPUImageColorPackingFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
uniform mat3 convolutionMatrix;
varying vec2 outputTextureCoordinate;
varying vec2 upperLeftInputTextureCoordinate;
varying vec2 upperRightInputTextureCoordinate;
varying vec2 lowerLeftInputTextureCoordinate;
varying vec2 lowerRightInputTextureCoordinate;
void main()
{
float upperLeftIntensity = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
float upperRightIntensity = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
float lowerLeftIntensity = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
float lowerRightIntensity = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
gl_FragColor = vec4(upperLeftIntensity, upperRightIntensity, lowerLeftIntensity, lowerRightIntensity);
}
);
#endif
@implementation GPUImageColorPackingFilter
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithVertexShaderFromString:kGPUImageColorPackingVertexShaderString fragmentShaderFromString:kGPUImageColorPackingFragmentShaderString]))
{
return nil;
}
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
return self;
}
- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
texelWidth = 0.5 / inputTextureSize.width;
texelHeight = 0.5 / inputTextureSize.height;
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext setActiveShaderProgram:filterProgram];
glUniform1f(texelWidthUniform, texelWidth);
glUniform1f(texelHeightUniform, texelHeight);
});
}
#pragma mark -
#pragma mark Managing the display FBOs
- (CGSize)sizeOfFBO;
{
CGSize outputSize = [self maximumOutputSize];
if ( (CGSizeEqualToSize(outputSize, CGSizeZero)) || (inputTextureSize.width < outputSize.width) )
{
CGSize quarterSize;
quarterSize.width = inputTextureSize.width / 2.0;
quarterSize.height = inputTextureSize.height / 2.0;
return quarterSize;
}
else
{
return outputSize;
}
}
#pragma mark -
#pragma mark Rendering
- (CGSize)outputFrameSize;
{
CGSize quarterSize;
quarterSize.width = inputTextureSize.width / 2.0;
quarterSize.height = inputTextureSize.height / 2.0;
return quarterSize;
}
@end
+21
View File
@@ -0,0 +1,21 @@
#import "GPUImageFilterGroup.h"
// This generates image-wide feature descriptors using the ColourFAST process, as developed and described in
//
// A. Ensor and S. Hall. ColourFAST: GPU-based feature point detection and tracking on mobile devices. 28th International Conference of Image and Vision Computing, New Zealand, 2013, p. 124-129.
//
// Seth Hall, "GPU accelerated feature algorithms for mobile devices", PhD thesis, School of Computing and Mathematical Sciences, Auckland University of Technology 2014.
// http://aut.researchgateway.ac.nz/handle/10292/7991
@class GPUImageColourFASTSamplingOperation;
@class GPUImageBoxBlurFilter;
@interface GPUImageColourFASTFeatureDetector : GPUImageFilterGroup
{
GPUImageBoxBlurFilter *blurFilter;
GPUImageColourFASTSamplingOperation *colourFASTSamplingOperation;
}
// The blur radius of the underlying box blur. The default is 3.0.
@property (readwrite, nonatomic) CGFloat blurRadiusInPixels;
@end
+48
View File
@@ -0,0 +1,48 @@
#import "GPUImageColourFASTFeatureDetector.h"
#import "GPUImageColourFASTSamplingOperation.h"
#import "GPUImageBoxBlurFilter.h"
@implementation GPUImageColourFASTFeatureDetector
@synthesize blurRadiusInPixels;
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
// First pass: apply a variable Gaussian blur
blurFilter = [[GPUImageBoxBlurFilter alloc] init];
[self addFilter:blurFilter];
// Second pass: combine the blurred image with the original sharp one
colourFASTSamplingOperation = [[GPUImageColourFASTSamplingOperation alloc] init];
[self addFilter:colourFASTSamplingOperation];
// Texture location 0 needs to be the sharp image for both the blur and the second stage processing
[blurFilter addTarget:colourFASTSamplingOperation atTextureLocation:1];
self.initialFilters = [NSArray arrayWithObjects:blurFilter, colourFASTSamplingOperation, nil];
self.terminalFilter = colourFASTSamplingOperation;
self.blurRadiusInPixels = 3.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
{
blurFilter.blurRadiusInPixels = newValue;
}
- (CGFloat)blurRadiusInPixels;
{
return blurFilter.blurRadiusInPixels;
}
@end
+22
View File
@@ -0,0 +1,22 @@
#import "GPUImageTwoInputFilter.h"
// This is the feature extraction phase of the ColourFAST feature detector, as described in:
//
// A. Ensor and S. Hall. ColourFAST: GPU-based feature point detection and tracking on mobile devices. 28th International Conference of Image and Vision Computing, New Zealand, 2013, p. 124-129.
//
// Seth Hall, "GPU accelerated feature algorithms for mobile devices", PhD thesis, School of Computing and Mathematical Sciences, Auckland University of Technology 2014.
// http://aut.researchgateway.ac.nz/handle/10292/7991
@interface GPUImageColourFASTSamplingOperation : GPUImageTwoInputFilter
{
GLint texelWidthUniform, texelHeightUniform;
CGFloat texelWidth, texelHeight;
BOOL hasOverriddenImageSizeFactor;
}
// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects.
@property(readwrite, nonatomic) CGFloat texelWidth;
@property(readwrite, nonatomic) CGFloat texelHeight;
@end
+204
View File
@@ -0,0 +1,204 @@
#import "GPUImageColourFASTSamplingOperation.h"
NSString *const kGPUImageColourFASTSamplingVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
attribute vec4 inputTextureCoordinate2;
uniform float texelWidth;
uniform float texelHeight;
varying vec2 textureCoordinate;
varying vec2 pointATextureCoordinate;
varying vec2 pointBTextureCoordinate;
varying vec2 pointCTextureCoordinate;
varying vec2 pointDTextureCoordinate;
varying vec2 pointETextureCoordinate;
varying vec2 pointFTextureCoordinate;
varying vec2 pointGTextureCoordinate;
varying vec2 pointHTextureCoordinate;
void main()
{
gl_Position = position;
float tripleTexelWidth = 3.0 * texelWidth;
float tripleTexelHeight = 3.0 * texelHeight;
textureCoordinate = inputTextureCoordinate.xy;
pointATextureCoordinate = vec2(textureCoordinate.x + tripleTexelWidth, textureCoordinate.y + texelHeight);
pointBTextureCoordinate = vec2(textureCoordinate.x + texelWidth, textureCoordinate.y + tripleTexelHeight);
pointCTextureCoordinate = vec2(textureCoordinate.x - texelWidth, textureCoordinate.y + tripleTexelHeight);
pointDTextureCoordinate = vec2(textureCoordinate.x - tripleTexelWidth, textureCoordinate.y + texelHeight);
pointETextureCoordinate = vec2(textureCoordinate.x - tripleTexelWidth, textureCoordinate.y - texelHeight);
pointFTextureCoordinate = vec2(textureCoordinate.x - texelWidth, textureCoordinate.y - tripleTexelHeight);
pointGTextureCoordinate = vec2(textureCoordinate.x + texelWidth, textureCoordinate.y - tripleTexelHeight);
pointHTextureCoordinate = vec2(textureCoordinate.x + tripleTexelWidth, textureCoordinate.y - texelHeight);
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageColourFASTSamplingFragmentShaderString = SHADER_STRING
(
precision highp float;
varying vec2 textureCoordinate;
varying vec2 pointATextureCoordinate;
varying vec2 pointBTextureCoordinate;
varying vec2 pointCTextureCoordinate;
varying vec2 pointDTextureCoordinate;
varying vec2 pointETextureCoordinate;
varying vec2 pointFTextureCoordinate;
varying vec2 pointGTextureCoordinate;
varying vec2 pointHTextureCoordinate;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
const float PITwo = 6.2832;
const float PI = 3.1416;
void main()
{
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
vec3 pointAColor = texture2D(inputImageTexture, pointATextureCoordinate).rgb;
vec3 pointBColor = texture2D(inputImageTexture, pointBTextureCoordinate).rgb;
vec3 pointCColor = texture2D(inputImageTexture, pointCTextureCoordinate).rgb;
vec3 pointDColor = texture2D(inputImageTexture, pointDTextureCoordinate).rgb;
vec3 pointEColor = texture2D(inputImageTexture, pointETextureCoordinate).rgb;
vec3 pointFColor = texture2D(inputImageTexture, pointFTextureCoordinate).rgb;
vec3 pointGColor = texture2D(inputImageTexture, pointGTextureCoordinate).rgb;
vec3 pointHColor = texture2D(inputImageTexture, pointHTextureCoordinate).rgb;
vec3 colorComparison = ((pointAColor + pointBColor + pointCColor + pointDColor + pointEColor + pointFColor + pointGColor + pointHColor) * 0.125) - centerColor;
// Direction calculation drawn from Appendix B of Seth Hall's Ph.D. thesis
vec3 dirX = (pointAColor*0.94868) + (pointBColor*0.316227) - (pointCColor*0.316227) - (pointDColor*0.94868) - (pointEColor*0.94868) - (pointFColor*0.316227) + (pointGColor*0.316227) + (pointHColor*0.94868);
vec3 dirY = (pointAColor*0.316227) + (pointBColor*0.94868) + (pointCColor*0.94868) + (pointDColor*0.316227) - (pointEColor*0.316227) - (pointFColor*0.94868) - (pointGColor*0.94868) - (pointHColor*0.316227);
vec3 absoluteDifference = abs(colorComparison);
float componentLength = length(colorComparison);
float avgX = dot(absoluteDifference, dirX) / componentLength;
float avgY = dot(absoluteDifference, dirY) / componentLength;
float angle = atan(avgY, avgX);
vec3 normalizedColorComparison = (colorComparison + 1.0) * 0.5;
gl_FragColor = vec4(normalizedColorComparison, (angle+PI)/PITwo);
}
);
#else
NSString *const kGPUImageColourFASTSamplingFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 pointATextureCoordinate;
varying vec2 pointBTextureCoordinate;
varying vec2 pointCTextureCoordinate;
varying vec2 pointDTextureCoordinate;
varying vec2 pointETextureCoordinate;
varying vec2 pointFTextureCoordinate;
varying vec2 pointGTextureCoordinate;
varying vec2 pointHTextureCoordinate;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
const float PITwo = 6.2832;
const float PI = 3.1416;
void main()
{
vec3 centerColor = texture2D(inputImageTexture, textureCoordinate).rgb;
vec3 pointAColor = texture2D(inputImageTexture, pointATextureCoordinate).rgb;
vec3 pointBColor = texture2D(inputImageTexture, pointBTextureCoordinate).rgb;
vec3 pointCColor = texture2D(inputImageTexture, pointCTextureCoordinate).rgb;
vec3 pointDColor = texture2D(inputImageTexture, pointDTextureCoordinate).rgb;
vec3 pointEColor = texture2D(inputImageTexture, pointETextureCoordinate).rgb;
vec3 pointFColor = texture2D(inputImageTexture, pointFTextureCoordinate).rgb;
vec3 pointGColor = texture2D(inputImageTexture, pointGTextureCoordinate).rgb;
vec3 pointHColor = texture2D(inputImageTexture, pointHTextureCoordinate).rgb;
vec3 colorComparison = ((pointAColor + pointBColor + pointCColor + pointDColor + pointEColor + pointFColor + pointGColor + pointHColor) * 0.125) - centerColor;
// Direction calculation drawn from Appendix B of Seth Hall's Ph.D. thesis
vec3 dirX = (pointAColor*0.94868) + (pointBColor*0.316227) - (pointCColor*0.316227) - (pointDColor*0.94868) - (pointEColor*0.94868) - (pointFColor*0.316227) + (pointGColor*0.316227) + (pointHColor*0.94868);
vec3 dirY = (pointAColor*0.316227) + (pointBColor*0.94868) + (pointCColor*0.94868) + (pointDColor*0.316227) - (pointEColor*0.316227) - (pointFColor*0.94868) - (pointGColor*0.94868) - (pointHColor*0.316227);
vec3 absoluteDifference = abs(colorComparison);
float componentLength = length(colorComparison);
float avgX = dot(absoluteDifference, dirX) / componentLength;
float avgY = dot(absoluteDifference, dirY) / componentLength;
float angle = atan(avgY, avgX);
vec3 normalizedColorComparison = (colorComparison + 1.0) * 0.5;
gl_FragColor = vec4(normalizedColorComparison, (angle+PI)/PITwo);
}
);
#endif
@implementation GPUImageColourFASTSamplingOperation
@synthesize texelWidth = _texelWidth;
@synthesize texelHeight = _texelHeight;
#pragma mark -
#pragma mark Initialization and teardown
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [super initWithVertexShaderFromString:kGPUImageColourFASTSamplingVertexShaderString fragmentShaderFromString:kGPUImageColourFASTSamplingFragmentShaderString]))
{
return nil;
}
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
return self;
}
- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
if (!hasOverriddenImageSizeFactor)
{
_texelWidth = 1.0 / filterFrameSize.width;
_texelHeight = 1.0 / filterFrameSize.height;
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext setActiveShaderProgram:filterProgram];
if (GPUImageRotationSwapsWidthAndHeight(inputRotation))
{
glUniform1f(texelWidthUniform, _texelHeight);
glUniform1f(texelHeightUniform, _texelWidth);
}
else
{
glUniform1f(texelWidthUniform, _texelWidth);
glUniform1f(texelHeightUniform, _texelHeight);
}
});
}
}
#pragma mark -
#pragma mark Accessors
- (void)setTexelWidth:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelWidth = newValue;
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
}
- (void)setTexelHeight:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelHeight = newValue;
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
}
@end
+14
View File
@@ -0,0 +1,14 @@
#import "GPUImageFilter.h"
/** Adjusts the contrast of the image
*/
@interface GPUImageContrastFilter : GPUImageFilter
{
GLint contrastUniform;
}
/** Contrast ranges from 0.0 to 4.0 (max contrast), with 1.0 as the normal level
*/
@property(readwrite, nonatomic) CGFloat contrast;
@end
+66
View File
@@ -0,0 +1,66 @@
#import "GPUImageContrastFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float contrast;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);
}
);
#else
NSString *const kGPUImageContrastFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float contrast;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4(((textureColor.rgb - vec3(0.5)) * contrast + vec3(0.5)), textureColor.w);
}
);
#endif
@implementation GPUImageContrastFilter
@synthesize contrast = _contrast;
#pragma mark -
#pragma mark Initialization
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageContrastFragmentShaderString]))
{
return nil;
}
contrastUniform = [filterProgram uniformIndex:@"contrast"];
self.contrast = 1.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setContrast:(CGFloat)newValue;
{
_contrast = newValue;
[self setFloat:_contrast forUniform:contrastUniform program:filterProgram];
}
@end
+14
View File
@@ -0,0 +1,14 @@
#import "GPUImageFilter.h"
@interface GPUImageCropFilter : GPUImageFilter
{
GLfloat cropTextureCoordinates[8];
}
// 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
+274
View File
@@ -0,0 +1,274 @@
#import "GPUImageCropFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);
#else
NSString *const kGPUImageCropFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
}
);
#endif
@interface GPUImageCropFilter ()
- (void)calculateCropTextureCoordinates;
@end
@interface GPUImageCropFilter()
{
CGSize originallySuppliedInputSize;
}
@end
@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 Rendering
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
{
if (self.preventRendering)
{
return;
}
// if (overrideInputSize)
// {
// if (CGSizeEqualToSize(forcedMaximumSize, CGSizeZero))
// {
// return;
// }
// else
// {
// CGRect insetRect = AVMakeRectWithAspectRatioInsideRect(newSize, CGRectMake(0.0, 0.0, forcedMaximumSize.width, forcedMaximumSize.height));
// inputTextureSize = insetRect.size;
// return;
// }
// }
CGSize rotatedSize = [self rotatedSize:newSize forIndex:textureIndex];
originallySuppliedInputSize = rotatedSize;
CGSize scaledSize;
scaledSize.width = rotatedSize.width * _cropRegion.size.width;
scaledSize.height = rotatedSize.height * _cropRegion.size.height;
if (CGSizeEqualToSize(scaledSize, CGSizeZero))
{
inputTextureSize = scaledSize;
}
else if (!CGSizeEqualToSize(inputTextureSize, scaledSize))
{
inputTextureSize = scaledSize;
}
}
#pragma mark -
#pragma mark GPUImageInput
- (void)calculateCropTextureCoordinates;
{
CGFloat minX = _cropRegion.origin.x;
CGFloat minY = _cropRegion.origin.y;
CGFloat maxX = CGRectGetMaxX(_cropRegion);
CGFloat maxY = CGRectGetMaxY(_cropRegion);
switch(inputRotation)
{
case kGPUImageNoRotation: // Works
{
cropTextureCoordinates[0] = minX; // 0,0
cropTextureCoordinates[1] = minY;
cropTextureCoordinates[2] = maxX; // 1,0
cropTextureCoordinates[3] = minY;
cropTextureCoordinates[4] = minX; // 0,1
cropTextureCoordinates[5] = maxY;
cropTextureCoordinates[6] = maxX; // 1,1
cropTextureCoordinates[7] = maxY;
}; break;
case kGPUImageRotateLeft: // Fixed
{
cropTextureCoordinates[0] = maxY; // 1,0
cropTextureCoordinates[1] = 1.0 - maxX;
cropTextureCoordinates[2] = maxY; // 1,1
cropTextureCoordinates[3] = 1.0 - minX;
cropTextureCoordinates[4] = minY; // 0,0
cropTextureCoordinates[5] = 1.0 - maxX;
cropTextureCoordinates[6] = minY; // 0,1
cropTextureCoordinates[7] = 1.0 - minX;
}; break;
case kGPUImageRotateRight: // Fixed
{
cropTextureCoordinates[0] = minY; // 0,1
cropTextureCoordinates[1] = 1.0 - minX;
cropTextureCoordinates[2] = minY; // 0,0
cropTextureCoordinates[3] = 1.0 - maxX;
cropTextureCoordinates[4] = maxY; // 1,1
cropTextureCoordinates[5] = 1.0 - minX;
cropTextureCoordinates[6] = maxY; // 1,0
cropTextureCoordinates[7] = 1.0 - maxX;
}; break;
case kGPUImageFlipVertical: // Works for me
{
cropTextureCoordinates[0] = minX; // 0,1
cropTextureCoordinates[1] = maxY;
cropTextureCoordinates[2] = maxX; // 1,1
cropTextureCoordinates[3] = maxY;
cropTextureCoordinates[4] = minX; // 0,0
cropTextureCoordinates[5] = minY;
cropTextureCoordinates[6] = maxX; // 1,0
cropTextureCoordinates[7] = minY;
}; break;
case kGPUImageFlipHorizonal: // Works for me
{
cropTextureCoordinates[0] = maxX; // 1,0
cropTextureCoordinates[1] = minY;
cropTextureCoordinates[2] = minX; // 0,0
cropTextureCoordinates[3] = minY;
cropTextureCoordinates[4] = maxX; // 1,1
cropTextureCoordinates[5] = maxY;
cropTextureCoordinates[6] = minX; // 0,1
cropTextureCoordinates[7] = maxY;
}; break;
case kGPUImageRotate180: // Fixed
{
cropTextureCoordinates[0] = maxX; // 1,1
cropTextureCoordinates[1] = maxY;
cropTextureCoordinates[2] = minX; // 0,1
cropTextureCoordinates[3] = maxY;
cropTextureCoordinates[4] = maxX; // 1,0
cropTextureCoordinates[5] = minY;
cropTextureCoordinates[6] = minX; // 0,0
cropTextureCoordinates[7] = minY;
}; break;
case kGPUImageRotateRightFlipVertical: // Fixed
{
cropTextureCoordinates[0] = minY; // 0,0
cropTextureCoordinates[1] = 1.0 - maxX;
cropTextureCoordinates[2] = minY; // 0,1
cropTextureCoordinates[3] = 1.0 - minX;
cropTextureCoordinates[4] = maxY; // 1,0
cropTextureCoordinates[5] = 1.0 - maxX;
cropTextureCoordinates[6] = maxY; // 1,1
cropTextureCoordinates[7] = 1.0 - minX;
}; break;
case kGPUImageRotateRightFlipHorizontal: // Fixed
{
cropTextureCoordinates[0] = maxY; // 1,1
cropTextureCoordinates[1] = 1.0 - minX;
cropTextureCoordinates[2] = maxY; // 1,0
cropTextureCoordinates[3] = 1.0 - maxX;
cropTextureCoordinates[4] = minY; // 0,1
cropTextureCoordinates[5] = 1.0 - minX;
cropTextureCoordinates[6] = minY; // 0,0
cropTextureCoordinates[7] = 1.0 - maxX;
}; break;
}
}
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
{
static const GLfloat cropSquareVertices[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
[self renderToTextureWithVertices:cropSquareVertices textureCoordinates:cropTextureCoordinates];
[self informTargetsAboutNewFrameAtTime:frameTime];
}
#pragma mark -
#pragma mark Accessors
- (void)setCropRegion:(CGRect)newValue;
{
NSParameterAssert(newValue.origin.x >= 0 && newValue.origin.x <= 1 &&
newValue.origin.y >= 0 && newValue.origin.y <= 1 &&
newValue.size.width >= 0 && newValue.size.width <= 1 &&
newValue.size.height >= 0 && newValue.size.height <= 1);
_cropRegion = newValue;
[self calculateCropTextureCoordinates];
}
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
{
[super setInputRotation:newInputRotation atIndex:textureIndex];
[self calculateCropTextureCoordinates];
}
@end
+17
View File
@@ -0,0 +1,17 @@
#import "GPUImageFilter.h"
@interface GPUImageCrosshairGenerator : GPUImageFilter
{
GLint crosshairWidthUniform, crosshairColorUniform;
}
// The width of the displayed crosshairs, in pixels. Currently this only works well for odd widths. The default is 5.
@property(readwrite, nonatomic) CGFloat crosshairWidth;
// The color of the crosshairs is specified using individual red, green, and blue components (normalized to 1.0). The default is green: (0.0, 1.0, 0.0).
- (void)setCrosshairColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
// Rendering
- (void)renderCrosshairsFromArray:(GLfloat *)crosshairCoordinates count:(NSUInteger)numberOfCrosshairs frameTime:(CMTime)frameTime;
@end
+139
View File
@@ -0,0 +1,139 @@
#import "GPUImageCrosshairGenerator.h"
NSString *const kGPUImageCrosshairVertexShaderString = SHADER_STRING
(
attribute vec4 position;
uniform float crosshairWidth;
varying vec2 centerLocation;
varying float pointSpacing;
void main()
{
gl_Position = vec4(((position.xy * 2.0) - 1.0), 0.0, 1.0);
gl_PointSize = crosshairWidth + 1.0;
pointSpacing = 1.0 / crosshairWidth;
centerLocation = vec2(pointSpacing * ceil(crosshairWidth / 2.0), pointSpacing * ceil(crosshairWidth / 2.0));
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING
(
uniform lowp vec3 crosshairColor;
varying highp vec2 centerLocation;
varying highp float pointSpacing;
void main()
{
lowp vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy);
lowp float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09);
gl_FragColor = vec4(crosshairColor * axisTest, axisTest);
// gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0);
}
);
#else
NSString *const kGPUImageCrosshairFragmentShaderString = SHADER_STRING
(
GPUImageEscapedHashIdentifier(version 120)\n
uniform vec3 crosshairColor;
varying vec2 centerLocation;
varying float pointSpacing;
void main()
{
vec2 distanceFromCenter = abs(centerLocation - gl_PointCoord.xy);
float axisTest = step(pointSpacing, gl_PointCoord.y) * step(distanceFromCenter.x, 0.09) + step(pointSpacing, gl_PointCoord.x) * step(distanceFromCenter.y, 0.09);
gl_FragColor = vec4(crosshairColor * axisTest, axisTest);
// gl_FragColor = vec4(distanceFromCenterInX, distanceFromCenterInY, 0.0, 1.0);
}
);
#endif
@implementation GPUImageCrosshairGenerator
@synthesize crosshairWidth = _crosshairWidth;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithVertexShaderFromString:kGPUImageCrosshairVertexShaderString fragmentShaderFromString:kGPUImageCrosshairFragmentShaderString]))
{
return nil;
}
runSynchronouslyOnVideoProcessingQueue(^{
crosshairWidthUniform = [filterProgram uniformIndex:@"crosshairWidth"];
crosshairColorUniform = [filterProgram uniformIndex:@"crosshairColor"];
self.crosshairWidth = 5.0;
[self setCrosshairColorRed:0.0 green:1.0 blue:0.0];
});
return self;
}
#pragma mark -
#pragma mark Rendering
- (void)renderCrosshairsFromArray:(GLfloat *)crosshairCoordinates count:(NSUInteger)numberOfCrosshairs frameTime:(CMTime)frameTime;
{
if (self.preventRendering)
{
return;
}
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext setActiveShaderProgram:filterProgram];
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
#else
glEnable(GL_POINT_SPRITE);
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
#endif
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO];
[outputFramebuffer activateFramebuffer];
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, crosshairCoordinates);
glDrawArrays(GL_POINTS, 0, (GLsizei)numberOfCrosshairs);
[self informTargetsAboutNewFrameAtTime:frameTime];
});
}
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
{
// Prevent rendering of the frame by normal means
}
#pragma mark -
#pragma mark Accessors
- (void)setCrosshairWidth:(CGFloat)newValue;
{
_crosshairWidth = newValue;
[self setFloat:_crosshairWidth forUniform:crosshairWidthUniform program:filterProgram];
}
- (void)setCrosshairColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
{
GPUVector3 crosshairColor = {redComponent, greenComponent, blueComponent};
[self setVec3:crosshairColor forUniform:crosshairColorUniform program:filterProgram];
}
@end
+13
View File
@@ -0,0 +1,13 @@
#import "GPUImageFilter.h"
@interface GPUImageCrosshatchFilter : GPUImageFilter
{
GLint crossHatchSpacingUniform, lineWidthUniform;
}
// The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03.
@property(readwrite, nonatomic) CGFloat crossHatchSpacing;
// A relative width for the crosshatch lines. The default is 0.003.
@property(readwrite, nonatomic) CGFloat lineWidth;
@end
+163
View File
@@ -0,0 +1,163 @@
#import "GPUImageCrosshatchFilter.h"
// Shader code based on http://machinesdontcare.wordpress.com/
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp float crossHatchSpacing;
uniform highp float lineWidth;
const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
void main()
{
highp float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W);
lowp vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);
if (luminance < 1.00)
{
if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.75)
{
if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.50)
{
if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.3)
{
if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
gl_FragColor = colorToDisplay;
}
);
#else
NSString *const kGPUImageCrosshatchFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float crossHatchSpacing;
uniform float lineWidth;
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
void main()
{
float luminance = dot(texture2D(inputImageTexture, textureCoordinate).rgb, W);
vec4 colorToDisplay = vec4(1.0, 1.0, 1.0, 1.0);
if (luminance < 1.00)
{
if (mod(textureCoordinate.x + textureCoordinate.y, crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.75)
{
if (mod(textureCoordinate.x - textureCoordinate.y, crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.50)
{
if (mod(textureCoordinate.x + textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
if (luminance < 0.3)
{
if (mod(textureCoordinate.x - textureCoordinate.y - (crossHatchSpacing / 2.0), crossHatchSpacing) <= lineWidth)
{
colorToDisplay = vec4(0.0, 0.0, 0.0, 1.0);
}
}
gl_FragColor = colorToDisplay;
}
);
#endif
@implementation GPUImageCrosshatchFilter
@synthesize crossHatchSpacing = _crossHatchSpacing;
@synthesize lineWidth = _lineWidth;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageCrosshatchFragmentShaderString]))
{
return nil;
}
crossHatchSpacingUniform = [filterProgram uniformIndex:@"crossHatchSpacing"];
lineWidthUniform = [filterProgram uniformIndex:@"lineWidth"];
self.crossHatchSpacing = 0.03;
self.lineWidth = 0.003;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setCrossHatchSpacing:(CGFloat)newValue;
{
CGFloat singlePixelSpacing;
if (inputTextureSize.width != 0.0)
{
singlePixelSpacing = 1.0 / inputTextureSize.width;
}
else
{
singlePixelSpacing = 1.0 / 2048.0;
}
if (newValue < singlePixelSpacing)
{
_crossHatchSpacing = singlePixelSpacing;
}
else
{
_crossHatchSpacing = newValue;
}
[self setFloat:_crossHatchSpacing forUniform:crossHatchSpacingUniform program:filterProgram];
}
- (void)setLineWidth:(CGFloat)newValue;
{
_lineWidth = newValue;
[self setFloat:_lineWidth forUniform:lineWidthUniform program:filterProgram];
}
@end
+7
View File
@@ -0,0 +1,7 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageDarkenBlendFilter : GPUImageTwoInputFilter
{
}
@end
+52
View File
@@ -0,0 +1,52 @@
#import "GPUImageDarkenBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
lowp vec4 base = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0);
}
);
#else
NSString *const kGPUImageDarkenBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlayer = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(min(overlayer.rgb * base.a, base.rgb * overlayer.a) + overlayer.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlayer.a), 1.0);
}
);
#endif
@implementation GPUImageDarkenBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDarkenBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+7
View File
@@ -0,0 +1,7 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageDifferenceBlendFilter : GPUImageTwoInputFilter
{
}
@end
+50
View File
@@ -0,0 +1,50 @@
#import "GPUImageDifferenceBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
mediump vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a);
}
);
#else
NSString *const kGPUImageDifferenceBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = vec4(abs(textureColor2.rgb - textureColor.rgb), textureColor.a);
}
);
#endif
@implementation GPUImageDifferenceBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDifferenceBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+16
View File
@@ -0,0 +1,16 @@
#import "GPUImageTwoPassTextureSamplingFilter.h"
// For each pixel, this sets it to the maximum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center.
// This extends out bright features, and is most commonly used with black-and-white thresholded images.
extern NSString *const kGPUImageDilationRadiusOneVertexShaderString;
extern NSString *const kGPUImageDilationRadiusTwoVertexShaderString;
extern NSString *const kGPUImageDilationRadiusThreeVertexShaderString;
extern NSString *const kGPUImageDilationRadiusFourVertexShaderString;
@interface GPUImageDilationFilter : GPUImageTwoPassTextureSamplingFilter
// Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4.
- (id)initWithRadius:(NSUInteger)dilationRadius;
@end
+431
View File
@@ -0,0 +1,431 @@
#import "GPUImageDilationFilter.h"
@implementation GPUImageDilationFilter
NSString *const kGPUImageDilationRadiusOneVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
uniform float texelWidthOffset;
uniform float texelHeightOffset;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
void main()
{
gl_Position = position;
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
centerTextureCoordinate = inputTextureCoordinate;
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
}
);
NSString *const kGPUImageDilationRadiusTwoVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
uniform float texelWidthOffset;
uniform float texelHeightOffset;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
void main()
{
gl_Position = position;
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
centerTextureCoordinate = inputTextureCoordinate;
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
}
);
NSString *const kGPUImageDilationRadiusThreeVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
uniform float texelWidthOffset;
uniform float texelHeightOffset;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
void main()
{
gl_Position = position;
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
centerTextureCoordinate = inputTextureCoordinate;
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);
threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);
}
);
NSString *const kGPUImageDilationRadiusFourVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec2 inputTextureCoordinate;
uniform float texelWidthOffset;
uniform float texelHeightOffset;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
varying vec2 fourStepsPositiveTextureCoordinate;
varying vec2 fourStepsNegativeTextureCoordinate;
void main()
{
gl_Position = position;
vec2 offset = vec2(texelWidthOffset, texelHeightOffset);
centerTextureCoordinate = inputTextureCoordinate;
oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;
oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;
twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);
twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);
threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);
threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);
fourStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 4.0);
fourStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 4.0);
}
);
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
maxValue = max(maxValue, threeStepsPositiveIntensity);
maxValue = max(maxValue, threeStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
varying vec2 fourStepsPositiveTextureCoordinate;
varying vec2 fourStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
maxValue = max(maxValue, threeStepsPositiveIntensity);
maxValue = max(maxValue, threeStepsNegativeIntensity);
maxValue = max(maxValue, fourStepsPositiveIntensity);
maxValue = max(maxValue, fourStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
#else
NSString *const kGPUImageDilationRadiusOneFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusTwoFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusThreeFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
maxValue = max(maxValue, threeStepsPositiveIntensity);
maxValue = max(maxValue, threeStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
NSString *const kGPUImageDilationRadiusFourFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
varying vec2 fourStepsPositiveTextureCoordinate;
varying vec2 fourStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
float maxValue = max(centerIntensity, oneStepPositiveIntensity);
maxValue = max(maxValue, oneStepNegativeIntensity);
maxValue = max(maxValue, twoStepsPositiveIntensity);
maxValue = max(maxValue, twoStepsNegativeIntensity);
maxValue = max(maxValue, threeStepsPositiveIntensity);
maxValue = max(maxValue, threeStepsNegativeIntensity);
maxValue = max(maxValue, fourStepsPositiveIntensity);
maxValue = max(maxValue, fourStepsNegativeIntensity);
gl_FragColor = vec4(vec3(maxValue), 1.0);
}
);
#endif
#pragma mark -
#pragma mark Initialization and teardown
- (id)initWithRadius:(NSUInteger)dilationRadius;
{
NSString *fragmentShaderForThisRadius = nil;
NSString *vertexShaderForThisRadius = nil;
switch (dilationRadius)
{
case 0:
case 1:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString;
fragmentShaderForThisRadius = kGPUImageDilationRadiusOneFragmentShaderString;
}; break;
case 2:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString;
fragmentShaderForThisRadius = kGPUImageDilationRadiusTwoFragmentShaderString;
}; break;
case 3:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString;
fragmentShaderForThisRadius = kGPUImageDilationRadiusThreeFragmentShaderString;
}; break;
case 4:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString;
}; break;
default:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
fragmentShaderForThisRadius = kGPUImageDilationRadiusFourFragmentShaderString;
}; break;
}
if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius]))
{
return nil;
}
return self;
}
- (id)init;
{
if (!(self = [self initWithRadius:1]))
{
return nil;
}
return self;
}
@end
@@ -0,0 +1,19 @@
#import "GPUImageFilter.h"
@interface GPUImageDirectionalNonMaximumSuppressionFilter : GPUImageFilter
{
GLint texelWidthUniform, texelHeightUniform;
GLint upperThresholdUniform, lowerThresholdUniform;
BOOL hasOverriddenImageSizeFactor;
}
// The texel width and height determines how far out to sample from this texel. By default, this is the normalized width of a pixel, but this can be overridden for different effects.
@property(readwrite, nonatomic) CGFloat texelWidth;
@property(readwrite, nonatomic) CGFloat texelHeight;
// These thresholds set cutoffs for the intensities that definitely get registered (upper threshold) and those that definitely don't (lower threshold)
@property(readwrite, nonatomic) CGFloat upperThreshold;
@property(readwrite, nonatomic) CGFloat lowerThreshold;
@end
@@ -0,0 +1,141 @@
#import "GPUImageDirectionalNonMaximumSuppressionFilter.h"
@implementation GPUImageDirectionalNonMaximumSuppressionFilter
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING
(
precision mediump float;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp float texelWidth;
uniform highp float texelHeight;
uniform mediump float upperThreshold;
uniform mediump float lowerThreshold;
void main()
{
vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb;
vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);
float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r;
float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r;
float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);
float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
multiplier = multiplier * thresholdCompliance;
gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
}
);
#else
NSString *const kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float texelWidth;
uniform float texelHeight;
uniform float upperThreshold;
uniform float lowerThreshold;
void main()
{
vec3 currentGradientAndDirection = texture2D(inputImageTexture, textureCoordinate).rgb;
vec2 gradientDirection = ((currentGradientAndDirection.gb * 2.0) - 1.0) * vec2(texelWidth, texelHeight);
float firstSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate + gradientDirection).r;
float secondSampledGradientMagnitude = texture2D(inputImageTexture, textureCoordinate - gradientDirection).r;
float multiplier = step(firstSampledGradientMagnitude, currentGradientAndDirection.r);
multiplier = multiplier * step(secondSampledGradientMagnitude, currentGradientAndDirection.r);
float thresholdCompliance = smoothstep(lowerThreshold, upperThreshold, currentGradientAndDirection.r);
multiplier = multiplier * thresholdCompliance;
gl_FragColor = vec4(multiplier, multiplier, multiplier, 1.0);
}
);
#endif
@synthesize texelWidth = _texelWidth;
@synthesize texelHeight = _texelHeight;
@synthesize upperThreshold = _upperThreshold;
@synthesize lowerThreshold = _lowerThreshold;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalNonmaximumSuppressionFragmentShaderString]))
{
return nil;
}
texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
upperThresholdUniform = [filterProgram uniformIndex:@"upperThreshold"];
lowerThresholdUniform = [filterProgram uniformIndex:@"lowerThreshold"];
self.upperThreshold = 0.5;
self.lowerThreshold = 0.1;
return self;
}
- (void)setupFilterForSize:(CGSize)filterFrameSize;
{
if (!hasOverriddenImageSizeFactor)
{
_texelWidth = 1.0 / filterFrameSize.width;
_texelHeight = 1.0 / filterFrameSize.height;
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext setActiveShaderProgram:filterProgram];
glUniform1f(texelWidthUniform, _texelWidth);
glUniform1f(texelHeightUniform, _texelHeight);
});
}
}
#pragma mark -
#pragma mark Accessors
- (void)setTexelWidth:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelWidth = newValue;
[self setFloat:_texelWidth forUniform:texelWidthUniform program:filterProgram];
}
- (void)setTexelHeight:(CGFloat)newValue;
{
hasOverriddenImageSizeFactor = YES;
_texelHeight = newValue;
[self setFloat:_texelHeight forUniform:texelHeightUniform program:filterProgram];
}
- (void)setLowerThreshold:(CGFloat)newValue;
{
_lowerThreshold = newValue;
[self setFloat:_lowerThreshold forUniform:lowerThresholdUniform program:filterProgram];
}
- (void)setUpperThreshold:(CGFloat)newValue;
{
_upperThreshold = newValue;
[self setFloat:_upperThreshold forUniform:upperThresholdUniform program:filterProgram];
}
@end
@@ -0,0 +1,5 @@
#import "GPUImage3x3TextureSamplingFilter.h"
@interface GPUImageDirectionalSobelEdgeDetectionFilter : GPUImage3x3TextureSamplingFilter
@end
@@ -0,0 +1,103 @@
#import "GPUImageDirectionalSobelEdgeDetectionFilter.h"
@implementation GPUImageDirectionalSobelEdgeDetectionFilter
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING
(
precision mediump float;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
vec2 gradientDirection;
gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
float gradientMagnitude = length(gradientDirection);
vec2 normalizedDirection = normalize(gradientDirection);
normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0
gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
}
);
#else
NSString *const kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;
float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;
float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;
float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;
float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;
float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;
float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;
float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;
vec2 gradientDirection;
gradientDirection.x = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;
gradientDirection.y = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
float gradientMagnitude = length(gradientDirection);
vec2 normalizedDirection = normalize(gradientDirection);
normalizedDirection = sign(normalizedDirection) * floor(abs(normalizedDirection) + 0.617316); // Offset by 1-sin(pi/8) to set to 0 if near axis, 1 if away
normalizedDirection = (normalizedDirection + 1.0) * 0.5; // Place -1.0 - 1.0 within 0 - 1.0
gl_FragColor = vec4(gradientMagnitude, normalizedDirection.x, normalizedDirection.y, 1.0);
}
);
#endif
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDirectionalSobelEdgeDetectionFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+11
View File
@@ -0,0 +1,11 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageDissolveBlendFilter : GPUImageTwoInputFilter
{
GLint mixUniform;
}
// Mix ranges from 0.0 (only image 1) to 1.0 (only image 2), with 0.5 (half of either) as the normal level
@property(readwrite, nonatomic) CGFloat mix;
@end
+72
View File
@@ -0,0 +1,72 @@
#import "GPUImageDissolveBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform lowp float mixturePercent;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = mix(textureColor, textureColor2, mixturePercent);
}
);
#else
NSString *const kGPUImageDissolveBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
uniform float mixturePercent;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
vec4 textureColor2 = texture2D(inputImageTexture2, textureCoordinate2);
gl_FragColor = mix(textureColor, textureColor2, mixturePercent);
}
);
#endif
@implementation GPUImageDissolveBlendFilter
@synthesize mix = _mix;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDissolveBlendFragmentShaderString]))
{
return nil;
}
mixUniform = [filterProgram uniformIndex:@"mixturePercent"];
self.mix = 0.5;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setMix:(CGFloat)newValue;
{
_mix = newValue;
[self setFloat:_mix forUniform:mixUniform program:filterProgram];
}
@end
+5
View File
@@ -0,0 +1,5 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageDivideBlendFilter : GPUImageTwoInputFilter
@end
+96
View File
@@ -0,0 +1,96 @@
#import "GPUImageDivideBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageDivideBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
mediump float ra;
if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a)))
ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
else
ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
mediump float ga;
if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a)))
ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
else
ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
mediump float ba;
if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a)))
ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
else
ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
mediump float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(ra, ga, ba, a);
}
);
#else
NSString *const kGPUImageDivideBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
float ra;
if (overlay.a == 0.0 || ((base.r / overlay.r) > (base.a / overlay.a)))
ra = overlay.a * base.a + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
else
ra = (base.r * overlay.a * overlay.a) / overlay.r + overlay.r * (1.0 - base.a) + base.r * (1.0 - overlay.a);
float ga;
if (overlay.a == 0.0 || ((base.g / overlay.g) > (base.a / overlay.a)))
ga = overlay.a * base.a + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
else
ga = (base.g * overlay.a * overlay.a) / overlay.g + overlay.g * (1.0 - base.a) + base.g * (1.0 - overlay.a);
float ba;
if (overlay.a == 0.0 || ((base.b / overlay.b) > (base.a / overlay.a)))
ba = overlay.a * base.a + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
else
ba = (base.b * overlay.a * overlay.a) / overlay.b + overlay.b * (1.0 - base.a) + base.b * (1.0 - overlay.a);
float a = overlay.a + base.a - overlay.a * base.a;
gl_FragColor = vec4(ra, ga, ba, a);
}
);
#endif
@implementation GPUImageDivideBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageDivideBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+8
View File
@@ -0,0 +1,8 @@
#import "GPUImage3x3ConvolutionFilter.h"
@interface GPUImageEmbossFilter : GPUImage3x3ConvolutionFilter
// The strength of the embossing, from 0.0 to 4.0, with 1.0 as the normal level
@property(readwrite, nonatomic) CGFloat intensity;
@end
+49
View File
@@ -0,0 +1,49 @@
#import "GPUImageEmbossFilter.h"
@implementation GPUImageEmbossFilter
@synthesize intensity = _intensity;
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
self.intensity = 1.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setIntensity:(CGFloat)newValue;
{
// [(GPUImage3x3ConvolutionFilter *)filter setConvolutionMatrix:(GPUMatrix3x3){
// {-2.0f, -1.0f, 0.0f},
// {-1.0f, 1.0f, 1.0f},
// { 0.0f, 1.0f, 2.0f}
// }];
_intensity = newValue;
GPUMatrix3x3 newConvolutionMatrix;
newConvolutionMatrix.one.one = _intensity * (-2.0);
newConvolutionMatrix.one.two = -_intensity;
newConvolutionMatrix.one.three = 0.0f;
newConvolutionMatrix.two.one = -_intensity;
newConvolutionMatrix.two.two = 1.0;
newConvolutionMatrix.two.three = _intensity;
newConvolutionMatrix.three.one = 0.0f;
newConvolutionMatrix.three.two = _intensity;
newConvolutionMatrix.three.three = _intensity * 2.0;
self.convolutionKernel = newConvolutionMatrix;
}
@end
+11
View File
@@ -0,0 +1,11 @@
#import "GPUImageTwoPassTextureSamplingFilter.h"
// For each pixel, this sets it to the minimum value of the red channel in a rectangular neighborhood extending out dilationRadius pixels from the center.
// This extends out dark features, and is most commonly used with black-and-white thresholded images.
@interface GPUImageErosionFilter : GPUImageTwoPassTextureSamplingFilter
// Acceptable values for erosionRadius, which sets the distance in pixels to sample out from the center, are 1, 2, 3, and 4.
- (id)initWithRadius:(NSUInteger)erosionRadius;
@end
+312
View File
@@ -0,0 +1,312 @@
#import "GPUImageErosionFilter.h"
#import "GPUImageDilationFilter.h"
@implementation GPUImageErosionFilter
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageErosionRadiusOneFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
lowp float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusTwoFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
lowp float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusThreeFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
lowp float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
minValue = min(minValue, threeStepsPositiveIntensity);
minValue = min(minValue, threeStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusFourFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
varying vec2 fourStepsPositiveTextureCoordinate;
varying vec2 fourStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
lowp float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
minValue = min(minValue, threeStepsPositiveIntensity);
minValue = min(minValue, threeStepsNegativeIntensity);
minValue = min(minValue, fourStepsPositiveIntensity);
minValue = min(minValue, fourStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
#else
NSString *const kGPUImageErosionRadiusOneFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusTwoFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusThreeFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
minValue = min(minValue, threeStepsPositiveIntensity);
minValue = min(minValue, threeStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
NSString *const kGPUImageErosionRadiusFourFragmentShaderString = SHADER_STRING
(
varying vec2 centerTextureCoordinate;
varying vec2 oneStepPositiveTextureCoordinate;
varying vec2 oneStepNegativeTextureCoordinate;
varying vec2 twoStepsPositiveTextureCoordinate;
varying vec2 twoStepsNegativeTextureCoordinate;
varying vec2 threeStepsPositiveTextureCoordinate;
varying vec2 threeStepsNegativeTextureCoordinate;
varying vec2 fourStepsPositiveTextureCoordinate;
varying vec2 fourStepsNegativeTextureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;
float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;
float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;
float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;
float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;
float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;
float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;
float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;
float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;
float minValue = min(centerIntensity, oneStepPositiveIntensity);
minValue = min(minValue, oneStepNegativeIntensity);
minValue = min(minValue, twoStepsPositiveIntensity);
minValue = min(minValue, twoStepsNegativeIntensity);
minValue = min(minValue, threeStepsPositiveIntensity);
minValue = min(minValue, threeStepsNegativeIntensity);
minValue = min(minValue, fourStepsPositiveIntensity);
minValue = min(minValue, fourStepsNegativeIntensity);
gl_FragColor = vec4(vec3(minValue), 1.0);
}
);
#endif
#pragma mark -
#pragma mark Initialization and teardown
- (id)initWithRadius:(NSUInteger)dilationRadius;
{
NSString *fragmentShaderForThisRadius = nil;
NSString *vertexShaderForThisRadius = nil;
switch (dilationRadius)
{
case 0:
case 1:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusOneVertexShaderString;
fragmentShaderForThisRadius = kGPUImageErosionRadiusOneFragmentShaderString;
}; break;
case 2:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusTwoVertexShaderString;
fragmentShaderForThisRadius = kGPUImageErosionRadiusTwoFragmentShaderString;
}; break;
case 3:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusThreeVertexShaderString;
fragmentShaderForThisRadius = kGPUImageErosionRadiusThreeFragmentShaderString;
}; break;
case 4:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
fragmentShaderForThisRadius = kGPUImageErosionRadiusFourFragmentShaderString;
}; break;
default:
{
vertexShaderForThisRadius = kGPUImageDilationRadiusFourVertexShaderString;
fragmentShaderForThisRadius = kGPUImageErosionRadiusFourFragmentShaderString;
}; break;
}
if (!(self = [super initWithFirstStageVertexShaderFromString:vertexShaderForThisRadius firstStageFragmentShaderFromString:fragmentShaderForThisRadius secondStageVertexShaderFromString:vertexShaderForThisRadius secondStageFragmentShaderFromString:fragmentShaderForThisRadius]))
{
return nil;
}
return self;
}
- (id)init;
{
if (!(self = [self initWithRadius:1]))
{
return nil;
}
return self;
}
@end
+7
View File
@@ -0,0 +1,7 @@
#import "GPUImageTwoInputFilter.h"
@interface GPUImageExclusionBlendFilter : GPUImageTwoInputFilter
{
}
@end
+56
View File
@@ -0,0 +1,56 @@
#import "GPUImageExclusionBlendFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageExclusionBlendFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
varying highp vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
mediump vec4 base = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
// Dca = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
gl_FragColor = vec4((overlay.rgb * base.a + base.rgb * overlay.a - 2.0 * overlay.rgb * base.rgb) + overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a), base.a);
}
);
#else
NSString *const kGPUImageExclusionBlendFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2;
void main()
{
vec4 base = texture2D(inputImageTexture, textureCoordinate);
vec4 overlay = texture2D(inputImageTexture2, textureCoordinate2);
// Dca = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
gl_FragColor = vec4((overlay.rgb * base.a + base.rgb * overlay.a - 2.0 * overlay.rgb * base.rgb) + overlay.rgb * (1.0 - base.a) + base.rgb * (1.0 - overlay.a), base.a);
}
);
#endif
@implementation GPUImageExclusionBlendFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageExclusionBlendFragmentShaderString]))
{
return nil;
}
return self;
}
@end
+11
View File
@@ -0,0 +1,11 @@
#import "GPUImageFilter.h"
@interface GPUImageExposureFilter : GPUImageFilter
{
GLint exposureUniform;
}
// Exposure ranges from -10.0 to 10.0, with 0.0 as the normal level
@property(readwrite, nonatomic) CGFloat exposure;
@end
+66
View File
@@ -0,0 +1,66 @@
#import "GPUImageExposureFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageExposureFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform highp float exposure;
void main()
{
highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w);
}
);
#else
NSString *const kGPUImageExposureFragmentShaderString = SHADER_STRING
(
varying vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform float exposure;
void main()
{
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4(textureColor.rgb * pow(2.0, exposure), textureColor.w);
}
);
#endif
@implementation GPUImageExposureFilter
@synthesize exposure = _exposure;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageExposureFragmentShaderString]))
{
return nil;
}
exposureUniform = [filterProgram uniformIndex:@"exposure"];
self.exposure = 0.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setExposure:(CGFloat)newValue;
{
_exposure = newValue;
[self setFloat:_exposure forUniform:exposureUniform program:filterProgram];
}
@end
@@ -0,0 +1,33 @@
#import "GPUImageFilterGroup.h"
@class GPUImageGrayscaleFilter;
@class GPUImage3x3TextureSamplingFilter;
@class GPUImageNonMaximumSuppressionFilter;
/*
An implementation of the Features from Accelerated Segment Test (FAST) feature detector as described in the following publications:
E. Rosten and T. Drummond. Fusing points and lines for high performance tracking. IEEE International Conference on Computer Vision, 2005.
E. Rosten and T. Drummond. Machine learning for high-speed corner detection. European Conference on Computer Vision, 2006.
For more about the FAST feature detector, see the resources here:
http://www.edwardrosten.com/work/fast.html
*/
typedef enum { kGPUImageFAST12Contiguous, kGPUImageFAST12ContiguousNonMaximumSuppressed} GPUImageFASTDetectorType;
@interface GPUImageFASTCornerDetectionFilter : GPUImageFilterGroup
{
GPUImageGrayscaleFilter *luminanceReductionFilter;
GPUImage3x3TextureSamplingFilter *featureDetectionFilter;
GPUImageNonMaximumSuppressionFilter *nonMaximumSuppressionFilter;
// Generate a lookup texture based on the bit patterns
// Step 1: convert to monochrome if necessary
// Step 2: do a lookup at each pixel based on the Bresenham circle, encode comparison in two color components
// Step 3: do non-maximum suppression of close corner points
}
- (id)initWithFASTDetectorVariant:(GPUImageFASTDetectorType)detectorType;
@end

Some files were not shown because too many files have changed in this diff Show More