Sign in to follow this  
DestX

[SDL?]libpng error: decompression error.

Recommended Posts

Hello, I'm having a rather weird problem here this time, I'm pretty far into finishing a game I'm working on, and lately I just started getting this libpng error I wrote as the title for I don't even know what reason. The reason it's weird is because when it does happen, it's only when I'm about 3-5 minutes into the game, when all sprites are loaded in the begining. Debugging in Visual Studio shows me that the program crashes at the line for transparency code:
SDL_SetColorKey(block[i].blockS, SDL_SRCCOLORKEY, SDL_MapRGB(block[i].blockS->format, 255, 255, 255));
However, the line it is pointing to is actually at the beginning of the code and outside of the main loop for the game, it should not be accessible or repeated to by any means after even 1 second of gameplay, yet it directs me here for some reason... If I'm not on debug mode and that happens, the game will keep running and not crush, but all the sprites(Other than the one it points to in debugging and one more, surprisingly enough) disappear. I don't know if it has to do with it, but block[i].blockS is a SDL_Surface that's declared as a class member, and the file it stores changes from time to time during runtime, about every 10 seconds, but it works completely fine up until that point at 3-5 minutes). I've searched the forums here and Google to no avail, so I'm hoping if I ask this, someone might still know what to answer me = Thanks in advance for those willing to help.

Share this post


Link to post
Share on other sites
I got this decompression error before on some projects and, as far as I can remember, it happened because of badly written png files (e.g. CRC not matching with the chunk data). Maybe it's because of an image you added recently.

Try not loading the two images that don't show up and see if the release build crashes.

EDIT: I now realized that only two images show and the rest dissapear :) I guess you can do some trial and error with the last added images.

[Edited by - kitzkar on September 10, 2009 9:38:10 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by brunooo
It may be something wrong with your code, block[i] does not exists or block[i].blockS is not allocated (trash)! 'block' is a static array?


block is a dynamic array, I needed to determine the size during runtime at one point, but I removed the aspect that needed it to, would making it static again make a difference?

EDIT: I made it back to static and it still does the same thing.

As for the block[i] not existing or blockS not being allocated, that can't happen, I left no room for the surface to be empty during the runtime, the surface has a loaded image even when it is offscreen and when it changes, it changes right away, no NULLifying or anything, and block[i] always exists too as it just goes offscreen until it is shuffled another value and goes back onscreen.


Quote:
I got this decompression error before on some projects and, as far as I can remember, it happened because of badly written png files (e.g. CRC not matching with the chunk data). Maybe it's because of an image you added recently.

Try not loading the two images that don't show up and see if the release build crashes.

EDIT: I now realized that only two images show and the rest dissapear :) I guess you can do some trial and error with the last added images.

[Edited by - kitzkar on September 10, 2009 9:38:10 AM]


I don't really think that's the case, all the sprites that are supposed to load at that time already exist and work fine from the first second of the game's running time, yet the error only shows up after a few minutes, there shouldn't be any new sprites loaded at that time, so I don't think that's it =
[Edited by - DestX on September 10, 2009 11:07:19 AM]

Share this post


Link to post
Share on other sites
Sorry for a double post, but the old post was already quite a mess as it is.

Anyway, I fixed it.
What I did before was have a part of the managing function of the instances assign the file to the SDL_Surface that's part of the class.
void manageBlock(...){
...
if(block.blockType == 0) block.blockS = IMG_Load("redB.png");
....
}


That might have been stupid to begin with actually.
What I did now was to make surfaces for all of the images right in the beginning, out of the loop, and then assign them to the SDL_Surface members.
Main(){
...
SDL_Surface *redB = IMG_Load("redB.png");
...
}

{
...
if(block[i].blockType == 0) block[i].blockS = redB;
...
}


Which I actually moved out of the manage function onto the main one to save the need to pass all the Surfaces as arguments to it.

Which btw, I must ask, the way the game works, I split it to 4 pages of similiar code for the main game system with minor differences(4 different game modes that couldn't work with one another on the same page of code), and in each of them I had to add the lines of the assigning in each mode's main function twice(Right before it goes into the managing function I showed above)(Twice before I need it to manage once before the main loop and constantly within it).
Now, the question is, which way is it more efficient for the program? It working outside of the managing function and instead of being typed once, being done 8 times(Only 2 a time are relevant though), or just changing the function to pass the Surfaces to it as arguments?

Anyway, just in case someone needs this for reference in the future, that's what I did.
And thanks for anyone that might answer my new question.

Share this post


Link to post
Share on other sites
I just asked if it was static because if its not you could be not allocing it :)

