Undefined reference to `PNG_LoadFile@16'

General FreeBASIC programming questions.
lassar
Posts: 306
Joined: Jan 17, 2006 1:35

Re: Undefined reference to `PNG_LoadFile@16'

Post by lassar »

caseih wrote:
lassar wrote:The freebasic 1.05 compiler I am using is 32-bit.
So the result from this code is 4?

Code: Select all

dim as integer ptr g
print sizeof(g)
It would probably help if you posted a complete, self-contained, compile-able example that illustrated this apparent bug. And a link to where the .bi and .a files are.
Here's a link to PngLib


Showpng3.bas

Code: Select all

'
' This sample show work with PNGlib and FBGfx
' Bugs: Crash palette in palette's PNG images with more 128 colors...
'       Dont work with 16-colors PNG...
' True color PNG images worked no problem...
'
' for work need PNGlib of course...
' take it here: http://antarman.nm.ru/files/FreeBASIC/PNGLIB.zip
'
' p.s. It all some green, green BETA...
'
#lang "fblite"

#include once "pnglib2.bi"
#include once "fbgfx.bi"

'$Dynamic


 

DECLARE FUNCTION LoadPNG(byval filename$)
DECLARE SUB ShowPng(Figure$)
DECLARE SUB LoadDirPng()


' Demo main part:

screenres 640,480,32,,&H01
    PRINT "Press any key to see car"
    SLEEP
    ShowPNG "car.png"
    DO:LOOP UNTIL INKEY$ = ""
    DO:LOOP UNTIL INKEY$ <> ""
    LoadDirPng
    SLEEP
    END

Option Nogosub

Function LoadPNG(byval Filename$)
' function load PNG and return pointer to image in FBGfx format...
	dim png_image AS PNGINFO
	dim as ubyte ptr PngSource,palete,VideoPtr


	if PNG_Init(@png_image)=0 then return 0
	if PNG_LoadFile(@png_image, Filename$)=0 then return 0
	if PNG_Decode(@png_image)=0 then return 0

	palete=png_image.pPNGPalette
	PngSource=png_image.lpOutput
	PNG_OutputRaw(@png_image,PngSource,0)
    VideoPtr = SCREENPTR
' It may be made in one cycle, but it will be slowly...

    NumberOfDwords% = 640 * 480
	if Palete=0 then
        SCREENLOCK
		ASM
			MOV EBX,[NumberOfDwords%]
			MOV ESI,[PngSource]
		    MOV EDI,[VideoPtr]
		    MOV ECX,[NumberOfDwords%]
		DoItAgain:
            MOV EAX,0
            LODSB
            SHL EAX,8
            LODSB
            SHL EAX,8
            LODSB
            STOSD
        LOOP    DoItAgain
		END ASM
        SCREENUNLOCK
    else
        SCREENLOCK
		ASM
			MOV EBX,[NumberOfDwords%]
			MOV ESI,[PngSource]
		    MOV EDI, [VideoPtr]
		    MOV ECX,[NumberOfDwords%]
		DoItAgain2:
		    MOV EAX,0
		    LODSB
			MOV EBX,EAX
			ADD EAX,EBX
			ADD EAX,EBX
            PUSH ESI
            MOV ESI,[palete]
            ADD ESI, EAX
            MOV EAX,0
            LODSB
            SHL EAX,8
            LODSB
            SHL EAX,8
            LODSB
            STOSD
            POP ESI
		LOOP DoItAgain2
		END ASM
        SCREENUNLOCK
    end if

	PNG_Cleanup(@png_image)

    FUNCTION = sprite
end function

Option GoSub

SUB ShowPng(PngFile$)
    LoadPNG PngFile$
END SUB


SUB LoadDirPng()
    Fn$ = DIR$("DATA\*.PNG")
    WHILE Fn$ <> ""
        FilePath$ = CURDIR$ + "\DATA\" +  Fn$
        ShowPng FilePath$
        Fn$ = DIR$
    WEND
END SUB

pnglib2.bi

Code: Select all

'=============================================================================='
'                      +--\ |\  | +----   |    | +---\                         '
'                      |  | | \ | | __    |    | |___/                         '
'                      +--/ |  \| |   \   |    | |   \                         '
'                      |    |   | +---/   +--- ' +---/                         '
'=============================================================================='
' PNGLIB v1.0                                                                  '
'
' Include file for use with FreeBasic
'                                                                              '
'	PNGlib version 1.0
' Written by Thomas Bleeker. (C) 2002.                                         '
' Thomas@MadWizard.org                                                         '
' www.MadWizard.org                                                            '
'------------------------------------------------------------------------------'

' note: total size of PNGINFO structure has to be a multiple of 4 bytes
#ifndef __png_library__

