Copyright (C) 2007-2010 Simon Nash/Eric Cowles
Copyright (C) 2022 Ebben Feagan
zlib code (C) 1995-2017 Jean-loup Gailly and Mark Adler
See license.txt and zlib/zlib.h for more information.
This library provides easy to use functions for using PNG images in your FreeBASIC programs. The functions provide a way to load PNG images to old or new style PUT buffers and also in a format ready for use with OpenGL. Images can be loaded from file, or memory buffer.
In order to compile you need GNU make, FreeBASIC 0.20 or newer, and GCC if you wish to compile in the zlib. Just type 'make' in the main directory to make the default build.
Options:
'STATICZ=1' Include static zlib
'DEBUG=1' Include memory leak detector
'PROFILE=1' Profile library
'EXX=1' Full debug support
'PNG_NO_OLD_API=1' No "version 1" api
'PNG_NO_PALETTE_8=1' No 8-bit palette target
'PNG_NO_RGB_16=1' No 16-bit rgb target
'PNG_NO_RGB_32=1' No 32-bit rgb target
'PNG_NO_ARGB_32=1' No 32-bit argb target
'PNG_NO_ABGR_32=1' No 32-bit abgr target
The changes for this version are as follows:
- 64-bit and modern FreeBASIC compiler (1.07+ tested) support
The changes for this version are as follows:
- Added memory save function to save to a memory image (png_save_mem creates and returns a memory pointer).
- Added pixel format functions to return the color type and bit depth of a png.
- Added "version 2" load, save functions which are more low-level and can be used by any graphics library via the use of callbacks.
- Updated conversion code to make conversion from any png to (almost) any image format possible. Total output pixel formats include PALETTE_8, RGB_16, RGB_32, ARGB_32, ABGR_32. "Version 1" functions only support ARGB_32 and ABGR_32.
- Internal function tables are used to streamline the decode sequence resulting in a 20% speed increase.
The changes for this version are as follows:
- The prebuilt windows static zlib version was bugged in v1.9.3 due to a misbuild. That is now rectified.
- Static versions of the library are now built under a new name, 'libfbpngs.a'. This will mean you can keep both in your FreeBASIC lib/ directory without having any clashes as it takes precedence. Hopefully this will help stop a lot of the problems people had using the static version.
- A lot of code has been changed in png_image_convert.bas in order to improve it's efficiency. I am seeing around 40% faster times on my machine.
The changes for this version are as follows:
- A bug was found, and fixed in the PNG dimensions code thanks to user dreamerman. This bug affected users who called png_dimensions many times.
- Some new logic has been added to set the default image type based on the FB version has been added thanks to 1000101. It now detects if you are using <= 0.17, and will use the old image format, otherwise it will use the new image format. This means that for most users who will be using 0.20 FBC the default has changed. It won't effect many people though I hope, as most of those will be using the new image format anyway, and it's only people who do more low level stuff with the buffer who will be negatively affected. If you find your program misbehaves with the new version of FBPNG, then try specifying PNG_TARGET_FBOLD in your png_load calls.
fbpng has now been modified, so that it will work with the version of ImageDestroy that that comes with FB 0.21. However, YOU SHOULD NOT USE IMAGEDESTROY. This addition is partly a compatibility patch to help people out, you should be using png_destroy instead in order to be as future-proof as possible. This change means that you cannot use ImageDestroy anymore if you are using FB 0.20. You should either update your code to use png_destroy, or just carry on using your old version of fbpng. Also, if you plan to use the STATICZ version you should do;
#define PNG_STATICZ 1
#include "fbpng.bi"
in your program, as otherwise it will still try to link to a dynamic version of zlib. Thank you to Z!re for making me aware of this.
The major change for this version of fbpng, is that buffers created by fbpng will now be aligned in memory to a multiple of 16 bytes, this is to match the change in the FB 0.21 ImageCreate/Destroy functions, which now also do the same, and allows users who know SSE to be able to use it more effectively. Thanks to {1000101} for helping me out with the method that this uses, and to counting_pine, whose patch I modified and incorperated.
Since version 0.21.0 of FreeBASIC you can no longer use ImageDestroy to free the memory used by a png image, you should now use the new png_destroy() sub for this purpose.
The librarys interface has changed, due to the new target parameter, and the old redundant target depth has been removed, the library always returns a 32 bit image. There is also now no error global variable, however if you compile with make DEBUG=1 then much debugging info will be printed to the console.
Once compiled you will need two files, 'build/libfbpng.a' and 'inc/fbpng.bi'. These should be placed either in your projects directory, or in the lib/ and inc/ dirs of your FreeBASIC installation, along with the other libary and header files. On Linux the correct directories are likely to be /usr/include/freebasic/ and /usr/lib/freebasic/linux/
There are 13 functions for users, details are given here:
For those functions that accept a target, the following are the allowed values
For an old style FreeBASIC buffer, as used in older versions of FB PNG_TARGET_FBOLD
For a new style FreeBASIC buffer, as used in the newer versions of FB PNG_TARGET_FBNEW
For a buffer that is ready to be used with OpenGL PNG_TARGET_OPENGL
For a buffer that is suitable for the version of FB in use. PNG_TARGET_DEFAULT
declare function png_load cdecl alias "png_load" _
( _
byref filename as string, _
byval target as png_target_e = PNG_TARGET_DEFAULT _
) as any ptr
The filename parameter should be obvious, something like "foo.png" The target parameter is one of the values listed above, ie PNG_TARGET_FBOLD
The return value will be a pointer to a buffer that contains the image in the format specified by target. The returned buffer will always be a 32-bit image.
If the function fails, then the return will be NULL
It is the users responsibity to free the returned image when finished with, using the normal DEALLOCATE/free
Example
dim as any ptr img
screenres 640, 480, 32
img = png_load( "test.png" )
if img <> NULL then
put( 0, 0 ), img
png_destroy( img )
else
print "Failed to load"
end if
declare function png_load_mem cdecl alias "png_load_mem" _
( _
byval buffer as any ptr, _
byval buffer_len as integer, _
byval target as png_target_e = PNG_TARGET_DEFAULT _
) as any ptr
The buffer parameter is a pointer to a memory location that holds a PNG image The buffer_len parameter is the size of this buffer, ie the files size The target parameter is one of the values listed above, ie PNG_TARGET_FBOLD
The return value will be a pointer to a buffer that contains the image in the format specified by target. The returned buffer will always be a 32-bit image.
If the function fails, then the return will be NULL
It is the users responsibity to free the returned image when finished with, using png_destroy
declare function png_save cdecl alias "png_save" _
( _
byref filename as string, _
byval img as any ptr, _
byval source as png_target_e = PNG_TARGET_DEFAULT _
) as integer
The filename parameter should be obvious, something like "foo.png" The img parameter is a pointer to either a new or old style FreeBASIC buffer, it must be in ARGB_32 format. The source parameter tells the library what the img format it, the default depends on what version of fbc you are using, either PNG_TARGET_FBOLD for 0.17 or older and PNG_TARGET_FBNEW for newer.
The return value will be 0 (zero) on success, and non zero otherwise
declare function png_save_mem cdecl alias "png_save_mem" _
( _
byref buffer_len as integer, _
byval img as any ptr, _
byval source as png_target_e = PNG_TARGET_DEFAULT _
) as any ptr
The buffer_len parameter is the size of the return buffer, note byref The img parameter is a pointer to either a new or old style FreeBASIC buffer, it must be in ARGB_32 format. The source parameter tells the library what the img format it, the default depends on what version of fbc you are using, either PNG_TARGET_FBOLD for 0.17 or older and PNG_TARGET_FBNEW for newer.
The return value will be a valid pointer on success, and zero otherwise
declare sub png_dimensions cdecl alias "png_dimensions" _
( _
byref filename as string, _
byref w as uinteger, _
byref h as uinteger _
)
The filename parameter should be obvious, something like "foo.png" The w and h parameters (note the byref) are how the dimensions are returned
If the sub fails, then then w and h will be zero
Example
dim as uinteger w, h
png_dimensions( "test.png", w, h )
print w, h
declare sub png_dimensions_mem cdecl alias "png_dimensions_mem" _
( _
byval buffer as any ptr, _
byref w as uinteger, _
byref h as uinteger _
)
The buffer parameter is a pointer to a memory location that holds a PNG image The w and h parameters (note the byref) are how the dimensions are returned
If the sub fails, then then w and h will be zero
declare sub png_destroy cdecl alias "png_destroy" _
( _
byval buffer as any ptr _
)
The buffer parameter is a pointer to a memory location that holds a PNG image
This sub should be used to deallocate the memory allocated by png_load or png_load_mem
declare sub png_pixelformat cdecl alias "png_pixelformat" _
( _
byref filename as string, _
byref colortype as uinteger, _
byref bitdepth as uinteger _
)
The filename parameter should be obvious, something like "foo.png" The colortype and bitdepth parameters (note the byref) are how the dimensions are returned
If the sub fails, then then colortype and bitdepth will be zero
declare sub png_pixelformat_mem cdecl alias "png_pixelformat_mem" _
( _
byref buffer as any ptr, _
byref colortype as uinteger, _
byref bitdepth as uinteger _
)
The buffer parameter is a pointer to a memory location that holds a PNG image The colortype and bitdepth parameters (note the byref) are how the dimensions are returned
If the sub fails, then then colortype and bitdepth will be zero
declare function png_load2 cdecl alias "png_load2" _
( _
byref filename as string, _
byref img as any ptr, _
byval img_bpp as integer, _
byref cb as png_cb, _
byval outpal as any ptr _
) as integer
The filename parameter should be obvious, something like "foo.png" The img parameter is pointer to be filled with the png image, it is created and validated by cb.create. Note, you can pass an already valid image and cb.create should validate it without creating a new image. The img_bpp perameter is the images bits per pixel, valid values are graphics library dependant. Typical values are 0 (do not force bit depth), 8, 16, 32 The cb parameter are the callbacks to use for loading the png, png_cb is explained later in this document. The outpal parameter is an optional pointer to a palette, this pointer must be large enough to hold the entire palette for the png. Palettes are only returned for indexed and greyscale images.
The return value will be 0 (zero) on success, and non zero otherwise
It is the users responsibity to free the returned image when finished with, this should be done using the graphics libraries function to free images and not png_destroy
Example
dim as any ptr img
screenres 640, 480, 32
img = png_load2( "test.png", img, 32, GFXLIB2_NEW_CB )
if img <> NULL then
put( 0, 0 ), img
imagedestroy( img )
else
print "Failed to load"
end if
declare function png_load2_mem cdecl alias "png_load2_mem" _
( _
byval buffer as any ptr, _
byval buffer_len as integer, _
byref img as any ptr, _
byval img_bpp as integer, _
byref cb as png_cb, _
byval outpal as any ptr _
) as integer
The buffer parameter is a pointer to a memory location that holds a PNG image The buffer_len parameter is the size of this buffer, ie the files size The img parameter is pointer to be filled with the png image, it is created and validated by cb.create. Note, you can pass an already valid image and cb.create should validate it without creating a new image. The img_bpp perameter is the images bits per pixel, valid values are graphics library dependant. Typical values are 0 (do not force bit depth), 8, 16, 32 The cb parameter are the callbacks to use for loading the png, png_cb is explained later in this document. The outpal parameter is an optional pointer to a palette, this pointer must be large enough to hold the entire palette for the png. Palettes are only returned for indexed and greyscale images.
The return value will be 0 (zero) on success, and non zero otherwise
It is the users responsibity to free the returned image when finished with, this should be done using the graphics libraries function to free images and not png_destroy
declare function png_save2 cdecl alias "png_save2" _
( _
byref filename as string, _
byval img as any ptr, _
byref cb as png_cb, _
byval outpal as any ptr _
) as integer
The filename parameter should be obvious, something like "foo.png" The img parameter is a pointer to a valid image, it must be in ARGB_32 format. The cb parameter are the callbacks to use for saving the png, png_cb is explained later in this document. The outpal parameter is an optional pointer to a palette, this is for future use and must be NULL
The return value will be 0 (zero) on success, and non zero otherwise
declare function png_save2_mem cdecl alias "png_save2_mem" _
( _
byref buffer_len as integer, _
byval img as any ptr, _
byref cb as png_cb, _
byval outpal as any ptr _
) as any ptr
The buffer_len parameter is the size of the return buffer, note byref The img parameter is a pointer to a valid image, it must be in ARGB_32 format. The cb parameter are the callbacks to use for saving the png, png_cb is explained later in this document. The outpal parameter is an optional pointer to a palette, this is for future use and must be NULL
The return value will be a valid pointer on success, and zero otherwise
This section covers advanced topics for using fbpng with any graphics library through the use of a callback structure. The library can used in it's full form or be rebuilt with a few definitions for any graphics library.
If you choose to rebuild the library with a different set of output targets it is very important to update png_image_convert.bas This contains the tables used to choosing the image decoders. At this time fbc (0.20b) does not support preprocessor statements in the generation of static tables. If this changes in the future then you will not have to modify the library source.
#define PNG_STATICZ
#include "fbpng.bi"
This will include the static zlib build of fbpng. This removes the dependency on an external dynamic library for your program.
#define PNG_DEBUG
#include "fbpng.bi"
This will use a memory leak detector which will aid in the debugging and management of images and other user allocated memory resources.
#define PNG_NO_OLD_API
#include "fbpng.bi"
This completely disables access to fbpng "version 1" and earlier load and store API functions.
Invalidates: png_load, png_load_mem, png_save, png_save_mem, png_destroy GFXLIB2_NEW_CB, GFXLIB2_OLD_CB, OPENGL_CB
Validates: PNG_NO_PALETTE_8, PNG_NO_RGB_16, PNG_NO_RGB_32, PNG_NO_ARGB_32, PNG_NO_ABGR_32
#define PNG_NO_OLD_API
#define PNG_NO_PALETTE_8
#include "fbpng.bi"
Forces the exclusion of 8-bit paletted targets. Requires fbpng rebuilt with same settings.
#define PNG_NO_OLD_API
#define PNG_NO_RGB_16
#include "fbpng.bi"
Forces the exclusion of 16-bit RGB targets. Requires fbpng rebuilt with same settings.
#define PNG_NO_OLD_API
#define PNG_NO_RGB_32
#include "fbpng.bi"
Forces the exclusion of 32-bit RGB targets. Requires fbpng rebuilt with same settings.
#define PNG_NO_OLD_API
#define PNG_NO_ARGB_32
#include "fbpng.bi"
Forces the exclusion of 32-bit ARGB targets. Requires fbpng rebuilt with same settings.
#define PNG_NO_OLD_API
#define PNG_NO_ABGR_32
#include "fbpng.bi"
Forces the exclusion of 32-bit ABGR targets. Requires fbpng rebuilt with same settings.
type png_cb
/'
All functions return the output in "result". The functions themselves return pass/fail.
If the function passes (0) the result is valid. All callbacks must conform to this
convention.
'/
as function cdecl _
( _
byref img as any ptr, _
byval w as integer, _
byval h as integer, _
byref bpp as integer, _
byval ct as integer, _
byval bd as integer _
) as integer create
as sub cdecl _
( _
byval img as any ptr _
) destroy
as function cdecl _
( _
byval img as any ptr, _
byref result as integer _
) as integer img_width
as function cdecl _
( _
byval img as any ptr, _
byref result as integer _
) as integer img_height
as function cdecl _
( _
byval img as any ptr, _
byref result as integer _
) as integer img_bpp
as function cdecl _
( _
byval img as any ptr, _
byref result as integer _
) as integer img_format
as function cdecl _
( _
byval img as any ptr, _
byref result as any ptr, _
byval row as integer _
) as integer img_row
as function cdecl _
( _
byref result as integer _
) as integer palette_format
end type
See png_gfxlib2.bas and png_opengl.bas
declare function png_cb_create cdecl alias "png_cb_create" _
( _
byref img as any ptr, _
byval w as integer, _
byval h as integer, _
byref bpp as integer, _
byval ct as integer, _
byval bd as integer _
) as integer
The img parameter is a pointer to an image, this function will either validate a pointer passed or on NULL create a valid pointer The w and h parameters are the width and height of the png The bpp parameter is the requested image bit depth, if it is non-zero then the image should be validated to be that bit depth or created with that bit depth. The ct and bd parameters are the png colortype and bit depth, these can be used if the bpp parameter is zero (0) and the img parameter is NULL to decide what bit depth and format to create the return image.
This function will return zero (0) and valid values for img and result on success or non zero on failure
declare sub png_cb_destroy cdecl alias "png_cb_destroy" _
( _
byval img as any ptr _
)
The img parameter is a pointer to a valid image to be free'd, if the image is valid then this function shall free the resources for the image
declare function png_cb_img_width cdecl alias "png_cb_img_width" _
( _
byval img as any ptr, _
byref result as integer _
) as integer
The img parameter is a pointer to a valid image The result parameter will return a valid width in pixels of the image
This function will return zero (0) and valid values for result on success or non zero on failure
declare function png_cb_img_height cdecl alias "png_cb_img_height" _
( _
byval img as any ptr, _
byref result as integer _
) as integer
The img parameter is a pointer to a valid image The result parameter will return a valid height in rows of the image
This function will return zero (0) and valid values for resulton success and or non zero on failure
declare function png_cb_img_bpp cdecl alias "png_cb_img_bpp" _
( _
byval img as any ptr, _
byref result as integer _
) as integer
The img parameter is a pointer to a valid image The result parameter will return the valid bit depth of the image, valid values are 8, 16 and 32
This function will return zero (0) and valid values for result on success or non zero on failure
declare function png_cb_img_format cdecl alias "png_cb_img_format" _
( _
byval img as any ptr, _
byref result as integer _
) as integer
The img parameter is a pointer to a valid image The result parameter will return the valid pixel format of the image, valid values are PALETTE_8, RGB_16, RGB_32, ARGB_32, ABGR_32
This function will return zero (0) and valid values for result on success or non zero on failure
declare function png_cb_img_row cdecl alias "png_cb_img_row" _
( _
byval img as any ptr, _
byref result as any ptr, _
byval row as integer _
) as integer
The img parameter is a pointer to a valid image The result parameter will return a valid pointer to the first pixel of the row in the image
This function will return zero (0) and valid values for result on success or non zero on failure
declare function png_cb_palette_format cdecl alias "png_cb_palette_format" _
( _
byref result as integer _
) as integer
The result parameter will return the valid palette format, valid values are RGB_16, RGB_32, ARGB_32, ABGR_32
This function will return zero (0) and valid values for result on success or non zero on failure
#define GFXLIB2_NEW_CB Type<png_cb>( @gfxlib2_cb_create_new, @gfxlib2_cb_destroy, @gfxlib2_cb_img_width, @gfxlib2_cb_img_height, @gfxlib2_cb_img_bpp, @gfxlib2_cb_img_format, @gfxlib2_cb_img_row, @gfxlib2_cb_palette_format )
This is a simple type definition for simple access to the internal gfxlib2 callbacks for the fbc 0.17 and newer image format. It is intended to be used with "version 2" load and store functions and used internally by the library.
#define GFXLIB2_OLD_CB Type<png_cb>( @gfxlib2_cb_create_old, @gfxlib2_cb_destroy, @gfxlib2_cb_img_width, @gfxlib2_cb_img_height, @gfxlib2_cb_img_bpp, @gfxlib2_cb_img_format, @gfxlib2_cb_img_row, @gfxlib2_cb_palette_format )
This is a simple type definition for simple access to the internal gfxlib2 callbacks for the fbc 0.16 and older image format. It is intended to be used with "version 2" load and store functions and used internally by the library.
#define OPENGL_CB Type<png_cb>( @opengl_cb_create , @opengl_cb_destroy , @opengl_cb_img_width , @opengl_cb_img_height , @opengl_cb_img_bpp , @opengl_cb_img_format , @opengl_cb_img_row , @opengl_cb_palette_format )
This is a simple type definition for simple access to the internal opengl callbacks It is intended to be used with "version 2" load and store functions and used internally by the library.
The opengl create function (and png_load[_mem]) creates a buffer with the following structure:
base_pointer = cptr( any ptr ptr, img )[ -1 ]
width = cptr( integer ptr, img )[ -2 ]
height = cptr( integer ptr, img )[ -3 ]
abgr_pixels = cptr( integer ptr, img )[ 0... ]
Technical credits:
victor for the FreeBASIC compiler, and the rest of the team for their work on it.
The creators of the PNG format, and the RFC that was very useful for me.
Willem van Schaik for the pngsuite of testing images.
The creators of zlib, for the compression, and decompression routines.
counting_pine, for one line of code that has since been eliminated, but was
very helpful at the time, and also for the base FB code I modified for the SSE
patch to fbpng. It's my modified version, so if anyone finds any bug in that part
don't hassle him about it. :P
DrV for the memory leak detector
Coderjeff and others for the Wiki manual
The makers of all the other tools I use, especially GDB, valgrind, gcc, fasm, make
cha0s, nkk and sir_mud for building the windows prebuilt version in some versions of fbpng
1000101 for default image format logic, and the work on 3.2.q
Dr_D for the OpenGL test program.
Other bug reporters.
General greetings:
All FreeBASIC users, especially those who are on the IRC channel and the forum, in
particular (but in no particular order)
mr_cha0s, stylin, {1000101}, voodooattack, {Nathan}, spaz, pritchard,
shadowwolf, insomninja, ijjekw, DJ Peters, relsoft, Dr_D, Mysoft, nkk,
mindless, hexdude
The source files for zlib are just taken directly from an official zlib distribution I haven't modified them in any way