Search code examples
iosobjective-cuiscrollviewuiimagegpuimage

Apply filter to current image index in UIScrollView GPUImage


Im currently deploying a ImageScroller by UIScrollView, and it contain a filter toolbar at the bottom as you can see on the image.

enter image description here

But im facing a problem is that when i press the button, the filters is only apply to the last image as example below:

Gif Example

Gif Example

So please anyone can help me to solve this one, my expected output is the filter is applied to the current displaying image, not only the last one. Here i would attach my code for your reference and thank you so much.

@interface EditImageVC ()
@end

@implementation EditImageVC


UIImageView *img;


- (void)viewDidLoad {
    [super viewDidLoad];
    int x=0;
    for (int i = 0; i < _scrollViewImageArray.count ; i++) {

        _picture = [_scrollViewImageArray objectAtIndex:i];
        img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width, 
        self.imgScrollView.frame.size.height)];
        img.image =_picture;
        x=x+[[UIScreen mainScreen] bounds].size.width;
        [_imgScrollView addSubview:img];
    }
    _imgScrollView.backgroundColor = [UIColor blackColor];
    _imgScrollView.contentSize=CGSizeMake(x, 
    _imgScrollView.frame.size.height);
    _imgScrollView.contentOffset=CGPointMake(0, 0);
    img.contentMode = UIViewContentModeScaleAspectFit;
}


-(void)viewDidLayoutSubviews{
     self.automaticallyAdjustsScrollViewInsets = NO;
}



 - (IBAction)filterAction:(UIButton *)sender {

    for (int i = 0; i < _scrollViewImageArray.count ; i++) {
        UIImage *picture = [_scrollViewImageArray objectAtIndex:i];
        GPUImageFilter *selectedFilter;
        switch (sender.tag) {
            case 0:
                selectedFilter = [[GPUImageSepiaFilter alloc] init];
                break;
            case 1:
                selectedFilter = [[GPUImageToonFilter alloc] init];
                break;
            default:
                break;
        }
        UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
        [img setImage:filteredImage];
    }
}

Solution

  • Just filter the last shown image and when filter image when scrollview scrolled to another image.

    remember to add UIScrollViewDelegate

    @interface EditImageVC : UIViewController <UIScrollViewDelegate>   {
    }
    
    @end
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        imageViewsArray = [[NSMutableArray alloc] init];
        int x=0;
        for (int i = 0; i < _scrollViewImageArray.count ; i++) {
    
            _picture = [_scrollViewImageArray objectAtIndex:i];
            img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width,
    
            self.imgScrollView.frame.size.height)];
            img.image =_picture;
            [imageViewsArray addObject:img];
            x=x+[[UIScreen mainScreen] bounds].size.width;
            [self.imgScrollView addSubview:img];
        }
        self.imgScrollView.backgroundColor = [UIColor blackColor];
        self.imgScrollView.contentSize=CGSizeMake(x,
                                              self.imgScrollView.frame.size.height);
        self.imgScrollView.contentOffset=CGPointMake(0, 0);
        img.contentMode = UIViewContentModeScaleAspectFit;
    
        self.imgScrollView.delegate = self;
    }
    
    GPUImageFilter *selectedFilter = nil;
    
    NSInteger currentShownIndex = 0;
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        NSInteger indexAfterScrolled = scrollView.contentOffset.x / scrollView.frame.size.width;
        if(indexAfterScrolled==currentShownIndex) return;
        currentShownIndex = indexAfterScrolled;
        if(selectedFilter!=nil) {
            UIImage *filteredImage = [selectedFilter imageByFilteringImage:[_scrollViewImageArray objectAtIndex:currentShownIndex]];
            [[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
        }
    }
    
    - (IBAction)filterAction:(UIButton *)sender {
    
        switch (sender.tag) {
            case 0:
                selectedFilter = [[GPUImageSepiaFilter alloc] init];
                break;
            case 1:
                selectedFilter = [[GPUImageToonFilter alloc] init];
                break;
            default:
                break;
        }
        UIImage *picture = [_scrollViewImageArray objectAtIndex:currentShownIndex];
        UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
        [[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
    }
    

    Updated If you want to filter current shown image, not need to apply UIScrollViewDelegate:

        - (void)viewDidLoad {
            [super viewDidLoad];
            imageViewsArray = [[NSMutableArray alloc] init];
            int x=0;
            for (int i = 0; i < _scrollViewImageArray.count ; i++) {
    
                _picture = [_scrollViewImageArray objectAtIndex:i];
                img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width,
    
                self.imgScrollView.frame.size.height)];
                img.image =_picture;
                [imageViewsArray addObject:img];
                x=x+[[UIScreen mainScreen] bounds].size.width;
                [self.imgScrollView addSubview:img];
            }
            self.imgScrollView.backgroundColor = [UIColor blackColor];
            self.imgScrollView.contentSize=CGSizeMake(x,
                                                  self.imgScrollView.frame.size.height);
            self.imgScrollView.contentOffset=CGPointMake(0, 0);
            img.contentMode = UIViewContentModeScaleAspectFit;
    
            self.imgScrollView.delegate = self;
        }
    
        - (IBAction)filterAction:(UIButton *)sender {
            NSInteger objectAtIndex:currentShownIndex = scrollView.contentOffset.x / scrollView.frame.size.width;
                GPUImageFilter *selectedFilter = nil;
    
            switch (sender.tag) {
                case 0:
                    selectedFilter = [[GPUImageSepiaFilter alloc] init];
                    break;
                case 1:
                    selectedFilter = [[GPUImageToonFilter alloc] init];
                    break;
                default:
                    break;
            }
            UIImage *picture = [_scrollViewImageArray objectAtIndex:currentShownIndex];
            UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
            [[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
        }