Reading (and comparing) pixels in SDL2

Started by
4 comments, last by Zotoaster 10 years, 3 months ago

Okay so let me explain roughly what I'm trying to do. I've got a spritesheet of a character, and I wish to attach a sword to his hand. To achieve this I'm putting two pixels on his hand per frame, one being RGB (1, 2, 3) and the other being (3, 2, 1). If I can read in and store the positions of these pixels, I should be able to position the sword as the player animates.

So, I've got a Texture class (which keeps a reference to the SDL surface), and I'm using this code to read pixels: http://sdl.beuc.net/sdl.wiki/Pixel_Access

Now, I'm going through each frame, and for each frame, going through each pixel, and comparing it to 'spec1' and 'spec2', which are Uint32 values which define the pixel colour. Here's the code:


        // read special pixels
        if (_readSpecial)
        {
            SDL_LockSurface(_texture->GetSDLSurface());
            
            // convert special SDL_Color to Uint32
            Uint32 spec1 = SDL_MapRGB(_texture->GetSDLSurface()->format, _spec1.r, _spec1.g, _spec1.b);
            Uint32 spec2 = SDL_MapRGB(_texture->GetSDLSurface()->format, _spec2.r, _spec2.g, _spec2.b);
            
            
            // start looping through frames
            for (int f = start; f < end; f++)
            {
                int frmx = f % _cols;
                int frmy = f / _cols;
                
                // get rectangle around frame
                SDL_Rect clip;
                clip.x = frmx * _frmWidth;
                clip.y = frmy * _frmHeight;
                clip.w = _frmWidth;
                clip.h = _frmHeight;
                
                bool found1 = false;
                bool found2 = false;
                
                
                // loop through all pixels in frame
                for (int y = clip.y; y < clip.y + clip.h; y++)
                {
                    if (found1 && found2) break;
                    
                    for (int x = clip.x; x < clip.x + clip.w; x++)
                    {
                        
                        // get pixel at (x, y)
                        Uint32 pix = _texture->GetPixel(x, y);

                        // if pixel is a special value, store it in animation
                        if (pix == spec1)
                        {
                            SDL_Point pt = {x, y};
                            anim->Special1.push_back(pt);
                            found1 = true;
                        }
                        else if (pix == spec2)
                        {
                            SDL_Point pt = {x, y};
                            anim->Special2.push_back(pt);
                            found2 = true;
                        }
                    }
                }
                
                // if not found special value, add dummy value
                SDL_Point none = {-1, -1};
                if (!found1) anim->Special1.push_back(none);
                if (!found2) anim->Special2.push_back(none);
            } 
            
            SDL_UnlockSurface(_texture->GetSDLSurface());
            
        }

Now, I'm putting breakpoints in the "if (pix == spec1)" statements, to check if the pixels have been found, but that breakpoint never gets reached. I'm trying to figure out why this is. Does anyone have any clues?

Thanks

[Edit]

Forgot to mention, I'm using a PNG image, not sure if that's part of the problem...

Advertisement

My shot in the dark guess would be GetPixel returns RGBA while SDL_MapRGB returns RGB. You can find out by just printing both in hex. If that's it, you could use SDL_MapRGBA.

If that's not it, I'm not sure since I kind of stopped reading your code after I ran into start, end, _cols with unknown values.

I tried it with SDL_MapRGBA but that didn't work either. Here's a condensed version of the code showing only the important bits:


// convert special SDL_Color to Uint32
            Uint32 spec1 = SDL_MapRGBA(_texture->GetSDLSurface()->format, _spec1.r, _spec1.g, _spec1.b, 255);
            Uint32 spec2 = SDL_MapRGBA(_texture->GetSDLSurface()->format, _spec2.r, _spec2.g, _spec2.b, 255);


// ...

// while looping through pixels

                        // get pixel at (x, y)
                        // CODE FOR THIS IN LINK ON FIRST POST
                        Uint32 pix = _texture->GetPixel(x, y);

                        // if pixel is a special value, store it in animation
                        if (pix == spec1)
                        {

                            // breakpoint never reaches here

                            SDL_Point pt = {x, y};
                            anim->Special1.push_back(pt);
                            found1 = true;
                        }
                        else if (pix == spec2)
                        {
                            SDL_Point pt = {x, y};
                            anim->Special2.push_back(pt);
                            found2 = true;
                        }

Did you either fprintf (or cout or equivalent) the hex values of the pixels or step through with a debugger watching the values? I can't possibly know the value of your special pixel (did you use a lossy image format? PNG does offer a lot of options). I also don't know if you're stepping on spec1 or spec2. I also don't know if you're even looping through the part of the image that has your special pixel.

Once you do look at the values of the pixels, maybe you can provide the hex for each here so people have a better idea what is going wrong. What is the hex value you get right after assigning to spec1 and spec2? Are those still the same when you get to the comparisons in your loop? What values are you getting for the special pixel being read from the image? You should know the position of the special pixel, so you should be able to add an if (x == what I want) && (y == what I want) fprintf(pix) in your loop. Heck, with that information you might even fix the bug yourself.

When I get stumped by bugs, it's usually because the code I think is important is not actually the problem. For that reason, I strongly recommend against deciding what the important bits are when asking others for help.

I know for a fact that I'm looping through the correct part of the image because the 'clip' rect is directly taken from the part of my code that renders each sprite frame, which works fine. As for working through all the hex values, each frame is 64x64 pixels, that's 4096 values to look through.

I posted the "important" bits in my second post, but in my first post all the relevant code is there.

I'll try your idea of testing the known positions of the special pixels and report back.

Thanks

Okay so I tried putting a pixel at 0,0 of the whole image with RGB values 66, 77 and 88. It read them in as 84, 96 and 107, so obviously the colours are either being changed or not read in properly. However, when I try it with a specific alpha value, it reads it in perfectly. I would change my system to only use alpha values but it seems the pixel editor I'm using removes the alpha value once you put in the pixel and blends it in with the rest of the image.

This topic is closed to new replies.

Advertisement