Sign in to follow this  
kzar

Need a bit of help making a little SDL pixle function

Recommended Posts

I have been following the tutorial of how to use bitmapped fonts here: http://sol.planet-d.net/gp/ch15.html . Up to now I have ignored pixel stuff and have just been using blit's but the code that scans the character's pixels to figure out its width and offset ovbiously can't be done with blit's. I have been trying to neaten the code up so that I understand it and its a bit simpler. I have managed most of it but I am stuck with the code that figures out a characters width and offset. Here is the code from the tutorial:
// Offset of character data per character
int gFontOfs[256];
// Width of character data per character
int gFontWidth[256];

  int i, j, k;
  for (k = 0; k < gFont->h / gFont->w; k++)
  {
    gFontOfs[k] = gFont->w;
    gFontWidth[k] = 0;
    for (i = 0; i < gFont->w; i++)
    {
      for (j = 0; j < gFont->w; j++)
      {
        if (((unsigned int*)gFont->pixels)[(i + k * gFont->w) * 
                                           (gFont->pitch / 4) + j] != 0) 
        {
          if (j < gFontOfs[k])
            gFontOfs[k] = j;

          if (j > gFontWidth[k])
            gFontWidth[k] = j;
        }
      }
    }
    gFontWidth[k] -= gFontOfs[k];
  }


Now I thought I would start by putting the "non-zero pixel" check into a function but it isn't working. The original is this:
if (((unsigned int*)gFont->pixels)[(i + k * gFont->w) * 
                                           (gFont->pitch / 4) + j] != 0) 


And now here is my attempt at neatening it up:
if ( blank_pixel(i , j, gFont) != true )

bool blank_pixel(int x, int y, SDL_Surface *surface) 
{
    Uint8 *p;

    p = surface->pixels + (y * surface->pitch) + (x * 4);
    
    if (p == 0)
        return true;
    else
        return false; 
}


It seems to always return false, even when the pixle is blank and I don't really know why. Sorry if I have missunderstood somthing but I don't really see the purpose of the pitch and things! Thanks

Share this post


Link to post
Share on other sites
I haven't had a chance to look at that code, but take a quick look at this tutorial on the same site for an explanation of pitch and such. There is a neat graphic that should help you comprehend what pitch is and what it is used for. Also you might not want to 'neaten' up pizel functions. Most of them are done in a way for optimization and you could break them. I think your translation of the pixel reader might me off a bit, so that's why it is not working. Alos note that they used k to represent the graphic index they were using and you have left that out, so the first character is the one always being tested. Hope this kind of makes sense, but if not I can try to explain some more.

- Drew

Share this post


Link to post
Share on other sites
ahh I think I understand pitch now, thanks. Yea I'm sure my function is a bit off but I am making it so I can start to understand all of the things about pixles :)

edit: looking at how the original check worked I think this is closer:


if ( blank_pixel(j, (i + k * gFont->w), gFont) != true )



It still isn't working properly though :(

[Edited by - kzar on February 7, 2005 10:15:05 AM]

Share this post


Link to post
Share on other sites
I am thinking it is not working because you are working with the alpha channel as well. Try this method, I think it goes RGBA in SDL:

if (p == 0x000000FF)
return true;
else
return false;


For the method is checks to see that R G B are all 0 and there is the default alpha value. The reason for this is that the pixels are stored in a 32bit unsigned integer when you are working with 32bit surfaces. A value of FF in the last two digits says there is no alpha I believe - or the converse. Regardless of what it means, it is what you would need to test with to see if it is indeed the pixel you are looking for. Give that a try and let us know.

- Drew

Share this post


Link to post
Share on other sites
"if (p == 0x000000FF)" gave a warning about comparing an integer and a pointer and didn't work still. So I tried "if (*p == 0x000000FF)" and that didn't get an error but it didn't work either :(

I am starting to understand how it all works but I am confused. P is a pointer so I don't understand why we are changing it using x etc, surely thats changing where it points to? Are there lots of pixles in a row and we move the pointer on to point at the desired pixel? If so is the size of things like Uint8 and the size of a pixel actualy important? How do I know how much space is taken up by them?

Share this post


Link to post
Share on other sites
*OPS* I'm sorry. I totally blew that. Let me start over. On this page there is an example of how to get a pixel from a surface. Take a look at that for a better understanding. In that case, it returned a Uint32, which I confused with your last post, so disregard my last post.

If you use the 'getpixel' function, it will return a integer in the format: 0xRRGGBBAA RR,GG,BB,AA, all being 8 bits per pair can hold a value of 255 different integers, or from 0 - 255. So if you get back 0x000000FF, it will be black with an alpha value.

I hope I have not utterly confused you. If I have, sorry! I would suggest talking a look over those two functions to see how they work on the link. Maybe they can aid you in understanding how the pixel business works.

Also you might want to read this tutorial on bitmapped fonts. I think it might help a bit as well.

- Drew

Share this post


Link to post
Share on other sites
Thanks for the help. I have read those pages before but not totaly understood them, I am understanding it a lot more now though so I will try again :) . I'l post again if I'm stuck. Thanks

edit: Ok I'm starting to get it working. I finaly understand why they sometiems multiplied and divided by 4. The picture is using 32 bits per pixel but the pitch thing uses 8 bits per pixel.

Share this post


Link to post
Share on other sites
Hey I just got it working, heres the code:


if ( blank_pixel(j, (i + k * gFont->w), gFont) != true )

bool blank_pixel(int x, int y, SDL_Surface *surface)
{
Uint32 *p;

SDL_LockSurface(surface);

p = (unsigned int*)surface->pixels + ( y * (surface->pitch / 4) ) + x;

SDL_UnlockSurface(surface);

if (*p == 0)
return true;
else
return false;
}



It suddenly started working when I added the "(unsigned int*)" cast like the tutorial's source did but I don't understand why it makes any difference. I checked and "unsigned int" and "Uint32" are both 32 bits, so is there any difference between the two and why does casting one as the other matter?

Apart from that I just about understand it now so thanks for the help.

Share this post


Link to post
Share on other sites
I think I know why now. pixels is define as:

void *pixels;


So when you were 'adding' or 'advancing' the pointer, it probabally did not know exactly what to do since void is, well void. I'm glad you got though. Nothing worse than little logic errors such as that...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this