Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

GPUImagePicture: don't redraw using CoreGraphics unless you have to #1267

Merged
merged 2 commits into from

2 participants

@karlvr

There was support for this but it appeared to have been disabled. I've tested this in my project and it seems to still work as expected, and significantly reduces memory usage by not needing to redraw these graphics. I think was just a typo.

@karlvr karlvr GPUImagePicture: don't redraw using CoreGraphics unless you have to
There was support for this but it appeared to have been disabled.
08d1521
@BradLarson
Owner

I disabled that for a while, because it was actually slower in my benchmarks (and produced no memory reduction), while potentially being more fragile (it's possible that input images won't align to the image properties that I specify there).

I've since heard that this is more performant and may avoid issues with premultiplied alpha, but I'm still concerned about the possibility that this will break with certain images. See Tyler's comment for a little background on this: http://stackoverflow.com/questions/448125/how-to-get-pixel-data-from-a-uiimage-cocoa-touch-or-cgimage-core-graphics/1247963#comment3435194_1247963

If I was sure that this would work with all images, I'd accept this.

@karlvr
@BradLarson
Owner

It sounds like byte order (BGRA vs. RGBA) and the presence or absence of an alpha channel are the big ones. The texture format that the image was uploaded into could be adjusted based on these parameters, if we could determine what they were. I'm pretty sure there's a way to extract that, but I don't have it in front of me now.

@karlvr
@karlvr karlvr GPUImagePicture: only access image bytes directly if the bitmap byte …
…order and format is compatible with GL

This correct non-redrawing for JPGs from my previous commit, as they are big endian.
62c8311
@karlvr

Please see the latest commit. I have tested this particularly with JPG files supplied to GPUImagePicture and this works great.

@BradLarson BradLarson merged commit b662c2e into BradLarson:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 17, 2013
  1. @karlvr

    GPUImagePicture: don't redraw using CoreGraphics unless you have to

    karlvr authored
    There was support for this but it appeared to have been disabled.
Commits on Oct 20, 2013
  1. @karlvr

    GPUImagePicture: only access image bytes directly if the bitmap byte …

    karlvr authored
    …order and format is compatible with GL
    
    This correct non-redrawing for JPGs from my previous commit, as they are big endian.
This page is out of date. Refresh to see the latest.
Showing with 33 additions and 3 deletions.
  1. +33 −3 framework/Source/iOS/GPUImagePicture.m
View
36 framework/Source/iOS/GPUImagePicture.m
@@ -74,7 +74,7 @@ - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoot
pixelSizeOfImage = CGSizeMake(widthOfImage, heightOfImage);
CGSize pixelSizeToUseForTexture = pixelSizeOfImage;
- BOOL shouldRedrawUsingCoreGraphics = YES;
+ BOOL shouldRedrawUsingCoreGraphics = NO;
// For now, deal with images larger than the maximum texture size by resizing to be within that limit
CGSize scaledImageSizeToFitOnGPU = [GPUImageContext sizeThatFitsWithinATextureForSize:pixelSizeOfImage];
@@ -98,12 +98,42 @@ - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoot
GLubyte *imageData = NULL;
CFDataRef dataFromImageDataProvider;
+ GLenum format = GL_BGRA;
+
+ if (!shouldRedrawUsingCoreGraphics) {
+ /* Check that the bitmap pixel format is compatible with GL */
+ CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(newImageSource);
+ if ((bitmapInfo & kCGBitmapFloatComponents) != 0) {
+ /* We don't support float components for use directly in GL */
+ shouldRedrawUsingCoreGraphics = YES;
+ } else {
+ CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
+ if (byteOrderInfo == kCGBitmapByteOrder32Little) {
+ /* Little endian, for alpha-first we can use this bitmap directly in GL */
+ CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
+ if (alphaInfo != kCGImageAlphaPremultipliedFirst && alphaInfo != kCGImageAlphaFirst &&
+ alphaInfo != kCGImageAlphaNoneSkipFirst) {
+ shouldRedrawUsingCoreGraphics = YES;
+ }
+ } else if (byteOrderInfo == kCGBitmapByteOrderDefault || byteOrderInfo == kCGBitmapByteOrder32Big) {
+ /* Big endian, for alpha-last we can use this bitmap directly in GL */
+ CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
+ if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast &&
+ alphaInfo != kCGImageAlphaNoneSkipLast) {
+ shouldRedrawUsingCoreGraphics = YES;
+ } else {
+ /* Can access directly using GL_RGBA pixel format */
+ format = GL_RGBA;
+ }
+ }
+ }
+ }
// CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent();
if (shouldRedrawUsingCoreGraphics)
{
- // For resized image, redraw
+ // For resized or incompatible image: redraw
imageData = (GLubyte *) calloc(1, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * 4);
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
@@ -148,7 +178,7 @@ - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoot
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
// no need to use self.outputTextureOptions here since pictures need this texture formats and type
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, 0, format, GL_UNSIGNED_BYTE, imageData);
if (self.shouldSmoothlyScaleOutput)
{
Something went wrong with that request. Please try again.