load unlimited images

BlitzMax Forums/BlitzMax Beginners Area/load unlimited images

ssdw(Posted 2010) [#1]
hello everyone,

I just bought blitzmax (I have little experience with it), and I have a question.

I'm working on a program where the user should be able to load unlimited images. My question is how can I do that?
I've tried a lot but could not find the answer.

Thank You a lot!


ImaginaryHuman(Posted 2010) [#2]
Load them as pixmaps using LoadPixmap.... you obviously aren't going to be able to VIEW a huge amount of images all on-screen at once, so you can simply convert them to `Images` as you need to show them. You won't be able to keep them all in video ram as Images, there just isn't enough of it (e.g. maybe only 32-64mb on many systems), so you'll have to figure out a way to spool them from pixmaps into images in a fairly smooth way - perhaps by using small `pixmap windows` from each pixmap and thus uploading only small sections of image each frame - e.g. 64x64 or 256x256, so that you are drawing `tiles` on the screen as the image scrolls or whatever. It should be fast enough to be smooth. You just wont be able to do an upload of a whole big image every frame and expect it to be smooth. By loading into pixmaps with LoadPixmap you are using main memory, so you could have a gigabyte or more available, depening on the computer. You also might consider storing the image in a compressed format in ram and only decompress as you need to view it. You could use zip or something similar. Another option is to spool images from disk as they are needed - a bit slower and more difficult to get smooth but it'd allow you to use a lot less memory.


Czar Flavius(Posted 2010) [#3]
What do you mean by unlimited images?


Zeke(Posted 2010) [#4]
What do you mean by unlimited images?

Repeat
	Local img:TImage = LoadImage("myimage.png")
Forever

heh. this was just joke but... im too thinking about unlimited images..


Czar Flavius(Posted 2010) [#5]
But what does that mean? Why would you do that?

If you want to use the same image multiple times, you should load it as a pixmap, and then deal with that pixmap. Particularly with pngs as they are relatively slow to load, as they must be decompressed. By loading a png once into a pixmap, and then using that pixmap for all my image operations, I speeded up my loading routine by several seconds.


ssdw(Posted 2010) [#6]
@ ImaginaryHuman
Thanks.
I did some experimentation with LoadPixmap.
it works well, but it is too slow.

@ Tsaar Flavius
The user can load images into the program.
There should be no restriction (with images).

@ Zeke
if this was possible...


xlsior(Posted 2010) [#7]
The difference between an image and a pixmap, is that the image is stored in your videocards' memory, while a pixmap is in your normal computer RAM.

They are slow to draw, because each time you draw a pixmap, it needs to be copied across the motherboard into video memory first.

but... pixmaps are only limited by the amount of memory windows can access, which is huge in part hanks to the ability to access virtual memory if there isn't enough.
By comparison, your video card needs to store everything in video memory, which tends to be significantly smaller.

Other complicating factors:

- Images are stored *uncompressed* in video memory, taking 4 bytes for each pixel (32 bit: 24 bits for the color, and 8 bits for alpha info)
- memory allocated rounded *up* to the nearest power-of-two size.
This means that an 800x600 pixel JPEG file that's 50KB on disk, all of a sudden takes up 1024 x 1024 x 4 = 4 MB of video RAM.

Just because you WANT to load infinite images doesn't mean that your videocard can store an infinite amount of those 4 MB data chunks. Even completely ignoring the video memory requirements of the windows GUI itself and all it entails, you're not going to fit more than 64 of those in the video memory of a fairly typical video adapter with 256MB onboard memory.

You'll either need to put up with the hassle of pixmaps, or you'll have to come up with some fancy system to load/unload your data dynamically where the user may not notice what's going on... But there are very real system limitations you're running into here.


Dabhand(Posted 2010) [#8]
Very real, and very physical limitations for something like that!

If you try to store an unlimited amount of images in every PC there is on the planet, you'll still eventually run out of room.

What I would do is something boarding on 3D trickery when it comes to them doing large out door areas, as an example, load up, say 9 images and think of them images as a grid (With the centre on being the only visible one), if the user clicks to look right, bring the ones to the right to the centre which they see the new middle image, the old centre ones go to the left of the grid, thus, losing the original left images and fill the now vacant right hand side with new images from the harddrive!

Do that for all directions, like up, down, left and right, and move, lose and replace images respectively.

Obviously, you'll need a filing system in place so it knows what to drag in, but that shouldnt be too much hassle really... So, at anyone time you should only have 9 images in memory (Be in video or system), but with the potential to navigate around massive image libraries (I'll not say unlimited, because, well, theres always a limit really)

Dabz


ssdw(Posted 2010) [#9]
I am aware that there is a limitation.
This limitation is different for each computer.
EDIT: the Programme should be able to load images until memory is full.

is it also possible that all the picture pasted together into one big picture?
and that the program shows a part of that big picture?

@Dabhand
I use blitzmax, not blitz3d.
3d is a bit difficult ;)


Dabhand(Posted 2010) [#10]

I use blitzmax, not blitz3d.
3d is a bit difficult ;)



Yeah, but my example on how you could handle it was based on how they manage to create massive game areas, they load bits in, the player wanders over somewhere, new bits are loaded while behind them bits of the level are dropped.

This is the same, yet, instead of a entire 3D level to show, you could use the same system to display shedfuls of images without hogging the users system and crippling it!

:)

Dabz


Czar Flavius(Posted 2010) [#11]
is it also possible that all the picture pasted together into one big picture?
and that the program shows a part of that big picture?

Have a look at GrabPixmap.

you'll have to come up with some fancy system to load/unload your data dynamically where the user may not notice what's going on

I thought the video card automatically swapped images between vram and ram if there is a shortage of memory. Slow of course, but shuoldn't crash the program.


I think by "unlimited" he means "arbitrary amount"


ssdw(Posted 2010) [#12]
I've tried to make a load/unload system.
here:
==============================================
AppTitle$ = "load multi image"
Graphics 600,400

'add here the lokations of the images. they must be separated by a space
imageopen$ = "images/intro.png images/ge.PNG images/boss.png images/maxball.png" + " "

#beg

'vieuw image names
oldimageopen$ = imageopen$
y = 0
#vieu
DrawText(Left(oldimageopen,Instr(oldimageopen," ")-1),0,y)
oldimageopen$ = Mid(oldimageopen,Instr(oldimageopen," ")+1)
y = y + 12
If Len(oldimageopen) > 1 Then Goto vieu

'select a picture
If MouseHit(1) Then
choose = MouseY()/12
changepic = 1
EndIf

'image
If changepic = 1 Then
Cls
choose1 = 0
oldimageopen$ = imageopen$
If choose > 0 Then
#vieua
choose1 = choose1 + 1
oldimageopen$ = Mid(oldimageopen,Instr(oldimageopen," ")+1)
If choose1 < choose Then Goto vieua
EndIf
pict = LoadPixmap(Left(oldimageopen,Instr(oldimageopen," ")-1))
DrawPixmap(pict,200,50)
changepic = 0
EndIf

'exit
If KeyHit(key_escape) Then End

'vieuw screen
Flip

Goto beg

==============================================


Dabhand(Posted 2010) [#13]
Ouch...

To start, and this isnt meant to be personal, so please dont take it the wrong way... But to start, you really need to look at how you are setting your apps out, thats horrible to read, check out the samples or the archives and get a bit of a handle on how everyone is programming using things like functions, loops and types.

Secondly, if you want to achieve your aim, you need a bit of a plan, its okay for us to suggest stuff, and now and again people do knock out example code, by the looks of things though, someone could knock out an example and (I mean no disrespect) you wouldnt know how it works... Which is pointless really!

So, what would I do if I was in your shoes... Well, I'd look at other code, read tutorials just generally play around... While I'm at it, I'd scrawl on a bit off of paper ideas that would help me get around the problem, theres been idea's here, so I would work on the best way of doing it...

If I have time tomorrow (Its late here now and I'm shot) I could write something (Unless someone chips in first), but, I wouldnt explain everything, you'll have to take it as it is... Which is the worry! ;)

Dabz


Czar Flavius(Posted 2010) [#14]
Merry Christmas!!!
SuperStrict 'this makes us need to state the types of variables and reduces bugs

AppTitle$ = "load multi image"
Graphics 600,400

'add here the locations of the images. they must be separated by a " ? "
Global image_open:String = "images/intro.png ? images/ge.PNG images/boss.png ? images/maxball.png"

'the Split method will automatically split up our string for us
Global images:String[] = image_open.Split(" ? ")

'this will hold the image we load
Global display_image:TImage

'we will do our work within the main game loop
main_loop()
End



Function view_image_names()
    Local y:Int = 0
    
    'this will go through every image file path
    For Local image:String = EachIn images
        DrawText image, 0, y
        'TextHeight can give us the height of the next no matter the font
        y = y + TextHeight(image_open)
    Next
End Function

Function choose_picture:Int()
    'this returns the index number of the image path the user has chosen
    'or it returns -1 to show nothing has been selected
    Local choose:Int = -1
    If MouseHit(1) Then
        choose = MouseY()/TextHeight(image_open)
    End If
    Return choose
End Function

Function draw_picture()
    'if a picture has been loaded, draw it
    If display_image
        DrawImage display_image, 200, 50
    End If
End Function

Function main_loop()
    'repeat until escape is pressed or the red X is clicked
    While (Not KeyDown(KEY_ESCAPE)) And (Not AppTerminate())
        Cls
        'draw the list of image paths
        view_image_names()
        'draw the picture if one has been loaded
        draw_picture()
        Flip
        Delay 1
        
        'find out what the user has chosen
        Local choose:Int = choose_picture()
        
        'if choose is -1 then nothing has been chosen
        'if the user clicks below the text it will give a number too big
        'so check also that choose is within the number of images!
        If choose > -1 And choose < images.Length
            'load the image from the path at this position number
            display_image = LoadImage(images[choose])
            'check that the image was loaded. if the image file doesn't exist for example, give an error message
            If Not display_image Then RuntimeError "Could not find " + images[choose] + "."
        End If
    Wend
End Function



ima747(Posted 2010) [#15]
I have a project that works with theoretically limitless numbers of images, here's a little background that may be useful.

There are 3 limits to keep in mind. Displayable images (limited by the video card usually), loadable images (limited by the system's ram) and processing time (this is key to maximizing your limits).

First, you can't just load things forever, you're going to hit a hardware limitation sooner rather than later. So what it comes down to is how to you make it LOOK like you're loading an infinite number of pictures. My personal approach is scaling and caching on the fly. I get a list of everything I need loaded, I then cycle through that and create batches if needed (my users actually create batches in the form of Albums) then cycle through the active batch and create thumbnails which are small so I can get tons of them in memory at once. When a user requests a full size image I display the thumbnail scaled (DrawImageRect()...) to the size of the real image (it will be blocky and blurry but it lets them know somehing is happening) then load the full image and replace the thumbnail with that ASAP.

If you combine this with a caching system that retains the full size image as long as possible (until too many have been requested, however you define "too many") then you can get a fairly smooth experience.

I also use threading to do the loading in the background while the rest of my program is working.

If you are working on composits you could go a step further as was mentioned above and use grabimage or grabpixmap to store that, allowing you to dump the origonals...

it's all very use specific, but the key is how can you make it transparent to the user that something is being removed or added to give the impression that everything is always there, rather than ACTUALLY having everything always there, which isn't possible.


ssdw(Posted 2010) [#16]
@Dabhand
I have not much experience.
sorry, I will do my best.

@Czar Flavius
great, This works great.
I've compared it with my and see that I have a lot to learn.
such as the locations (image_open) stride with a space, that was stupid of me.
Thank you very much!

The program must shows more than one picture at a time.
I go there a restriction on it, maby eight photos at the time.
I'm going to try to make a systeen.
I want to try the same structure as that of Czar Flavius (thanks again)


Dabhand(Posted 2010) [#17]

@Dabhand
I have not much experience.
sorry, I will do my best.



Dont apologize, we all started somewhere, but, it is recommended that you have a good hunt through all the tutorials on here to get a general feel on how to get the best out of the language! :)

It'll go a long way! ;)

Dabz


Czar Flavius(Posted 2010) [#18]
SuperStrict


Global image_list:TList = New TList


'you can add any image variable, but for this example we use this one
Local image:TImage

'load an image from wherever
image = LoadImage(...)

'add it to the list!
image_list.AddLast(image)

'load an image from wherever
image = LoadImage(...)

'add it to the list!
image_list.AddLast(image)

'load an image from wherever
image = LoadImage(...)

'add it to the list!
image_list.AddLast(image)


Function display_all_images()
    Local y:Int = 0
    
    For Local image:TImage = EachIn image_list
        DrawImage image, 0, y
        y :+ ImageWidth(image)
    Next
End Function

'you can use this to remove an image
image_list.Remove(image)

'you can use this to find out how many things are in your list
image_list.Count()

'you can use this to reset your list to 0
image_list.Clear()



ssdw(Posted 2010) [#19]
Czar Flavius, wooow, it look so easy but it isn't.
it work great. my problem is solved.
Thank you very much.

and thanks everyone for the help.