// This tutorial is part of a series that explains the basic concepts of the APRON simulation system.
// Please ensure you have read and understood any previous tutorial examples.
//
// © David R W Barr 2009
//
// Name: 		FILE INPUT AND OUTPUT
// Description:	This tutorial details how to import external data into a simulation
//				and how to export simulation data to disk.
// Usage:		Please STEP-THROUGH this algorithm in the simulator.


// Always include this line for an APRON simulation. This file includes many pre-defined
// types and functions that are used in a standard APRON simulation.
!include('apron.aps')



// Notice for this tutorial we are using different sized registers
!create_reg('128x128', 128, 128) 
!create_reg('64x64', 64, 64) 

// Firstly, lets automatically show and position the registers. These commands send
// signals to the simulator which mirror those as if the user had clicked on various
// simulation items
showreg(r[128x128]) 
showreg(r[64x64])
tile


// Often it is necessary to work on real data. It is also inconvenient to manually
// construct data for use as input to algorithms. APRON provides facilities that
// allow you to import and export data in various formats.

// The most convenient form of Data I/O in APRON is to use images.

// The input statement imports data into an APRON register

// The arguments are as follows:
// IO_IMAGE - we are using an image as the file data type
// File path (without file extension)
// UNUSED - We do not wish to append a number to the filename (see later)
// File extension - for image supports 'bmp', 'gif', 'png', 'jpg'

// So this command will load in a sample image called 'testcard.png'
r[128x128] = input(IO_IMAGE, 'tut_resources\testcard', UNUSED, 'png')

// SCALES and RANGES
// ~~~~~~~~~~~~~~~~~
//
// APRON registers have single precison (32-bit) floating point elements. This gives
// a huge range. However, Image data, and pictorial representations of register contents are
// limited to the range 0 - 255. There are some quirky conventions that APRON uses by default:
// When viewing a register the drawing range is -100 (red) through 0 (black) to +100 (green)
// Values outside the range are saturated and clamped to the range extremities, although the
// element data is not changed.

// When loading data from an image, the range is 0 - 255, and this is mapped onto an APRON
// register by subtracting 128 from it, i.e. -128 -> 0 -> 127. Therefore black in an image (0)
// will actually be (-128) in APRON

// The user is free to transform the data as they see fit. Suppose we wish to scale an image to 
// the range 0 - 100 in APRON
r[128x128] = r[128x128] / 2.56
r[128x128] = r[128x128] + 50


// Lets see what happens if we attempt to open an image that is not the same size as a register
r[64x64] = input(IO_IMAGE, 'tut_resources\testcard', UNUSED, 'png')

// As you can see, only the top part of the image has been loaded. We can specify that APRON
// scales the image, using a bi-linear filtering algorithm, by using the IO_IMAGE_S parameter
r[64x64] = input(IO_IMAGE_S, 'tut_resources\testcard', UNUSED, 'png')	

// Notice that the scaling has introduced artefacts into the data


// To output data, a similar command is used. Beware that for images, the data must be 
// in the rannge -128 -> 127 or distortion will occur
output(r[128x128], IO_IMAGE, 'tut_resources\test_output', UNUSED, 'bmp')

// A 128x128 bitmap file called test_output.bmp has just been created - check it!
// Notice how the black has turned to mid-level grey. If you were to load this image again
// it would be scaled automatically to look like the register you just exported.
r[128x128] = input(IO_IMAGE, 'tut_resources\test_output', UNUSED, 'png')


// IMAGE DATA
// ~~~~~~~~~~
//
// Images are stored using discrete integer values. Therefore any fine precision is lost. 
// Image processing applications can usually tolerate this, but other applications may not.
// APRON provides two other methods for reading and storing data.

// BINARY DATA
// ~~~~~~~~~~~
//
// Using the the argument IO_DATA will export and import binary chuncks of floating point
// data. which are easily manipulated by other applications. WARNING!! Dimension information
// is not stored in the binary information. Thus, you must know in advance what the dimensions
// should be when you load data this way, or else simulation errors will occur.

// CSV DATA
// ~~~~~~~~
//
// Using the argument IO_CSV will export and import floating point numbers stored in comma 
// seperated variable format. Again, no dimension information is stored in this data.
// CSV is a very useful format as it can be imported and exported directly from applicatoins
// such as MATLAB or MS Excel.



// Here we issue a breakpoint. This will halt the simulation so they can see the
// distinction between the two halves of this tutorial if they clicked run...
breakpoint


// FILE COUNTING
// ~~~~~~~~~~~~~
//
// APRON is fast enough to process video streams. A video stream can be defined as 
// a sequence of images. If lots of images are to be used, loading them by hand can be 
// time consuming. APRON provides an automatic numbering system for loading images in
// a sequence

sample = 0
#loop

	// Load the sample image, using the variable 'sample' appended to the filename
	r[128x128] = input(IO_IMAGE, 'tut_resources\sample_', sample, 'bmp')
	
	


	// Cause the simulator to redraw the register. During a 'run' this needs
	// to be explicitly called, unlike 'step' where it is automatically
	// called after each instruction. Redrawing a register imposes a significant
	// overhead and should be used sparingly
	simshow(r[128x128])

	sample = sample + 1
	// There are 236 sample files
	jumpif(sample, <, 236,  #loop)

	// Repeat indefinitely
	sample = 0
	jump(#loop)


end