Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
A category for Sparrow 1.X that allows a SPDisplayObject to be dynamically converted to a UIImage.
// SPDisplayObject+Image.h
// Sparrow
// Created by Shilo White on 11/9/11.
// Copyright (c) 2011 Shilocity Productions. All rights reserved.
#import "SPDisplayObject.h"
@interface SPDisplayObject (Image)
@property (nonatomic, readonly) UIImage *UIImage;
@property (nonatomic, readonly) UIImage *fullSizeUIImage;
- (UIImage *)UIImageWithBackgroundColor:(uint)backgroundColor;
- (UIImage *)UIImageWithBackgroundColor:(uint)backgroundColor fullSize:(BOOL)fullSize;
// SPDisplayObject+Image.m
// Sparrow
// Created by Shilo White on 11/9/11.
// Copyright (c) 2011 Shilocity Productions. All rights reserved.
#import "SPDisplayObject+Image.h"
#import "SPView.h"
#import "SPRenderSupport.h"
@interface SPView (RenderSupport)
@property (nonatomic, readonly) SPRenderSupport *renderSupport;
@implementation SPView (RenderSupport)
- (SPRenderSupport *)renderSupport {
return mRenderSupport;
@implementation SPDisplayObject (Image)
- (UIImage *)UIImage {
return [self UIImageWithBackgroundColor:0x0];
- (UIImage *)fullSizeUIImage {
return [self UIImageWithBackgroundColor:0x0 fullSize:YES];
- (UIImage *)UIImageWithBackgroundColor:(uint)backgroundColor {
return [self UIImageWithBackgroundColor:backgroundColor fullSize:NO];
- (UIImage *)UIImageWithBackgroundColor:(uint)backgroundColor fullSize:(BOOL)fullSize {
SPStage *stage = [SPStage mainStage];
SPView *nativeView = stage.nativeView;
int contentScaleFactor = [nativeView contentScaleFactor];
int width = self.width*contentScaleFactor;
int height = self.height*contentScaleFactor;
int bufferLength = width*height*4;
unsigned char buffer[bufferLength];
[SPRenderSupport clearWithColor:backgroundColor alpha:1.0f];
[self render:nativeView.renderSupport];
glReadPixels(0, (stage.height*contentScaleFactor)-height, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &buffer);
CGDataProviderRef dataProviderRef = CGDataProviderCreateWithData(NULL, &buffer, bufferLength, NULL);
CGImageRef imageRef = CGImageCreate(width, height, 8, 32, width*4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault, dataProviderRef, NULL, true, kCGRenderingIntentDefault);
if (!fullSize) {
width /= contentScaleFactor;
height /= contentScaleFactor;
uint32_t *pixels = (uint32_t *)malloc(bufferLength);
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width*4, CGImageGetColorSpace(imageRef), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
imageRef = CGBitmapContextCreateImage(context);
UIImage *image = [UIImage imageWithCGImage:imageRef];
return image;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment