appendPage doesn't append a page to a new TMultiFr

BlitzMax Forums/Brucey's Modules/appendPage doesn't append a page to a new TMultiFr

Kistjes(Posted 2009) [#1]
Hi,

I just downloaded your freeImage module because I have to load a lot of gifs.
Our graphic designers have small icons for buttons etc. For every button state (normal, rollover, disabled...) they make a separate file using a forced naming convention.
I would like to read the different button-state gifs into a TMultiFreeImage type and transform it into a multi frame TImage.
This is what I do:

Local oGif:TMultiFreeImage = TMultiFreeImage.Create("temp.gif", FIF_GIF)

Local oFI1:TFreeImage = LoadFreeImage("icon1.gif")
Local oFI2:TFreeImage = LoadFreeImage("icon2.gif")

oGif.appendPage(oFI1)

oGif.appendPage(oFI2)

Print oGif.pageCount()		'print 0 ?

Local oImg:TImage = oGif.toAnimImage()


It doesn't work.
Print oGif.pageCount() returns 0.

I also tried several combinations with lockPage() and unlockPage()

What am I doing wrong?


Brucey(Posted 2009) [#2]
What am I doing wrong?

Nothing :-)

I've updated SVN with a fix for creating multi-page images.

Also, due to the nature of how FreeImage appears to work, you'll need to call this after you've finished appending the pages :
oGif.close()
oGif.Load()

to flush the file to disk, since much of the paging functionality appears to work via file IO.

Sorry for the delay.


Kistjes(Posted 2009) [#3]
Thanks!
But how do I get this update?
Can you put the update on your Google code page?


Brucey(Posted 2009) [#4]
I suppose that's also a possibility.

Probably a good time to take a cut too.. since I see there's a new FreeImage update out, and it usually takes some time to sort it out - especially all the hacks I need to apply to get it to build on MinGW.

I'll try and do a release tonight.


Brucey(Posted 2009) [#5]
Hokay... I've released a new version (1.05), which includes these updates :

* Fixed conversion issue with 4-bit paletted images.
* Fixed GC problems when loading large anim images.
* Fixed problem with creation of new multi-page images.


Kistjes(Posted 2009) [#6]
Thank you, Brucey!


Kistjes(Posted 2009) [#7]
The last version (1.05) doesn't throw an error and results in a correct multi-frame TImage object. But...
The resulting gif file is corrupt and so is the image. The first frame looks nice but the others are distorted.
The same effect will occur when you change this:
Return LoadImage(oFreeImage.getPixmap().Copy(), iFlags)
to this:
Return LoadImage(oFreeImage.getPixmap(), iFlags)
in the code below.


This is my GifsToFrames function (first parameter is an array of Gif-URLs):

Function GIFsToFrames:TImage(aoGifs:Object[], iFlags:Int = -1)
	Local oImg:TImage
	'if there is only one gif file, then load, convert and return
	If aoGifs.Length = 1 Then
		Local oFreeImage:TFreeImage = LoadFreeImage(aoGifs[0])
		Return LoadImage(oFreeImage.getPixmap().Copy(), iFlags)		'this returns a correct single frame TImage type
	Else	'create a temporary gif file and append every gif file as a page.
		Local oGif:TMultiFreeImage = TMultiFreeImage.Create("temp.gif", FIF_GIF)
		For Local o:Object = EachIn aoGifs
			oGif.appendPage(LoadFreeImage(o))
		Next
		oGif.close()
		oGif.Load()
		'convert multi-page gif to a framed image
		oImg = oGif.toAnimImage(iFlags)
		oGif.close()
		Return oImg		'this returns a distorted multi-frame TImage type. 
					'Note: only the bitmap looks distorted, I do not get any runtime errors.
	End If
		
End Function


First question: Is this a bug? (perhaps some memory-leak-pointer-something-issue ;)
Second question: Is this actually the right way of doing this, or is there a better way?


Kistjes(Posted 2009) [#8]
I found another way of gluing multiple gif files to a single TImage:
rem
bbdoc: Converts an array of GIF urls to one multi-frame TImage object.
end rem
Function GIFsToFrames:TImage(aoGifs:Object[], iFlags:Int = -1)
	Local oImg:TImage = Null
	Local iWidth:Int, iHeight:Int
	For Local o:Object = EachIn aoGifs
		' load a gif file
		Local oFreeImage:TFreeImage = LoadFreeImage(o)
		' convert FreeImage to a pixmap
		Local oPixmap:TPixmap = oFreeImage.getPixmap().Copy()
		
		If Not oImg Then
			' simply copy the first pixmap into a TImage object
			oImg = LoadImage(oPixmap, iFlags)
			iWidth = oImg.width
			iHeight = oImg.height
		Else
			' add a frame to the TImage object and copy pixmap
			If (iWidth <> oPixmap.width) | (iHeight <> oPixmap.height) Then Notify("Images are not the same size!")
			' slice our frame counters to cater for the extra image
			oImg.frames = oImg.frames[..Len(oImg.frames) + 1]
			oImg.pixmaps = oImg.pixmaps[..Len(oImg.pixmaps) + 1]
			oImg.seqs = oImg.seqs[..Len(oImg.seqs) + 1]
			' include our new pixmap in the existing array of pixmaps
			oImg.SetPixmap(Len(oImg.pixmaps) - 1, oPixmap)
			' create a frame from the pixmap
			oImg.frame(Len(oImg.frames) - 1)
		End If
	Next
	Return oImg
End Function



Kistjes(Posted 2009) [#9]
Am I right by saying that you can not use incbin'd files with
LoadFreeImage()
LoadAnimFreeImage()
CreateFromFile()
?
If so, is it hard to make this possible in a next version, cos I incbin almost always my (graphical) assets?


Brucey(Posted 2009) [#10]
LoadFreeImage() does support TStream, so you can use that with incbin:: -> assuming you pass in a RamStream.

I haven't directly implemented incbin:: support, thinking the TStream support was enough.

As for the other two functions... I'm not entirely sure that they can support the custom I/O class that LoadFreeImage can use. In which case, they are unfortunately tied to the filesystem.
Certainly, the writing of the gif requires the filesystem (rather than to RAM) - which I saw while trawling through the source.

There's not much I can do if the underlying library does not provide the level of I/O abstraction required to redirect it to use TStream. :-(


Brucey(Posted 2009) [#11]
Although.. I have found this : FreeImage_LoadMultiBitmapFromMemory()

But that one won't support TStream.. I suppose if I add "incbin::" support for the filename of the multi-page bitmap... it ... might ... just ... work.