Packing Graphics?

BlitzMax Forums/BlitzMax Programming/Packing Graphics?

Robby(Posted 2012) [#1]
Hi guys! Just had a graphic storage question here. Suppose I have something like this:

Global tiles:TImage[848]

For gcount = 1 To 847
name="tile" + gcount
tiles[gcount] = LoadImage(name,MASKEDIMAGE)
Next

Those tiles are 46x46 pixels each, and 847 of them in the directory.

Is there some way I can load them in like this, but then save them out as one big file, like graphics.gfx or something, and be able to reload the whole pack back into the tiles[847] so I don't need to have all the zillions of little graphics in the directory?

Any help appreciated!! -Rob


Yasha(Posted 2012) [#2]
LoadAnimImage should do what you want. It automatically cuts the image into the specified number of frames.


Captain Wicker (crazy hillbilly)(Posted 2012) [#3]
I just
Incbin "image.blim" 'my own format
Global blimey:TImage=LoadImage("incbin::image.blim")

If you want to tile an image just use G.I.M.P. :)
http://www.gimp.org/


SystemError51(Posted 2012) [#4]
Question moved to appropriate topic

Last edited 2012


Midimaster(Posted 2012) [#5]
With...
BigImage=CreateImage(46*40,46*22)
...you should be able to create a new empty image with 1840x1012pixel (space for 40*22=880 tiles).

Now you load the 847 small images, display them on the screen like tiles: 40 in a line and 22 rows.

Then copy the screen into the big image with...
GrabImage(BigImage,0,0,0)


At the end you save the big image with
SavePixmapPNG()


When loading again now use LoadAnimImage() with the big picture.

Last edited 2012


BladeRunner(Posted 2012) [#6]
ok, first of all:
tiles:timage[848] - this creates an Array with 848 entries.
for gcount = 1 to 847 ... this iterates only 847 of them, arrays start with index '0'. Just a little thing, but such things sum up ;)
Also, if you are nto doing already keep your programs with superstrict, this will show you many errors before they get weird.

Then, for your question:
you can load your images as you do by now, draw them and capture the whole image with all of them and save it. Try to make a Picture thats nearly square, considering 847 images this would be:
sqr(847) -> ~30*30 Images -> 1380*1380px in Size.
I would recoomend using Imagesizes in Powers of 2 in the future as most graphic cards handle them faster (e.g. 32*32, oder 64*128).

See SavePixMapPNG and GrabPixMap for this.
It's as simple as that.

After this, which is a one-time-duty, you can easily load and draw your Images with LoadAnimimage and Drawimage.


Robby(Posted 2012) [#7]
I can make a 30 x 30 png or bmp. In fact, this is how they were first arranged. But I couldn't find any info on how to split the big image into an array. I can certainly leave some blanks for future expansion - and in fact a few of those 847 are already blanks. So lets suppose I already made a 30 x 30 grid of 46 x 46 tiles. That would be a bmp or png of 1380 x 1380, as you mentioned. This I can do.

What I don't know is how to do something like read it left to right, top to bottom into my array. Something like:

Global tiles:TImage[900] (or 901 if I want to use 1-900 vs. 0-899]

gcount = 0

For y = 0 To 1334 Step 46
For x = 0 To 1334 Step 46
gcount = gcount + 1
tiles[gcount] = (Load a 46x46 chunk)
' like tiles[gcount] = ChopAChunk(x,y,46,46) ???
Next
Next

Also, I need them to be images for what I do in the rest of the program. I forgot why, but couldn't do it if loaded as PixMap.

Its that "load a 46x46 chunk" I can't figure out. Thanks, -Rob


Midimaster(Posted 2012) [#8]
There is no need for using an array. You could directly use the frames of the big image.
DrawImage() has a paramter FRAME after x and y:
for i=0 to 10 ' or 847
     DrawImage BigImage, 50, i*50, i 
Next


Your BigImage, loaded as AnimImage() is not really one image but already 847 little images. You can handle them like 847 independent pictures.


BladeRunner(Posted 2012) [#9]
if you save a pixmap, you can load is at image later on - it's stored as a .png and bmax won't bother if you loadimage or loadpixmap it.

As midimaster said:
LoadAnimImage and DrawImage is all you need. Write them in your IDE, hit F1 two times and bMax will tell you what the parameters are. (I would recommend hotdocs for a better documentation, can be found in the code archive on www.blitzforum.de)


Captain Wicker (crazy hillbilly)(Posted 2012) [#10]
if you save a pixmap

that is one of the easiest ways of doing things. :)
I like to be more 'sophisticated' with my code and image processing. ;)


SystemError51(Posted 2012) [#11]
But I couldn't find any info on how to split the big image into an array


That's super easy.

[bbcode]' Load our big image
Global myLargePixmap : TPixmap = LoadPixmap("path/to/your/image.png")

' Dynamic array holding smaller images
Global pxArray : TPixmap[]

' Figure out how many images we need
' // insert some code to figure out number //
'
' For the purpose of this post, let's just say we want 32x32 (w and h) images.
' This would set the big image at 1024x1024 image size.
Global numImages = 1024

' Make room for all our images.
pxArray = pxArray[.. numImages]

' Three locals
Local i
Local xpos
Local ypos

' Create all images from the big image
For i=1 To numImages

' Read the appropriate section from the large pixmap
pxArray[i-1] = New TPixmap ' Prevent ExceptionViolation errors
pxArray[i-1] = PixmapWindow(myLargePixmap, xpos, ypos, 32, 32)

' Increase horizontal position
xpos = xpos + 32

' Update row and jump back to 0
If xpos > 1024
xpos = 0
ypos = ypos + 32
EndIf

Next


' Release the pixmap
myLargePixmap = Null[/bbcode]

That's pretty much it... you now have made smaller images out of the big one, and all in memory.

(I don't know why there's a ";" after the bigger-than symbol ">" - that is not supposed to be there)

PixmapWindow API call

Last edited 2012


BladeRunner(Posted 2012) [#12]
if you save a pixmap

that is one of the easiest ways of doing things. :)
I like to be more 'sophisticated' with my code and image processing. ;)

First of all, why shoud he go more complicated than needed.
Second, instead of just speaking that you have sophisticated ways (which sounds like pure posing) you should SHOW them- 'cause that would be real help for the asking person here.
So share your great wisdom with us, Cap.

SystemError: although you answer his question to the point I think it would be better to keep stuff simple for him. I got the trong feeling that this post had to be in the beginners section.


Robby(Posted 2012) [#13]
You guys are the greatest! And I appreciate all the advice I'm getting here.

I think one of my biggest personal problems not only in programming but other stuff, is that I often leave out huge gaps of information when asking a question as I forget to mention any background info, which can confuse my intent, and I apologize for my absent mindedness!

What I'm working on is over here, maybe 1/3 done at this point:

http://web.me.com/drdungeon/Site/MADMAN.html

I use IMAGES because my understanding is that they are in graphics memory and are much faster. If I read correctly, they also support LoadImage with the MASKED flag, which I need.

I have 847 diamond tiles, white background as mask so they mesh up on the screen when drawn.

I use a tile array because its much easier to refer to specific tiles, like when clicking dough on a firepit to make bread, etc. These numbers comparing tiles are all over the program.

Its also the reason I use 1-847 instead of 0-846. I keep mixing up 0 as first or 1 as first, plus the 0 gives me a left-over extra spot in case I need it.

Originally I searched for a way to split up a big bitmap or png, and my understanding was that you needed to load as a pixmap to do this - to work with it at a pixel level, or chop sections.

PixMap is in main memory, Image is a representation of Pixmap in video ram and is much faster, plus supports the MASKED image flag and likely others.

All this is fine and works like a charm. MADMAN is coming along!

Its just my aesthetic sense doesn't like the hundreds - and possibly thousands of little tiles in the directory.

So the point is I can't convert the thing at this point to do a completely different drawing method - as I said, that tile array and a similar people and object array are all over the place, and make the program far easier to work with.

Ideally, then - if I can't save my tile array to a file, much as we would an integer array, is it possible to save a pixmap array to one file?

The idea is then I could re-load a big map into a pixmap - which apparently I need to split into 46x46 tiles, then somehow convert them into my MASKED tile image array, which is used all over the program.

I'm thinking that AnimImage() might work, but I'm unfamiliar with using that.

So the goal is to get one big graphic file loaded into an IMAGE array of MASKED tiles. Thanks again! You know, programing is the only thing I know of that can be fun and maddening at the same time! -Rob


BladeRunner(Posted 2012) [#14]
Ok, one more time:
You have by now (correct me if I am wrong) something like this:

drawimage bla[tilenumber],x,y, and this a lot of times in your program.

What we suggest is converting all of those little images to one big as midimaster and i told you, then replace those drawimages with sth like this:

drawimage bla,x,y,tilenumber

Replacing this should be no pain in the arse as you don't need to modify anithyng else in your code. if you use the find/replace button in the BMax IDE (just make a backub before you do it, sometimes the IDE behaves a little weird).

The only matter is a one-time-conversion of your tiles into one set.
load all of them as images,
draw them to screen side by side, capture them all together(grabpixmap) and save them (savepixmappng).
If you need to keep the white background for your tiles: setclscolor 255,255,255.

Ah, btw: BMax can handle alphachanneled images, so a masking color isn't needed anymore, you can make different tones of visibility. Just for future projects, as I wouldnt want to replace all those white pixels now.

I suggest reading the help to the named functions, as they will clear things a little up.