Question

I wrote this code to change the brightness of an UIImage via an UISlider and the GPUImageBrightnessFilter. But every time I'll test it the app crashes.

My code:

- (IBAction)sliderBrightness:(id)sender {

    CGFloat midpoint = [(UISlider *)sender value];
    [(GPUImageTiltShiftFilter *)brightnessFilter setTopFocusLevel:midpoint - 0.1];
    [(GPUImageTiltShiftFilter *)brightnessFilter setBottomFocusLevel:midpoint + 0.1];

    [sourcePicture processImage];
}

- (void) brightnessFilter {

    UIImage *inputImage = imgView.image;

    sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
    brightnessFilter = [[GPUImageTiltShiftFilter alloc] init];
    //    sepiaFilter = [[GPUImageSobelEdgeDetectionFilter alloc] init];

    GPUImageView *imageView = (GPUImageView *)self.view;
    [brightnessFilter forceProcessingAtSize:imageView.sizeInPixels]; // This is now needed to make the filter run at the smaller output size

    [sourcePicture addTarget:brightnessFilter];
    [brightnessFilter addTarget:imageView];

    [sourcePicture processImage];
}
Was it helpful?

Solution

Let me make an alternative architectural suggestion. Instead of creating a GPUImagePicture and GPUImageBrightnessFilter each time you change the brightness, then saving that out as a UIImage to a UIImageView, it would be far more efficient to reuse the initial picture and filter and render that to a GPUImageView.

Take a look at what I do in the SimpleImageFilter example that comes with GPUImage. For the tilt-shifted image that's displayed to the screen, I create a GPUImagePicture of the source image once, create one instance of the tilt-shift filter, and then send the output to a GPUImageView. This avoids the expensive (both performance and memory-wise) process of going to a UIImage and then displaying that in a UIImageView, and will be much, much faster. While you're at it, you can use -forceProcessingAtSize: on your filter to only render as many pixels as will be displayed in your final view, also speeding things up.

When you have the right settings for filtering your image, and you want the final UIImage out, you can do one last render pass to extract the processed UIImage. You'd set your forced size back to 0 right before doing that, so you now process the full image.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top