This might possibly be of some help, though it downloads images from the internet while animating, so you'll have to let it go online. (Leave it running a while as it downloads multiple images.)
It's a messy work-in-progress, but I'm only loading Pixmaps outside the main thread, as my understanding is that Images are tied up with graphics contexts (not thread-friendly), while Pixmaps are only blocks of memory. I just convert the resulting Pixmap to an Image once it's returned.
' Needs SVN version of BlitzMax, with Program menu
' -> Build Options -> Threaded Build enabled!
' Sometimes gives ***** UNKNOWN THREAD EXCEPTION ***** on exit...
' EDIT: Handling ESC while DownloadPixmap's Read/WriteStream are
' open ought to solve this. Think a message needs to be sent to this
' part of the thread before End to allow CloseStream, etc.
' Stupid delay code fixed (so that's what Delay is for)...
' Converted returned pixmap to images for more flexibility...
' Spinning and shadows! Might have been a bit early for this sort of thing...
' Single-CPU test function (Windows only)...
' Tidied and commented...
Strict
' Thread functions...
' DownloadPixmapThread: Calls DownloadPixmap in background. Uses pixmaps
' instead of images as images interact with graphics drivers (not thread-
' friendly) while pixmaps are just blocks of memory...
Function DownloadPixmapThread:Object (data:Object)
' Index for global Pic[] array...
Local img:Int = 0
' Infinite loop while main program runs...
Repeat
Local photo:TPixmap = DownloadPixmap (Pic[img]) ' Download pixmap...
TThread.Main ().SendMsg photo ' Send copy to main program...
img = img + 1 ' Image index increased for
If img > PicNum - 1 Then img = 0 ' next URL...
Delay Timeout ' Wait before downloading a
' new image...
Forever
End Function
' Timer for redrawing. Sends message to main program advising when to redraw...
Function RenderTimerThread:Object (data:Object)
Repeat
' Delay 16
TThread.Main ().SendMsg Null
Forever
End Function
' Enable next line to force everything onto first CPU on multicore systems...
' ForceSingleCPU () ' Windows only!
' Wait this many milliseconds after each download...
Global Timeout = 5000
AppTitle = "New download attempted after " + (Timeout / 1000) + " seconds (IDE Output window shows progress)..."
Const PicNum = 7
Global Pic$ [PicNum]
Pic [0] = ConvURL ("http://www.blitzbasic.com/img/platypus.jpg")
Pic [1] = ConvURL ("http://www.blitzbasic.com/img/auto_cross_racing.jpg")
Pic [2] = ConvURL ("http://www.blitzbasic.com/img/super_gerball.jpg")
Pic [3] = ConvURL ("http://www.blitzbasic.com/img/tank_universal.jpg")
Pic [4] = ConvURL ("http://www.blitzbasic.com/img/tecno.jpg")
Pic [5] = ConvURL ("http://www.blitzbasic.com/img/master_of_defence.jpg")
Pic [6] = ConvURL ("http://www.blitzbasic.com/img/kingdom_elemental_tactics.jpg")
' Try a big pic! Comment out previous line, uncomment next...
Pic [0] = ConvURL ("http::nuerburgring.de/fileadmin/webcam/webcam.jpg")
Graphics 640, 480
SetClsColor 71, 132, 217
AutoMidHandle True
SetBlend ALPHABLEND
' List for copies of downloaded images...
Local ImgList:TList = CreateList ()
' Downloaded image control type...
Type Img
Field image:TImage
Field x#
Field y#
Field xs# = Rnd (-8, 8)
Field ys# = Rnd (-8, 8)
Field ang#
Field angsp# = Rnd (-4, 4)
End Type
' Start threads...
New TThread.Start DownloadPixmapThread, Null
New TThread.Start RenderTimerThread, Null
Local photo:TPixmap
Local i:Img
Local image:TImage
Repeat
Local mx:Int = MouseX ()
Local my:Int = MouseY ()
' Get thread messages...
Local msg:Object = TThread.RecvMsg ()
TThread.ReplyMsg Null
' Check if msg is a pixmap...
If TPixmap (msg) ' Came from DownloadPixmapThread...
' Create local pixmap and convert to image (for flexibility)...
photo = TPixmap (msg)
image:TImage = LoadImage (photo)
' Add copy of image to list...
i:Img = New Img
i.image = image
i.x = mx
i.y = my
ListAddLast ImgList, i
Else ' Must be from RenderTimerThread...
Cls
' Draw twirling copies of downloaded images...
For i:Img = EachIn ImgList
i.ang = i.ang + i.angsp
SetRotation i.ang
DrawImage i.image, i.x, i.y
i.x = i.x + i.xs
i.y = i.y + i.ys
If i.x < 0 Or i.x > GraphicsWidth () - 1 Then i.xs = -i.xs; i.x = i.x + i.xs
If i.y < 0 Or i.y > GraphicsHeight () - 1 Then i.ys = -i.ys; i.y = i.y + i.ys
Next
' Reset image rotation...
SetRotation 0
' If we have a downloaded image, draw it...
If image
' Shadow...
SetAlpha 0.25
SetColor 0, 0, 0
DrawRect (mx - ImageWidth (image) / 2.0) + 8, (my - ImageHeight (image) / 2.0) + 8, ImageWidth (image) + 2, ImageHeight (image) + 2
' Border...
SetAlpha 1
SetColor 255, 255, 255
DrawRect (mx - ImageWidth (image) / 2.0) - 1, (my - ImageHeight (image) / 2.0) - 1, ImageWidth (image) + 2, ImageHeight (image) + 2
' Draw image...
DrawImage image, mx, my
EndIf
Flip
EndIf
Until KeyHit (KEY_ESCAPE)
End
' Non-thread functions...
Function DownloadPixmap:TPixmap (img$, bail = 3)
Local pix:TPixmap ' Downloaded pixmap...
Local url:TStream ' Download stream...
Local copy:TStream ' Local copy of download...
Local count:Int ' Byte count during download...
Local retry:Int ' If download fails, retry 'bail' times...
Local quit:Int ' Too many fails, exit...
Repeat
Print ""
Print "Attempting new download..."
Print ""
url = ReadStream (img$)
If url
' Create local copy...
copy = WriteStream ("local.jpg")
If copy
' Reset byte count...
count = 0
Repeat
' Not every efficient (one byte at a time), but works as a demo...
WriteByte copy, ReadByte (url)
' Count bytes downloaded...
count = count + 1
If count Mod 1024 = 0 Then Print count + " bytes downloaded in background"
Until Eof (url)
CloseStream copy
' Try to load pixmap...
pix = LoadPixmap ("local.jpg")
EndIf
CloseStream url
EndIf
' Download failed? Retry 'bail' times...
If pix = Null
retry = retry + 1
If retry = bail
quit = True
Print "Failed to download after " + bail + " attempts..."
Else
Print "Retrying..."
EndIf
EndIf
Until pix Or quit
Return pix ' May still be Null after 'bail' failed attempts...
End Function
Function ConvURL$ (url$)
Return Replace (url$, "://", "::")
End Function
Function ForceSingleCPU () ' Windows only!
?win32
Extern "win32"
Const PROCESS_SET_INFORMATION = $200
Function GetCurrentProcessId ()
Function OpenProcess (desiredaccess, inherithandle, processid)
Function SetProcessAffinityMask (processhandle, processaffinitymask)
End Extern
Local proc:Int = GetCurrentProcessId ()
Local handle:Int = OpenProcess (PROCESS_SET_INFORMATION, 0, proc)
SetProcessAffinityMask (handle, %00000000000000000000000000000001)
?
End Function