Skip to content

Commit

Permalink
Added a halftone filter.
Browse files Browse the repository at this point in the history
  • Loading branch information
BradLarson committed Sep 18, 2012
1 parent 58f8826 commit 7e37da4
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ Documentation is generated from header comments using appledoc. To build the doc
- *fractionalWidthOfAPixel*: How large the dots are, as a fraction of the width and height of the image (0.0 - 1.0, default 0.05)
- *dotScaling*: What fraction of each grid space is taken up by a dot, from 0.0 to 1.0 with a default of 0.9.

- **GPUImageHalftoneFilter**: Applies a halftone effect to an image, like news print
- *fractionalWidthOfAPixel*: How large the halftone dots are, as a fraction of the width and height of the image (0.0 - 1.0, default 0.05)

- **GPUImageCrosshatchFilter**: This converts an image into a black-and-white crosshatch pattern
- *crossHatchSpacing*: The fractional width of the image to use as the spacing for the crosshatch. The default is 0.03.
- *lineWidth*: A relative width for the crosshatch lines. The default is 0.003.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
case GPUIMAGE_PIXELLATE: cell.textLabel.text = @"Pixellate"; break;
case GPUIMAGE_POLARPIXELLATE: cell.textLabel.text = @"Polar pixellate"; break;
case GPUIMAGE_POLKADOT: cell.textLabel.text = @"Polka dot"; break;
case GPUIMAGE_HALFTONE: cell.textLabel.text = @"Halftone"; break;
case GPUIMAGE_CROSSHATCH: cell.textLabel.text = @"Crosshatch"; break;
case GPUIMAGE_SOBELEDGEDETECTION: cell.textLabel.text = @"Sobel edge detection"; break;
case GPUIMAGE_PREWITTEDGEDETECTION: cell.textLabel.text = @"Prewitt edge detection"; break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef enum {
GPUIMAGE_PIXELLATE,
GPUIMAGE_POLARPIXELLATE,
GPUIMAGE_POLKADOT,
GPUIMAGE_HALFTONE,
GPUIMAGE_CROSSHATCH,
GPUIMAGE_SOBELEDGEDETECTION,
GPUIMAGE_PREWITTEDGEDETECTION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ - (void)setupFilter;

filter = [[GPUImagePolkaDotFilter alloc] init];
}; break;
case GPUIMAGE_HALFTONE:
{
self.title = @"Halftone";
self.filterSettingsSlider.hidden = NO;

[self.filterSettingsSlider setValue:0.01];
[self.filterSettingsSlider setMinimumValue:0.0];
[self.filterSettingsSlider setMaximumValue:0.05];

filter = [[GPUImageHalftoneFilter alloc] init];
}; break;
case GPUIMAGE_CROSSHATCH:
{
self.title = @"Crosshatch";
Expand Down Expand Up @@ -1335,6 +1346,7 @@ - (IBAction)updateFilterFromSlider:(id)sender;
case GPUIMAGE_PIXELLATE: [(GPUImagePixellateFilter *)filter setFractionalWidthOfAPixel:[(UISlider *)sender value]]; break;
case GPUIMAGE_POLARPIXELLATE: [(GPUImagePolarPixellateFilter *)filter setPixelSize:CGSizeMake([(UISlider *)sender value], [(UISlider *)sender value])]; break;
case GPUIMAGE_POLKADOT: [(GPUImagePolkaDotFilter *)filter setFractionalWidthOfAPixel:[(UISlider *)sender value]]; break;
case GPUIMAGE_HALFTONE: [(GPUImageHalftoneFilter *)filter setFractionalWidthOfAPixel:[(UISlider *)sender value]]; break;
case GPUIMAGE_SATURATION: [(GPUImageSaturationFilter *)filter setSaturation:[(UISlider *)sender value]]; break;
case GPUIMAGE_CONTRAST: [(GPUImageContrastFilter *)filter setContrast:[(UISlider *)sender value]]; break;
case GPUIMAGE_BRIGHTNESS: [(GPUImageBrightnessFilter *)filter setBrightness:[(UISlider *)sender value]]; break;
Expand Down
8 changes: 8 additions & 0 deletions framework/GPUImage.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
BC27A3CC15654F5A004F2D45 /* GPUImagePerlinNoiseFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC27A3CA15654F5A004F2D45 /* GPUImagePerlinNoiseFilter.m */; };
BC3AC8B015E6F6170065144E /* GPUImageAverageColor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3AC8AE15E6F6170065144E /* GPUImageAverageColor.h */; };
BC3AC8B115E6F6170065144E /* GPUImageAverageColor.m in Sources */ = {isa = PBXBuildFile; fileRef = BC3AC8AF15E6F6170065144E /* GPUImageAverageColor.m */; };
BC4D03CF160919AE00F64358 /* GPUImageHalftoneFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC4D03CD160919AE00F64358 /* GPUImageHalftoneFilter.h */; };
BC4D03D0160919AE00F64358 /* GPUImageHalftoneFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC4D03CE160919AE00F64358 /* GPUImageHalftoneFilter.m */; };
BC54D563151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = BC54D561151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.h */; };
BC54D564151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC54D562151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.m */; };
BC56D82A1579779700CC9C1E /* GPUImageUIElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BC56D8281579779700CC9C1E /* GPUImageUIElement.h */; };
Expand Down Expand Up @@ -388,6 +390,8 @@
BC27A3CA15654F5A004F2D45 /* GPUImagePerlinNoiseFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImagePerlinNoiseFilter.m; path = Source/GPUImagePerlinNoiseFilter.m; sourceTree = SOURCE_ROOT; };
BC3AC8AE15E6F6170065144E /* GPUImageAverageColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageAverageColor.h; path = Source/GPUImageAverageColor.h; sourceTree = SOURCE_ROOT; };
BC3AC8AF15E6F6170065144E /* GPUImageAverageColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageAverageColor.m; path = Source/GPUImageAverageColor.m; sourceTree = SOURCE_ROOT; };
BC4D03CD160919AE00F64358 /* GPUImageHalftoneFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageHalftoneFilter.h; path = Source/GPUImageHalftoneFilter.h; sourceTree = SOURCE_ROOT; };
BC4D03CE160919AE00F64358 /* GPUImageHalftoneFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageHalftoneFilter.m; path = Source/GPUImageHalftoneFilter.m; sourceTree = SOURCE_ROOT; };
BC54D561151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageChromaKeyBlendFilter.h; path = Source/GPUImageChromaKeyBlendFilter.h; sourceTree = SOURCE_ROOT; };
BC54D562151904FF003F4A41 /* GPUImageChromaKeyBlendFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPUImageChromaKeyBlendFilter.m; path = Source/GPUImageChromaKeyBlendFilter.m; sourceTree = SOURCE_ROOT; };
BC56D8281579779700CC9C1E /* GPUImageUIElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GPUImageUIElement.h; path = Source/GPUImageUIElement.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -769,6 +773,8 @@
BCB5DE0C14E87F32000AF3C2 /* GPUImagePixellateFilter.m */,
BCF851B815CF29B3000EBC8B /* GPUImagePolkaDotFilter.h */,
BCF851B915CF29B3000EBC8B /* GPUImagePolkaDotFilter.m */,
BC4D03CD160919AE00F64358 /* GPUImageHalftoneFilter.h */,
BC4D03CE160919AE00F64358 /* GPUImageHalftoneFilter.m */,
BCABED8A15263CF20098A93E /* GPUImagePolarPixellateFilter.h */,
BCABED8B15263CF20098A93E /* GPUImagePolarPixellateFilter.m */,
BCC1E669152368130006EFA5 /* GPUImageCrosshatchFilter.h */,
Expand Down Expand Up @@ -1187,6 +1193,7 @@
BCB3B46A15F2FD1B00EDA3BE /* GPUImageHighPassFilter.h in Headers */,
BCB3B47915F3108700EDA3BE /* GPUImageMotionDetector.h in Headers */,
4308B1D715F7EED30014437A /* GPUImageNormalBlendFilter.h in Headers */,
BC4D03CF160919AE00F64358 /* GPUImageHalftoneFilter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1438,6 +1445,7 @@
BCB3B46B15F2FD1B00EDA3BE /* GPUImageHighPassFilter.m in Sources */,
BCB3B47A15F3108700EDA3BE /* GPUImageMotionDetector.m in Sources */,
4308B1D815F7EED30014437A /* GPUImageNormalBlendFilter.m in Sources */,
BC4D03D0160919AE00F64358 /* GPUImageHalftoneFilter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
3 changes: 2 additions & 1 deletion framework/Source/GPUImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,5 @@
#import "GPUImageChromaKeyFilter.h"
#import "GPUImageLowPassFilter.h"
#import "GPUImageHighPassFilter.h"
#import "GPUImageMotionDetector.h"
#import "GPUImageMotionDetector.h"
#import "GPUImageHalftoneFilter.h"
5 changes: 5 additions & 0 deletions framework/Source/GPUImageHalftoneFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import "GPUImagePixellateFilter.h"

@interface GPUImageHalftoneFilter : GPUImagePixellateFilter

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

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

uniform sampler2D inputImageTexture;

uniform highp float fractionalWidthOfPixel;
uniform highp float aspectRatio;
uniform highp float dotScaling;

const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);

void main()
{
highp vec2 sampleDivisor = vec2(fractionalWidthOfPixel, fractionalWidthOfPixel / aspectRatio);

highp vec2 samplePos = textureCoordinate - mod(textureCoordinate, sampleDivisor) + 0.5 * sampleDivisor;
highp vec2 textureCoordinateToUse = vec2(textureCoordinate.x, (textureCoordinate.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp vec2 adjustedSamplePos = vec2(samplePos.x, (samplePos.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp float distanceFromSamplePoint = distance(adjustedSamplePos, textureCoordinateToUse);

lowp vec3 sampledColor = texture2D(inputImageTexture, samplePos ).rgb;
highp float dotScaling = 1.0 - dot(sampledColor, W);

lowp float checkForPresenceWithinDot = 1.0 - step(distanceFromSamplePoint, (fractionalWidthOfPixel * 0.5) * dotScaling);

gl_FragColor = vec4(vec3(checkForPresenceWithinDot), 1.0);
}
);

@implementation GPUImageHalftoneFilter

- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageHalftoneFragmentShaderString]))
{
return nil;
}

self.fractionalWidthOfAPixel = 0.01;

return self;
}

@end

0 comments on commit 7e37da4

Please sign in to comment.