#define __png_library__
#inclib "pnglib2"

type PNGINFO field=1
	iWidth		  as integer			' Width of image
	iHeight		  as integer			' Height of image
	dwLastError	  as integer			' Last error code (PNGLIB_ERR_*)
	nColors		  as integer			' Number of palette entries, if present
	PNGColorType  as byte				' Original PNG color type (PNG_CT_*)
	PNGBitDepth	  as byte  		    	' Original PNG bit depth (bits/sample)
	PNGInterlaced as byte				' Interlace method (PNG_IM_*)

	' The following structure members are used internally
	' by PNGlib. You should not rely in any way on these values,
	' nor assume they will be present in later versions.
	' They are included *only* to reserve space for them.

	lpPNGData	  as byte ptr			' pointer to data in PNG file
	lnPNGData	  as integer			' length of data pointed to by lpPNGData
	lpCurrent	  as byte ptr			' 'current pointer', used internally
	lpOutput	  as byte ptr			' pointer to decompressed (unfiltered) output data, used internally
	lnOutput	  as integer			' size of output data pointed to by lpOutput
	pPNGPalette   as byte ptr			' pointer to data in PLTE chunk
	dwLoadType	  as integer			' type of data currently loaded (PNGI_LT_*)
	pHeader		  as byte ptr			' pointer to raw IHDR chunk *data* (&chunk+8)
	pIDAT		  as byte ptr			' pointer to start of first IDAT chunk
	curState	  as integer			' PNGI_STATE_*
end type

