abitofcode

CCRenderTexture category – percentage complete

Here’s a Category to return the percentage of a CCRendertexture that is transparent i.e what percentage of the pixels have an alpha value of zero. Question originally asked on cocos2d forum.

I’ve thrown together a quick example project where a country scene is scratched off to reveal the same location in colder times, once the entire image is scratched off the percentage transparent should be 100 (download available at bottom of post)

Tap the image 3 times to reset.


//
//  CCRenderTexture+Percentage.m
//  Scratch
//
//  Created by Christopher Wilson on 30/04/2012.
//  Copyright (c) 2012 abitofcode ltd. All rights reserved.
//
 
#import "CCRenderTexture.h"
#import "CCRenderTexture+Percentage.h"
 
@implementation CCRenderTexture (Percentage)
 
-(float)getPercentageTransparent
{
    NSAssert(pixelFormat_ == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image");
 
    CGSize s = [texture_ contentSizeInPixels];
    int tx = s.width;
    int ty = s.height;
 
    int bitsPerPixel                = 4 * 8;
    int bytesPerPixel               = bitsPerPixel / 8;
    int bytesPerRow                 = bytesPerPixel * tx;
    NSInteger myDataLength          = bytesPerRow * ty;
 
    int numberOfPixels              = tx * ty;
    float numberOfTransparent       = 0;
 
    GLubyte *buffer = malloc(sizeof(GLubyte)*myDataLength);
 
    if( ! (buffer) ) {
        CCLOG(@"cocos2d: CCRenderTexture#getUIImageFromBuffer: not enough memory");
        free(buffer);
        return -1.0f;
    }
 
    [self begin];
    glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, buffer);
    [self end];
 
    int x,y;
    for(y = 0; y < ty; y++) {
        // just want the last byte (alpha) for each pixel
        for(x = 0; x < tx; x++) {
            GLubyte alpha = buffer[(y * 4 * tx + ((x * 4)+3))];
            if(alpha == 0) {
                numberOfTransparent++;
            }
        }
    }    
 
    free(buffer);
 
    return (numberOfTransparent/numberOfPixels)*100;
}
 
@end
CCRenderTexture category files (415)

 

The images used in this project are available separately below;

 

 

 

 

Scratch - sample project (822)

 
If you like this sort of stuff you can follow me on twitter

7 Comments

  1. Hi Tim,

    Thanks a lot for your article and source code! I am going to use it on a game which consist on scratching several layers…

    Do you have an idea how to extend this to be able to scratch one layer after the other?
    I am going to be researching this topic in the following days so if i come to a good solution share it with you guys.

    Best regards
    Alex recently posted..Frano’s portfolio is available on the Android MarketMy Profile

  2. Hi Chris,

    Thanks for the code…I was looking for something like this. I notice your copyright statement in the header. Am I allowed to use your code without obligation?

    Best regards,

    Jim

    Check out my iPhone app: http://itunes.com/apps/jrchemistryset

  3. @Jim Doh! Yep feel free to use, I keep forgetting to change the headers :)

  4. Hi Chris,

    It’s working pretty well but in my app I allow the user to switch from portrait to landscape while scratching which messes up the scratch coordinates so they have to return to landscape to finish…

    Any suggestions?

    Jim

  5. Hi Chris,

    Thanks for the great tutorials,
    can you please give me some idea on the following things?

    Suppose i am having an image having few portion is non-transparent.

    By using your code can i replace non-transparent portion of the image to some other colors and transparent portion will be remain as it is.

    Thanks,
    Nikhil

  6. Hey Chris,
    I am trying following things:

    -(void)tick: (ccTime) dt
    {
    CCRenderTexture *scratchableImage = (CCRenderTexture*)[self getChildByTag:SCRATCHABLE_IMAGE];
    // Update the render texture
    [scratchableImage begin];
    //Limit drawing to the alpha channel
    glColorMask(1.0f, 1.0f, 1.0f, 1.0f);
    //Draw
    [[scratchableImage sprite] setBlendFunc: (ccBlendFunc)
    {
    GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
    }];

    //reset mask color…
    glColorMask(0.0f, 1.0f,.0f, 1.0f);
    [revealSprite visit];
    [scratchableImage end];
    }
    Can you please give me an idea as i don’t know much about open gl
    Thanks,
    Nikhil

  7. As a new programmer to the i-developer community, I can’t thank you and the whole cocos-2d community enough for this post/source code. You are making this seemingly complex process of learning feasible.

%d bloggers like this: