Open pegurov opened 10 years ago
SaturationHueLuminanceFilter.h
#import <GPUImage.h>
@interface SaturationHueLuminanceFilter : GPUImageFilter
{
GLfloat referenceTones[8]; // Blue and Aqua are included twice to manage edge cases
}
// Accept an array on 6 floats from -1.0 to 1.0 for Red, Yellow, Green, Aqua, Blue and Magenta respectively
@property(nonatomic) GLfloat* saturation;
@property(nonatomic) GLfloat* hue;
@property(nonatomic) GLfloat* luminance;
@end
SaturationHueLuminanceFilter.m
#import "SaturationHueLuminanceFilter.h"
NSString *const kSatuationHueLuminanceFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
const highp vec3 kRGBToYPrime = vec3 (0.299, 0.587, 0.114);
const highp vec3 kRGBToI = vec3 (0.595716, -0.274453, -0.321263);
const highp vec3 kRGBToQ = vec3 (0.211456, -0.522591, 0.31135);
const highp vec3 kYIQToR = vec3 (1.0, 0.9563, 0.6210);
const highp vec3 kYIQToG = vec3 (1.0, -0.2721, -0.6474);
const highp vec3 kYIQToB = vec3 (1.0, -1.1070, 1.7046);
const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
uniform mediump float referenceTones[8]; // it's actually const, but GLES 2.0 dosen't do const arrays
const mediump float relevanceRange = 0.7;
uniform lowp float saturationTones[8];
uniform lowp float hueTones[8];
uniform lowp float luminanceTones[8];
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec3 color = textureColor.rgb;
highp float YPrime = dot (color, kRGBToYPrime); // convert to YIQ
highp float I = dot (color, kRGBToI);
highp float Q = dot (color, kRGBToQ);
highp float hue = atan (Q, I); // calculate the hue and chroma
highp float chroma = sqrt (I * I + Q * Q);
mediump float luminanceAmount = 0.0;
mediump float hueAmount = 0.0;
mediump float saturationAmount = 0.0;
lowp int toneNumber;
mediump float normalizedRelevance;
for (toneNumber=0;toneNumber<8;toneNumber++)
{
normalizedRelevance = clamp(1.0 - (abs(referenceTones[toneNumber] - hue)-0.2)/relevanceRange,0.0,1.0);
luminanceAmount += normalizedRelevance*luminanceTones[toneNumber];
saturationAmount += normalizedRelevance*saturationTones[toneNumber];
hueAmount += normalizedRelevance*hueTones[toneNumber];
}
hue = hue + (-hueAmount*3.14); // apply hue adjustment
Q = chroma * sin (hue); // back to YIQ
I = chroma * cos (hue);
highp vec3 yIQ = vec3 (YPrime, I, Q); // back to RGB
color.r = dot (yIQ, kYIQToR);
color.g = dot (yIQ, kYIQToG);
color.b = dot (yIQ, kYIQToB);
color = color + luminanceAmount*0.2; // apply luminance adjustment
lowp float luminance = dot(color.rgb, luminanceWeighting); // apply saturation adjustment
lowp vec3 greyscaleColor = vec3(luminance);
color = mix(greyscaleColor, color, saturationAmount + 1.0);
gl_FragColor = vec4(color.rgb, textureColor.a);
}
);
@implementation SaturationHueLuminanceFilter
- (id) init;
{
if (!(self = [super initWithFragmentShaderFromString:kSatuationHueLuminanceFragmentShaderString])) {
return nil;
}
referenceTones[0] = 0.3326; // red
referenceTones[1] = -0.7761; // yellow
referenceTones[2] = -2.0574; // green
referenceTones[3] = -2.8212; // aqua
referenceTones[4] = 2.3777; // blue
referenceTones[5] = 1.0964; // magenda
referenceTones[6] = 3.5; // aqua again
referenceTones[7] = -3.9; // blue again
[self setFloatArray:referenceTones length:8 forUniform:@"referenceTones"];
return self;
}
- (void) setFloat:(GLfloat*)array forUniform:(NSString*)uniformName
{
array = (GLfloat*)realloc((void*)array, sizeof(GLfloat)*8);
array[6] = array[3];
array[7] = array[4];
[self setFloatArray:array length:8 forUniform:uniformName];
}
- (void) setSaturation:(GLfloat *)saturationValues;
{
_saturation = saturationValues;
[self setFloat:saturationValues forUniform:@"saturationTones"];
}
- (void) setHue:(GLfloat *)hueValues;
{
_hue = hueValues;
[self setFloat:hueValues forUniform:@"hueTones"];
}
- (void) setLuminance:(GLfloat *)luminanceValues;
{
_luminance = luminanceValues;
[self setFloat:luminanceValues forUniform:@"luminanceTones"];
}
@end
Hey Brad! I have a very weird issue, that I'm unable to fix on my own, I've been trying for days to figure out what is wrong.
The situation is following: One of our developers wrote a custom filter, as an extension of GPUImageFiler. The purpose of the filter is to change Hue Saturation and Luminance for different tones of an image. He is not an iOS developer.
So he wrote it, and I tried to use it. The problem is this: it works on 64-bit architecture (iPhone 5S and all of the simulators), but doesn't work on 32 bit. On 32-bit architecture it just returns a clear image. But the weirdest part of it all is that even if i just initialise the filter but don't use it (don't add any targets to it), but just change some of its parameters, other filters that I'm using start returning a clear image too.
Here is the link to the repository: https://bitbucket.org/pashagurov/filtersapp When you launch the app you can actually choose the filters swiping left and right at the bottom part of the app. So when you change parameters of tone curve filter, it works as expected, but when you swipe to custom filter and change something there, the image disappears, but that filter is not even added as a target anywhere.
Could you please help me to solve the issue? If you don't want to clone the repository, then i can just paste the code here, i just thought that giving a link to the repository would be cleaner.