GLImageData.m 2.7 KB
Newer Older
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
1

2
#import "GLImageData.h"
3 4
#import "RCTUtils.h"
#import "RCTLog.h"
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
5 6

// This structure aims to be used in an immutable way
7
@implementation GLImageData
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
8 9 10 11 12 13
{
  GLubyte *_data;
  int _width;
  int _height;
}

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
GLImageData *EMPTY_PIXELS;

+ (GLImageData *)empty
{
  if (!EMPTY_PIXELS) {
    int width = 2, height = 2;
    GLubyte* data = (GLubyte *) malloc(width*height*4*sizeof(GLubyte));
    for (int i = 0; i < width * height * 4; i+=4) {
      data[i] = data[i+1] = data[i+2] = 0;
      data[i+3] = 0;
    }
    EMPTY_PIXELS = [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
  }
  return EMPTY_PIXELS;
}

+ (GLImageData *)genPixelsWithImage: (UIImage *)image
{
  int width = image.size.width;
  int height = image.size.height;
  if (width == 0 || height == 0) {
    RCTLogError(@"The image must be loaded in setPixelsWithImage call");
    return nil;
  }
  GLubyte* data = malloc(width * height * 4);
  CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
  if (ctx == NULL) {
    RCTLogError(@"unable to create the bitmap context");
    CGColorSpaceRelease(colorSpace);
    free(data);
    return nil;
  }
  CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, height);
  CGContextConcatCTM(ctx, flipVertical);
  
  CGRect rect = CGRectMake(0.0, 0.0, width, height);
  CGContextClearRect(ctx, rect);
  CGContextDrawImage(ctx, rect, image.CGImage);
  CGColorSpaceRelease(colorSpace);
  CGContextRelease(ctx);
  return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}

+ (GLImageData *)genPixelsWithView: (UIView *)view
{
  float width = RCTScreenScale() * view.bounds.size.width;
  float height = RCTScreenScale() * view.bounds.size.height;
  GLubyte *data = (GLubyte *)malloc(4 * width * height);
  CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef ctx = CGBitmapContextCreate(data, width, height, 8, 4 * width, colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
  CGColorSpaceRelease(colourSpace);
  CGContextClearRect(ctx, CGRectMake(0.0, 0.0, width, height));
  CGContextScaleCTM(ctx, RCTScreenScale(), RCTScreenScale());
  [view.layer renderInContext:ctx];
  CGContextRelease(ctx);
  return [[GLImageData alloc] initWithData:data withWidth:width withHeight:height];
}

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
- (instancetype)initWithData: (GLubyte *)data withWidth:(int)width withHeight:(int)height
{
  self = [super init];
  if (self) {
    _data = data;
    _width = width;
    _height = height;
  }
  return self;
}

- (void)dealloc
{
  if (_data) {
    free(_data);
    _data = nil;
    _width = 0;
    _height = 0;
  }
}

@end