FreeImage questions

BlitzMax Forums/Brucey's Modules/FreeImage questions

sswift(Posted 2009) [#1]
Hey Brucey, thanks for making that freeimage mod for BlitzMax. It's gonna be a huge help as I rewrite Seamless Texture Generator in BlitzMax. (Oops, did I say that out loud?)


I'm trying to find the most optimal way to load images with it, and convert them to a pixmap in PF_RGBA8888 format. But in the process of trying to figure that out, a few questions about your code have popped up.

I notice that your LoadPixmap wrapper first loads a FreeTImage, and then copies the pixmap with CopyPixmap. CopyPixmap however does a memcopy to copy the pixmap. Is there any reason you don't simply return freeImage.pixmap instead? I would assume that, even if the freeImage type gets garbage collected, that if you've saved the pointer to the pixmap, the pixmap will remain valid.


Also, I was looking at the freeimage type working out how it loads the image, and I notice you flip the pixmap on the Y axis before returning it. Is there some reason you do that? Does freeimage store images internally in a BMP like format? That seems like an odd choice for them to make!

I do know that when I used freeimage in BlitzPlus, I didn't need to flip the image. I notice you're using a number of different conversion functions. I don't know if those behave differently from the one I used, but this is what I did:

; Copy the FI_Image to the Blitz image.
   
        LockBuffer DestImageBuffer
           
            DestImageBank      = LockedPixels(DestImageBuffer)
            DestImagePitch     = LockedPitch(DestImageBuffer)
            DestImageFormat    = LockedFormat(DestImageBuffer)
           
            DestImageDepth     = FIB_BitDepth[DestImageFormat]
            DestimageRedMask   = FIB_RedMask[DestImageFormat]
            DestimageGreenMask = FIB_GreenMask[DestImageFormat]
            DestimageBlueMask  = FIB_BlueMask[DestImageFormat]
           
            FIToBank(DestImageBank, FI_Bitmap, DestImagePitch, DestImageDepth, DestimageRedMask, DestimageGreenMask, DestimageBlueMask, 0)                

        UnlockBuffer DestImageBuffer

Where FIToBank is really defined as:
FIToBank( Bank*,FIBITMAP%,Pitch%,Depth%,Red_Mask%,Green_Mask%,Blue_Mask%,TopDown% ) : "_FreeImage_ConvertToRawBits@32"



But this is BlitPlus we're talking about, and I suppose it may have been storing the images bottom up since it's written for Win32 only. That would make sense since I appear to have set the last parameter there to false. However, I see no reason you could not set that last parameter to true so as to avoid the need to flip the image at the end of your Init() function.


Anyway, I think the most ideal setup would be to always have the images loaded be in top down PF_STDFORMAT (which is PF_RGBA8888, and the format BlitzMax prefers internally, converting back and forth from it to convert other formats) regardless of OS, so that you don't have to do the additonal step of converting it to that format yourself, or putting a bunch of conditional compiles in your code to handle the diferent formats on different OS's.


What are your thoughts on this?


sswift(Posted 2009) [#2]
Have you taken a look at this Brucey?


Brucey(Posted 2009) [#3]
The "pixmap" is just a visual reference for your BlitzMax application. Otherwise the image data itself is always retained internally as a FreeImage bitmap.

For LoadPixmap, the reason freeImage.pixmap isn't returned directly, is because the pixmap object belongs to TFreeImage instance, which will be GC'd at some point (spooky, I just looked at the code, and the comment states this almost exactly to the word...shiver)
Since LoadPixmap is a simple wrapper (for those who don't care for the underlying image model, the TFreeImage instance is only temporary. The pixmap itself is "static", referencing a specific block of allocated memory. When the TFreeImage instance is GC'd, this "static" memory is also freed - goodbye pixmap data. Therefore we copy it.
The reason for using "static" data to create the pixmap, is to forgo an extra copy when the data is already available in the correct format.

For more advanced use, you access the TFreeImage API directly.

As you've realised, we need to Y Flip the visual image because it is stored with 0,0 at the bottom left (which I believe is fairly typical), while BlitzMax has 0,0 at the top left.
Of course, the FreeImage bitmap data is never modified during any of these conversions.

Originally, I had the FreeImage bitmap Y-flip, but this obviously wasn't such a great idea, as one should leave base data alone if one can help it.

Also, you should use getPixmap() to access the pixmap data, since this will refresh if required.

If you need access to the raw data, GetScanline() will return you a Byte Ptr to the first pixel of a scan line, which you could use to read/write.


sswift(Posted 2009) [#4]
The pixmap itself is "static", referencing a specific block of allocated memory. When the TFreeImage instance is GC'd, this "static" memory is also freed - goodbye pixmap data. Therefore we copy it.


Okay, I think I understand what's going on now. I didn't know it was a static pixmap referencing memory that was freed. Your comment didn't mention that.


Brucey(Posted 2009) [#5]
Your comment didn't mention that.

It didn't really need to. The comment is only there to remind me, in my old age, why the copy is there at all. :-)