PNG Opacity using IGAD Template

8060f823d3b004e7f088076ae8a159c7
0
TheJjokerR 101 May 02, 2011 at 17:52

Hey guys,

Using the template here: http://www.devmaster.net/articles/intro-to-c++-with-game-dev/part2.php

What would I have to do to make PNG’s Alpha value effect in the actual game.

I need this because I want to have 2 actual layers, 1 with tiles for the terrain, and 1 on top that shows green tiles(with opacity) where you can build and red tiles(also with opacity) where you can not build.

Thanks in advance, any help is appreciated.

TJ

7 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 May 02, 2011 at 18:43

Which lesson are you on? You linked to lesson 2, but I don’t think PNG images show up until awhile later.

Anyway, assuming that you can already load the PNG including the alpha channel into a surface, in order to composite it onto an underlying image with alpha you’ll need to write code that loops over the pixels of the tile and calculates the correct color for each individual pixel. That is, you won’t be able to use the CopyTo method anymore. (Unless the IGAD framework includes a CopyTo method that does alpha compositing, which I don’t think it does.)

Anyway, once you’ve got a loop that runs over the pixels, you’ll need to extract the RGB color components of both the destination pixel (the pixel on the screen that you’re writing to) and the pixel from the tile that is supposed to go over it. You’ll also need the alpha component of the tile pixel. Convert the alpha to 0-1 range by converting it to a float, then dividing it by 255.0f. Then calculate:

dest_color = dest_color * (1.0f - alpha) + src_color * alpha

This calculation should be done separately for each RGB color channel. Convert back to integers, put the RGB back together into a 32-bit color value and store it in the screen buffer, and you’re done.

8060f823d3b004e7f088076ae8a159c7
0
TheJjokerR 101 May 02, 2011 at 18:53

Thanks for your fast reply,

I see what I should do, but I need a way to load the image and read it’s pixels. I think it has something to do with Surface::LoadImage(), but I’m not sure..

Thanks

EDIT:

Ignore that, I can use surface->GetBuffer(), I’ll be back later after trying some stuff

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 May 02, 2011 at 18:59

I think the Surface::GetBuffer() method is what you want. Have a look at lesson 8 again; it seems to be doing similar stuff.

8060f823d3b004e7f088076ae8a159c7
0
TheJjokerR 101 May 02, 2011 at 19:35

Ok, I think I’m on the right track now, but I must’ve done something wrong here, because this doesn’t really look right.

interesting.png

I’ve got this code so far.

tileSet[tile]->CopyTo( m_Screen, posX * 32, posY * 32 );

Pixel* tileAddress;
Pixel* worldAddress = tileSet[tile]->GetBuffer();

if(tile == 0){
    tileAddress = tileGreen->GetBuffer();
}else{
    tileAddress = tileRed->GetBuffer();
}

for (int readPixel = 0; readPixel < 32 * 32; readPixel++)
{
    float dest_color = worldAddress[readPixel] * (1.0f - 50) + tileAddress[readPixel] * 50;

    worldAddress[readPixel] = (Pixel) dest_color;
}

As you can see I am using 50 as a fixed value for the alpha as I had no idea how to get the alpha value from the image.

Here’s what it looks like without the dest_color and just tileAddress[readPixel]:

normali.png

As you can see the image looks fine like that, but after using your calculation it goes into “Trippin’-mode”(Might actually use it for some kind of power-up :P)

I figured out I’m writing to the wrong buffer. Seeing how I’m writing back to the “worldAddress” which is the buffer of the tile. Instead I should write to the screen buffer, yet I cant figure out how to get write it properly:

Pixel* screenAddress = m_Screen->GetBuffer();
for (int readPixel = 0; readPixel < 32 * 32; readPixel++)
{
    float dest_color = worldAddress[readPixel] * (1.0f - 50) + tileAddress[readPixel] * 50;

    screenAddress[((posX * 32) + readPixel / 32) + ((posY * 32) + readPixel / 32) * SCRWIDTH] = (Pixel) dest_color;
}

