Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » fast put_pixels(again) or al_load_bitmap(void* data)

This thread is locked; no one can reply to it. rss feed Print
 1   2 
fast put_pixels(again) or al_load_bitmap(void* data)
aniquilator
Member #9,841
May 2008
avatar

Hello, I'm facing some performance problems now.
The thing is: I'm programming a framework for games development. In my framework I have a class called SpritesPack. This class stores a lot of sprites, palettes, and some other information about the sprites.
So, the thing is, this spritepack I can save it to the HD, and then just load it back. For this I have a load and save function, when I found an image, I create it, lock and use put pixel for every pixel in it. but, the thing is: this is slow, even with the locking thing. Why? I have some spritepacks for my game with a lot of images...
And I can't use al_load_bitmap either, because I load the spritepack with a std::fstream for example. And the al_load_bitmap dont have a way to load data, with a char*, or void*, for example. Using allegro4, or SDL, I can load this data faster, a lot faster.

What do you recomend me doing? Thanks in advance.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

aniquilator
Member #9,841
May 2008
avatar

I thought about that Edgar, but the thing is: my single sprite is composed of: group, index, optional name, xoffset, yoffset, and so. And this sprite has to be a single file.. If I use the PhysFs for the spritepack I will still have the problem with the sprite.

BTW, I implemented a class called SFF, that derives from spritepack, that loads a mugen sff file. WHY: sometimes you dont have sprites to test, so I get some mugen ones for test.
And, in this case I can't use PhysFS in no way...

I thought about implementing a method to load images based in allegro's addon, but, if someone changes some function there my loader will stop to work.. And thats bad.

