In the project I'm working on, I have a level file with multiple images and some associated data (how many images, their dimensions etc).
I would like to have a single level data file combining all of these images and the details about the images. I'm hoping someone can give me a better solution than what I've come up with
My first idea
1) Write whatever strings/floats etc to the file for various bits of relevant information
2) Write a field with the number of pngs
3) For each png,
3i) write its size to the file
3ii) read bytes from the png, write them to the data file.
That will work, but the only way I can think of to read the data back and draw the images is to then recreate each of the individual png files by writing each file back to disk, then using loadbmp for each file.
My second idea
1/2) as above
3) Draw all pngs to a virtual screen
4) Use getpixel thousands of times and store the results in the file
This makes drawing the images later easy (read through the file, and do lots of setpixel commands) but it will be SLOOOOOOOOOOOOOOOW!
Does anyone have a better solution? Maybe some funky C++ code to grab the data as a buffer instead of lots of getpixel reads?
In case I've managed to confuse everyone, effectively I'm trying to create my own shoebox I suppose.
Pity there's no "add file to shoebox" command :(
I did this with SpriteZ
You use getpixel only during development phase.
WRITE data info to the file, [x,y,color]
OPEN to read and splits$ to get the fields into an array.
Once the game is done, you stop building the data files.
Loading the data is a bit faster than getpixel.
I dont recommend doing all your graphics like this, however, it is possible.
The only thing i used it for was to create those zonemaps.
The zonemaps store white pixel locations into a data file.
On my TODO there's a command to create images from an array and vice versa. Not highest priority, though. And not very quick as well. Also you won't get the compression you get with png then.
Okay, I might end up going getpixel/setpixel - speed won't be too much of an issue, and it sounds like the only feasible option at this point. All good, thanks guys!!!
Why not do a system whereby graphics can be embedded into the program (when compiling) - and can then be loaded etc ?
You mean like Shoebox? :-)
Yes, I was thinking about the IncludeBinary thing.
For my purposes I have player designed levels with their own graphics in them, so that rules out DATA type statements, though an "add to shoebox" would be perfect for the problem.
Gernot,
Hopefully you'll see this thread - is there any way (C++ inline I assume) to grab the data from an image buffer? I have to do about 250,000 pixel read/writes to load/save my player files and it is pretty slow. Can I grab a sprite from memory and dump it to disk (and later read it back from disk) directly as a memory buffer of some type?
the easiest would be to use SAVESPRITE as a BMP (it saves a 24 bit bitmap) and read that with READ...
The 24 bit bitmaps are really easy to read. If you know the size of the image before, you can skip all the header stuff and read the pixels directly.
Here's about bitmap format in 32 bits:
CONSTANT BITMAPFILEHEADERSIZE 0x0000000e
readbyte B // must be ASC("B")
readbyte M // must be ASC("M")
if(!file.ReadLong(bitmapHeader.bfSize)) goto fail;
if(!file.ReadWord(bitmapHeader.bfReserved1)) goto fail;
if(!file.ReadWord(bitmapHeader.bfReserved2)) goto fail;
if(!file.ReadLong(bitmapHeader.bfOffBits)) goto fail;
// Read in bitmap information structure
lInfoSize = bitmapHeader.bfOffBits - BITMAPFILEHEADERSIZE;
pBitmapInfo = (BITMAPINFO *) new BYTE[lInfoSize];
memset(pBitmapInfo, 0, lInfoSize);
// if(!file.Read(pBitmapInfo, lInfoSize)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biSize)) goto fail;
switch(pBitmapInfo->bmiHeader.biSize)
{
case 40:
if(!file.ReadLong(pBitmapInfo->bmiHeader.biWidth)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biHeight)) goto fail;
if(!file.ReadWord(pBitmapInfo->bmiHeader.biPlanes)) goto fail;
if(!file.ReadWord(pBitmapInfo->bmiHeader.biBitCount)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biCompression)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biSizeImage)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biXPelsPerMeter)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biYPelsPerMeter)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biClrUsed)) goto fail;
if(!file.ReadLong(pBitmapInfo->bmiHeader.biClrImportant)) goto fail;
// 40 bytes for that block
break;
}
pBitmapInfo->bmiHeader.biHeight=abs(pBitmapInfo->bmiHeader.biHeight);
BytesPerPixel=pBitmapInfo->bmiHeader.biBitCount/8;
if(mod(pBitmapInfo->bmiHeader.biWidth,4) == 0)
{
BytesPerLine=( pBitmapInfo->bmiHeader.biWidth * pBitmapInfo->bmiHeader.biBitCount ) / 8;
}
else
{
BytesPerLine=( pBitmapInfo->bmiHeader.biWidth * pBitmapInfo->bmiHeader.biBitCount ) / 8;
// BytesPerLine= pBitmapInfo->bmiHeader.biWidth * BytesPerPixel;
if(mod(BytesPerLine,4))
{
BytesPerLine+=(4-mod(BytesPerLine,4));
}
}
lBitSize=BytesPerLine*pBitmapInfo->bmiHeader.biHeight;
// and here the pixels start. Read 3 bytes (BGR) for each pixel.
// the bitmap is stored upside down.
Thanks for the information!!!! That'll be a lot better solution - the pixel read/writes are extremely resource intensive.
:good: