Left over garbage pixels from copying a pixel value to new location? C/SDL

Started by
12 comments, last by Servant of the Lord 11 years, 6 months ago
Hi all I'm able to draw pixels in many ways and get pixel values and place them somewhere on the screen surface but when It happens the left over pixel is still there and I was hoping someone could show me code and explain how to remove it from the screen surface here is my code to draw and to get pixels :


#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <math.h>
#undef main
int y = 10;
int x = 10;
int x2 = 40;
int y2 = 40;
SDL_Surface *Screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE),
*Image;
void pixeldraw(int x, int y , int color)
{
unsigned int *ptr = static_cast <unsigned int *> (Screen->pixels);
int offset = y * (Screen->pitch / sizeof(unsigned int));
ptr[offset + x] = color;
}

unsigned int pixelget(int x, int y)
{
unsigned int *ptr = static_cast <unsigned int *> (Screen->pixels);
int offset = y * (Screen->pitch / sizeof(unsigned int));
return ptr[offset + x];
}

int main(int argc , char *argv[])
{

SDL_WM_SetCaption("Image Pixel Manipulation", "PM");

Image = IMG_Load("image.png");


//unsigned int *src0 = (unsigned int *) Image->pixels + y * //Image->pitch;


SDL_FillRect(Screen,NULL,(0,0,0));

pixeldraw(10, 10, 0x0000FF);


unsigned int color = pixelget(10, 10);

pixeldraw(x2,y2, color);

printf("%08x\n", color);


//unsigned int *pixels = (unsigned int*) Screen->pixels;

//unsigned int color = pixels[y * (Screen->pitch / /sizeof(unsigned int)) + x];

// pixels[y2 * (Screen->pitch / sizeof(unsigned int) + x2] = color;

//src0[1] = 0;

bool done = false;

SDL_Event event;

while(!done)
{
//SDL_BlitSurface(Image,NULL,Screen,NULL);

while(SDL_PollEvent(&event))
{

switch(event.type)
{

case SDL_QUIT:
return 0;
break;

}

}

SDL_Flip(Screen);
}

return 0;
}






any tips and suggestions are also welcome although this was intended as a test case not a perfect example of coding grammatically and correctly per-say of my ability.

Thanks for anyone who reads this :D.
Advertisement
You aren't removing a pixel with 'pixelget()', you are only reading a value.

You never "removed" the pixel from the first location, you just asked what color it was.
People never actually are able to "erase" anything (what would that look like? A hole in your window? happy.png), we just set it to a new color (I explain it more in this thread).

pixeldraw() sets the color value of a pixel that already exists. The pixel already exists, you're just setting its value.
pixelget() copies and returns the color value of a pixel that already exists, but doesn't set the already-existing pixel to anything new.

Does that help explain it?
Servant the lord : I know I have to redraw over it but how can I detect the pixels around the area of the garbage pixel automatically?

I don't know the code to do it.
Anyone? :(
BUMP
[size=2]It takes time to respond (it's only slightly less than 24 hours since my last post) - you don't need to bump so soon (and certainly not twice). smile.png

I'm not sure what you mean by "detect", and by "garbage pixel". Since I don't quite understand what you are wanting (sorry!), I'm going to ask some questions. Please be as specific and detailed as possible, so I can understand fully, so I can help you.

1) What type of pixels are you looking to "detect"? Are they a certain color?

2) What type of pixels do you consider "garbage"? What makes them "garbage" - their color or some action?

3) You said detect "around" the area of the garbage pixel. What does "around" mean? One pixel around? Two pixels around?

4A) Could you also explain, carefully (it takes me some time to understand wink.png), what it is, in detail, that you are wanting (and why)?
4B) How are you currently attempting it?

5A) What is the correct result that you'd like?
5B) What is the wrong result your current attempt is giving you?

I'm extremely happy to help (really!) but I need more info, 'cause I'm not quite understanding what you want. mellow.png
1) What type of pixels are you looking to "detect"? Are they a certain color?

