6

Why do I need this?

Basically I need to turn a color image into gray-scale. Including a gray-scale version of the image could be a solution, but space is tight in my situation - I don't want my APK to be too big. Besides, I would like to work on the pixels for some effects too. Again, this is to make the APK smaller.

I have found getPixel setPixel from CCTexture2D and Getting image's pixel RGBA, but I would like something more simple.

Any help is appreciated.

Thank you!

2 Answers2

7

Here is my solution for you :

1.First make a CCImage version of your image:

I) from File :

CCImage *img=  new CCImage();
img->initWithImageFile("colors.png");

II) From Sprite :

  • II.1) CCSprite -> RenderTexture2D

  • II.2) RenderTexture2D -> CCImage (CCImage *testImage = RenderText2D->newCCImage();)

2.Then You can do what you need :

    CCImage *img= ... // make CCImage from CCSprite
    int x=3;
    if(img->hasAlpha())
        x=4;

    unsigned char *data = new unsigned char[img->getDataLen()*x];   
    data = img->getData();
    // [0][0] => Left-Top Pixel !
    // But cocos2d Location Y-axis is Bottom(0) to Top(max)

    for(int i=0;i<img->getWidth();i++)
    {
        for(int j=0;j<img->getHeight();j++)
        {
            unsigned char *pixel = data + (i + j * img->getWidth()) * x;
            
           // You can see/change pixels' RGBA value(0-255) here !
            unsigned char r = *pixel;
            unsigned char g = *(pixel + 1);
            unsigned char b = *(pixel + 2) ;
            unsigned char a = *(pixel + 3);
        }
    }

3.Then, convert it to texture_2D

//CCImage -> Texture2d
    texture_2D= new CCTexture2D();
    texture_2D->initWithImage(img);

4.And Finally back to CCSprite

CCSprite *result=  CCSprite::createWithTexture(texture_2D);
Community
  • 1
  • 1
Emadpres
  • 3,466
  • 2
  • 29
  • 44
  • I understand how you can see the rgba values, since you're setting char r = *pixel. But how do you change the value of the pixel ? I'm a bit confused about what you're doing with the pointers. Can you explain ? – Rahul Iyer Oct 05 '16 at 10:59
  • 1
    @John Sure. It's almost similar. As you understood, we could access the `R` value of each pixel using the `*pixel` pointer. This is a Read (`xxx=*pixel`) and Write (`*pixel=xxx`) access. (use `*(pixel+1)` for `G` and so on) – Emadpres Oct 05 '16 at 15:47
  • Aren't you leaking memory by doing *data = new unsigned..... and then in the next line doing data = img->getData() ? – Rahul Iyer Oct 11 '16 at 10:16
  • @John For using the `getData()` you need to allocate some memory beforehand. Anyway you are right.. you of course have to free the `data` memory at the end of procedure: `delete data`. – Emadpres Oct 12 '16 at 13:08
  • haha... actually I asked someone else a question about this and they told me I was leaking data based on doing new, and then the next line as I mentioned..... I do the delete but I didn't allocated... right now I'm just assigning right away (not allocating), because isn't it already allocated by img ? I feel like towelie... i have no idea whats going on.. .XD – Rahul Iyer Oct 12 '16 at 13:49
  • @John Well. I wrote the code years ago and in that time I find that I need to allocate memory. But Cocos2dx improves month by month and they may have changed the behavior of `getData()`. Anyway, I can not test it now, please check if it needed or not. – Emadpres Oct 13 '16 at 07:53
0

This can be done a couple of ways. What I have done in the past is to just called setColor on the sprite to some color close to what you are looking for. That had worked for my purposes.

my_sprite.setColor( ccc3( 128, 128, 128 ) );

Another solution (more thorough and precise): how to implement grayscale rendering in OpenGL?

Community
  • 1
  • 1
irwinb
  • 993
  • 2
  • 10
  • 20