123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- #import "GPUImageLuminosity.h"
- #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
- NSString *const kGPUImageInitialLuminosityFragmentShaderString = 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;
-
- const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);
- void main()
- {
- highp float upperLeftLuminance = dot(texture2D(inputImageTexture, upperLeftInputTextureCoordinate).rgb, W);
- highp float upperRightLuminance = dot(texture2D(inputImageTexture, upperRightInputTextureCoordinate).rgb, W);
- highp float lowerLeftLuminance = dot(texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).rgb, W);
- highp float lowerRightLuminance = dot(texture2D(inputImageTexture, lowerRightInputTextureCoordinate).rgb, W);
- highp float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance);
- gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0);
- }
- );
- NSString *const kGPUImageLuminosityFragmentShaderString = 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 float upperLeftLuminance = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
- highp float upperRightLuminance = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
- highp float lowerLeftLuminance = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
- highp float lowerRightLuminance = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
-
- highp float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance);
- gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0);
- }
- );
- #else
- NSString *const kGPUImageInitialLuminosityFragmentShaderString = SHADER_STRING
- (
- uniform sampler2D inputImageTexture;
-
- varying vec2 outputTextureCoordinate;
-
- varying vec2 upperLeftInputTextureCoordinate;
- varying vec2 upperRightInputTextureCoordinate;
- varying vec2 lowerLeftInputTextureCoordinate;
- varying vec2 lowerRightInputTextureCoordinate;
-
- const vec3 W = vec3(0.2125, 0.7154, 0.0721);
-
- void main()
- {
- float upperLeftLuminance = dot(texture2D(inputImageTexture, upperLeftInputTextureCoordinate).rgb, W);
- float upperRightLuminance = dot(texture2D(inputImageTexture, upperRightInputTextureCoordinate).rgb, W);
- float lowerLeftLuminance = dot(texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).rgb, W);
- float lowerRightLuminance = dot(texture2D(inputImageTexture, lowerRightInputTextureCoordinate).rgb, W);
-
- float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance);
- gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0);
- }
- );
- NSString *const kGPUImageLuminosityFragmentShaderString = SHADER_STRING
- (
- uniform sampler2D inputImageTexture;
-
- varying vec2 outputTextureCoordinate;
-
- varying vec2 upperLeftInputTextureCoordinate;
- varying vec2 upperRightInputTextureCoordinate;
- varying vec2 lowerLeftInputTextureCoordinate;
- varying vec2 lowerRightInputTextureCoordinate;
-
- void main()
- {
- float upperLeftLuminance = texture2D(inputImageTexture, upperLeftInputTextureCoordinate).r;
- float upperRightLuminance = texture2D(inputImageTexture, upperRightInputTextureCoordinate).r;
- float lowerLeftLuminance = texture2D(inputImageTexture, lowerLeftInputTextureCoordinate).r;
- float lowerRightLuminance = texture2D(inputImageTexture, lowerRightInputTextureCoordinate).r;
-
- float luminosity = 0.25 * (upperLeftLuminance + upperRightLuminance + lowerLeftLuminance + lowerRightLuminance);
- gl_FragColor = vec4(luminosity, luminosity, luminosity, 1.0);
- }
- );
- #endif
- @implementation GPUImageLuminosity
- @synthesize luminosityProcessingFinishedBlock = _luminosityProcessingFinishedBlock;
- #pragma mark -
- #pragma mark Initialization and teardown
- - (id)init;
- {
- if (!(self = [super initWithVertexShaderFromString:kGPUImageColorAveragingVertexShaderString fragmentShaderFromString:kGPUImageInitialLuminosityFragmentShaderString]))
- {
- return nil;
- }
-
- texelWidthUniform = [filterProgram uniformIndex:@"texelWidth"];
- texelHeightUniform = [filterProgram uniformIndex:@"texelHeight"];
-
- __unsafe_unretained GPUImageLuminosity *weakSelf = self;
- [self setFrameProcessingCompletionBlock:^(GPUImageOutput *filter, CMTime frameTime) {
- [weakSelf extractLuminosityAtFrameTime:frameTime];
- }];
- runSynchronouslyOnVideoProcessingQueue(^{
- [GPUImageContext useImageProcessingContext];
-
- secondFilterProgram = [[GPUImageContext sharedImageProcessingContext] programForVertexShaderString:kGPUImageColorAveragingVertexShaderString fragmentShaderString:kGPUImageLuminosityFragmentShaderString];
-
- if (!secondFilterProgram.initialized)
- {
- [self initializeSecondaryAttributes];
-
- if (![secondFilterProgram link])
- {
- NSString *progLog = [secondFilterProgram programLog];
- NSLog(@"Program link log: %@", progLog);
- NSString *fragLog = [secondFilterProgram fragmentShaderLog];
- NSLog(@"Fragment shader compile log: %@", fragLog);
- NSString *vertLog = [secondFilterProgram vertexShaderLog];
- NSLog(@"Vertex shader compile log: %@", vertLog);
- filterProgram = nil;
- NSAssert(NO, @"Filter shader link failed");
- }
- }
-
- secondFilterPositionAttribute = [secondFilterProgram attributeIndex:@"position"];
- secondFilterTextureCoordinateAttribute = [secondFilterProgram attributeIndex:@"inputTextureCoordinate"];
- secondFilterInputTextureUniform = [secondFilterProgram uniformIndex:@"inputImageTexture"]; // This does assume a name of "inputImageTexture" for the fragment shader
- secondFilterInputTextureUniform2 = [secondFilterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
-
- secondFilterTexelWidthUniform = [secondFilterProgram uniformIndex:@"texelWidth"];
- secondFilterTexelHeightUniform = [secondFilterProgram uniformIndex:@"texelHeight"];
- [GPUImageContext setActiveShaderProgram:secondFilterProgram];
-
- glEnableVertexAttribArray(secondFilterPositionAttribute);
- glEnableVertexAttribArray(secondFilterTextureCoordinateAttribute);
- });
- return self;
- }
- - (void)initializeSecondaryAttributes;
- {
- [secondFilterProgram addAttribute:@"position"];
- [secondFilterProgram addAttribute:@"inputTextureCoordinate"];
- }
- /*
- - (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
- {
- if (self.preventRendering)
- {
- [firstInputFramebuffer unlock];
- return;
- }
-
- // Do an initial render pass that both convert to luminance and reduces
- [GPUImageContext setActiveShaderProgram:filterProgram];
-
- glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
- glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
- GLuint currentFramebuffer = [[stageFramebuffers objectAtIndex:0] intValue];
- glBindFramebuffer(GL_FRAMEBUFFER, currentFramebuffer);
-
- #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
- CGSize currentStageSize = [[stageSizes objectAtIndex:0] CGSizeValue];
- #else
- NSSize currentStageSize = [[stageSizes objectAtIndex:0] sizeValue];
- #endif
- glViewport(0, 0, (int)currentStageSize.width, (int)currentStageSize.height);
- GLuint currentTexture = [firstInputFramebuffer texture];
- 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.5 / currentStageSize.width);
- glUniform1f(texelHeightUniform, 0.5 / currentStageSize.height);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- currentTexture = [[stageTextures objectAtIndex:0] intValue];
- // Just perform reductions from this point on
- [GPUImageContext setActiveShaderProgram:secondFilterProgram];
- glVertexAttribPointer(secondFilterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
- glVertexAttribPointer(secondFilterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
- NSUInteger numberOfStageFramebuffers = [stageFramebuffers count];
- for (NSUInteger currentStage = 1; currentStage < numberOfStageFramebuffers; currentStage++)
- {
- currentFramebuffer = [[stageFramebuffers objectAtIndex:currentStage] intValue];
- glBindFramebuffer(GL_FRAMEBUFFER, currentFramebuffer);
-
- #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
- currentStageSize = [[stageSizes objectAtIndex:currentStage] CGSizeValue];
- #else
- currentStageSize = [[stageSizes objectAtIndex:currentStage] sizeValue];
- #endif
- glViewport(0, 0, (int)currentStageSize.width, (int)currentStageSize.height);
-
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, currentTexture);
-
- glUniform1i(secondFilterInputTextureUniform, 2);
-
- glUniform1f(secondFilterTexelWidthUniform, 0.5 / currentStageSize.width);
- glUniform1f(secondFilterTexelHeightUniform, 0.5 / currentStageSize.height);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- currentTexture = [[stageTextures objectAtIndex:currentStage] intValue];
-
- // NSUInteger totalBytesForImage = (int)currentStageSize.width * (int)currentStageSize.height * 4;
- // GLubyte *rawImagePixels2 = (GLubyte *)malloc(totalBytesForImage);
- // glReadPixels(0, 0, (int)currentStageSize.width, (int)currentStageSize.height, GL_RGBA, GL_UNSIGNED_BYTE, rawImagePixels2);
- // CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rawImagePixels2, totalBytesForImage, NULL);
- // CGColorSpaceRef defaultRGBColorSpace = CGColorSpaceCreateDeviceRGB();
- //
- // CGFloat currentRedTotal = 0.0f, currentGreenTotal = 0.0f, currentBlueTotal = 0.0f, currentAlphaTotal = 0.0f;
- // NSUInteger totalNumberOfPixels = totalBytesForImage / 4;
- //
- // for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
- // {
- // currentRedTotal += (CGFloat)rawImagePixels2[(currentPixel * 4)] / 255.0f;
- // currentGreenTotal += (CGFloat)rawImagePixels2[(currentPixel * 4) + 1] / 255.0f;
- // currentBlueTotal += (CGFloat)rawImagePixels2[(currentPixel * 4 + 2)] / 255.0f;
- // currentAlphaTotal += (CGFloat)rawImagePixels2[(currentPixel * 4) + 3] / 255.0f;
- // }
- //
- // NSLog(@"Stage %d average image red: %f, green: %f, blue: %f, alpha: %f", currentStage, currentRedTotal / (CGFloat)totalNumberOfPixels, currentGreenTotal / (CGFloat)totalNumberOfPixels, currentBlueTotal / (CGFloat)totalNumberOfPixels, currentAlphaTotal / (CGFloat)totalNumberOfPixels);
- //
- //
- // CGImageRef cgImageFromBytes = CGImageCreate((int)currentStageSize.width, (int)currentStageSize.height, 8, 32, 4 * (int)currentStageSize.width, defaultRGBColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
- //
- // UIImage *imageToSave = [UIImage imageWithCGImage:cgImageFromBytes];
- //
- // NSData *dataForPNGFile = UIImagePNGRepresentation(imageToSave);
- //
- // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- // NSString *documentsDirectory = [paths objectAtIndex:0];
- //
- // NSString *imageName = [NSString stringWithFormat:@"AverageLevel%d.png", currentStage];
- // NSError *error = nil;
- // if (![dataForPNGFile writeToFile:[documentsDirectory stringByAppendingPathComponent:imageName] options:NSAtomicWrite error:&error])
- // {
- // return;
- // }
- }
-
- [firstInputFramebuffer unlock];
- }
- */
- #pragma mark -
- #pragma mark Callbacks
- - (void)extractLuminosityAtFrameTime:(CMTime)frameTime;
- {
- runSynchronouslyOnVideoProcessingQueue(^{
- // we need a normal color texture for this filter
- NSAssert(self.outputTextureOptions.internalFormat == GL_RGBA, @"The output texture 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 luminanceTotal = 0;
- NSUInteger byteIndex = 0;
- for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
- {
- luminanceTotal += rawImagePixels[byteIndex];
- byteIndex += 4;
- }
-
- CGFloat normalizedLuminosityTotal = (CGFloat)luminanceTotal / (CGFloat)totalNumberOfPixels / 255.0;
-
- if (_luminosityProcessingFinishedBlock != NULL)
- {
- _luminosityProcessingFinishedBlock(normalizedLuminosityTotal, frameTime);
- }
- });
- }
- @end
|