/*_ Magie library                                   _*/
/*_ Copyright (c) 2007, Ivan Bezdomniy              _*/
/*_ This program is free software. It may be distributed
 * and/or modified under the terms of the Lesser General
 * Public License. See the GNU Lesser General Public
 * License for more details */


#ifndef __OFFIMAGE_HEADER
#define __OFFIMAGE_HEADER

#include <stdint.h>


/*_ Some constants						*/
#define OFFI_ALIGN			0x04    /* Image line aligment size     */
#define	OFFI_STATEBYTES		0x80	/* State data size, in bytes	*/
#define _FSM_GAUSS_TM		0x04    /* Depth of terms in filter     */
#define _FSM_GAUSS_MAX		0xffff  /* Maximum allowed item value   */
/* Boundary imageo offset value			*/
#define	OFFI_BNDRY			_FSM_GAUSS_TM
/* Image unit size, allways 16bit uint	*/
#define	OFFI_USIZE			sizeof(uint16_t)

/*_ Opcodes								*/
#define	OFFI_GET			0x0001	/* Get value				*/
#define	OFFI_SET			0x0002	/* Set value				*/
#define	OFFI_BNDRY_EXT		0x0003	/* Extend boundaries		*/
#define	OFFI_BNDRY_SET		0x0004	/* Set boundaries to value	*/
#define	OFFI_MSK_OP			0x00ff	/* Opcode mask				*/
#define	OFFI_MOP(_o)		(_o&OFFI_MSK_OP)
/*_ Opflags								*/
#define	OFFI_COL_FULL		0x0100	/* Use full col instead p-l	*/
#define	OFFI_ROW_FULL		0x0200	/* Use full row instead p-l	*/
/*_ Some return values					_*/
#define	OFFI_R_OK			0
#define	OFFI_R_LACK_SUPP	-4	/* Lack of functionality*/
#define	OFFI_R_INVALID_S	-2	/* Invalid state object	*/
#define	OFFI_R_INVALID		-1	/* Other error			*/


/*_ Offline image buffer controls	_*/
typedef	struct	{
	int			sx;		/* x-size of an image	*/
	int			sy;		/* y-size of an image	*/
	int			sl;		/* Line size, in bytes	*/
	int			ch;		/* Channels				*/
	int			su;		/* Unit size, in bytes	*/
	void*		data;	/* Image buffer			*/
} OFFIMAGE;


/*_ Offline image pointertype (w/a for strict-aliasing	_*/
typedef union {
	void**		void_pp;
	uint16_t**	ui16_pp;
}OFFI_PP;


/*_ Interrupted execution control_*/
/* State holder types			*/
#define	OFFI_HNONE		0x00000000	/* State is free	*/
#define	OFFI_HBLUR		0x5fab4219	/* Blur call holder	*/

typedef struct {
	int			holder;			/* State holder type		*/
	/* Cycles state						*/
	int			cycles;			/* Cycles per interrupt		*/
	int			total;			/* Total cycles				*/
	int			unused;			/* Unused cycles			*/
	/* These values are free in usage	*/
	int			stage;			/* Custom execution stage	*/
	int			step;			/* Custom execution step	*/
	/* Control flags					*/
	struct {
		int	is_stored		:1;	/* Execution state stored	*/
		int	is_finished		:1;	/* Execution finished		*/
		int	is_released		:1;	/* State is released		*/
		int	is_terminate	:1;	/* Release resources & exit	*/
	};
	/* State storage				*/
	char		state[OFFI_STATEBYTES];
} OFFISTATE;


/*_ State object operation macro	_*/
#define	OFFI_STATE_RESET(_o, _c) {	\
	(_o)->holder = OFFI_HNONE;	\
	(_o)->cycles 		= _c;	\
	(_o)->is_stored		= 0;	\
	(_o)->is_finished	= 0;	\
	(_o)->is_released	= 0;	\
	(_o)->is_terminate	= 0; }

#define	OFFI_STATE_TERM(_o)		(_o)->is_terminate = 1
#define	OFFI_STATE_IS_FIN(_o)	(_o)->is_finished

#define	OFFI_STATE_IS_FINOK(_o) \
	((_o)->is_finished  && (_o)->is_released )

/*_ Some useful macro				_*/
#define	OFFI_NULL(_i)		{(_i)->data = NULL; }
#define	OFFI_ISNULL(_i)		((_i)->data == NULL)
#define	OFFI_LEN_ROW(_i)	((_i)->sx - 2*OFFI_BNDRY)
#define	OFFI_LEN_COL(_i)	((_i)->sy - 2*OFFI_BNDRY)
/*_ Pixels access 					_*/
#define	OFFI_PX(_i, _x, _y)	((_i)->data + (OFFI_BNDRY+(_y))*(_i)->sl + \
							 (OFFI_BNDRY + (_x))*(_i)->su)
/* Full rows acces, with boundaries	*/
#define	OFFI_FROW(_i, _y)	OFFI_PX(_i, -OFFI_BNDRY, _y)
#define	OFFI_FROW_SIZE(_i)	(((_i)->sx )*(_i)->su)
/* Payload only row access			*/
#define	OFFI_PROW(_i, _y)	OFFI_PX(_i, 0, _y)
#define	OFFI_PROW_SIZE(_i)	(((_i)->sx - 2*OFFI_BNDRY)*(_i)->su)



/*_ Offline image calls		_*/
/* Object maintance 		*/
int			offimage_init	(OFFIMAGE*, int, int, int);
void		offimage_free	(OFFIMAGE*);
/* Pixels transfer fumctions*/
void    	offimage_col	(OFFIMAGE*, void*, int, int);
void		offimage_row_p	(OFFIMAGE*, OFFI_PP, int, int);
/* Image manipulation stuff	*/
int			offimage_extent	(OFFIMAGE*, int, int);
int			offimage_blur	(OFFIMAGE*, int, int, OFFISTATE*);

void		offimage_print	(OFFIMAGE*);

#endif/*__OFFIMAGE_HEADER */




#ifdef	__OFFIMAGE_INTERNAL
/*_ Subsystems control objects	_*/


/* Gaussian FSM params			*/
struct  FSM_Gauss {
	/* FSM  Constants		 */
	double      M0;			 /* "Mean" response      */
	double      SY;			 /* Boundary Y-summ      */
	double      X1, X2, X3, X4;
	double      Y1, Y2, Y3, Y4;
	 /* State buffer		 */
	double*     SL;			 /* State for L-conveyer */
	double*     SR;			 /* State for R-conveyer */
};


/*_ State objects				_*/
struct State_Blur {
	struct FSM_Gauss	fsm;	/* FSM state object		*/
	void*				vert;	/* Vertical line buffer	*/
};


#define	OFFI_SIZE_STBLUR	sizeof(struct State_Blur)

/*_ Macro calls					_*/
#define	NULL_FREE(_p) \
	if (_p != NULL) { free(_p); _p = NULL; }

#define	SET_STAGE(_s, _p) \
	if (sco) {							\
		sco->stage = _s; 				\
		if (_p != -1) sco->step = _p; }

#define	SET_STEP_J(_c, _p) \
	if (sco && (_c)) {  sco->step = _p; goto L_STAGE_FF; }

	

/*_ Misc proccessing tools   	_*/
void	fsm_gauss_set	(struct FSM_Gauss*, double);
void	fsm_gauss_line	(struct FSM_Gauss*, void*, int, int);


#endif/*__OFFIMAGE_INTERNAL*/



