Yeah, I use FreeImage with Paul Snart's Blitz3D wrapper. I cut down the wrapper to my own requirements and fixed a few minor bugs. It only saves images in 24-bit, though. Here's the code, in case it's of any use:
; FreeImage Open-source Userlib Include
; Writen By Paul Snart
; Copyright Pacific Software
;
; Cut-down version with bug fixes by Chris Chadwick 13/7/2005.
;
; This Userlib is free to use in commercial and non-commercial programs
; Please also follow the guidlines set by the FreeImage Development team
; with regards to a GPL License (Included)
;
; #### Main Include Library ####
;
; Version: 1.3
;
Global FIImage.ImageList
Global BiHeader = CreateBank(18)
Global FIB_RedMask[4],FIB_GreenMask[4],FIB_BlueMask[4],FIB_BitDepth[4]
Global Int32 = CreateBank(4)
Global FI_Word = CreateBank(2)
FIB_BitDepth[1]=16
FIB_RedMask[1]=$1F
FIB_GreenMask[1]=$7E0
FIB_BlueMask[1]=$F800
FIB_BitDepth[2]=16
FIB_RedMask[2]=$1F
FIB_GreenMask[2]=$3E0
FIB_BlueMask[2]=$7C00
FIB_BitDepth[3]=24
FIB_RedMask[3]=$FF0000
FIB_GreenMask[3]=$FF00
FIB_BlueMask[3]=$FF
FIB_BitDepth[4]=32
FIB_RedMask[4]=$FF0000
FIB_GreenMask[4]=$FF00
FIB_BlueMask[4]=$FF
Dim CRC_Table(256)
Dim FI_FileEXT$(24,1)
Dim FI_SaveList(24)
ComputeCRC()
Restore LoadExtentions
Read FI_FIFType
Repeat
Read FI_FileEXT(FI_FIFType,0)
FI_FileEXT(FI_FIFType,1) = FI_GetFIFDescription(FI_FIFType)
If FI_FIFSupportsWriting(FI_FIFType) = 1 Then FI_SaveList(FI_FIFType) = True
Read FI_FIFType
Until FI_FIFType = -1
Type ImageList
; Original/New File Info
Field FileName$
Field FileDirectory$
Field ImageFormat%
Field ImageFormatDescript$
Field File_Size%
Field Format%
Field LoadFlags%
Field SaveFlags%
Field FIBITMAP ; If Used
; Blitz Image Variables
Field Image%
Field Width%
Field Height%
Field DisplayPitch%
Field ImageSize%
Field Depth%
Field RedMask%
Field GreenMask%
Field BlueMask%
; Alpha & Palette Storage
Field Palette%
Field PixMap%
Field AlphaMap%
Field AlphaPitch%
; FIBITMAP Variables
Field DIBSize%
Field Pitch%
Field Planes%
Field BitCount%
Field Flags%
Field SizeImage%
Field XPelsPerMeter%
Field YPelsPerMeter%
Field ClrUsed%
Field ClrImportant%
Field FIRedMask%
Field FIGreenMask%
Field FIBlueMask%
End Type
;
; #### Constant Declarations ####
;
; **** Image Format Constants
Const FIF_UNKNOWN=-1
Const FIF_BMP=0
Const FIF_ICO=1
Const FIF_JPEG=2
Const FIF_JNG=3
Const FIF_KOALA=4
Const FIF_LBM=5
Const FIF_MNG=6
Const FIF_PBM=7
Const FIF_PBMRAW=8
Const FIF_PCD=9
Const FIF_PCX=10
Const FIF_PGM=11
Const FIF_PGMRAW=12
Const FIF_PNG=13
Const FIF_PPM=14
Const FIF_PPMRAW=15
Const FIF_RAS=16
Const FIF_TARGA=17
Const FIF_TIFF=18
Const FIF_WBMP=19
Const FIF_PSD=20
Const FIF_CUT=21
Const FIF_IFF=FIF_LBM
Const FIF_XBM=22
Const FIF_XPM=23
Const FIF_DDS=24
.LoadExtentions
Data FIF_BMP,"BMP"
Data FIF_ICO,"ICO"
Data FIF_JPEG,"JPG"
Data FIF_JNG,"JNG"
Data FIF_KOALA,"KOA"
Data FIF_LBM,"IFF"
Data FIF_MNG,"MNG"
Data FIF_PBM,"PBM"
Data FIF_PBMRAW,"PBX"
Data FIF_PCD,"PCD"
Data FIF_PCX,"PCX"
Data FIF_PGM,"PGM"
Data FIF_PGMRAW,"PGX"
Data FIF_PNG,"PNG"
Data FIF_PPM,"PPM"
Data FIF_PPMRAW,"PPX"
Data FIF_RAS,"RAS"
Data FIF_TARGA,"TGA"
Data FIF_TIFF,"TIFF"
Data FIF_WBMP,"WBMP"
Data FIF_PSD,"PSD"
Data FIF_CUT,"CUT"
Data FIF_XBM,"XBM"
Data FIF_XPM,"XPM"
Data FIF_DDS,"DDS"
Data -1
; **** Image Types
Const FIT_UNKNOWN=0 ; unknown Type
Const FIT_BITMAP=1 ; standard image : 1-, 4-, 8-, 16-, 24-, 32-bit
Const FIT_UINT16=2 ; array of unsigned short : unsigned 16-bit
Const FIT_INT16=3 ; array of short : signed 16-bit
Const FIT_UINT32=4 ; array of unsigned long : unsigned 32-bit
Const FIT_INT32=5 ; array of long : signed 32-bit
Const FIT_FLOAT=6 ; array of Float : 32-bit IEEE floating point
Const FIT_DOUBLE=7 ; array of double : 64-bit IEEE floating point
Const FIT_COMPLEX=8 ; array of FICOMPLEX : 2 x 64-bit IEEE floating point
; **** Image Colour Type Constants
Const FIC_MINISWHITE=0 ; min value is white
Const FIC_MINISBLACK=1 ; min value is black
Const FIC_RGB=2 ; RGB Color model
Const FIC_PALETTE=3 ; Color map indexed
Const FIC_RGBALPHA=4 ; RGB Color model with alpha channel
Const FIC_CMYK=5 ; CMYK Color model
; **** Colour Channel Constants
Const FICC_RGB=0 ; Use red, green And blue channels
Const FICC_RED=1 ; Use red channel
Const FICC_GREEN=2 ; Use green channel
Const FICC_BLUE=3 ; Use blue channel
Const FICC_ALPHA=4 ; Use alpha channel
Const FICC_BLACK=5 ; Use black channel
Const FICC_REAL=6 ; Complex images: use real part
Const FICC_IMAG=7 ; Complex images: use imaginary part
Const FICC_MAG=8 ; Complex images: use magnitude
Const FICC_PHASE=9
; **** Colour Quantize Constants
Const FIQ_WUQUANT=0 ; Xiaolin Wu Color quantization algorithm
Const FIQ_NNQUANT=1 ; NeuQuant neural-net quantization algorithm by Anthony Dekker
; **** Dither Constants
Const FID_FS=0 ; Floyd & Steinberg error diffusion
Const FID_BAYER4x4=1 ; Bayer ordered dispersed dot dithering (order 2 dithering matrix)
Const FID_BAYER8x8=2 ; Bayer ordered dispersed dot dithering (order 3 dithering matrix)
Const FID_CLUSTER6x6=3 ; Ordered clustered dot dithering (order 3 - 6x6 matrix)
Const FID_CLUSTER8x8=4 ; Ordered clustered dot dithering (order 4 - 8x8 matrix)
Const FID_CLUSTER16x16=5 ; Ordered clustered dot dithering (order 8 - 16x16 matrix)
; **** Resample Consrants
Const FILTER_BOX=0 ; Box, pulse, Fourier window, 1st order (constant) b-spline
Const FILTER_BICUBIC=1 ; Mitchell & Netravali's two-param cubic filter
Const FILTER_BILINEAR=2 ; Bilinear filter
Const FILTER_BSPLINE=3 ; 4th order (cubic) b-spline
Const FILTER_CATMULLROM=4 ; Catmull-Rom spline, Overhauser spline
Const FILTER_LANCZOS3=5 ; Lanczos3 filter
; **** Loading/Saving Flag Constants
Const BMP_DEFAULT=0
Const BMP_SAVE_RLE=1
Const CUT_DEFAULT=0
Const DDS_DEFAULT=0
Const ICO_DEFAULT=0
Const IFF_DEFAULT=0
Const JPEG_DEFAULT=0
Const JPEG_FAST=1
Const JPEG_ACCURATE=2
Const JPEG_QUALITYSUPERB=$80
Const JPEG_QUALITYGOOD=$100
Const JPEG_QUALITYNORMAL=$200
Const JPEG_QUALITYAVERAGE=$400
Const JPEG_QUALITYBAD=$800
Const KOALA_DEFAULT=0
Const LBM_DEFAULT=0
Const MNG_DEFAULT=0
Const PCD_DEFAULT=0
Const PCD_BASE=1 ; load the bitmap sized 768 x 512
Const PCD_BASEDIV4=2 ; load the bitmap sized 384 x 256
Const PCD_BASEDIV16=3 ; load the bitmap sized 192 x 128
Const PCX_DEFAULT=0
Const PNG_DEFAULT=0
Const PNG_IGNOREGAMMA=1 ; avoid gamma correction
Const PNM_DEFAULT=0
Const PNM_SAVE_RAW=0 ; If set the writer saves in RAW format (i.e. P4, P5 Or P6)
Const PNM_SAVE_ASCII=1 ; If set the writer saves in ASCII format (i.e. P1, P2 Or P3)
Const PSD_DEFAULT=0
Const RAS_DEFAULT=0
Const TARGA_DEFAULT=0
Const TARGA_LOAD_RGB888=1 ; If set the loader converts RGB555 And ARGB8888 -> RGB888.
Const TIFF_DEFAULT=0
Const TIFF_CMYK=$1 ; reads/stores tags For separated CMYK (use | To combine with compression flags)
Const TIFF_PACKBITS=$100 ; save using PACKBITS compression
Const TIFF_DEFLATE=$200 ; save using DEFLATE compression
Const TIFF_ADOBE_DEFLATE=$400 ; save using ADOBE DEFLATE compression
Const TIFF_NONE=$800 ; save without any compression
Const WBMP_DEFAULT=0
Const XBM_DEFAULT=0
Const XPM_DEFAULT=0
;
; Fast Save JPG Images (24Bit Only).
;
;Function SaveJPG(Image, File$, Compression%=JPEG_QUALITYSUPERB)
;
; ; Compression:
; ; JPEG_QUALITYSUPERB = Superb Quality, Low Compression (100:1)
; ; JPEG_QUALITYGOOD = Good Quality, Low-Medium Compression (75:1) (DEFAULT)
; ; JPEG_QUALITYNORMAL = Normal Quality, Normal Compression (50:1)
; ; JPEG_QUALITYAVERAGE = Average Quality, Normal-High Compression (25:1)
; ; JPEG_QUALITYBAD = Poor Quality, High Compression (10:1)
;
; If Image
; FIBITMAP = FIQSend(Image)
; Suc = FI_Save(FIF_JPEG,FIBITMAP,File$,Compression)
; FI_Unload FIBITMAP
; If Not Suc Then RuntimeError "JPG Save Failed" + Chr(10) + File$
; Else
; RuntimeError "Image Instance Not Found (JPG Save)"
; EndIf
;
;End Function
;
; Fast Save TGA Images (24Bit Only).
;
Function SaveTGA(Image, File$)
If Image
FIBITMAP = FIQSend(Image)
Suc = FI_Save(FIF_TARGA,FIBITMAP,File$,0)
FI_Unload FIBITMAP
Return Suc
Else
RuntimeError "Image Instance Not Found (TGA Save)"
EndIf
End Function
;
; Fast Save TIFF Images (24Bit Only).
;
;Function SaveTIFF(Image, File$, Compression%=TIFF_NONE)
;
; ; Compression
; ; TIFF_PACKBITS = save using PACKBITS compression
; ; TIFF_DEFLATE = save using DEFLATE compression
; ; TIFF_ADOBE_DEFLATE = save using ADOBE DEFLATE compression
; ; TIFF_NONE = save without any compression (DEFAULT)
;
; If Image
; FIBITMAP = FIQSend(Image)
; Suc = FI_Save(FIF_TIFF,FIBITMAP,File$,Compression)
; FI_Unload FIBITMAP
; If Not Suc Then RuntimeError "TIFF Save Failed" + Chr(10) + File$
; Else
; RuntimeError "Image Instance Not Found (TIFF Save)"
; EndIf
;
;End Function
;
; Fast Save BMP Images (24Bit Only).
;
Function SaveBMP(Image, File$)
If Image
FIBITMAP = FIQSend(Image)
Suc = FI_Save(FIF_BMP,FIBITMAP,File$,0)
FI_Unload FIBITMAP
Return Suc
Else
RuntimeError "Image Instance Not Found (BMP Save)"
EndIf
End Function
;
; Fast Save PNG Images (24Bit Only).
;
Function SavePNG(Image, File$)
If Image
FIBITMAP = FIQSend(Image)
Suc = FI_Save(FIF_PNG,FIBITMAP,File,0)
FI_Unload FIBITMAP
Return Suc
Else
RuntimeError "Image Instance Not Found (PNG Save)"
EndIf
End Function
;
; Load image file.
;
Function FILoadImage(File$)
Local FI_FIFType%, FIBITMAP%
Local FI_n%, ImType$, ImageBank
Local FIF_FLAG%
FI_FIFType = FI_GetFileType(File$,0)
If FI_FIFType = -1
FI_FIFType = FI_GetFIFFromFilename(File$)
If FI_FIFType = -1 Then Return 0 ; ** FAIL
EndIf
If FI_FIFType = 0 Then FIF_FLAG = PNG_AVOIDGAMMA
FIBITMAP = FI_Load(FI_FIFType,File$,FIF_FLAG)
If FIBITMAP = 0 Then Return 0 ; ** FAIL
FIImage = New ImageList
; Get file type (extension), name and directory.
For FI_n = Len(File$) To 1 Step -1
If Mid(File$,FI_n,1) = "."
ImType$ = Upper(Right(File$,Len(File$)-FI_n))
EndIf
If Mid(File$,FI_n,1) = ""
FIImage\FileName = Right(File$,Len(File$)-FI_n)
FIImage\FileDirectory = Left(File$,FI_n)
Exit
EndIf
Next
If FIImage\FileName = ""
FIImage\FileName = File$
FIImage\FileDirectory = CurrentDir()
EndIf
PopulateFIType FIImage,FIBITMAP
FIImage\File_Size = FileSize(File$)
FIImage\ImageFormatDescript = FI_GetFIFDescription(FI_FIFType)
FIImage\ImageFormat = FI_FIFType
FIImage\Image = CreateImage(FIImage\Width,FIImage\Height)
iBuffer = ImageBuffer(FIImage\Image)
LockBuffer iBuffer
ImageBank = FI_PeekIntEx(iBuffer,72)
FIImage\DisplayPitch = FI_PeekIntEx(iBuffer,56)
FIImage\ImageSize = FIImage\Height*FIImage\Pitch
FIImage\Depth = FI_PeekIntEx(iBuffer,100)
FIImage\RedMask = FI_PeekIntEx(iBuffer,112)
FIImage\GreenMask = FI_PeekIntEx(iBuffer,116)
FIImage\BlueMask = FI_PeekIntEx(iBuffer,120)
FI_ConvertToRawBits3D ImageBank,FIBITMAP,FIImage\DisplayPitch,FIImage\Depth,FIImage\RedMask,FIImage\GreenMask,FIImage\BlueMask,0
UnlockBuffer iBuffer
Image = FIImage\Image
FI_Unload FIBITMAP
Delete FIImage
Return Image
End Function
;
;
;
Function FI_PeekIntEx(iBuffer, Offset)
RtlMoveMemory_From Int32,iBuffer+Offset,4
Return PeekInt(Int32,0)
End Function
;
;
;
Function FI_PeekWordEx(iBuffer, Offset)
RtlMoveMemory_From FI_Word,iBuffer+Offset,2
Return PeekShort(FI_Word,0)
End Function
;
; Quickly Sends a Blitz Image to an FIBITMAP Instance.
;
Function FIQSend(Image)
Local iBuffer%, iPitch%, iFormat%
Local FIBITMAP%, nFIBITMAP%, iBank%
iBuffer = ImageBuffer(Image)
LockBuffer iBuffer
iBank = FI_PeekIntEx(iBuffer,72)
iPitch = FI_PeekIntEx(iBuffer,56)
FIBITMAP = FI_ConvertFromRawBits3D(iBank,ImageWidth(Image),ImageHeight(Image),iPitch,FI_PeekIntEx(iBuffer,100),FI_PeekIntEx(iBuffer,112),FI_PeekIntEx(iBuffer,116),FI_PeekIntEx(iBuffer,120),0)
UnlockBuffer iBuffer
If FI_GetBPP(FIBITMAP) <> 24
nFIBITMAP = FI_ConvertTo24Bits(FIBITMAP)
If nFIBITMAP
FI_Unload FIBITMAP
FIBITMAP = nFIBITMAP
EndIf
EndIf
Return FIBITMAP
End Function
;
; Quickly Returns an FIBITMAP Instance to a BlitzImage.
;
Function FIQGrab(Image, FIBITMAP)
Local iBuffer%, iPitch%, iFormat%
Local iBank%
iBuffer = ImageBuffer(Image)
LockBuffer iBuffer
iBank = FI_PeekIntEx(iBuffer,72)
iPitch = FI_PeekIntEx(iBuffer,56)
iFormat = FI_PeekIntEx(iBuffer,104)
FI_ConvertToRawBits3D iBank,FIBITMAP,iPitch,FIB_BitDepth[iFormat],FIB_RedMask[iFormat],FIB_GreenMask[iFormat],FIB_BlueMask[iFormat],0
UnlockBuffer iBuffer
End Function
;
; Populate the FreeImage Type Instance (.ImageList).
;
Function PopulateFIType(FI.ImageList, FIBITMAP)
FI\Width = FI_GetWidth(FIBITMAP)
FI\Height = FI_GetHeight(FIBITMAP)
FI\BitCount = FI_GetBPP(FIBITMAP)
FI\Pitch = FI_GetPitch(FIBITMAP)
FI\ClrUsed = FI_GetColorsUsed(FIBITMAP)
FI\FIRedMask = FI_GetRedMask(FIBITMAP)
FI\FIGreenMask = FI_GetGreenMask(FIBITMAP)
FI\FIBlueMask = FI_GetBlueMask(FIBITMAP)
FI\DIBSize = FI_GetDIBSize(FIBITMAP)
End Function
;
;
;
Function ComputeCRC()
c = CreateBank(4)
For n=0 To 255
PokeInt c,0,n
For k = 0 To 7
If (PeekInt(c,0) And 1)
PokeInt c,0,($EDB88320 Xor (PeekInt(c,0) Shr 1))
Else
PokeInt c,0,(PeekInt(c,0) Shr 1)
EndIf
Next
CRC_Table(n) = CreateBank(4)
PokeInt CRC_Table(n),0,PeekInt(c,0)
Next
FreeBank c
End Function
P.S. It seems a bit strange that Blitz3D can't save PNG images natively, given that it uses FreeImage itself. :/