Skip to content

Instantly share code, notes, and snippets.

@vgoltv
Created August 19, 2016 17:51
Show Gist options
  • Save vgoltv/32dc2c8823568ebe1578181a07b6e60b to your computer and use it in GitHub Desktop.
Save vgoltv/32dc2c8823568ebe1578181a07b6e60b to your computer and use it in GitHub Desktop.
display CIImage via GLKView
//
// FWKCIImageView.h
// LineEngraver
//
// Created by Viktor Goltvyanytsya on 8/8/16.
//
//
#import <UIKit/UIKit.h>
@interface FWKCIImageView : UIView
- (CIImage *)ciImage;
- (void)setCiImage:(CIImage *)image;
@end
//
// FWKCIImageView.m
// LineEngraver
//
// Created by Viktor Goltvyanytsya on 8/8/16.
//
//
#import "FWKCIImageView.h"
#import <GLKit/GLKView.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@interface FWKCIImageView ()<GLKViewDelegate>
{
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment