Blitz FreeImage Library

BlitzPlus Forums/BlitzPlus Beginners Area/Blitz FreeImage Library

CoderX(Posted 2005) [#1]
I'm trying to use Snarty's Blitz FreeImage Library to load some gif images into my application.

It works well, but I was looking at his code and I'm a little confused. This may be because I'm extremely new to image encoding.

Global FIB_RedMask[4], FIB_GreenMask[4], FIB_BlueMask[4], FIB_BitDepth[4]

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

In the code block above, how are the constant values for RedMask, GreenMask, and BlueMask determined?

And what is the significance of the "$" sign in front of the constant?

Many Thanks.

- Nick


sswift(Posted 2005) [#2]
A color is made up of four bytes. 32 bits. A long int. In Blitz, all ints are long ints.

The colors are arranged like so:

ARGB

Each letter is one byte.

The significance of the $ is that it means that number is in hexadecimal. Hexadecimal is a base 16 system. Decimal, the normal number system you use is base 10. Base 10 has 10 digits, 0..9. Base 16 has 16 digits. 0..9 then A..F

In hexadecimal:
$09 or just $9 = 9
$0A = 10
$0B = 11
$0F = 15
$10 = 16
$11 = 17

You can see where this is going. $FF in hexadecimal is 255. And 255 is the highest value a byte can have. So, if we use hexadecimal we can write numbers in a shorter manner. And this comes in useful when dealing with bytes. We could re-write our byte structure for our colors like so:

AARRGGBB

Then we could write a hexadecimal number to fit that:

$FFFFFFFF

See how the red mask for bitdepth 3, 24bit format has $FF0000 for red mask? Well $FF0000 is equivalent to $00FF0000 And when you compare THAT to the ARGB structure I listed above, you can see the FF falls right on the red byte. So that is saying that the red byte should be 255.

Now if the red byte is 255 but all the others are 0, then you could caculate what the number is in decimal like so:

AA * 16777216 + RR * 65536 + GG * 256 + BB

So $00FF0000 is 16711680


Now the reason those masks are what they are is because they are telling the program which BITS in the bytes actually make up each color. The AARRGGBB thing only applies in 24 bit and 32 bit color mode. In 16bit color mode, each color bits into TWO bytes, so you have to squeeze the red green abd blue into there. (No alpha)

Each byte is 8 bits, 1 or 0. With two bytes, you have 16 bits. And if we write out the way the 16 bit color is stored you get one of two methods.

I'm not going to bother figuring out if this is correct or not, but if each letter is a bit, then you either have 565 or 555 format for a 16 bit color. That means 5 bits of blue, 6 of green, then 5 of red. I'll just do the 565 since I think I can get that right without deciphering the hex in his code:

BBBBBGGG GGGRRRRR

That's two bytes, and as you can see, the green spans the two bytes because it can't fit into one or the other.


Well that should answer your question.


sswift(Posted 2005) [#3]
Btw, you might find my version of his lib to be easier to use. I made some changes if I remember correctly, I used some of his method and some of someone else's method so that I could do more of the stuff with Blitzplus commands instead of DLL calls.

My functions don't support all the functionality of the library, they just do what you probably want to, which is load and save images as simply as possible.

; -----------------------------------------------------------------------------------------------------------------------------------
; To use these functions you must create a freeimage.decls file in your decls directory with the following lines:
;
; 	.lib "FreeImage.dll"
;
; 	FIAllocate%( Width%,Height%,BPP%,RedMask%,GreenMask%,BlueMask% ) : "_FreeImage_Allocate@24"
; 	FILoad%( ImageType%,File$,Mode% ) : "_FreeImage_Load@12"
; 	FISave%( ImapeType%,FIBITMAP%,File$,Flags% ) : "_FreeImage_Save@16"
; 	FIUnload%( FIBITMAP% ) : "_FreeImage_Unload@4"
;	FIGetDescription$( FREE_IMAGE_FORMAT% ) : "_FreeImage_GetFIFDescription@4"
; 	FIGetType%( File$,Default% ) : "_FreeImage_GetFileType@8"
;	FIToBank( Bank*,FIBITMAP%,Pitch%,Depth%,Red_Mask%,Green_Mask%,Blue_Mask%,TopDown% ) : "_FreeImage_ConvertToRawBits@32"
;	FIGuessType%( File$ ) : "_FreeImage_GetFIFFromFilename@4"
;	FIGetClrUsed%( FIBITMAP% ) : "_FreeImage_GetColorsUsed@4"
;	FIGetBitStart%( FIBITMAP% ) : "_FreeImage_GetBits@4"
;	FIGetScanLine%( FIBITMAP%,ScanLine% ) : "_FreeImage_Get@8"
; 	FIGetDepth%( FIBITMAP% ) : "_FreeImage_GetBPP@4"
;	FIGetWidth%( FIBITMAP% ) : "_FreeImage_GetWidth@4"
;	FIGetBits%( FIBITMAP% ) : "_FreeImage_GetBits@4"
;	FIGetHeight%( FIBITMAP% ) : "_FreeImage_GetHeight@4"
;	FIGetLine%( FIBITMAP% ) : "_FreeImage_GetLine@4"
;	FIGetPitch%( FIBITMAP% ) : "_FreeImage_GetPitch@4"
;	FIGetSize%( FIBITMAP% ) : "_FreeImage_GetDIBSize@4"
;	FIGetPalette%( FIBITMAP% ) : "_FreeImage_GetPalette@4"
;	FIGetDPMX%( FIBITMAP% ) : "_FreeImage_GetDotsPerMeterX@4"
;	FIGetDPMY%( FIBITMAP% ) : "_FreeImage_GetDotsPerMeterY@4"
;	FIGetHeader%( FIBITMAP% ) : "_FreeImage_GetInfoHeader@4"
;	FIGetInfo%( FIBITMAP% ) : "_FreeImage_GetInfo@4"
;	FIGetColorType%( FIBITMAP% ) : "_FreeImage_GetColorType@4"
;	FIGetRedMask%( FIBITMAP% ) : "_FreeImage_GetRedMask@4"
;	FIGetGreenMask%( FIBITMAP% ) : "_FreeImage_GetGreenMask@4"
;	FIGetBlueMask%( FIBITMAP% ) : "_FreeImage_GetBlueMask@4"
;	FIGetTranCount%( FIBITMAP% ) : "_FreeImage_GetTransparencyCount@4"
;	FIGetTranTable%( FIBITMAP% ) : "_FreeImage_GetTransparencyTable@4"
;	FISetTran( FIBITMAP%,Flag% ) : "_FreeImage_SetTransparent@8"
;	FIIsTran%( FIBITMAP% ) : "_FreeImage_IsTransparent@4"
;	FIConvert8Bits%( FIBITMAP% ) : "_FreeImage_ConvertTo8Bits@4"
;	FIConvert555%( FIBITMAP% ) : "_FreeImage_ConvertTo16Bits555@4"
;	FIConvert565%( FIBITMAP% ) : "_FreeImage_ConvertTo16Bits565@4"
;	FIConvert24Bits%( FIBITMAP% ) : "_FreeImage_ConvertTo24Bits@4"
;	FIConvert32Bits%( FIBITMAP% ) : "_FreeImage_ConvertTo32Bits@4"
;	FIColorQuantize%( FIBITMAP%,Flag% ) : "_FreeImage_ColorQuantize@8"
;	FIThreshold%( FIBITMAP%,Flag% ) : "_FreeImage_Threshold@8"
;	FIDither%( FIBITMAP%,Algo% ) : "_FreeImage_Dither@8"
;	FIFromBank%( Bank*,Width%,Height%,Pitch%,Depth%,RedMask%,GreenMask%,BlueMask%,TopDown% ) : "_FreeImage_ConvertFromRawBits@36"
;	FIClone%(DIB%) : "_FreeImage_Clone@4"
;
; -----------------------------------------------------------------------------------------------------------------------------------
; Freeimage supports the following file types:
;
; 	BMP files       [reading, writing]
; 	TARGA files     [reading, writing]
; 	TIFF files      [reading, writing]
; 	JPEG/JIF files  [reading, writing]
; 	GIF files       [reading, writing]
; 	PNG files       [reading, writing]
; 	WBMP files      [reading, writing]
; 	ICO files       [reading, writing]
; 	PBM files       [reading, writing]
; 	PGM files       [reading, writing]
; 	PPM files       [reading, writing]
; 	XPM files       [reading, writing]
;
;	DDS files       [reading]
; 	PhotoShop files [reading]
; 	Kodak PhotoCD   [reading]
; 	PCX files       [reading]
; 	Dr. Halo files  [reading] 
; 	IFF files       [reading]
; 	JNG files       [reading]
; 	KOALA files     [reading]
; 	LBM files       [reading]
; 	MNG files       [reading]
; 	Sun RAS files   [reading]
; 	XBM files       [reading]
; -----------------------------------------------------------------------------------------------------------------------------------


; Image formats:

	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_IFF     =  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_XBM     = 22
	Const FIF_XPM     = 23
	Const FIF_DDS     = 24
	Const FIF_GIF     = 25


; Compression settings:

	Const FIC_DEFAULT            = $0

	Const FIC_BMP_RLE            = $1

	Const FIC_JPEG_SUPERB        = $80	; 100% quality
	Const FIC_JPEG_GOOD          = $100	;  75% quality (default)
	Const FIC_JPEG_NORMAL        = $200	;  50% quality
	Const FIC_JPEG_AVERAGE       = $400	;  25% quality
	Const FIC_JPEG_BAD           = $800	;  10% quality
	Const FIC_TIFF_PACKBITS      = $100
	Const FIC_TIFF_DEFLATE       = $200
	Const FIC_TIFF_ADOBE_DEFLATE = $400	
	Const FIC_TIFF_NONE          = $800 


; Image loading flags:

	Const JPEG_ACCURATE = 2

; Image formats:

	Global FIB_BitDepth[4]
	Global FIB_RedMask[4]
	Global FIB_GreenMask[4]
	Global FIB_BlueMask[4]

	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


; -----------------------------------------------------------------------------------------------------------------------------------
; This function loads an image into Blitz using the Freeimage library.
; -----------------------------------------------------------------------------------------------------------------------------------
Function FILoadImage(Filename$)

	Local FI_FileType
	Local FI_Bitmap
	Local FI_Width, FI_Height
	Local DestImage, DestImageBuffer
	Local DestImageBank, DestImagePitch, DestImageFormat
	Local DestImageDepth, DestImageRedMask, DestImageGreenMask, DestImageBlueMask

	; Get the filetype.
		
		; First try to get the file type from the file header.
		; If that fails, try to guess the filetype from the file extension.
		; If that fails, return from function with failure.
		
		FI_FileType = FIGetType(Filename$, 0)
		
		If FI_FileType = -1
			FI_FileType = FIGuessType(Filename$)
			If FI_FileType = -1 Return
		EndIf
	
	; Attempt to load the image.  If the image fails to load, return from the function.
		
		If FI_FileType = FIF_JPEG
			;FI_Bitmap = FILoad(FI_FileType, Filename$, JPEG_ACCURATE)
			FI_Bitmap = FILoad(FI_FileType, Filename$, 0)
		Else
			FI_Bitmap = FILoad(FI_FileType, Filename$, 0)
		EndIf
		
		If Not FI_Bitmap Return 	
	
	; Get the width and height of the image.
		FI_Width  = FIGetWidth(FI_Bitmap)		
		FI_Height = FIGetHeight(FI_Bitmap)
		
	; Create an image in Blitz with the same width and height as the image loaded with freeimage.			
		DestImage = CreateImage(FI_Width, FI_Height, 1, 1)
		DestImageBuffer = ImageBuffer(DestImage)
	
	; 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

	; Free the loaded image.
		FIUnload FI_Bitmap
	
	; Return the pointer to the new Blitz image.
		Return DestImage
	
End Function


; -----------------------------------------------------------------------------------------------------------------------------------
; This function saves an image from Blitz using the Freeimage library.
; For JPEG, can specify integer 0..100 for compression to indicate desired quality.
; -----------------------------------------------------------------------------------------------------------------------------------
Function FISaveImage(SrcImage, Filename$, FI_FileType=FIF_UNKNOWN, FI_Compression=0)

	Local FI_Bitmap
	Local Success

	If SrcImage <> 0

		; If FI_FileType is unknown, attempt to determine the filetype the user is trying to save from the file extension.
		; Return from the function if fail.

			If FI_FileType = FIF_UNKNOWN
		
				FI_FileType = FIGuessType(Filename$)
				If FI_FileType = FIF_UNKNOWN Return
	
			EndIf
				
		; Is saving supported for this format?
				
		; Create a FI bitmap from the source image.
			FI_Bitmap = FIConvertImageToFIB(SrcImage)
		
		; Attempt to save the bitmap using the specified format.
			Success = FISave(FI_FileType, FI_Bitmap, Filename$, FI_Compression)
			If Not Success Then Notify "Unable to save image:" + Chr(10) + Filename$, True

		; Free the FI bitmap.		
			FIUnload(FI_Bitmap)
		
	EndIf

End Function


; -----------------------------------------------------------------------------------------------------------------------------------
; This function takes a Blitz image as input, and returns a FI bitmap.
; -----------------------------------------------------------------------------------------------------------------------------------
Function FIConvertImageToFIB(SrcImage)

	Local SrcBuffer
	Local SrcWidth, SrcHeight
	Local SrcBank, SrcPitch, SrcFormat
	Local SrcDepth
	Local SrcRedMask, SrcGreenMask, SrcBlueMask
	Local FI_Bitmap, FI_Bitmap24

	; Convert the Blitz image to an FI_Bitmap:

		SrcBuffer = ImageBuffer(SrcImage)
	
		LockBuffer SrcBuffer
		
			SrcWidth  = ImageWidth(SrcImage)
			SrcHeight = ImageHeight(SrcImage)
			
			SrcBank   = LockedPixels(SrcBuffer)
			SrcPitch  = LockedPitch(SrcBuffer)
			SrcFormat = LockedFormat(SrcBuffer)
		
			SrcDepth     = FIB_BitDepth[SrcFormat]
			SrcRedMask   = FIB_RedMask[SrcFormat]
			SrcGreenMask = FIB_GreenMask[SrcFormat]
			SrcBlueMask  = FIB_BlueMask[SrcFormat]
		
			FI_Bitmap = FIFromBank(SrcBank, SrcWidth, SrcHeight, SrcPitch, SrcDepth, SrcRedMask, SrcGreenMask, SrcBlueMask,0)

		UnlockBuffer SrcBuffer
	
	; Convert FI_Bitmap to 24bit if neccessary:	

		If FIGetDepth(FI_Bitmap) <> 24
	
			FI_Bitmap24 = FIConvert24Bits(FI_Bitmap)
		
			If FI_Bitmap24
				FIUnload(FI_Bitmap)
				FI_Bitmap = FI_Bitmap24
			EndIf
	
		EndIf
	
	; Return FI_Bitmap:
		Return FI_Bitmap

End Function



CoderX(Posted 2005) [#4]
sswift,

Thanks for writing the comprehensive reply. I'll be bookmarking this page for future reference.

I guess I need to get more indepth with learning number systems and the theory behind bits and bytes.

And you're right, I just need to load and save different image files, so your code will come in handy.

Thanks again,

- Nick


EPS(Posted 2006) [#5]
hi,

it's a long time for this topic but i found it now.

Ok, the question: this code dosn't work by me. I get only a black image if i try to load one.

Can anybody help me? Thanks a lot and sorry for my bad englisch.


rolow(Posted 2006) [#6]
Hi all,

I'm new to BlitzBasic and am very impressed. I am trying to build my archives of great utilities to ease my transition to programming in B+/B3D. However, the link to download Snarty's Blitz FreeImage Library at www.blitzcoder.com isn't working at the moment.

Is there any other place to get it?

Thanks.....