/* This example use of imageio.library loads the image file specified
		on the command line and views it halved in size in a cybergraphics
		window. It demonstrates the use of a render callback hook.
*/

#include <stdio.h>

#include <dos/dos.h>
#include <exec/memory.h>
#include <exec/types.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/cybergraphics_protos.h>
#include <clib/intuition_protos.h>

#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/cybergraphics_pragmas.h>

#include <cybergraphics/cybergraphics.h>

#include <imageio/imageio.h>
#include <imageio/imageio_protos.h>
#include <imageio/imageio_pragmas.h>

/* Function prototypes */
__saveds __asm ULONG progressFunc( register __d0 ULONG curr, register __d1 ULONG lines, register __a0 void *userdata );
__saveds __asm ULONG renderFunc( register __a0 UBYTE *buffer, register __d0 ULONG scanline, register __d1 ULONG rowbytes, register __a1 void *userdata );
ULONG OpenCyberGfx( ULONG x, ULONG y );
void CloseCyberGfx( void );

extern struct Library *DOSBase;
struct Library *ImageIOBase, *IntuitionBase;
struct CyberGfxBase *CyberGfxBase;
struct Window *win;
ULONG x, y, bpp;
UBYTE cs;

void main( int argc, char **argv )
{
	if ( argv[1] != NULL )
	{
		ImageIOBase = OpenLibrary( "imageio.library", 2 );
		IntuitionBase = OpenLibrary( "intuition.library", NULL );
		if ( IntuitionBase && ImageIOBase )
		{
			struct ImageHandle *ih;
			ULONG err;
			BPTR fp;

			fp = Open( argv[1], MODE_OLDFILE );
			if ( fp != NULL )
			{
				err = AllocImage( &ih,
					IMG_SrcFile, fp,
					TAG_DONE );
				if ( !err )
				{
					ULONG num = 1, denom = 2;
					ULONG rs;
					UBYTE *buffer, it;

					err = GetImageAttrs( ih,
						IMG_ImageType, &it,
						TAG_DONE );
					if ( !err )
					{
						printf("Image type=%d\n",it);
					}

					err = GetImageAttrs( ih,
						IMG_Width, &x,
						IMG_Height,&y,
						IMG_BytesPerPixel, &bpp,
						IMG_ColourSpace, &cs,
						IMG_RowSize, &rs,
						IMG_TestScaleNum, num,
						IMG_TestScaleDenom, denom,
						TAG_DONE );
					if ( !err )
					{
						printf( "width=%ld, height=%ld\n", x, y );
						printf( "bytes per pixel=%ld, colourspace=%d\n", bpp, cs );
						printf( "row size=%ld\n", rs );

						if ( OpenCyberGfx( x, y ) )
						{
							err = ReadImage( ih,
								IMG_ScaleNum, num,
								IMG_ScaleDenom, denom,
								IMG_ImageBuffer, &buffer,
								IMG_ProgressHook, progressFunc,
								IMG_RenderHook, renderFunc,
								TAG_DONE );
							if ( !err )
							{
								struct Message *msg;

								Wait( 1L << win->UserPort->mp_SigBit );
								while ( ( msg = GetMsg( win->UserPort ) ) != NULL ) ReplyMsg( msg );

								/* Display image */
								CloseCyberGfx();
							}
							else printf( "read image error:%d\n", err );
						}
					}
					else printf( "get image attrs error:%d\n", err );

					FreeImage( ih );
				}
				else printf( "alloc image error:%d\n", err );

				Close( fp );
			}
			else printf( "cant open file\n" );
		}

		if ( ImageIOBase ) CloseLibrary( ImageIOBase );
		if ( IntuitionBase ) CloseLibrary ( IntuitionBase );
	}
	else printf( "no file specified\n" );
}

__saveds __asm ULONG progressFunc( register __d0 ULONG curr, register __d1 ULONG lines, register __a0 void *userdata )
{
	static int prevpercent = 0;

	int percent = ( curr * 100 ) / lines;

	if ( prevpercent != percent )
	{
		if ( percent % 10 == 0 ) printf( "%d%%\n", percent );
	}

	prevpercent = percent;

	return NULL;
}

__saveds __asm ULONG renderFunc( register __a0 UBYTE *buffer, register __d0 ULONG scanline, register __d1 ULONG rowbytes, register __a1 void *userdata )
{
	WritePixelArray( buffer, 0, 0, rowbytes, win->RPort, 0, scanline, x, 1, RECTFMT_RGB );

	return NULL;
}

ULONG OpenCyberGfx( ULONG x, ULONG y )
{
	ULONG ret = FALSE;

	CyberGfxBase = (struct CyberGfxBase *)OpenLibrary( "cybergraphics.library", 0L );
	if ( CyberGfxBase )
	{
		win = OpenWindowTags( NULL,
			WA_Title, "Proof",
			WA_Flags, WFLG_ACTIVATE | WFLG_SIMPLE_REFRESH |
				WFLG_SIZEGADGET | WFLG_RMBTRAP | WFLG_DRAGBAR |
				WFLG_DEPTHGADGET | WFLG_CLOSEGADGET,
			WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW |
				IDCMP_SIZEVERIFY | IDCMP_NEWSIZE | IDCMP_RAWKEY,
			WA_Left, 16,
			WA_Top, 16,
			WA_Width, x,
			WA_Height, y,
			TAG_DONE );

		if ( win != NULL )
		{
			ret = TRUE;
		}
		else printf( "failed to open window\n" );
	}
	else printf( "failed to open cybergfx.library\n" );

	return ret;
}

void CloseCyberGfx( void )
{
	if ( win ) CloseWindow( win );

	if ( CyberGfxBase ) CloseLibrary ( (struct Library *)CyberGfxBase );
}
