This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
tutorials:rendering_objects_into_a_uiimage [2012/02/17 09:58] – created daniel | tutorials:rendering_objects_into_a_uiimage [2013/03/05 10:19] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== How to render objects into an image ====== | ||
+ | For %appstore_link? | ||
+ | |||
+ | In order to accomplish that the whole display tree has to be rendered to an exportable image. That's why he extended the SPRenderTexture to allow rendering it to an UIImage. | ||
+ | |||
+ | <code objc> | ||
+ | @interface SPRenderTexture (RenderToImage) | ||
+ | - (UIImage*)renderToImage; | ||
+ | @end | ||
+ | </ | ||
+ | |||
+ | And here is the magical part. In short, it makes use of the bundleDrawCalls method on the SPRenderTexture to get to the current GL context. It then allocates memory for the resulting image and reads the pixels from the GL context into the allocated array. After that we can feed that array to a CGDataProvider, | ||
+ | |||
+ | <code objc> | ||
+ | @implementation SPRenderTexture (RenderToImage) | ||
+ | |||
+ | void releaseRawImageDataBufferCallback(void *info, const void *data, size_t size) | ||
+ | { | ||
+ | free((void*)data); | ||
+ | } | ||
+ | |||
+ | - (UIImage*)renderToImage | ||
+ | { | ||
+ | __block UIImage *image = nil; | ||
+ | |||
+ | [self bundleDrawCalls: | ||
+ | { | ||
+ | float scale = [SPStage contentScaleFactor]; | ||
+ | int width = scale * self.width; | ||
+ | int height = scale * self.height; | ||
+ | int nrOfColorComponents = 4; //RGBA | ||
+ | int bitsPerColorComponent = 8; | ||
+ | int rawImageDataLength = width * height * nrOfColorComponents; | ||
+ | GLenum pixelDataFormat = GL_RGBA; | ||
+ | GLenum pixelDataType = GL_UNSIGNED_BYTE; | ||
+ | BOOL interpolateAndSmoothPixels = NO; | ||
+ | CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; | ||
+ | CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; | ||
+ | |||
+ | CGDataProviderRef dataProviderRef; | ||
+ | CGColorSpaceRef colorSpaceRef; | ||
+ | CGImageRef imageRef; | ||
+ | |||
+ | @try | ||
+ | { | ||
+ | GLubyte *rawImageDataBuffer = (GLubyte *) malloc(rawImageDataLength); | ||
+ | |||
+ | glReadPixels(0, | ||
+ | |||
+ | dataProviderRef = CGDataProviderCreateWithData(NULL, | ||
+ | colorSpaceRef = CGColorSpaceCreateDeviceRGB(); | ||
+ | imageRef = CGImageCreate(width, | ||
+ | image = [UIImage imageWithCGImage: | ||
+ | } | ||
+ | @finally | ||
+ | { | ||
+ | CGDataProviderRelease(dataProviderRef); | ||
+ | CGColorSpaceRelease(colorSpaceRef); | ||
+ | CGImageRelease(imageRef); | ||
+ | } | ||
+ | }]; | ||
+ | |||
+ | return image; | ||
+ | } | ||
+ | |||
+ | @end | ||
+ | </ | ||
+ | |||
+ | With this extension, you can render any object into a UIImage -- you just have to render it into a normal '' |