Image pixels as in the pixels in the PNG Image which is RGBA 32bpp "That could be wrong format".

2) What type of pixels do you consider "garbage"? What makes them "garbage" - their color or some action?

There garbage if a pixel value and location is left-over after one pixel value is gotten and placed in a different location.

3) You said detect "around" the area of the garbage pixel. What does "around" mean? One pixel around? Two pixels around?

Detect the pixels around the area as in any area I specify could be 40 by 40 pixels or 100 by 100 pixels.

4A) Could you also explain, carefully (it takes me some time to understand ), what it is, in detail, that you are wanting (and why)?

To make a wave effect by moving 40 by 40 pixels up and down in a png image.

So I can have a decent and cool water effect without loading in each frame of animation of a Adobe After Effects Water Animation .

4B) How are you currently attempting it?

I don't actually know the code to get rid of pixel in a png image which has already been found from pixelget which puts in a different location with the pixel found by the function pixelget.

5A) What is the correct result that you'd like?

1.) having user-defined way to put in the x and y values of the area of pixels

2.) to find and place the pixels in a different location using the x and y values.

5B) What is the wrong result your current attempt is giving you?

Well I can get values and place them somewhere else but not automatically and in a area specified by me in the x and y .
Okay, I think I sortof understand, though I still have some confusion.
Have you checked out Sol's SDL tutorials?

In any case, let's establish some points first.

  • When drawing anything to the screen, it is permanently "there" until you draw something over it.
  • There is no such thing as "erasing" pixels. You can only draw over pixels with a different color.
  • Every frame you should re-draw everything currently on-screen - it's the easiest way to do computer graphics.



Also, your previous code was doing alot of things wrong, now that I look over it a second time.
Here's a list of serious errors:

  • You never freed your resources.
  • You initialized Screen at a global scope.
  • You never called SDL_Init.
  • You never called SDL_Quit.
  • You #undef main, apparently deciding SDL didn't know what it was doing. huh.png

That's the really bad stuff that could potentially break your program without you knowing why. There's also several bad practices (tons of global variables, for example), but those aren't actual errors like the list above.


[hr]

So, let's do a bit of code. First, our pixel putting and pixel getting functions shouldn't assume we are reading or writing pixels from the screen - we want to be able to read and write to any SDL_Surface (also, we don't want global variables, so the read and write pixel functions shouldn't know about the screen surface anyway).

My SDL is a bit rusty, but (editing your original code) this should work:
typedef unsigned int PixelColor;
void WritePixel(unsigned int x, unsigned int y, PixelColor color, SDL_Surface *surface)
{
PixelColor *pixels = static_cast<PixelColor*>(surface->pixels);
int offset = y * (surface->pitch / sizeof(unsigned int));
pixels[offset + x] = color;
}
unsigned int ReadPixel(unsigned int x, unsigned int y, SDL_Surface *surface)
{
PixelColor *pixels = static_cast<PixelColor*>(surface->pixels);
int offset = y * (surface->pitch / sizeof(unsigned int));
return pixels[offset + x];
}
//Make sure you lock surfaces before editing their pixels.
void LockSurface(SDL_Surface *surface)
{
if(SDL_MUSTLOCK(surface))
{
SDL_LockSurface(surface);
}
}
//Make sure you unlock surfaces once you are done editing their pixels.
void UnlockSurface(SDL_Surface *surface)
{
if(SDL_MUSTLOCK(surface))
{
SDL_UnlockSurface(surface);
}
}


I actually don't have SDL on my computer, and so I can't test anything I'm writing here. You might need to tweak some of the code to get it to work.