Do you check if the image is loaded correctly?

About your new question, are you using C or C++? Could you be more clear? I didnt understand it very well :p

Share this post


Link to post
Share on other sites
Yea, sorry about it, I tend to get messy when I type up long sentences =P

What I'm saying is that before, I had this function as part of the Block class:

void Block::manageBlock(Chara &chr, Block &block, int randFunct[], int rank){
if(block.blockType == 0) block.blockS = IMG_Load("red.png");
else if(block.blockType == 2) block.blockS = IMG_Load("green.png");
//etc for 9 blockTypes.
if(block.blockY > 354) block.blockY -= 100;
block.collisionCheck(chr, block);
if(block.blockActive){
block.blockFunct(block, chr, rank);
if(!(block.tim > 201))
block.tim = 201;
}
else if(block.functCheck(chr, block)) block.blockActive = true;
if(!block.blockOnScreen) block.blockX = -33;
block.tim++;
}


The way I fixed it was to take out the first 2 lines I show in this function and the ones for the other graphics, and put them at the beginning of the main function as:

SDL_Surface *redB = IMG_Load("red.png");
SDL_Surface *greenB = IMG_Load("green.png");
//etc.

So I don't have to reload them, and then further away in the main I allocated them outside of the manageBlock function in the main function:

//still in main
for(int i = 0; i < 5; i++){
if(block[i].blockType == 0) block[i].blockS = redB;
else if(block[i].blockType == 1) block[i].blockS = greenB
//etc.
//This calls for the function from the top of the post.
block[i].manageBlock(chr, block[i], randFunct, rank);
}


And I do that twice in the main function.
So, would it be more efficient to do it like that or as:
//main
for(int i = 0; i < 5; i++)
block[i].manageBlock(chr, block[i], randFunct, rank, redB, greenB);


and

//manageBlock funct
void Block::manageBlock(Chara &chr, Block &block, int randFunct[], int rank, SDL_Surface *redB, SDL_Surface *greenB){
if(block.blockType == 0) block.blockS = redB;
else if(block.blockType == 2) block.blockS = greenB;
//etc for 9 blockTypes.
if(block.blockY > 354) block.blockY -= 100;
block.collisionCheck(chr, block);
if(block.blockActive){
block.blockFunct(block, chr, rank);
if(!(block.tim > 201))
block.tim = 201;
}
else if(block.functCheck(chr, block)) block.blockActive = true;
if(!block.blockOnScreen) block.blockX = -33;
block.tim++;
}


Which of these would be more efficient?(Notice that it's actually 9 Surfaces that I'll need to pass to the function and not 2)

[Edited by - DestX on September 10, 2009 11:27:07 PM]

Share this post


Link to post
Share on other sites
You could load them in main and put them in a vector, than you call a function to set a pointer to that vector, something like this:


int main()
{
...
SDL_Surface* vector[9];
vector[0] = IMG_load(...);
vector[1] = ...
etc...

for(int i = 0; i < 5; i++)
block[i].setSurfaces(vector);

...
for(int i = 0; i < 5; i++)
block[i].manageBlock(chr, block[i], randFunct, rank, redB, greenB);
...

return 0;
}

void Block::setSurfaces(SDL_Surface** vector)
{
surfaces = vector;
}

void Block::manageBlock(Chara &chr, Block &block, int randFunct[], int rank){

block.blockS = surfaces[block.blockType];

if(block.blockY > 354) block.blockY -= 100;

block.collisionCheck(chr, block);

if(block.blockActive){

block.blockFunct(block, chr, rank);

if(!(block.tim > 201))

block.tim = 201;

}

else if(block.functCheck(chr, block)) block.blockActive = true;

if(!block.blockOnScreen) block.blockX = -33;

block.tim++;

}




Instead of using the setSurfaces func you could pass the vector of SDL_Surfaces to the manageBlock function. Also dont forget to check if the image is loaded correctly and free them when you will not use them anymore!

:)

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