Search code examples
iosfiltergpuimage

GPUImageView stop responding to "Filter Change" after two times


I'm probably missing something. I'm trying to change filter to my GPUImageView.It's actually working the first two times(sometimes only one time), and than stop responding to changes. I couldn't find a way to remove the target from my GPUImageView.

Code

for x in filterOperations
        {
            x.filter.removeAllTargets()
        }
        let f = filterOperations[randomIntInRange].filter
        let media = GPUImagePicture(image: self.largeImage)
        media?.addTarget(f as! GPUImageInput)
        f.addTarget(g_View)
        media.processImage()

Any suggestions? * Processing still image from my library

UPDATE

Updated Code

//Global

var g_View: GPUImageView!
var media = GPUImagePicture()

override func viewDidLoad() {
super.viewDidLoad()
    media = GPUImagePicture(image: largeImage)
}

func changeFilter(filterIndex : Int)
{
    media.removeAllTargets()
    let f = returnFilter(indexPath.row) //i.e GPUImageSepiaFilter()
    media.addTarget(f as! GPUImageInput)
    f.addTarget(g_View)

    //second Part
    f.useNextFrameForImageCapture()
    let sema = dispatch_semaphore_create(0)
    imageSource.processImageWithCompletionHandler({
    dispatch_semaphore_signal(sema)
        return
    })

     dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
     let img =       f.imageFromCurrentFramebufferWithOrientation(img.imageOrientation)
     if img != nil
     {
     //Useable - update UI

     }
     else
     {
        //  Something Went wrong

     }

}

Solution

  • My primary suggestion would be to not create a new GPUImagePicture every time you want to change the filter or its options that you're applying to an image. This is an expensive operation, because it requires a pass through Core Graphics and a texture upload to the GPU.

    Also, since you're not maintaining a reference to your GPUImagePicture beyond the above code, it is being deallocated as soon as you pass out of scope. That tears down the render chain and will lead to a black image or even crashes. processImage() is an asynchronous operation, so it may still be in action at the time you exit your above scope.

    Instead, create and maintain a reference to a single GPUImagePicture for your image, swap out filters (or change the options for existing filters) on that, and target the result to your GPUImageView. This will be much faster, churn less memory, and won't leave you open to premature deallocation.