We'll also want these, for convenience and code clarity:
//Stolen from Lazy Foo's SDL tutorial.
//See here: http://lazyfoo.net/SDL_tutorials/lesson03/windows/devcpp/index.php
//And here: http://lazyfoo.net/SDL_tutorials/lesson05/index.php
SDL_Surface *LoadSurface(const std::string &filepath, const SDL_Color &color = SDL_Color(0, 255, 255))
{
//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;

//Load the image using SDL_image
SDL_Surface* loadedImage = IMG_Load( filename.c_str() );

//If the image loaded
if( loadedImage != NULL )
{
//Create an optimized image
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free the old image
SDL_FreeSurface( loadedImage );

//If the image was optimized just fine
if( optimizedImage != NULL )
{
//Map the color key
Uint32 colorkey = SDL_MapRGB(optimizedImage->format, color.r, color.g, color.b);

//Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
}
}

//Check if everything went fine.
if(optimizedImage == NULL)
{
//Report an error.
std::cerr << "LoadSurface() - Something went wrong loading '" << filepath << "'.\n"
<< " Error: " << SDL_GetError() << std::endl;
}

//Return the optimized image
return optimizedImage;
}
//Also stolen from Lazy Foo's SDL tutorial.
//See here: http://lazyfoo.net/SDL_tutorials/lesson02/index.php
void DrawSurface(int x, int y, SDL_Surface *source, SDL_Surface *destination)
{
//Make a temporary rectangle to hold the offsets
SDL_Rect offset;

//Give the offsets to the rectangle
offset.x = x;
offset.y = y;

//Blit the surface
SDL_BlitSurface( source, NULL, destination, &offset);
}


They are slightly modified versions of the functions found at Lazy Foo's SDL tutorials; a set of tutorials you should go.

These two functions we'll also find useful:
void DrawRectangle(SDL_Surface *destination, const SDL_Color &color, SDL_Rect *rect = NULL)
{
SDL_FillRect(destination, rect, SDL_MapRGB(destination->format, color.r, color.g, color.b));
}
SDL_Surface *CreateEmptySurface(int width, int height, SDL_Surface *surfaceToCompareTo)
{
SDL_Surface *newSurface = SDL_CreateRGBSurface(surfaceToCompareTo->flags, int width, int height, surfaceToCompareTo->format->BitsPerPixel,
surfaceToCompareTo->format->Rmask, surfaceToCompareTo->format->Gmask,
surfaceToCompareTo->format->Bmask, surfaceToCompareTo->format->Amask);

if(!newSurface)
{
std::cerr << "CreateEmptySurface() - Something went wrong creating a " << width << "x" << height << " surface.\n"
<< " Error: " << SDL_GetError() << std::endl;
}

//Let's start off filling it with a solid color, like solid white.
DrawRectangle(newSurface, SDL_Color(255, 255, 255));

return newSurface;
}


[hr]

Here's what your code should actually look like, if done properly:
int main(int argc, char *argv[])
{
//----------------------------------
//Start up SDL.
SDL_Init(SDL_INIT_EVERYTHING);
//----------------------------------

//----------------------------------
//Create the window.
SDL_Surface *screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
//----------------------------------

//----------------------------------
//Load resources.

//Here we are loading an image just to show how.
//'exampleImage.png' is being looked for in the same folder that the program's executable is in.
SDL_Surface *exampleImage = LoadSurface("./exampleImage.png");

//----------------------------------

//----------------------------------
//Main loop:

bool done = false;

//Loop until we are done.
while(!done)
{
//----------------------------------
//Handle user input.
while(SDL_PollEvent(&event))
{

switch(event.type)
{
case SDL_QUIT:
{
//Don't do return 0 here, set the 'done' bool to true, so we exit properly and free our resources.
done = true;
}
break;
}

}

//----------------------------------
//Handle time-based updating.


//----------------------------------
//Handle logic/thinking.


//----------------------------------
//Draw everything.
{
//Reset the screen to all black.
DrawRectangle(screen);

//Draw any images.
DrawSurface(50, 50, exampleImage, screen);

//Update the screen. Anything drawn this frame now takes effect.
SDL_Flip(screen);
}

//----------------------------------

//----------------------------------
//Delay a little, so we don't take 100% CPU usage.
SDL_Delay(0);

//----------------------------------
}
//----------------------------------

//----------------------------------
//Free resources. Anything we load _must_ be freed - it's one of the marks of a good programmer.

//Any surfaces we load or create (except for 'screen'!) needs to be freed.
SDL_FreeSurface(exampleImage);

//----------------------------------

//----------------------------------
//Shut down SDL.

SDL_Quit(); //SDL_Quit() also frees 'screen' for us, so we don't need to.

//----------------------------------

return 0;
}