'/******************************************************************************
'	Function declararations
' ******************************************************************************/

	declare function PNG_Init			stdcall alias "PNG_Init"			(byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_Cleanup		stdcall alias "PNG_Cleanup"		(byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_LoadFile		stdcall alias "PNG_LoadFile"		(byval pPNGInfo as PNGINFO ptr, byval lpFileName as string) as integer
	declare function PNG_LoadResource	stdcall alias "PNG_LoadResource"	(byval pPNGInfo as PNGINFO ptr, byval hInstance as integer, byval lpResName as string) as integer
	declare function PNG_LoadCustom	stdcall alias "PNG_LoadCustom"		(byval pPNGInfo as PNGINFO ptr, byval lpData as byte ptr, byval lnData as integer) as integer
	declare function PNG_Decode		stdcall alias "PNG_Decode"			(byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_GetPalette	stdcall alias "PNG_GetPalette"		(byval pPNGInfo as PNGINFO ptr, byval lpOutput as any ptr, byval dwFormat as integer) as integer
	declare function PNG_OutputRaw	stdcall alias "PNG_OutputRaw"		(byval pPNGInfo as PNGINFO ptr, byval lpDest as byte ptr, byval dwFormat as integer) as integer
	declare function PNG_CreateBitmap	stdcall alias "PNG_CreateBitmap"	(byval pPNGInfo as PNGINFO ptr, byval hWndCompatible as integer, byval dwFormat as integer, bDDB as integer) as integer

'/******************************************************************************
'	Copyproc types, used to build the PNG_OUTF_* values
' ******************************************************************************/

#define	PNGCP_X_X				0
#define	PNGCP_16_16				1
#define	PNGCP_16_16_BGR			2
#define	PNGCP_16_16_BGR_SA		3
#define	PNGCP_16_16_BGRA		4
#define	PNGCP_16_16_SA			5
#define	PNGCP_16_8				6
#define	PNGCP_16_8_BGR			7
#define	PNGCP_16_8_BGR_SA		8
#define	PNGCP_16_8_BGRA			9
#define	PNGCP_16_8_SA			10
#define	PNGCP_2_4				11
#define	PNGCP_8_8_BGR			12
#define	PNGCP_8_8_BGR_SA		13
#define	PNGCP_8_8_BGRA			14
#define	PNGCP_8_8_SA 			PNGCP_16_8

'/******************************************************************************
'	Output formats
' ******************************************************************************/

#define PNG_OUTF_G1_G1			&h00010100+PNGCP_X_X
#define PNG_OUTF_G2_G2			&h00020000+PNGCP_X_X
#define PNG_OUTF_G2_G4			&h00020100+PNGCP_2_4
#define PNG_OUTF_G4_G4			&h00040100+PNGCP_X_X
#define PNG_OUTF_G8_G8			&h00080100+PNGCP_X_X
#define PNG_OUTF_G16_G16		&h00100000+PNGCP_16_16
#define PNG_OUTF_G16_G8			&h00100100+PNGCP_16_8

#define PNG_OUTF_T8_T8_BGR		&h02080100+PNGCP_8_8_BGR
#define PNG_OUTF_T16_T16_BGR	&h02100000+PNGCP_16_16_BGR
#define PNG_OUTF_T16_T8_BGR		&h02100100+PNGCP_16_8_BGR

#define PNG_OUTF_P1_P1			&h03010100+PNGCP_X_X
#define PNG_OUTF_P2_P2			&h03020000+PNGCP_X_X
#define PNG_OUTF_P2_P4			&h03020100+PNGCP_2_4
#define PNG_OUTF_P4_P4			&h03040100+PNGCP_X_X
#define PNG_OUTF_P8_P8			&h03080100+PNGCP_X_X

#define PNG_OUTF_GA8_GA8		&h04080000+PNGCP_X_X
#define PNG_OUTF_GA8_G8			&h04080100+PNGCP_8_8_SA
#define PNG_OUTF_GA16_GA16		&h04100000+PNGCP_16_16
#define PNG_OUTF_GA16_G16		&h04100000+PNGCP_16_16_SA
#define PNG_OUTF_GA16_GA8		&h04100000+PNGCP_16_8
#define PNG_OUTF_GA16_G8		&h04100100+PNGCP_16_8_SA

#define PNG_OUTF_TA8_TA8_BGRA	&h06080100+PNGCP_8_8_BGRA
#define PNG_OUTF_TA8_T8_BGR		&h06080100+PNGCP_8_8_BGR_SA
#define PNG_OUTF_TA16_TA16_BGRA	&h06100000+PNGCP_16_16_BGRA
#define PNG_OUTF_TA16_T16_BGR	&h06100000+PNGCP_16_16_BGR_SA
#define PNG_OUTF_TA16_TA8_BGRA	&h06100100+PNGCP_16_8_BGRA
#define PNG_OUTF_TA16_T8_BGR	&h06100100+PNGCP_16_8_BGR_SA

#define PNG_OUTF_AUTO				-1

'/******************************************************************************
'	Error codes
' ******************************************************************************/
' Couldn't open file
#define PNGLIB_ERR_OPENFILE					&h1000
#define PNGLIB_ERR_MEMALLOC					&h1001  ' Couldn't allocate memory
#define PNGLIB_ERR_ALREADY_LOADED			&h1002  ' Other data has already been loaded
#define PNGLIB_ERR_INVALIDPNG				&h2000  ' Corrupt or invalid PNG
#define PNGLIB_ERR_UNSUPPORTED				&h2001  ' PNG format not supported
#define PNGLIB_ERR_INVALIDFORMAT			&h2002  ' User error (!): Invalid format specified
#define PNGLIB_ERR_WRONGSTATE				&h2003  ' User error (!): Function call at the wrong time

#DEFINE PNGLIB_ERR_NOERROR					0		'No error has occurred
                                                    ' (e.g. decoding before loading data)
#define PNGLIB_ERR_NOPALETTE				&h2004  ' Palette requested for a non-paletted image
#define PNGLIB_ERR_INVALIDPARAMETER 		&h2005  ' Invalid parameter used for function
#define PNGLIB_ERR_CREATEBITMAP				&h2006  ' Couldn't create bitmap
#define PNGLIB_ERR_FINDRESOURCE				&h3001  ' Couldn't find resource
#define PNGLIB_ERR_LOADRESOURCE				&h3002  ' Couldn't load resource


#DEFINE PNG_CT_GRAYSCALE					0
#DEFINE PNG_CT_RGB_TRIPLES					2
#DEFINE PNG_CT_PALETTE_INDEX				3
#DEFINE PNG_CT_GRAYSCALE_ALPHA				4
#DEFINE PNG_CT_RGB_ALPHA_QUADS				6

#DEFINE PNG_IM_NONE		 		    0
#DEFINE PNG_IM_ADAM7				1

#define PNG_PF_RGB			0   ' output: red byte, green byte, blue byte
#define PNG_PF_BGRX			1   ' output: blue byte, green byte, red byte, zero byte

#endif
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Bug in freebasic 1.05 compiler

Post by counting_pine »

lassar wrote:There is a bug in the freebasic compiler.

There are 9 declare functions in pblib2.bi

And yet the compiler only complains about one of them.

Code: Select all

declare function PNG_LoadFile		stdcall alias "PNG_LoadFile"		(byval pPNGInfo as PNGINFO ptr, byval lpFileName as string) as integer
The compiler says "undefined reference to `PNG_LoadFile@16' "
The 'undefined reference' error happens at link-time, not compile-time. There might be a linker parameter that shows additional undefined references. Note that the linker error only happens if you use a function, not just declare it.
Think about it. the @16 says it needs 4 dwords for the parameters.(16 bytes)

And yet when you look at this function, It only need 2 dwords.(8 bytes)

I put pnglib2.a in notepad++, it mentions "_PNG_LoadFile@8": 2 dwords

This is a bug in freebasic 1.05 !
To be honest, I don't really like how you're assuming this is a bug in FB. Anyway...

This might be due to the behaviour change of ''byval as string', which happened since v0.20.
'byval as string' used to pass a zstring ptr ('byval as zstring ptr'), and now it makes a coy of the string and passes that by value.
If it pushes the whole string descriptor (I'm not sure if it does), then that would be 12 bytes, taking you to 16 total.
If you replace 'byval as string' with 'byval as zstring ptr' or 'byref as zstring', that might fix the problem.

This change could also be made in the library source code, for consistent behaviour across versions.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Undefined reference to `PNG_LoadFile@16'

Post by jj2007 »

Code: Select all

declare function PNG_LoadFile      stdcall alias "PNG_LoadFile"      (byval pPNGInfo as PNGINFO ptr, byval lpFileName as string) as integer
That is a PNGINFO ptr passed by value, and the size of that is the size of one pointer. FreeBasic complains that it can't find the @16, for me that looks like a bug indeed. If you change that to byval pPNGInfo as any ptr, the code compiles but it won't run.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Undefined reference to `PNG_LoadFile@16'

Post by caseih »

Thanks for the complete example. This should help those familiar with the compiler's inner workings figure out what is going wrong.

I can confirm this appears to be a compiler bug in the gas emitter backend in fbc. -gen gcc does not appear to have this bug, although it cannot (with my installed version of gcc) parse your in-line assembly for whatever reason.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Undefined reference to `PNG_LoadFile@16'

Post by dodicat »

Try this section.
Got rid of fblite.
Is it car.png ??
I have used car.png anyway, you might want to change it.

Code: Select all

  

#ifndef __png_library__

#define __png_library__
#inclib "pnglib2"


type PNGINFO field=1
	iWidth		  as integer			' Width of image
	iHeight		  as integer			' Height of image
	dwLastError	  as integer			' Last error code (PNGLIB_ERR_*)
	nColors		  as integer			' Number of palette entries, if present
	PNGColorType  as byte				' Original PNG color type (PNG_CT_*)
	PNGBitDepth	  as byte  		    	' Original PNG bit depth (bits/sample)
	PNGInterlaced as byte				' Interlace method (PNG_IM_*)

	' The following structure members are used internally
	' by PNGlib. You should not rely in any way on these values,
	' nor assume they will be present in later versions.
	' They are included *only* to reserve space for them.

	lpPNGData	  as byte ptr			' pointer to data in PNG file
	lnPNGData	  as integer			' length of data pointed to by lpPNGData
	lpCurrent	  as byte ptr			' 'current pointer', used internally
	lpOutput	  as byte ptr			' pointer to decompressed (unfiltered) output data, used internally
	lnOutput	  as integer			' size of output data pointed to by lpOutput
	pPNGPalette   as byte ptr			' pointer to data in PLTE chunk
	dwLoadType	  as integer			' type of data currently loaded (PNGI_LT_*)
	pHeader		  as byte ptr			' pointer to raw IHDR chunk *data* (&chunk+8)
	pIDAT		  as byte ptr			' pointer to start of first IDAT chunk
	curState	  as integer			' PNGI_STATE_*
    dummy as byte
end type

'' ========    end of declarations  ========




'print sizeof(pnginfo)

'/******************************************************************************
'	Function declararations
' ******************************************************************************/

	declare function PNG_Init			  alias "PNG_Init"			( byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_Cleanup		  alias "PNG_Cleanup"		( byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_LoadFile		  alias "PNG_LoadFile"		( byval pPNGInfo as PNGINFO ptr, byval  lpFileName as zstring ptr) as integer
	declare function PNG_LoadResource	  alias "PNG_LoadResource"	( byval pPNGInfo as PNGINFO ptr, byval  hInstance as integer, byval  lpResName as zstring ptr) as integer
	declare function PNG_LoadCustom	  alias "PNG_LoadCustom"		( byval pPNGInfo as PNGINFO ptr, byval  lpData as byte ptr, byval  lnData as integer) as integer
	declare function PNG_Decode		  alias "PNG_Decode"			( byval pPNGInfo as PNGINFO ptr) as integer
	declare function PNG_GetPalette	  alias "PNG_GetPalette"		( byval pPNGInfo as PNGINFO ptr, byval  lpOutput as any ptr,byval   dwFormat as integer) as integer
	declare function PNG_OutputRaw	  alias "PNG_OutputRaw"		(byval  pPNGInfo as PNGINFO ptr, byval  lpDest as ubyte ptr, byval  dwFormat as integer) as integer
	declare function PNG_CreateBitmap	  alias "PNG_CreateBitmap"	( byval pPNGInfo as PNGINFO ptr, byval  hWndCompatible as integer, byval  dwFormat as integer,byval bDDB as integer) as integer

#endif



DECLARE sub LoadPNG(byval filename as zstring ptr)
DECLARE SUB ShowPng(Figure as zstring ptr)
DECLARE SUB LoadDirPng()


' Demo main part:

screenres 640,480,32',,&H01
    PRINT "Press any key to see car"
    SLEEP
    ShowPNG "car.png"
    DO:LOOP UNTIL INKEY  = ""
    DO:LOOP UNTIL INKEY  <> ""
    LoadDirPng
    SLEEP
    END



sub LoadPNG(byval Filename as zstring ptr)
	dim png_image AS PNGINFO
	dim as ubyte ptr palete,VideoPtr
dim as ubyte ptr PngSource

	print PNG_Init(@png_image)'=0 then return 0
	print PNG_LoadFile(@png_image, *Filename )'=0 then return 0
	print PNG_Decode(@png_image)'=0 then return 0

	palete=png_image.pPNGPalette
	PngSource=png_image.lpOutput'cast(ubyte ptr,png_image.lpOutput)


	print PNG_OutputRaw(@png_image,PngSource,0)
  
    VideoPtr = SCREENPTR
' It may be made in one cycle, but it will be slowly...

 var   NumberOfDwords = 640 * 480
	if Palete=0 then
        SCREENLOCK
		ASM
			MOV EBX,[NumberOfDwords]
			MOV ESI,[PngSource]
		    MOV EDI,[VideoPtr]
		    MOV ECX,[NumberOfDwords]
		DoItAgain:
            MOV EAX,0
            LODSB
            SHL EAX,8
            LODSB
            SHL EAX,8
            LODSB
            STOSD
        LOOP    DoItAgain
		END ASM
        SCREENUNLOCK
    else
        SCREENLOCK
		ASM
			MOV EBX,[NumberOfDwords]
			MOV ESI,[PngSource]
		    MOV EDI, [VideoPtr]
		    MOV ECX,[NumberOfDwords]
		DoItAgain2:
		    MOV EAX,0
		    LODSB
			MOV EBX,EAX
			ADD EAX,EBX
			ADD EAX,EBX
            PUSH ESI
            MOV ESI,[palete]
            ADD ESI, EAX
            MOV EAX,0
            LODSB
            SHL EAX,8
            LODSB
            SHL EAX,8
            LODSB
            STOSD
            POP ESI
		LOOP DoItAgain2
		END ASM
        SCREENUNLOCK
    end if

	PNG_Cleanup(@png_image)

end sub


SUB ShowPng(PngFile as zstring ptr)

    LoadPNG PngFile

END SUB


SUB LoadDirPng()
   var Fn  = DIR ("DATA\*.PNG")
    WHILE Fn  <> ""
     var   FilePath  = CURDIR  + "\DATA\" +  Fn 
        ShowPng FilePath 
        Fn  = DIR 
    WEND
END SUB


 
I have put together some stuff for a gdi library.
I shall pop it in mediafire later.
windows only of course.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Undefined reference to `PNG_LoadFile@16'

Post by jj2007 »

dodicat wrote:Is it car.png ??
No, the file is OK, it displays fine with another library. In case you got it running: Can you post the exe somewhere? I'd like to see how it works in the debugger. So far I have not seen a successful one, even your latest code passes Init and Load but then throws an exception. Frustrating.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: Undefined reference to `PNG_LoadFile@16'

Post by dkl »

As counting_pine said, since the library has _PNG_LoadLibrary@8, not @16, it's probably BYVAL AS STRING from old FB versions where it was broken and worked like BYREF AS ZSTRING. The declaration can be changed to BYREF AS ZSTRING or BYVAL AS ZSTRING PTR now and then new FB versions can use the old library.

Otherwise if you really want BYVAL AS STRING then the library must be recompiled with the latest FB version so the symbol name is fixed (unfortunately FB isn't backwards compatible here).

Good job finding the inconsistency between -gen gas and -gen gcc for this case; new ticket: https://sourceforge.net/p/fbc/bugs/890/
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Undefined reference to `PNG_LoadFile@16'

Post by dodicat »

jj2007 wrote:
dodicat wrote:Is it car.png ??
No, the file is OK, it displays fine with another library. In case you got it running: Can you post the exe somewhere? I'd like to see how it works in the debugger. So far I have not seen a successful one, even your latest code passes Init and Load but then throws an exception. Frustrating.
Remember that your car.png must be 640 by 480.

Anyway I get a poor png here with some local images.

i'll get the gdi code tidy and post via mediafire.
Now i take the dog for a walk.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Undefined reference to `PNG_LoadFile@16'

Post by caseih »

So if I interpret what was written here and in the bug report correctly, it's the GCC emitter that has the bug in it, correct? The GAS emitter is doing the right thing. The bug is not in FBC but in Lassar's declaration in the .bi file. I feel sheepish for not seeing that before. pnglib2 is a C-based library, so it's going to be using zstring ptrs, not FB strings.

Lassar, in the future please be careful about declaring you've found bugs in the compiler. One's own code is always the first suspect, even when it used to compile before. That's not to say the compiler doesn't have bugs in it (although it appears you've inadvertently uncovered a compiler bug, just not the one you thought it was).
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Undefined reference to `PNG_LoadFile@16'

Post by dodicat »

Here is gdi code plus library file.
Thanks to member UEZ for much of the gdi work.
Compiled here with -gen gas.
(The only sure way)
http://www.mediafire.com/file/88h09094u ... images.zip

Windows only.
Should handle 8 bit png/jpeg/bmp ... also.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Undefined reference to `PNG_LoadFile@16'

Post by jj2007 »

dodicat wrote:Remember that your car.png must be 640 by 480.
Oops, I had not realised that: Your code (and only your code) works with a 640x480 car.png, congrats!
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Undefined reference to `PNG_LoadFile@16'

Post by dodicat »

If anyone has tested the GDI library I linked above.
For #lang "fblite"
I had to include byval on all the parameters.
So, I suppose I should have used byval anyway for lang fb

Here are the declarations suitable for fb and fblite
(I also tweaked the sub truck to suit fblite

Code: Select all

 
#inclib "images"

#lang "fblite"
declare Function ImageSave( Filename as wString,byval Image As any Ptr,byval JPGQual as ULong = 80) as Boolean
declare Function ImageLoad(Filename as String,byref i as any ptr=0) as long
declare sub getsize(Filename as string,byref w as single,byref h as single) 
declare Function resize(byval im As Any Ptr,byval Wdth As Single,byval Hght As Single,byval dx As Long=0,byval dy As Long=0) As Any Ptr

'usage
'imageload/imagesave/getsize any of ---  bmp jpeg gif tiff tif png  -----
'resize -- resize a image from freebasic to wdth hght

'=======   demo =============

screen 20,32
color ,rgb(200,200,200)
cls


declare function truck(as any ptr=imagecreate(500,500)) as any ptr


dim as any ptr  image=(resize(truck,640,480))

print imagesave("truck.png",image)

dim as single w,h

getsize "truck.png",w,h

dim as any ptr newimage=imagecreate(w,h)

print imageload("truck.png",newimage)

put(20,20),newimage,trans

locate 35,10
print "Press a key"
sleep
imageLoad("Bob.jpg")                            'straight to the screen with a .jpg

imagedestroy image
imagedestroy newimage



function truck(im as any ptr) as any ptr
    #macro thickline(x1,y1,x2,y2,thickness,colour,i)
 h=Sqr((x2-x1)^2+(y2-y1)^2)
 s=(y1-y2)/h
 c=(x2-x1)/h
For yp =-thickness/2 To thickness/2 Step 1/(thickness)
    Line im,(x1+(s*yp),y1+(c*yp))-(x2+(s*yp),y2+(c*yp)),colour
Next yp
#endmacro
dim as double h,s,c,yp
circle im,(220,185),25,rgb(55,55,0),,,2,f
circle im,(220,150),15,rgb(100,65,0),,,.8,f
thickline(220,165,180,200,5,rgb(55,55,0),im)'a
thickline(50,260,450,260,6,rgb(50,50,150),im)
thickline(65,260,65,200,6,rgb(50,50,150),im)'up
thickline(65,200,165,190,6,rgb(50,50,150),im)'bon
thickline(165,190,250,190,6,rgb(50,50,150),im)'lwin
thickline(165,190,175,130,3,rgb(10,10,10),im)'fw
thickline(175,130,250,130,6,rgb(10,10,10),im)'rf
circle im,(200,115),15,rgb(255,155,0),,,.5,f

thickline(250,130,250,220,3,rgb(50,50,150),im)'bcab
thickline(250,220,420,220,8,rgb(50,50,150),im)'bbase
thickline(420,220,420,260,8,rgb(50,50,150),im)'aft
thickline(265,100,265,200,10,rgb(50,50,50),im)'upright
thickline(265,110,450,100,2,rgb(50,50,50),im)'wire
paint im,(300,240),rgb(50,50,150),rgb(50,50,150)
thickline(50,260,450,260,6,rgb(100,100,200),im)

circle im,(265,205),12,rgb(20,20,20),,,,f
thickline(265,205,450,100,10,rgb(0,0,0),im)
thickline(450,100,450,230,5,rgb(0,0,0),im)'hk
circle im,(450,210),20,1,2.9
thickline(50,260,70,260,12,rgb(220,220,220),im)'fb
thickline(430,260,450,260,12,rgb(210,210,210),im)'ab
circle im,(130,270),30,rgb(50,50,50),,,,f
circle im,(370,270),30,rgb(50,50,50),,,,f
circle im,(130,270),20,rgb(150,150,150),,,,f
circle im,(370,270),20,rgb(150,150,150),,,,f
return im
end function

sleep  
For fblite the static library must be used (compiled with fb)
fblite cannot
#Include "win/gdiplus.bi"

because of the constructors e.t.c. therein.
UEZ
Posts: 972
Joined: May 05, 2017 19:59
Location: Germany

Re: Undefined reference to `PNG_LoadFile@16'

Post by UEZ »

dodicat wrote:Here are .png file load/save using GDI.
Mainly coded by UEZ originally.
i cannot get it to work in 64 bits.
But the 32 bit compiler works OK.
If you have problems try pset on line 28
and
point on line 55
by uncommenting

Code: Select all

  

#if sizeof(integer)=8
#include "windows.bi"
''declare sub CLSIDFromString alias "CLSIDFromString"(as wstring,as _guid ptr) ''for 64 bits but doesn't work
#endif
#Include  "win/gdiplus.bi"

#include "file.bi"

Function ImageLoad(Picture as String,byref i as any ptr) as long
    #define putpixel(_x,_y,colour)    *cptr(ulong ptr,row+ (_y)*pitch+ (_x) shl 2)  =(colour)
    static as integer pitch
    static as any ptr row
     Imageinfo i,,,,pitch,row
   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)
   GDIPLUS.GdipBitmapLockBits(Img,Cast(Any Ptr,@R),GDIPLUS.ImageLockModeRead,PixelFormat32bppARGB,@Pdata)
   For y as long = 0 To h-1
      For x as long = 0 To w-1 
          ' pset i,(x,y),Cast(ulong Ptr,Pdata.Scan0)[y*w+x]
        putpixel(x,y,(Cast(ulong Ptr,Pdata.Scan0)[y*w+x]))
      Next
   Next
return w*h
End Function

Function ImageSave( Filename as WString,Image As any Ptr, JPGQual as ULong = 80) as Boolean
    #define _getpixel(_x,_y)           *Cptr(Ulong Ptr,pixdata + (_y)*pitch + (_x) Shl 2)
   Dim as Integer w, h, bypp, pitch
   Dim pixdata As Any Ptr
   If 0 <> ImageInfo(Image, w, h, bypp, pitch, pixdata) Then Return False
   
   Dim GDIPlusStartupInput As GDIPLUS.GDIPLUSSTARTUPINPUT 
   Dim As ULONG_PTR GDIPlusToken 
   GDIPlusStartupInput.GdiplusVersion = 1   
   If (GDIPLUS.GdiplusStartup(@GDIPlusToken, @GDIPlusStartupInput, NULL) <> 0) Then Return 0
   Dim as Uinteger  x, y, RowOffset
   Dim As Any Ptr hBitmap
   Dim As GDIPLUS.BitmapData tBitmapData
   Dim As Rect tRect = Type(0, 0, w - 1, h - 1)
   GDIPLUS.GdipCreateBitmapFromScan0(w, h, 0, PixelFormat32bppARGB, 0, @hBitmap)
   GDIPLUS.GdipBitmapLockBits(hBitmap, Cast(Any Ptr, @tRect), GDIPLUS.ImageLockModeWrite, PixelFormat32bppARGB, @tBitmapData)
   For y = 0 to h - 1
      RowOffset = y * w
      for x = 0 to w - 1
           Cast(Integer Ptr, tBitmapData.Scan0)[RowOffset + x] = &hFF000000 + _getpixel(x, y)
         'Cast(Integer Ptr, tBitmapData.Scan0)[RowOffset + x] = &hFF000000 + point(x, y, Image)
      Next      
   Next
   GDIPLUS.GdipBitmapUnlockBits(hBitmap, @tBitmapData)
   
   Dim as Byte iErr = 0

   Dim as UInteger count, size
   GDIPLUS.GdipGetImageEncodersSize(@count, @size)
   Dim As GDIPLUS.ImageCodecInfo Ptr pImageCodecInfo, Clsid
   pImageCodecInfo = Allocate(size)
   GDIPLUS.GdipGetImageEncoders(count, size, pImageCodecInfo)
   
   For i as ulong = 0 to count
      If *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/bmp" and Right(Filename, 4) = ".bmp" Then
         If (GDIPLUS.GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
      Elseif *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/jpeg" and (Right(Filename, 4) = ".jpg" or Right(Filename, 5) = ".jpeg") Then
         'If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1   
         JPGQual = IIf(JPGQual < 0, 0, IIf(JPGQual > 100, 100, JPGQual))
         Dim tParams As GDIPLUS.EncoderParameters
         Dim EncoderQuality As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"
         tParams.Count = 1
    CLSIDFromString(Wstr(EncoderQuality), @tParams.Parameter(0).GUID) 'ERROR on 64 bits
   
         With tParams.Parameter(0)
            .NumberOfValues = 1
            .Type = GDIPLUS.EncoderParameterValueTypeLong
            .Value = VarPtr(JPGQual)
         End With
         If GDIPLUS.GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, @tParams) <> 0 Then iErr += 1          
      ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/gif" and Right(Filename, 4) = ".gif" Then
        If (GDIPLUS.GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
      ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/tiff" and (Right(Filename, 4) = ".tif" or Right(Filename, 5) = ".tiff") Then
        If (GDIPLUS.GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
      ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/png" and Right(Filename, 4) = ".png" Then
        If (GDIPLUS.GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1     
      Elseif  *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/ico" and Right(Filename, 4) = ".ico" Then
         iErr += 1
      End if
   Next

   Deallocate(pImageCodecInfo)

   GDIPLUS.GdipDisposeImage(hBitmap)
   GDIPLUS.GdiplusShutdown(GDIPlusToken)
   If iErr > 0 Then Return False

   Return True
End function

sub getsize(picture as string,byref w as single,byref h as single) 'unused
    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


screen 20,32

dim as any ptr im=imagecreate(500,500,rgb(0,0,150))

for n as long=0 to 100
    circle im,(rnd*500,rnd*500),5+rnd*15,rgb(rnd*255,rnd*255,rnd*255),,,,f
next

imagesave("circles.png",im)
if fileexists("circles.png") then print "OK" else print "Failed to save .png file"
dim as single w,h

getsize("circles.png",w,h)
print "width","height"
print w,h

dim as any ptr im2=imagecreate(w,h)
ImageLoad("circles.png",im2)

put(100,100),im2
sleep
imagedestroy im
imagedestroy im2


  
To get it work also on x64 just change the line in function
For i as ulong = 0 to count to For i as ulong = 0 to count - 1

This works:

Code: Select all

Function _GDIPlus_ImageSaveToFile(hBitmap As any Ptr, Filename as WString, JPGQual as ULong = 85) as Boolean
	Dim as Single iW, iH
	Dim As Long iStatus
	iStatus = GdipGetImageDimension(hBitmap, @iW, @iH)
	If iStatus <> 0 Then Return 0
	
	Dim as Byte iErr = 0

	Dim as ulong count, size
	GdipGetImageEncodersSize(@count, @size)
   
   dim as CLSID clsid
	Dim As ImageCodecInfo Ptr pImageCodecInfo
	pImageCodecInfo = Allocate(size)
	GdipGetImageEncoders(count, size, pImageCodecInfo)

	For i as ulong = 0 to count - 1
		If *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/bmp" and Right(Filename, 4) = ".bmp" Then
			If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
		Elseif *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/jpeg" and (Right(Filename, 4) = ".jpg" or Right(Filename, 5) = ".jpeg") Then
			'If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1   
			JPGQual = IIf(JPGQual < 0, 0, IIf(JPGQual > 100, 100, JPGQual))
			Dim tParams As EncoderParameters
			Dim EncoderQuality As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"
			tParams.Count = 1
			CLSIDFromString(Wstr(EncoderQuality), @tParams.Parameter(0).GUID)
			With tParams.Parameter(0)
            .NumberOfValues = 1
            .Type = EncoderParameterValueTypeLong
            .Value = VarPtr(JPGQual)
			End With
			If GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, @tParams) <> 0 Then iErr += 1          
		ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/gif" and Right(Filename, 4) = ".gif" Then
			If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
		ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/tiff" and (Right(Filename, 4) = ".tif" or Right(Filename, 5) = ".tiff") Then
			If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1
		ElseIf *cast(wstring ptr, pImageCodecInfo[i].MimeType) = "image/png" and Right(Filename, 4) = ".png" Then
			If (GdipSaveImageToFile(hBitmap, WStr(Filename), @pImageCodecInfo[i].Clsid, NULL) <> 0) Then iErr += 1     
		Else
			iErr += 1
		End if
	Next

	Deallocate(pImageCodecInfo)

	If iErr > 0 Then Return False

	Return True
End Function
Post Reply