Loading image files... (BMP/PNG...)

External libraries (GTK, GSL, SDL, Allegro, OpenGL, etc) questions.
Post Reply
Berkeley
Posts: 84
Joined: Jun 08, 2024 15:03

Loading image files... (BMP/PNG...)

Post by Berkeley »

Task: loading image files directly as buffers (or if you like - strings) and then converting into an image buffer used by PUT (x,y).

Troubles: the image libraries I found are converting 8 bpp bitmaps either into 32 bit or simply mix up the palette "automatically" - to the crappy VGA default.

Think of storing your bitmaps in a ZIP compressed file... - I don't want to make a temporary copy and then load the unpacked file.

- Where is the documentation of the image buffer format of FreeBASIC ? - Does it have a hidden part ?
- And what libraries do offer functions for image-data-decompression into a format, FreeBASIC can handle ?

Currently, I'm only interested in BMP and PNG, but GIF and JPEG hints won't disturb.
shadow008
Posts: 117
Joined: Nov 26, 2013 2:43

Re: Loading image files... (BMP/PNG...)

Post by shadow008 »

I use the FBImage library: https://www.freebasic.net/forum/viewtopic.php?t=24105

Works great for at least .png (I've not used other formats), and loads directly into a Freebasic Image type.
- Where is the documentation of the image buffer format of FreeBASIC ? - Does it have a hidden part ?
Image wiki is here: https://www.freebasic.net/wiki/TutFBgfxImgAndFontBuf
There's a bit on "FB.IMAGE Data Type" which might answer your questions. Alternatively, just look directly at the fbgfx.bi; there are no "hidden parts" per-se other than the fact that you interact not with the type, but with the API through ImageCreate, ImageInfo, etc.
And what libraries do offer functions for image-data-decompression into a format, FreeBASIC can handle ?
Hey if you're willing to manually fill in an FB.Image type yourself, then Freebasic can "handle" any format. The "handled" format is whatever you initialized the screen as (see also: https://freebasic.net/wiki/GfxInternalFormats). But as for image compression, I think the FBImage library also does saving to .png? I never needed it so I'm not sure.
Berkeley
Posts: 84
Joined: Jun 08, 2024 15:03

Re: Loading image files... (BMP/PNG...)

Post by Berkeley »

Thank you very much. Unfortunately currently I don't have time to check it. That FB.Image IS the buffer format used by PUT resp. IMAGECREATE was a kind of mental brownout. At least it stands almost in the reference of IMAGECREATE, although not explained for dummies.

It seems that the FBIMage library can't load PNG files as 8 bpp buffer, at least you have to convert them back from 32 bpp. - Which is not impossible, but it costs me time again - and I still don't know, whether LoadRGBAFile() really loads a 8-bpp-PNG and just converts it into 32 bpp. Worst case could be that it can't load palettised PNG files.
shadow008
Posts: 117
Joined: Nov 26, 2013 2:43

Re: Loading image files... (BMP/PNG...)

Post by shadow008 »

I've never used a palettised png, but here's the actual function I use when loading png images. I swap R/B due to satisfy the format my opengl shader uses. This loads images to a 32bits-per-pixel format (8 bits per color RGBA), then stores them in a direct 32 bit integer buffer, doing away with the FB.IMAGE type structure. Pallet conversion might be a bit more tricky I suppose.

Code provided as-is for reference and will not compile as it's missing context:

Code: Select all

function LoadPNGFileRGBA(byval filename as const zstring ptr, RetVal as RGBATextureType ptr) as uinteger
    
    dim loadedImage as any ptr
    
    loadedImage = LoadRGBAFile(filename)
    
    if loadedImage = 0 then
        return 0
    end if
    
    dim as uinteger i,j
    dim as integer w, h, bypp, pitch, size
    dim as ubyte ptr pixelPtr, newPixels = 0
    
    ImageInfo(loadedImage, w, h, bypp, pitch, pixelPtr, size)
    
    if bypp <> 4 then
        dprint("TextureHandling.bi: Error; loading image with pixel size ";bypp)
        sleep
        return 0
    end if

    newPixels = new ubyte[w*h*4]
    
    dim as uinteger pitchW = pitch / 4
    
    for i = 0 to h-1
        for j = 0 to w-1
            'Swap the R an B to make it properly adhere to OpenGL RGBA spec
            newPixels[(i*(w*4)) + (j*4) + 0] = pixelPtr[(i*(pitchW*4)) + (j*4) + 2]
            newPixels[(i*(w*4)) + (j*4) + 1] = pixelPtr[(i*(pitchW*4)) + (j*4) + 1]
            newPixels[(i*(w*4)) + (j*4) + 2] = pixelPtr[(i*(pitchW*4)) + (j*4) + 0]
            newPixels[(i*(w*4)) + (j*4) + 3] = pixelPtr[(i*(pitchW*4)) + (j*4) + 3]
        next
    next
    
    ImageDestroy(loadedImage)
    
    retVal->Width = w
    retVal->Height = h
    retVal->PixelPtr = cast(uinteger<32> ptr, newPixels)
    
    return 1
    
end function
Berkeley
Posts: 84
Joined: Jun 08, 2024 15:03

Re: Loading image files... (BMP/PNG...)

Post by Berkeley »

- I think you just have to add "SIZEOF(FB.IMAGE)" to the given pointer...

Conversion is easy because my RETROGRA library uses a palette that is RGB-based. Index 0-215 can be calculated with RGB steps of 0x33/51; R+G*6+B*36. You just can't use SHL/SHR/AND/OR for this though. If you'd have a higgledy-piggledy palette, it would be more difficult of course, you'd have to compare each pixel with all 256 colour entries and pick the nearest...
dodicat
Posts: 8160
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Loading image files... (BMP/PNG...)

Post by dodicat »

Windows.
For images 4 bytes or 1 byte per pixel
i.e.

screenres x,y,32
or
screenres x,y
to accept the picture/image

Code: Select all

#if sizeof(integer)=8 '64 bits
#include "windows.bi"
#endif
#Include  "win/gdiplus.bi"

#include "file.bi"
'An idea from UEZ in another thread.
Function Pload(Picture As String,Byref i As Any Ptr=0) As Long
    Dim As Long bpp
    If i Then Imageinfo i,,,bpp Else Screeninfo,,,bpp
    Dim As Uinteger TMP 
    GDIPLUS.GdiplusStartup(@TMP,@Type<GDIPLUS.GDIPLUSSTARTUPINPUT>(1),0)
    Dim As Any Ptr Img
    If GDIPLUS.GdipLoadImageFromFile(Picture,@Img)>0 Then Return 0
    Dim As Single w,h
    GDIPLUS.GdipGetImageDimension(Img,@w,@h)
    If w*h=0 Then Return 0
    Dim As GDIPLUS.BitmapData Pdata
    Dim As Rect R=Type(0,0,w-1,h-1)
    If bpp=4  Then GDIPLUS.GdipBitmapLockBits(Img,Cast(Any Ptr,@R),GDIPLUS.ImageLockModeRead,PixelFormat32bppARGB,@Pdata)
    If bpp=1 Then GDIPLUS.GdipBitmapLockBits(Img,Cast(Any Ptr,@R),GDIPLUS.ImageLockModeRead,PixelFormat8bppIndexed,@Pdata)
    For y As Long = 0 To h-1
        For x As Long = 0 To w-1 
            If bpp=4 Then Pset i,(x,y),Cast(Ulong Ptr,Pdata.Scan0)[y*w+x]
            If bpp=1 Then Pset i,(x,y),Cast(Ubyte Ptr,Pdata.Scan0)[y*w+x]
        Next
    Next
    Return w*h
End Function

Sub getsize(picture As String,Byref w As Single,Byref h As Single) 
    Dim As Uinteger TMP 
    GDIPLUS.GdiplusStartup(@TMP,@Type<GDIPLUS.GDIPLUSSTARTUPINPUT>(1),0)
    Dim As Any Ptr Img
    If GDIPLUS.GdipLoadImageFromFile(Picture,@Img)>0 Then Exit Sub
    GDIPLUS.GdipGetImageDimension(Img,@w,@h)
End Sub


Dim As String picture=Curdir+"\bob.png" ' or whatever
If Fileexists(picture)=0 Then Print picture + "  not found":Sleep:End

'get the desired image size and load the file to it
Dim As Single w,h
getsize(picture,w,h)
Screenres w,h,32

Dim As Any Ptr i=Imagecreate(w,h)
Pload(picture,i)
Put(0,0),i,Pset
Sleep
Imagedestroy i

  
Will do .gif, jpg, jpeg, bmp, png, and maybe some others.
Also will load directly to fb screen if no image is used (like bload)
Post Reply