[hr]
Moving on to the next portion: Proper timing.
Really, I'll just link to another Lazy Foo tutorial: Frame indpendant movement (lesson 32).

Here's the code I'm adding for time management. I find time is easier to manipulate if it's in a float or double, but that's a matter of preference.
float SecondsSinceLastFrame()
{
static Uint32 lastFrameTime = 0;

//Get the current time.
Uint32 currentTime = SDL_GetTicks();
Uint32 timeDifference = (currentTime - lastFrameTime);
if(timeDifference > 0)
{
//Store the new current time.
lastFrameTime = currentTime;

//Convert from millaseconds to seconds, and return as a float.
return (float(timeDifference) / 1000.0f);
}
else
{
return 0.0f;
}
}


[hr]
Now we can manipulate pixels based on time.

I'm going to create a new surface to hold what we are manipulating, rather than drawing on the screen directly.
SDL_Surface *waterImage = CreateEmptySurface(50, 50, screen);

Every 1/10th of a second, I'm going to update the water image with this function:
void MakeWaterSurface(SDL_Surface *surface, unsigned int frame)
{
//We only have 20 frames, so keep within range.
frame %= 20;

int offset = frame;
if(offset >= 10)
{
//0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1
offset = (10 - (offset - 10));
}

SDL_Color colors[] = {SDL_Color(100, 150, 190),SDL_Color(100, 160, 180),SDL_Color(100, 170, 170),SDL_Color(100, 180, 160),SDL_Color(100, 190, 150),
SDL_Color(100, 190, 170),SDL_Color(100, 190, 190),SDL_Color(100, 190, 210),SDL_Color(100, 190, 230),SDL_Color(100, 220, 250)};

for(int y = 0; y < surface->height; y++)
{
for(int x = 0; x < surface->height; x++)
{
//I'm coding blind without a compiler, so I have completely no idea if this will work or not.
int waveDepth = ((y + offset) % 10);

int waveHorizontalOffset = ((x + (offset/3)) % 20);
int waveVerticalOffset = ((x + waveHorizontalOffset) + offset);

unsigned colorIndex = (waveDepth + waveVerticalOffset) % 10;

WritePixel(x, y, colors[colorIndex], surface);
}
}
}


Not the best looking water in the world, I'm just showing you the basics of how it could be done.
I'm assuming it's not the best looking water in the world, anyway, since I can't compile it to see how it looks. laugh.png
Not only that, but I'm also really sleepy and not thinking straight, so double the chance of mistakes. sleep.png