I did it before without any problems at all, but I lost the code and forgot how to get the positioning right.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 May 02, 2011 at 20:03

The alpha value should be between 0 and 1, so you should probably use 0.5 instead of 50. You didn’t hear what I said about doing the math for all the RGB components independently. What you’re trying to do, treating the whole Pixel struct as a single number, won’t work. You need to extract the RGB components, do the math on each of them, and then put them back together into a Pixel again. See lesson 9 for more about this.

Your math for addressing the screen pixels is also wrong. Remember the destination image is not 32x32, so you need to calculate the correct address using the destination width, the posX and posY, and the x, y within the tile. You’ll probably want to do separate y and x loops instead of doing one loop on readPixel.

8060f823d3b004e7f088076ae8a159c7
0
TheJjokerR 101 May 03, 2011 at 11:05

@Reedbeta

The alpha value should be between 0 and 1, so you should probably use 0.5 instead of 50. You didn’t hear what I said about doing the math for all the RGB components independently. What you’re trying to do, treating the whole Pixel struct as a single number, won’t work. You need to extract the RGB components, do the math on each of them, and then put them back together into a Pixel again. See lesson 9 for more about this. Your math for addressing the screen pixels is also wrong. Remember the destination image is not 32x32, so you need to calculate the correct address using the destination width, the posX and posY, and the x, y within the tile. You’ll probably want to do separate y and x loops instead of doing one loop on readPixel.

Aah man, you know I did read it, but in the excitement of getting it to work I totally forgot. Sorry!

Thanks!

_______________________________

Ok, I have tried almost everything but I can’t get anything working now.. Here’s the code with stuff commented out of what I tried earlier.

I first thought I could use the >> operator to get the colours out of the Pixel struct, but that didn’t seem to work, then I tried using the Color struct, but that doesn’t do anything with it’s alpha value.

I can’t even get the positioning right…

for (int readPixelX = 0; readPixelX < 32; readPixelX++)
{
    for (int readPixelY = 0; readPixelY < 32; readPixelY++)
    {
        Pixel original_color = worldAddress[readPixelX * readPixelY];   //worldAddress[readPixelX * readPixelY] * (1.0f - 0.5f) + tileAddress[readPixelX * readPixelY] * 0.5f;
        Pixel src_color = tileAddress[readPixelX * readPixelY];
        
        Color extractedOriginal;
        extractedOriginal.Set(float (original_color >> 16), float (original_color >> 8), (float) original_color);
        Color extractedSource;
        extractedSource.Set(float (src_color >> 16), float (src_color >> 8), (float) src_color);
        
        /*
        int dest_color_red = int (extractedOriginal.r * (1.0f - extractedSource.a) + extractedSource.r * extractedSource.a);
        int dest_color_green = int (extractedOriginal.g * (1.0f - extractedSource.a) + extractedSource.g * extractedSource.a);
        int dest_color_blue = int (extractedOriginal.b * (1.0f - extractedSource.a) + extractedSource.b * extractedSource.a);
        */
        Color endColor = extractedOriginal + extractedSource;

        //worldAddress[readPixel] = (Pixel) dest_color; //tileAddress[readPixel]
        screenAddress[((posX * 32) + readPixelX) + ((posY * 32) + readPixelY) * SCRWIDTH] = (Pixel) ((int (endColor.r) << 16) + (int (endColor.g) << 8) + endColor.b);//(dest_color_red << 16) + (dest_color_green << 8) + (dest_color_blue);
    }
}

You must know that while I’m trying to make this work, I’m still reading a lot of tutorials on how to actually program in c++, so far I haven’t learned anything related to stuff like this… -.-“

Thanks…

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 May 03, 2011 at 16:45

You’re on the right track, but you need to mask as well as shifting when extracting colors, like:

red = (src_color & 0xff0000) >> 16;
green = (src_color & 0xff00) >> 8;
blue = src_color & 0xff;

The AND-ing zeroes out all the bits that aren’t part of the color channel you want to extract, then the shifting repositions the bits so the color channel you want is at the least-significant end of the word.