PNG Animation Util??

BlitzPlus Forums/BlitzPlus Programming/PNG Animation Util??

klasix(Posted 2004) [#1]
Hello all,

Have 1200 PNG files I need to put into a file(s?) that can be read with "LoadAnimImage". Can't find a utility that will allow creation of the proper format (PNG) with this many/size files. Prefer to do an entire directory at once (they are in alpha order). Tried using Jasc Animation Shop but no-go (file/save options <> PNG).

Read somewhere "LoadAnimImage" is limited to 1024 frames? Using B+.

Suggestion/comments appreciated.

Thanks in advance,
Jim


Eikon(Posted 2004) [#2]
Why not write a blitz program that draws each frame into a huge created image and then SaveImage it to a bmp for png conversion? You could make the png loading very simple by naming each img1.png, img2.png, etc. Hopefully the files already have some numbering or else renaming all 1,200 would require another program in itself ;)

For i = 1 to Num_Images
    tmp_Image = LoadImage("img" + Str(i) + ".png")
    ; Do a CopyRect from one ImageBuffer to the other here
    tmpX = tmpX + ImageWidth(tmp_Image) ; Move over for the next pic
next


Read somewhere "LoadAnimImage" is limited to 1024 frames? Using B+.


If so, I guess you'd have to use two images. Maybe each could hold 600 frames.


klasix(Posted 2004) [#3]
Thanks,

Had dawned on me .. but,

not sure if B+ will handle it. Used B+ to create 1200 309*309 BMP images .. each one 290K. "SaveImage" saves BMP only (from what I have gathered). Massive is a tad understated (for me anyway :) So .. created 1200 PNG's (using "pic2pic" freeware .. a little flaky but does the job) at about 9K apiece, an entire directory at one shot.

I'll give your idea a run (using BMP's) but will be crossing fingers I don't crash .. again :)

There has to be a util out their that deals with stitching PNG's together.

BTW: File names are sequential.

Thanks,


Eikon(Posted 2004) [#4]
I meant that you would SaveImage once, when you had the whole line up in the created image. Then you'd only need to convert one bmp to png. If you cant get it working then you can drop the images [a ftp://user:blitz@...] and i'll send you back the one png.


PGF(Posted 2004) [#5]
I like Eikon's suggestion but wonder about the practicality. It is going to be a large file even as a PNG on disk but when loaded into memory (if possible) it is going to be stored as a BMP anyway so bingo the PNG doesn't save you anything except disk and maybe disk to memory transfer time. Most likely it just won't fit in graphics memory.

I'm not sure but I understand that B+ can use system memory for graphics and move them on demand to graphics card memory which might get you across the line. Some optional flag for "managed" memory ?

If the memory isn't a problem but there is a limit of 1024 frames then use two AnimImages and switch at the appropriate point.

How about questioning the whole approach rather than looking for a solution to the perhaps impossible.

Could you show a frame or two to give a feel for the nature of the graphics ?

If frame to frame differences aren't great then a custom approach to recording the differences might work. Good old "run length encoding of the delta" might give enough compression and you can just read enough bytes to build a frame before it is displayed. Depends upon how much compression you'll get on the images from a simple algorithm.

What about streaming it continuously from disk ? You just might be able to read and display frames quickly and smoothly enough.

What else has to be going on at the same time ? Is it just a movie or do you need other animation to be running over it ?

Perhaps you need to compromise on the dimensions or number of frames.

Maybe the answer is to use some method external to Blitz invoked through a DLL.

Depends upon what the aim really is.


klasix(Posted 2004) [#6]
Thanks Eikon/PGF,

I wasn't ignoring you Eikon (appreciate the offer .. might hold ya to it ;) .. as observed .. questioning my approach and didn't want to waste your time :) Where can I post the BMP's ??

Here are all the gory details:

Using one 309x309 BMP as the graphics 'face'.
Using another BMP as the 'needle'. Overlay the face over the needle .. interesting effect :) though I can do it normally also.

Run a Blitz program that creates 3600 BMP's (.01 degree needle res). Why? because I can divide 3600 by 2/3/4/5/6/8/9/10/etc .. nice number .. I can 'pick and choose' the displayed tachometer resolution and some flexibility in other ways.

Then use the "Glueit" program to create "ani-strips" with the 280K BMP's .. has its limits though .. picked 100 (or other # as required) a strip as it gets a tad cranky if I push it further. Each 100 frame BMP is 37298K.

I then convert the BMP to PNG strips with the "pic2pic" program. It is an imbedded system so I need the initial storage space. BTW: Individual PNG strips are 217K (256 color).

Can't stream the data (don't know of a method) as a tach can bounce all over the place in very short order. Have a ~270 degree needle swing (11,000 RPM tach; a 200MPH speedo and some smaller gauges to do after I get the general issue completed).

Am trying to figure out the best method to 'grab' only the updated part of the tach face and save .. AND a means to allow the program that does the image display 'coordinating' to handle placement of image sizes 'automajikly'. That would allow much smaller ani-files and faster updates. Have not figured out exactly how to do it ?!?!?!?

The other method tried is simply grabbing each 'individual' file as needed from disk and using one frame. I can't say conclusively it is faster .. but at o'dark-thirty this morning it certainly looked like it was MUCH faster .. though I can't explain why. Note: I'll be using a RAMdisk also.

As to what else will be going on at the same time?
http://www.blitzbasic.com/Community/posts.php?topic=32901
covers it somewhat. Any questions just ask .. no secrets here.

Pretty much it. Ideas/suggestions/minor lambasts/etc OK. It is public domain project so what goes out the door is what they get .. but would like to do it right. Credit given where credit due.


Eikon(Posted 2004) [#7]

Where can I post the BMP's ??


Depending on their zipped size you can upload them to the [a ftp://user:blitz@... link[/a] I provided earlier (5MB or more), or email them to eikon@... (5MB or less)


Kuron(Posted 2004) [#8]
Tried using Jasc Animation Shop
Save it as MNG (animated form of PNG) and write a loader for the MNG image. Info about the MNG format can be found:

http://www.libmng.com/


klasix(Posted 2004) [#9]
Done,

Email and FTP .. a whole 10K :)

Thanks,
Jim


Eikon(Posted 2004) [#10]
To turn tachneedle.bmp into 360 seperate frames I used this code:
; Breaks Needle into 360 frames
; and places them into a 'need' dir
; Process will fail if 'need' directory doesnt exist
Needle = LoadImage("tachneedle.bmp")
tmp = CreateImage(264, 264)

For i = 0 To 359
	RotateImage Needle, i
	SetBuffer ImageBuffer(tmp): Cls
	DrawImage Needle, 132, 132
	SaveImage tmp, "need/img" + i + ".bmp"
	FreeImage Needle: Needle = LoadImage("tachneedle.bmp")
Next

If we were to combine all those frames into one AnimImage strip then it would be 95,040 x 95,040. This is simply not feasible for load time and video memory concerns. This is why I think a frame by frame loading animation technique would work best. Download this project which includes a mock up example and all 360 frames created with the program above. This method has zero load time and will only use the total vid memory of one frame, instead of them all. If this works out for you then your biggest worry will be finding a mass bmp->png converter. Im sure it wouldn't be too hard with the proper command line tool and a batch file.


klasix(Posted 2004) [#11]
Thanks !

Get back to you later .. have to depart the keyboard for a bit.

Jim


klasix(Posted 2004) [#12]
Hello Eikon,

Back for a bit. Mind if I upload the PNG's to your site?
Following is a hack on sample code to go with. Working on the other method as we speak.
Jim
--------------------------------------------------------
; LoadAnimImage/MaskImage Example
Global gfxTach,gfxTach1,gfxTach2

; Standard graphic declaration and double buffering setup
Graphics 309,309,0,2
SetBuffer BackBuffer()
; Load the imagestrips
gfxTach0=LoadAnimImage "\TachFace\Div_10\119.png",309,309,0,120)
gfxTach1=LoadAnimImage("\TachFace\Div_10\239.png",309,309,0,120)
gfxTach2=LoadAnimImage("\TachFace\Div_10\359.png",309,309,0,120)
Repeat
For i = 0 To 120 Step 1
If i > 119 Then Exit
If i = 61 Then Delay 1000
If i > 59 Then
DrawImage gfxTach1,0, 0, i ;draw the image
Flip ; show the buffer
Cls
End If
Next
For i = 0 To 120 Step 3
If i > 119 Then Exit
DrawImage gfxTach2,0, 0, i ;draw the image
Flip ; show the buffer
Cls
Next

For i = 0 To 120 Step 6
If i > 102 Then Exit
DrawImage gfxTach0,0, 0, i ; draw the image
Flip
Cls
Next
Delay 1000

Until KeyHit(1)
End


klasix(Posted 2004) [#13]
Caveat .. code was only used to determine CPU utilization and use if LoadAnimImage command.


PGF(Posted 2004) [#14]
Wait a minute - you're generating 3,600 images in order to display a tachometer ?!?

A tacho gives a quick indication of the reading so shouldn't need to be that precise. Insert a numeric readout to give the exact value if necessary.

I doubt that there would be very much difference at all between successive images at such small increments. Even say 360 or maybe 180 images would be smooth and accurate enough for just about any purpose.

And check your math - wouldn't 0.01 degree resolution require 36,000 images ? Maybe you meant 0.1 degree increments ?

I just think that you are on the entirely wrong track.

If you aren't happy with images at say 1 degree steps then a basic alternative would be to use trig functions to calculate the needle end points from the angle and just draw them as lines. If this isn't fancy enough then write a more complex drawing function using maybe circle endpoints. For a relatively small number of pixels, using anti-alias and per pixel colour calculation could make it even prettier.

Programming anything significant is a balancing act of features / programming effort / CPU time / memory / disk tradeoff and I think you're searching around at the extreme end of just one of those dimensions.


klasix(Posted 2004) [#15]
To no one in particular ...
Read/Writepixelfast next on the agenda. Found a bug (an unnoticed "Delay" statement) in the RAMDisk I/O comparison method .. disregard the 'MUCH faster' comment.

Eikon ..
Your code works just dandy (hats off to you for the examples :). Both of us are killing the CPU.

Later,


Eikon(Posted 2004) [#16]
Thanks for giving me something to toil over at work, besides work ;)

I stuck a 'Delay 5' above 'Flip: Cls' and got the CPU usage down to 25%

Good luck with whatever project your using this meter in. Adios


klasix(Posted 2004) [#17]
Hello PGF,

.1 it is.
Seems I have .01 imbedded on the brain.

As stated previously: Can divide 3600 images by 2/3/4/5/6/8/9/10/etc to get the screen res I want. I don't 'need' 3600. With 3600 I can 'start' at any given 1/3600th of a circle and increment my way around by extracting an offset from the selected '0' point. Only have to write the file once.

A close look at an ani-file will show there is more going on that one would think. Send you one if you would like. Think the average screen has 96DPI so a 5" gauge would have ~480 pixels top to bottom. 3600/8 = 450 is as close as I can get with one pixel res. Aliasing comes into play also (hence the differences in the ani-file). A 6" tach with 360 degrees res is a bit jumpy. On a 2.5" faced gauge it is fine (and a bit of overkill). Hence the multi-res. Change screen DPI and ...

Going through what every 'newbie' does I guess. And yes .. I explore to find a products methods limitations/ features/etc. Doing so I determine/derive/guess 'why' something doesn't work. In this case .. too much info to write in X time. But I know what to do if I don't need the speed :)

The 'math' approach is in queue and have the algo in hand.
Next in line is comparing needle image at X degrees with one at X+1 and comparing the differences. Store the 'difference in pixels' starting from 0 to max-X. Array storage should be small and hopefully fast as a result. Several drawbacks to the approach (can't jump from X to X+2). Dunno if that is an issue till I try. On to the math after that.

A digital readout will be implemented also. As will a shift light for the drag racers. You (well .. me anyway) can't shift with twirling numbers well. Needle on number works.

Eikon .. thanks again. Glad to .. mmmm 'help' with work :) Your code was more compact than mine and probably work with the smaller/slower gauges just fine. Implemented the delay same as you in both cases. Same results .. which helped a lot !!

Take care all,
Jim


PGF(Posted 2004) [#18]
klasix,

I doubt that I'll understand your intention and approach without seeing an image. If you're happy with your current method then don't worry. Otherwise please post or e-mail an example.

Otherwise we're probably misunderstanding each other.

Regards