Here's the whole main body again, with the additions:
const int NumWaterFrames = 20;
const int HalfOfWaterFrames = (NumWaterFrames/2);
const int NumColors = 10;
void MakeWaterSurface(SDL_Surface *surface, unsigned int frame)
{
//We only have 20 frames, so keep within range.
frame %= NumWaterFrames;

int offset = frame;
if(offset >= HalfOfWaterFrames)
{
//0 1 2 3 4 5 6 7 8 9 10 9 8 7 6 5 4 3 2 1
offset = (HalfOfWaterFrames - (offset - HalfOfWaterFrames));
}

SDL_Color colors[] = {SDL_Color(100, 150, 190),SDL_Color(100, 160, 180),SDL_Color(100, 170, 170),SDL_Color(100, 180, 160),SDL_Color(100, 190, 150),
SDL_Color(100, 190, 170),SDL_Color(100, 190, 190),SDL_Color(100, 190, 210),SDL_Color(100, 190, 230),SDL_Color(100, 220, 250)};

for(int y = 0; y < surface->height; y++)
{
for(int x = 0; x < surface->height; x++)
{
//I'm coding blind without a compiler, so I have completely no idea if this will work or not.
int waveDepth = ((y + offset) % NumColors);

int waveHorizontalOffset = ((x + (offset/3)) % NumWaterFrames);
int waveVerticalOffset = ((x + waveHorizontalOffset) + offset);

unsigned colorIndex = (waveDepth + waveVerticalOffset) % NumColors;

WritePixel(x, y, colors[colorIndex], surface);
}
}
}
int main(int argc, char *argv[])
{
//----------------------------------
//Start up SDL.
SDL_Init(SDL_INIT_EVERYTHING);
//----------------------------------

//----------------------------------
//Create the window.
SDL_Surface *screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
//----------------------------------

//----------------------------------
//Load resources.

//Here we are loading an image just to show how.
//'exampleImage.png' is being looked for in the same folder that the program's executable is in.
SDL_Surface *exampleImage = LoadSurface("./exampleImage.png");

SDL_Surface *waterImage = CreateEmptySurface(40, 40, screen);

//----------------------------------

//----------------------------------
//Main loop:

bool done = false;
float accumulatedWaterTime = 0.0f;
unsigned int currentWaterFrame = 0;

//Loop until we are done.
while(!done)
{
//----------------------------------
//Handle user input.
while(SDL_PollEvent(&event))
{

switch(event.type)
{
case SDL_QUIT:
{
//Don't do return 0 here, set the 'done' bool to true, so we exit properly and free our resources.
done = true;
}
break;
}

}

//----------------------------------
//Handle time-based updating.

float delta = SecondsSinceLastFrame();
if(delta > 0.0001f)
{

accumulatedWaterTime += delta;
bool updateSurface = false;
while(accumulatedWaterTime > 0.1f) //One tenth of a second.
{
currentWaterFrame++;
if(currentWaterFrame >= NumWaterFrames)
{
currentWaterFrame %= NumWaterFrames;
}

updateSurface = true;
}

if(updateSurface)
{
MakeWaterSurface(waterImage, currentWaterFrame);
}


}

//----------------------------------

//----------------------------------
//Handle logic/thinking.


//----------------------------------

//----------------------------------
//Draw everything.
{
//Reset the screen to all black.
DrawRectangle(screen);

//Draw any images.
DrawSurface(50, 50, exampleImage, screen);

//Update the screen. Anything drawn this frame now takes effect.
SDL_Flip(screen);
}

//----------------------------------

//----------------------------------
//Delay a little, so we don't take 100% CPU usage.
SDL_Delay(10);

//----------------------------------
}
//----------------------------------

//----------------------------------
//Free resources. Anything we load _must_ be freed - it's one of the marks of a good programmer.

//Any surfaces we load or create (except for 'screen'!) needs to be freed.
SDL_FreeSurface(exampleImage);

//----------------------------------

//----------------------------------
//Shut down SDL.

SDL_Quit(); //SDL_Quit() also frees 'screen' for us, so we don't need to.

//----------------------------------

return 0;
}


[hr]
Any questions about any of that? It's alot to chew at once, I'm sure.

I strongly suggest reading Lazy Foo's SDL tutorials, for starters, and following it up with Sol's SDL tutorials.
I generally have no idea about all of this accept my 2 functions , it would be awesome if someone could do like a simplist explanation on all this new stuff so I can see and know whats going on .


Your drawing a rectangle for the water right then altering the pixels on that rectangle how?

Why are we comparing surfaces?


How are you setting the area of which the pixels values can be gotten and placed elsewhere?

yes a full explanation is required ! biggrin.png
bump

This topic is closed to new replies.

Advertisement