:(

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

You can make a separate file to store the data, and include in it the relative path of the sprite in the zip file.

[Spritesheet name 1][Filename]
[...][...]

[Group][Index][Name][Xoffset][Yoffset]
....

Just separate the actual files from each other - keep the text/binary data in one file, and the sprites in separate files. I still think it could work.

Thomas Fjellstrom
Member #476
June 2000
avatar

You have two choices.

1. take a look at the memfile addon. It lets you treat an arbitrary block of data as a file handle you can use with Allegro's file functions.

2. Use al_load_bitmap_f and Allegro's file functions instead of std:iostream. Though, this may not work right with all image loaders.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Audric
Member #907
January 2001

I wonder what it the original cause for slowness compared with A4. Is it because A5 store bitmaps in video memory ? If this accounts for most time spent overall, reducing the file accesses will not change much.

aniquilator
Member #9,841
May 2008
avatar

Thomas thanks for the answer , I will take a look in the memfile addon right now. Thanks

Audric, the slowness is when puttin pixels in the images, in the loading. Not in the main loop, just when loading.

btw, I want some function that works similar to the blit in allegro4. I can use draw_scaled_bitmap for this purpose? Or there is some other function that works better? Thanks.

Trent Gamblin
Member #261
April 2000
avatar

al_draw_bitmap_region is equivalent to blit.

aniquilator
Member #9,841
May 2008
avatar

When I'm trying to load the image using what Thomas said I always get a NULL ALLEGRO_BITMAP. I create the allegro file, and tried to load it with al_load_bitmap_f;

#SelectExpand
1void ImageBase::load(Core::File& pFile, const int& pDataLength) 2{ 3 ALLEGRO_FILE* fake_file = NULL; 4 unsigned char* data = NULL; 5 bool isTarget = true; 6 try 7 { 8 if( mFreeSource && mData != NULL ) 9 { 10 isTarget = (al_get_target_bitmap() == mData) ? true : false; 11 al_destroy_bitmap(mData); 12 } 13 data = new unsigned char[pDataLength]; 14 pFile.read( (char*)data, pDataLength ); 15 fake_file = al_open_memfile((void*) data, pDataLength, "rb" ); 16 17 mData = al_load_bitmap_f( fake_file, "pcx" ); 18 if(mData != NULL) 19 { 20 printf("enter here\n"); 21 mBpp = al_get_pixel_format_bits(al_get_bitmap_format(mData)) ; 22 mWidth = al_get_bitmap_width(mData); 23 mHeight = al_get_bitmap_height(mData); 24 mFreeSource = true; 25 26 } 27 else 28 { 29 printf("error\n"); 30 } 31 al_fclose( fake_file ); //fecha o arquivo 32 delete data; //delata os dados 33 34 if(isTarget) applyAsTarget(); 35 } 36 catch(std::exception& e) 37 { 38 printf("exception.\n"); 39 } 40}

The FIle I test before, and it is open. THe length of the file is right too. But I always get a NULL ALLEGRO_BITMAP. What is the problem?
Thanks in advance.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

aniquilator
Member #9,841
May 2008
avatar

Yeah. I tried other formats as well. But I always get a NULL image. :(

Matthew Leverton
Supreme Loser
January 1999
avatar

"pcx" must be ".pcx".

aniquilator
Member #9,841
May 2008
avatar

I changed the "pcx" to ".pcx", but nothing changed, by the way, this extension, must be just as a tip to the function, no?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Matthew Leverton
Supreme Loser
January 1999
avatar

I changed the "pcx" to ".pcx", but nothing changed, by the way, this extension, must be just as a tip to the function, no?

Then you are supplying invalid data if Allegro can load the image with al_load_bitmap. (I assume you have initialized the image addon.)

aniquilator
Member #9,841
May 2008
avatar

I thought that the "ident" parameter was like a tip, the first loader it would try to use, them if it couldn't be used, it would just try another format. But Now I understand.
Is There some "ident" I can pass, so it will try to load until it reaches the correct format?

So I have made everything "almost" right. I can use the allegro loader with my Image class now, but, unfortunally I dont get the speed I was trying to get. :(
It is faster but not that faster I say.
Here is the code, is there a way to speed the things up a little? I mean, just modfing this method.

#SelectExpand
1void ImageBase::load(Core::File& pFile, const int& pDataLength) 2 { 3 ALLEGRO_FILE* fake_file = NULL; 4 unsigned char* data = NULL; 5 bool isTarget = false; 6 char const* extensions[] = { ".png", ".pcx", ".bmp", ".gif",".tga", ".tif", ".tiff", ".jpg", ".jpeg", NULL }; 7 8 try 9 { 10 if( mData != NULL ) 11 { 12 isTarget = ( al_get_target_bitmap() == mData ) ? true : false; 13 if( mFreeSource ) 14 { 15 al_destroy_bitmap( mData ); 16 } 17 } 18 19 data = new unsigned char[pDataLength]; 20 pFile.read( (char*)data, pDataLength ); 21 22 fake_file = al_open_memfile((void*) data, pDataLength, "rb" ); 23 24 for(register int i = 0; extensions[i] != NULL; ++i ) 25 { 26 al_fseek( fake_file, 0, ALLEGRO_SEEK_SET);//volta o ponteiro para a primeira posição do "arquivo" 27 mData = al_load_bitmap_f( fake_file, extensions[i] ); 28 29 if( mData != NULL ) //se encontar a imagem sai do loop. 30 { 31 break; 32 } 33 } 34 if(mData != NULL) 35 { 36 mBpp = al_get_pixel_format_bits(al_get_bitmap_format(mData)) ; 37 mWidth = al_get_bitmap_width(mData); 38 mHeight = al_get_bitmap_height(mData); 39 mFreeSource = true; 40 } 41 else 42 { 43 std::stringstream out; 44 out << "ImageBase::load(" << &pFile << ", " << pDataLength << "): Error in loading the image."; 45 raiseGraphicException( out.str() ); 46 } 47 48 al_fclose( fake_file ); //fecha o arquivo 49 delete data; //delata os dados 50 51 if(isTarget) applyAsTarget(); 52 } 53 catch(std::exception& e) 54 { 55 std::stringstream out; 56 out << "ImageBase::load(" << &pFile << ", " << pDataLength << "): Error in loading the image, couldn't allocate memory for image."; 57 raiseGraphicException( out.str() ); 58 } 59 }

So, I try to load the image, until I find the correct loader for it. The tests I made I'm loading pngs, so, the first test it finds the correct image.
I'm trying to load, like 903 Images and its taking like 18 seconds...
The allegro4 version, takes at its max, like 4 seconds to 5.

kazzmir
Member #1,786
December 2001
avatar

Maybe you could write/steal header detection code so you can tell with a high probability what the image format is yourself and pass along the proper extension to Allegro.

Elias
Member #358
May 2000

Is it faster if you load them as memory bitmaps? If you load video bitmaps, then it does much more than A4, it loads them but also uploads them to the GPU. If loading only memory bitmaps also is slower then likely something can be optimized.

--
"Either help out or stop whining" - Evert

aniquilator
Member #9,841
May 2008
avatar

Kazzmir, i think thats not the problem.. I have my own loaders as well. I figured out now, that the problem is because the bitmaps are ViDEO_BITMAPS...
When I changed the flag to force the use of MEMORY_BITMAPS, the load was about 2/3 seconds...

Instead drawing the images gets slower.. So I think that there's no way out of this. faster loadings and slow framerates or slow loading but faster frame rates...
Complicated. kkk
Edit:
Yeah Elias, its much faster when loading them as memory bitmaps. :(

kazzmir
Member #1,786
December 2001
avatar

Is calling load() 903 times taking the majority of time or do you process the bitmaps after loading them (calling putpixel a lot on them)?

If you load the bitmap as memory, process it, then convert it to video (by just calling al_clone_bitmap or use the new al_convert_to_video or whatever) then you will get fast performance at runtime, assuming you are just drawing the bitmaps to the screen without using putpixel.

aniquilator
Member #9,841
May 2008
avatar

Kazzmir, I'm just loading them, no prossessing on them.
Its like the same thing you do in your game, in the mugen mode..
Think that I'm loading an sff and displaying its sprites on screen. Thats it.

Edit
Btw how long is the loading time you get loading an sff of 900-1000 sprites ? Do you load them in memory bitmaps or video bitmaps?

kazzmir
Member #1,786
December 2001
avatar

I'm not sure exactly how long it takes me but I think its pretty fast, something like less than a second. Most of my loading time is taken up by parsing the rest of the mugen files (.cmd, .cns).

Are you loading sffv2 files? All sffv1 are .pcx.

Also it looks like you should set the target bitmap to NULL before destroying mData, just to be safe.

aniquilator
Member #9,841
May 2008
avatar

I saw that you are programmin an allegro 5 backend for your game, but this time you said is using the allegro5 backend ? Or the other ? Because, when I'm using allegro4 or sdl, I can load my spritepacks faster as hell.

Btw I'm not loading the sffs, it was just an example, in this case I mean. Cause I load sffv1, the second I dont looked into it yet.

I dont know if this slowness is because of my computer, or whatever.. (I program in a netbook.)

I have to change the target bitmap to NULL, just if the current target bitmap is the bitmap I'm destroying right?

kazzmir
Member #1,786
December 2001
avatar

Its basically the same speed in Allegro4/SDL/Allegro5 in my engine, although I haven't accurately measured it.

Btw I'm not loading the sffs, it was just an example, in this case I mean. Cause I load sffv1, the second I dont looked into it yet.

Now I'm lost. Are you loading sff files or something else?

Quote:

I have to change the target bitmap to NULL, just if the current target bitmap is the bitmap I'm destroying right?

Right, only if its the current target.

aniquilator
Member #9,841
May 2008
avatar

I'm loading my own spritepacks, its like the sff, but with some more info.
Thats strange, you getting the same speed loading the files.. now I'm lost.

 1   2 


Go to: