// // FWKCIImageView.m // LineEngraver // // Created by Viktor Goltvyanytsya on 8/8/16. // // #import "FWKCIImageView.h" #import #include #include @interface FWKCIImageView () { CIImage *_ciImage; EAGLContext *_eaglContext; CIContext *_ciContext; GLKView *_glView; } @end @implementation FWKCIImageView -(void)dealloc; { _ciImage = nil; _eaglContext = nil; _ciContext = nil; if( _glView ) { [_glView removeFromSuperview]; } _glView = nil; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code [self setBackgroundColor:[UIColor clearColor]]; [self setAutoresizesSubviews:NO]; [self setTranslatesAutoresizingMaskIntoConstraints:NO]; _eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; _eaglContext.multiThreaded = YES; _ciContext = [CIContext contextWithEAGLContext:_eaglContext options: @{kCIContextUseSoftwareRenderer: @NO} ]; _glView = [[GLKView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) context:_eaglContext]; _glView.enableSetNeedsDisplay = NO; _glView.delegate = self; _glView.drawableDepthFormat = GLKViewDrawableDepthFormat24; [self addSubview:_glView]; [EAGLContext setCurrentContext:_eaglContext]; } return self; } - (CIImage *)ciImage { return _ciImage; } - (void)setCiImage:(CIImage *)image { _ciImage = image; [self _drawCIImage:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; } - (void)setFrame:(CGRect)frame { BOOL changed = !CGSizeEqualToSize(self.frame.size, frame.size); [super setFrame:frame]; if (changed && _ciImage) { [self _drawCIImage:frame]; } } #pragma mark -GLKViewDelegate methods - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { } #pragma mark -Private methods - (void)_drawCIImage:(CGRect)frame { [_glView bindDrawable]; if (_eaglContext != [EAGLContext currentContext]) { [EAGLContext setCurrentContext:_eaglContext]; } // clear eagl view to grey glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT); // set the blend mode to "source over" so that CI will use that glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); if (_ciImage) { [_glView setFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; CGSize imageSize = _ciImage.extent.size; CGFloat drawableWidth = _glView.drawableWidth; CGFloat drawableHeight = _glView.drawableHeight; CGRect drawFrame = CGRectMake(0, 0, drawableWidth, drawableHeight); CGFloat imageAR = imageSize.width / imageSize.height; CGFloat viewAR = drawFrame.size.width / drawFrame.size.height; if (imageAR > viewAR) { drawFrame.origin.y += (drawFrame.size.height - drawFrame.size.width / imageAR) / 2.0; drawFrame.size.height = drawFrame.size.width / imageAR; } else { drawFrame.origin.x += (drawFrame.size.width - drawFrame.size.height * imageAR) / 2.0; drawFrame.size.width = drawFrame.size.height * imageAR; } [_ciContext drawImage:_ciImage inRect:drawFrame fromRect:[_ciImage extent]]; } [_glView display]; } @end