// In questa versione si aggiunge la funzione che inserisce il marker RED

// Per ora si suppone che venga aggiunto un solo RED, nel main header, e che sia
// utilizzata la modalità byte-range mode. Osserviamo che ci sono problemi realizzativi
// per l'utilizzo delle modalità a pacchetto (non ci sono pacchetti negli header!).
// Decidiamo di aggiungere il marker RED subito prima di SOT (alla fine di MH!!!).
// Per stare sicuri, come address length utilizziamo 4 bytes (b1=1).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <math.h>
#include "j2k.h"
#include "cio.h"
#include "jpw.h"

#define J2K_MS_SOC 0xff4f
#define J2K_MS_SIZ 0xff51
#define J2K_MS_SOT 0xff90
#define JPWL_MS_EPC 0xff68
#define JPWL_MS_EPB 0xff66
#define JPWL_MS_RED 0xff69
#define J2K_MS_EOC 0xffd9

#define J2K_STATE_MHSOC 0x0001
#define J2K_STATE_TPHSOT 0x0008
#define J2K_STATE_MH 0x0004
#define J2K_STATE_TPH 0x0010
#define J2K_STATE_MT 0x0020

#define mm  8           /* RS code over GF(2**4) - change to suit */

int pp [mm+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };

int *alpha_to, *index_of, *gg;
int *recd, *data, *bb;


static long crcSum;

static int CrcT16[256] =
{0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};

static long CrcT32[256] = {0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};

typedef struct {
	unsigned int id;
	unsigned int lid;
	unsigned char *pid;
} id_tecn;

typedef struct {
	unsigned int lepc;
	unsigned int pcrc;
	unsigned long cl;
	unsigned char pepc;
	id_tecn *tecn;   // array di strutture di tipo id_tecn!!!
} EPC_par;

typedef struct {
	unsigned int lepb;
	unsigned char depb;
	unsigned long ldpepb;
	unsigned long pepb;
	unsigned int ldata;
} EPB_par;
typedef struct	//***********Questa struttura non dovrebbe servire effettivamente!!!!
{
	unsigned int lesd;
	unsigned char cesd1;
	unsigned int cesd2;
	unsigned char pesd;
} ESD_MS;
typedef struct
{
	unsigned int lred;
	unsigned char pred;
	unsigned char *reddata;
} RED;


EPC_par epc;
ESD_MS *esd;
RED red;
int lmex, nbckpar, epbpm, next, startsot;
unsigned long psot;

unsigned char *cssrc;// Queste variabili servono per la gestione della codestream.
unsigned int cslen;  // Se voglio utilizzare le funzioni "cio" per gestire un buffer,
int cspos;			 // queste variabili consentono di reinizializzare cio per la CS!!
unsigned int csread; // Lunghezza della codestream letta...serve per uscire in caso di errori

int redpos; // Per la gestione del passaggio delle funzioni "cio" al e dal buffer RED
int decodeflag; // Vale 1 se RS è stato decodificato, 0 altrimenti
unsigned long redlen; // Lunghezza del buffer che contiene REDdata
int redmode; // Se vale 0 allora RED in MH, se vale 1 allora RED in MH e nei vari TPH
int redlenok; // Lunghezza del campo dati della RED che non necessita aggiornamento offset
int nepbrd; // Tiene conto del numero di EPB letti
int lastepb; // Se vale 1 l'EPB corrente è l'ultimo dell'header in questione!


// La funzione seguente cerca la presenza nella codestream del marker EPC
// in modo da determinare se si tratta di una codestream JPWL
// Ritorna il numero di EPC presenti nella codestream
int decode_JPWL(unsigned char *src, int len)
{
	unsigned int temp, nepb, j2k_state, pos, nepc, posi, mem, rest;
	//int flag; // se 0 vuol dire che ha trovato EPC dopo SIZ, se 1 dopo EPB
	int err; // se 1 vuol dire che EPC è corretto, se 0 vuol dire che contiene
	         // ancora errori!
	unsigned long psot, i;
	FILE *f,*g;


	cssrc = src;  //*********Aggiunta in questa versione 1.7
	cslen = len;  //*********Aggiunta in questa versione 1.7
	redpos = 0;   //*********Aggiunta in questa versione 1.7
	redlen = 0;   //*********Aggiunta in questa versione 1.7
	redlenok = 0;
	redmode = 0;  //*********Aggiunta in questa versione 1.7
				  // Per default si assume che la RED è scritta solo in MH!!!	

	csread = 0;	

	f = fopen("output.j2c","wb");
	if (f==NULL)
		printf("Unable to open file!\n");
	cio_seek(0);
	//printf("CL: %d\n",epc.cl);
	for (i=0; i<len; i++)
		fputc(cio_read(1),f);
	fclose(f);
	cio_seek(0);

	temp = cio_read(2);
    /*if (temp != J2K_MS_SOC)
	{
			printf("Expected marker SOT\n");
			return 0;
	}*/
	//csread+=2;

	//temp = cio_read(2);  // qui dovrebbe leggere SIZ
	//if (temp >> 8 != 0xff) {
	//	fprintf(stderr, "%.8x: expected a marker instead of %x\n",
	//        cio_tell() - 2, temp);
	//	return 0;
	//}
	//temp = cio_read(2); // qui dovrebbe leggere la lunghezza di SIZ: Lsiz
	//cio_skip(temp-2);

	
	j2k_state = 0; // inizializza j2k_state ad un valore indefinito
	nepc = 0; // inizializza a zero il numero di EPC finora trovati
	nepbrd = 0;
	lastepb = 0;


	//while ((j2k_state != J2K_STATE_MT)&&(csread < cslen))
	while (j2k_state != J2K_STATE_MT)
	{
		
		//nepc = find_EPC(nepc,&j2k_state);
		temp = cio_read(2);  // qui dovrebbe leggere SIZ o SOT
		/*if (temp >> 8 != 0xff) {
			fprintf(stderr, "%.8x: expected a marker instead of %x\n",
			    cio_tell() - 2, temp);
			return nepc;
		}*/
		//csread+=2;

		posi = cio_tell();  // memorizza la posizione a monte della lunghezza di SIZ o SOT
		
		//ncomp = 3;  // di default si assume che l'immagine abbia 3 componenti!!!
		if (temp == J2K_MS_SIZ) // Ha letto SIZ!!!
		{
			temp = cio_read(2); // legge Lsiz
			//csread+=2;
			//ncomp = (temp - 38)/3;  // calcola il numero di componenti dell'immagine
			// nbckpar serve per modificare il numero di blocchi di decodifica per la prima 
			// parte del primo EPB in base al numero di componenti utilizzate!!!
			lmex = temp + 17;  // lunghezza dei dati da proteggere;
			nbckpar = (int)ceil((double)lmex / 96); // 96 è nn-kk per il primo EPB
									// temp=Lsiz, 17 tiene conto di EPB,SIZ,SOC
			
		}
		else  // sta leggendo SOT oppure sta leggendo SIZ ma ci sono errori nel marker SIZ!!!
		{     // ...in tal caso il decoder assume che l'immagine sia composta da 3 componenti
			nbckpar = 1;
			temp = cio_read(2); // qui dovrebbe leggere la lunghezza di SIZ o SOT
		}
		cio_skip(temp-2);
		//csread += (temp - 2);
		


		temp = cio_read(2);  // qui dovrebbe leggere EPC o EPB, se ci sono
		//if (temp >> 8 != 0xff) {
		//	fprintf(stderr, "%.8x: expected a marker instead of %x\n",
		//		cio_tell() - 2, temp);
		//	return nepc;
		//}
		//csread += 2;
		if (temp != JPWL_MS_EPC)
		{
			temp = cio_read(2); // qui dovrebbe leggere la lunghezza di EPB, se c'è: Lepb
			cio_skip(temp-2);
			temp = cio_read(2); // qui dovrebbe leggere EPC, se c'è!!
			//if (temp >> 8 != 0xff) {
			//fprintf(stderr, "%.8x: expected a marker instead of %x\n",
			//	cio_tell() - 2, temp);
			//return nepc;
			//}
			//csread += temp + 2;

			pos = cio_tell();

			if ((temp != JPWL_MS_EPC)&&(nepc == 0))
			{
				cio_seek(0);
				/*return nepc; */ // non ha trovato EPC => vede la codestream come NON JPWL
				_exit(-1);
			}
			
			if ((temp != JPWL_MS_EPC)&&(nepc != 0))  //vuol dire che il TPH in questione non ha EPC
			{
				cio_seek(posi); // siamo a monte della lunghezza di SOT
				cio_skip(4);
				psot = cio_read(4);
				if (psot == 0)  // vuol dire che siamo nell'ultimo TPH
					j2k_state = J2K_STATE_MT;  // cosi' al passo seguente si esce dal ciclo
				cio_seek(posi-2);
				cio_skip(psot); // si pone a valle dei dati del tile corrente
				if (cio_read(2) == J2K_MS_EOC)
					j2k_state = J2K_STATE_MT;
				cio_skip(-2); // si pone a valle dei dati del tile corrente
				//csread += (psot - pos);
				//return nepc;

			}
			if (temp == JPWL_MS_EPC) // ha trovato l'EPC non subito dopo SIZ, quindi c'è EPB!
			{
				if (nepc == 0)
				{
					j2k_state = J2K_STATE_MHSOC;
					cio_seek(posi-4);   // si posiziona a monte di SOC
					next = cio_tell();  // assegna a next = 0!!!!
				}
				if (nepc != 0)
				{
					j2k_state = J2K_STATE_TPHSOT;
					cio_seek(posi-2); // si posiziona a monte di SOT
					next = cio_tell();
				}
				//printf("next: %x\n",next);
				red.reddata = (char *) malloc(len * sizeof(char));// Allochiamo lo spazio necessario per RED
																// Scegliamo len per "stare larghi"
				
				// ********Cio' che segue è un'aggiunta in jpwldec1.9!!!!**********
				mem = next;
				i = 0;
				if (!(rest = read_EPB_2(&j2k_state)))// legge il primo EPB(della CS o del tile,caso + EPC!)
					return nepc;
				i += rest;
				temp = cio_tell(); // Memorizza posizione a valle di EPB
				cio_seek(pos); // si posiziona a valle del marker EPC
				err = read_EPC();  // Legge il primo EPC, o comunque il primo EPC di un tile
				//if (err == 1)
				//	printf("CRC EPC corretto!\n");
				//else
				//	printf("CRC EPC errato!\n");
				nepc++;				// nel caso di più EPC usati nella codestream
				nepb = epc.tecn[0].lid / 4;  // calcola il numero di EPB presenti
				//printf("nepb: %d\n",nepb);
				/***********************************************************************
					Qui dovrà essere aggiunta la porzione di codice per la gestione
					della scrittura della RED anche nei tile!
				*************************************************************************/
				
				//while ((i<nepb)&&(csread < cslen))
				while (i<nepb)
				{	
					if ((j2k_state == J2K_STATE_MH)&&(lastepb == 0))
					{	
						cio_seek(temp);
						do
						{
							if (!(rest = read_EPB_2(&j2k_state)))
								return nepc;
							i += rest;
						}
						while (lastepb == 0);
						//while ((lastepb == 0)&&(csread < cslen));
					}
					if ((j2k_state == J2K_STATE_MH)&&(lastepb == 1))
					{
						temp = cio_read(2);
						//if (temp >> 8 != 0xff) {
						//	fprintf(stderr, "%.8x: expected a marker instead of %x\n",
						//		cio_tell() - 2, temp);
						//	return nepc;
						//}

						//while ((temp != J2K_MS_SOT)&&(csread < cslen))
						while (temp != J2K_MS_SOT)
						{
							cio_skip(cio_read(2)-2);
							temp = cio_read(2);
							//if (temp >> 8 != 0xff) {
							//fprintf(stderr, "%.8x: expected a marker instead of %x\n",
							//	cio_tell() - 2, temp);
							//return nepc;
							//}
							//csread += 2;
						}
						cio_skip(-2);
					}
					j2k_state = J2K_STATE_TPHSOT;
					if (j2k_state == J2K_STATE_TPHSOT)
					{	
						cio_seek(temp); // Si posiziona all'inizio di SOT
						pos = cio_tell();
						//printf("pos: %x\n",pos);
						//system("pause");
						do
						{
							if (!(rest = read_EPB_2(&j2k_state)))
								return nepc;
							i += rest;
							//printf("state: %x\n",j2k_state);
						}
						while (lastepb == 0);
						//printf("ciao!\n");
						//while ((lastepb == 0)&&(csread < cslen));
						//printf("state: %x\n",j2k_state);
						//system("pause");
					}
					temp = cio_read(2);
					//printf("mrk: %x\n",temp);
					//system("pause");
					//if (temp >> 8 != 0xff) {
					//fprintf(stderr, "%.8x: expected a marker instead of %x\n",
					//	cio_tell() - 2, temp);
					//return nepc;
					//}
					//csread += 2;
					if (temp != J2K_MS_EOC)
					{
						if ((j2k_state == J2K_STATE_TPH)||(temp != J2K_MS_SOT))
						{
							cio_seek(pos);
							cio_skip(6);
							psot = cio_read(4);
							cio_seek(pos);
							cio_skip(psot);
							temp = cio_read(2);
							if (temp == J2K_MS_EOC)
								j2k_state = J2K_STATE_MT;
							else
							{
								j2k_state = J2K_STATE_TPHSOT;
								cio_skip(-2);
								temp = cio_tell();
							}
							
						}
						if (temp == J2K_MS_SOT)
						{
							cio_skip(-2);
							temp = cio_tell();
							j2k_state = J2K_STATE_TPHSOT;
						}
					}
				}
				// Ora sono stati letti tutti gli EPB associati all'ultimo EPC letto
				//printf("temp: %x\n",temp);

				//while ((temp != J2K_MS_EOC)&&(csread < cslen))
				//while (temp != J2K_MS_EOC)
				//{
				//	cio_seek(pos);
				//	cio_skip(6);
				//	psot = cio_read(4);
				//	cio_seek(pos);
				//	cio_skip(psot);
				//	temp = cio_read(2);
				//	//if (temp >> 8 != 0xff) {
				//	//fprintf(stderr, "%.8x: expected a marker instead of %x\n",
				//	//	cio_tell() - 2, temp);
				//	//return nepc;
				//	//}
				//	//csread += 2;
				//}
				//cio_skip(-2); // A questo punto siamo all'inizio di EOC
				//j2k_state = J2K_STATE_MT;
				
			}
		}
		else // ho trovato EPC dopo SIZ o SOT
		{
			err = read_EPC();
			//if (err == 1)
			//		printf("CRC EPC corretto!\n");
			//else
			//		printf("CRC EPC errato!\n");
			if (nepc == 0)
			{
				cio_seek(posi); // siamo a monte della lunghezza di SIZ
				cio_skip(cio_read(2)-2);  // si pone a valle di SIZ
				temp = cio_read(2); // legge il marker successivo
				//if (temp >> 8 != 0xff) {
				//	fprintf(stderr, "%.8x: expected a marker instead of %x\n",
				//		cio_tell() - 2, temp);
				//	return nepc;
				//}

				//while ((temp != J2K_MS_SOT)&&(csread < cslen))
				while (temp != J2K_MS_SOT)
				{
					cio_skip(cio_read(2)-2); // si pone a valle del MS corrente
					temp = cio_read(2);  // legge il marker successivo
					//if (temp >> 8 != 0xff) {
					//fprintf(stderr, "%.8x: expected a marker instead of %x\n",
					//	cio_tell() - 2, temp);
					//return nepc;
					//}
					//csread += 2;
					//printf("MS: %x\n",temp);
				}
				cio_skip(-2); // si posiziona a valle del main header
			}
			if (nepc != 0)
			{
				cio_seek(posi); // siamo a monte della lunghezza di SOT
				cio_skip(4);
				psot = cio_read(4);
				if (psot == 0)  // vuol dire che siamo nell'ultimo TPH
					j2k_state = J2K_STATE_MT;  // cosi' al passo seguente si esce dal cilclo
				cio_seek(posi-2);
				cio_skip(psot); // si pone a valle dei dati del tile corrente
				temp = cio_read(2);
				if (temp == J2K_MS_EOC)
				{
					j2k_state = J2K_STATE_MT;
				}
				 cio_skip(-2); // si pone a valle dei dati del tile corrente
			}
			//j2k_state = J2K_STATE_MT;
			nepc++;
		}
	} // fine while (j2k_state != J2K_STATE_MT)!!

	//printf("Eccomi!\n");
	//f = fopen("output","wb");
	//if (f==NULL)
	//	printf("Unable to open file!\n");
    //cio_seek(0);
	//printf("CL: %d\n",epc.cl);
	//for (i=0; i<epc.cl; i++)
	//	fputc(cio_read(1),f);
	//fclose(f);

	cio_seek(0);
	//printf("redlen: %d\n",redlen);
	if ((redlen != 0)&&(redmode==0))
		{
			red.lred = redlen + 3; // Tiene conto del campo Lred e del campo Pred
			red.pred = 0x43; // Pred = 01000011 , per i motivi specificati all'inizio!
			// Dobbiamo posizionarci alla fine del MH
			temp = cio_read(2); // Legge SOC
			
			//while ((temp != J2K_MS_SOT)&&(csread < cslen))
			while (temp != J2K_MS_SOT)
			{
				cio_skip(2);
				cio_skip(cio_read(2)-2);
				temp = cio_read(2);
				//if (temp >> 8 != 0xff) {
				//	fprintf(stderr, "%.8x: expected a marker instead of %x\n",
				//		cio_tell() - 2, temp);
				//	return nepc;
				//}
				cio_skip(-2);
			}
			//cio_skip(-2);
			//printf("sdfpo: %x\n",cio_read(2));
			// A questo punto ci troviamo a valle dell'ultimo marker del MH
			// Dobbiamo inserire il marker RED!!!
			insert_RED(cio_tell(),red.lred+2,redlenok);
			g = fopen("output.j2c","wb");
			if (g==NULL)
				printf("Unable to open file!\n");
			cio_seek(0);
			for (i=0; i<(epc.cl+redlen+5); i++)
				fputc(cio_read(1),g);
			fclose(g);
			_exit(-1);
			cslen = epc.cl + redlen + 5;
			//free(red.reddata);
		}
	else
	{
		f = fopen("output.j2c","wb");
		if (f==NULL)
			printf("Unable to open file!\n");
		cio_seek(0);
		//printf("CL: %d\n",epc.cl);
		for (i=0; i<epc.cl; i++)
			fputc(cio_read(1),f);
		fclose(f);
		_exit(-2);
	}
	//free(red.reddata);
	cio_seek(0);
	_exit(-3);
	//printf("Eccomi qua!\n");
	return nepc;
	}

int read_EPC() // ritorna 1 se trova epc, 0 se non lo trova
{
	
	unsigned int id, lid;  
	//unsigned char *pid;  						   
	int i, h, pos, nid;
	unsigned int ltec, count;
	unsigned char *buff;

	//FILE *f;
	

	pos = cio_tell()-2; // memorizza la posizione a monte del marker EPC

	
	epc.lepc = cio_read(2);
	epc.pcrc = cio_read(2);
	epc.cl = cio_read(4);
	//printf("CL: %d\n",epc.cl);
	epc.pepc = cio_read(1);
	if ((epc.pepc>>4)&1)	// E' presente una o più ESD !!!
	{
		esd = (ESD_MS *) malloc(10 * sizeof(ESD_MS)); // ******Si puo' togliere!!!!!
		//printf("La codestream contiene il marker ESD!\n");
	}
	ltec = epc.lepc - 9; // lunghezza dell'EPC a partire dalla fine di pepc
	count = 0;
	nid = 0; // numero di tecniche id usate
	while (count<ltec)
	{
		id = cio_read(2);
		count += 2;
		lid = cio_read(2);
		count += 2 + lid;
		cio_skip(lid); // salta il campo Pid
		nid ++;
	} // fine while (count<ltec)
	// Ora nid contiene il numero totale di tecniche usate!!!
	epc.tecn = (id_tecn *) malloc(nid * sizeof(id_tecn));
	cio_seek(pos + 11); // si posiziona a valle di pepc!
	for (i=0; i<nid; i++)
	{
		epc.tecn[i].id = cio_read(2);
		epc.tecn[i].lid = cio_read(2);
		epc.tecn[i].pid = (char *) malloc(epc.tecn[i].lid * sizeof(char));
		for (h=0; h<epc.tecn[i].lid; h++)
				epc.tecn[i].pid[h] = cio_read(1);
	}

	/*f = fopen("epc.txt","w");
	fprintf(f,"ECP: \t%x\n",0xff97);
	fprintf(f,"Lepc:\t%x\n",epc.lepc);
	fprintf(f,"Pcrc:\t%x\n",epc.pcrc);
	fprintf(f,"CL:  \t%x\n",epc.cl);
	fprintf(f,"Pepc:\t%x\n",epc.pepc);
	fprintf(f,"ID:  \t%x\n",epc.tecn[0].id);
	fprintf(f,"Lid: \t%x\n",epc.tecn[0].lid);
	fprintf(f,"Pid: \tN.D.\n");
	fclose(f);*/

	/*
	// Facciamo riscrivere tutto l'EPC letto!
	printf("Lepc: %d\n",epc.lepc);
	printf("Pcrc: %d\n",epc.pcrc);
	printf("CL: %d\n",epc.cl);
	printf("Pepc: %d\n",epc.pepc);
	for (i=0; i<nid; i++)
	{
		printf("id[%d] : %d\n",i,epc.tecn[i].id);
		printf("lid[%d] : %d\n",i,epc.tecn[i].lid);
		for (h=0; h<epc.tecn[i].lid; h++)
			printf("pid[%d] : %x\t",i,epc.tecn[i].pid[h]);
		printf("\n");
	}
	*/
	//f = fopen("pepbs","w");
	//if (f==NULL)
	//	printf("Unable to open file 'pepbs'!\n");
	//for (i=0; i<(epc.tecn[0].lid/4); i++)
	//{	for (h=0; h<4; h++)
			//fputc(epc.tecn[0].pid[i+h],f);
	//		fprintf(f,"%x",epc.tecn[0].pid[i*4+h]);
	//	fprintf(f,"\n");
	//}
	//fclose(f);

	// Ora occorre verificare la correttezza del campo Pcrc
	buff = (char *) malloc(epc.lepc* sizeof(char));
	cio_seek(pos); // si posiziona all'inizio di EPC
	for (i=0; i<4; i++)
		buff[i] = cio_read(1);  // copia nel buffer epc fino a pcrc escluso
	//pcrc = cio_read(2); // ora abbiamo copiato in pcrc il campo corrispondente dell'EPC
	cio_skip(2);
	for (i=4; i<epc.lepc; i++)
		buff[i] = cio_read(1);
	//for (i=0; i<(epc.lepc); i++)
	//	printf("%x ",buff[i]);
	//printf("\n");
	// Ora buff contiene tutto l'epc a meno di pcrc!
	// Bisogna applicare la codifica crc a buff e verificare che il risultato coincida
	// con pcrc salvato!
	ResetCRC();
	for (i=0; i < epc.lepc; i++){
		UpdateCRC16(buff[i]);	
	}
	//printf("CRCSUM: %x\n",crcSum);
	if (crcSum == epc.pcrc)
		return 1;  // se la funzione read_EPC ritorna 1 vuol dire che CRC è corretto
	else
		return 0;  // vuol dire che il campo Pcrc indica la presenza di errori in EPC
}

int read_EPB_2(int *j2k_state) // ritorna il numero di EPB letti
{
	unsigned int lepb, lsiz, temp, ldata, lsot, lbuf;
	int posdata, posdata2, nblock, i,h, pos, lante, lpar;
	int nn, kk, tt, nn1, kk1; // parametri per la decodifica RS
	//int pos1, pos2, h; // utili per la gestione della decodifica della seconda parte di EPB
	int nepbpm, posfirst, posend, count;
	unsigned long lpack, ldpread;
	EPB_par *epb;
	unsigned long ldpepb, pepb, ndata, datacrc;  // ndata è utile per la decodifica della seconda parte EPB
	unsigned char depb;
	unsigned char *buff;
	int lparity, packall; // se packall = 1 allora tutti gli EPB del tile sono packed

	//FILE *f;
	if (*j2k_state == J2K_STATE_MHSOC)  
		{
			// Se siamo giunti a questo punto vuol dire che SOC e i primi due campi di SIZ non sono
			// errati!!...ora ci dobbiamo posizionare subito a valle di SIZ
			//printf("j2k_state: %x\n",*j2k_state);
			cio_skip(4); // si pone all'inizio del campo Lsiz
			lsiz = cio_read(2);
			cio_skip(lsiz-2); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			//*printf("EPB: %x\n",temp);
			nn = 160; kk = 64; tt = 48;  // inizializzazione per codice RS(160,64)
			lante = lsiz+4; 
			
		} // fine if (j2k_state == J2K_STATE_MHSOC)

		if (*j2k_state == J2K_STATE_TPHSOT)
		{
			
			//printf("j2k_state: %x\n",*j2k_state);
			startsot = cio_tell(); // memorizza nella variabile globale la posizione di SOT
			//printf("sot: %x\n",startsot);
			cio_skip(2); // si pone all'inizio del campo Lsot
			lsot = cio_read(2);
			cio_skip(2); // si posiziona all'inizio del campo Psot
			psot = cio_read(4); // Legge il campo Psot
			cio_skip(-6); // si riposiziona a valle del campo Lsot
			//*printf("lsot: %d\n",lsot);
			cio_skip(8); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			//printf("pos: %x\n",pos);
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			//*printf("EPB: %x\n",temp);
			nn = 80; kk = 25; tt = 28;  // inizializzazione per codice RS(80,25)
			lante = lsot+2;
		}

		if ((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_TPH))
		{
			//printf("j2k_state: %x\n",*j2k_state);
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2); // ci si aspetta qui di trovare il marker EPB
			nn = 40; kk = 13; tt = 14;  // inizializzazione per codice RS(40,13)
			lante = 0;
		}

    // A questo punto possiamo decodificare la prima parte di dati tramite i codici di default

	//printf("state: %x\n",*j2k_state);
	//system("pause");
	//printf("nn,kk,tt: %d,%d,%d\n",nn,kk,tt);
	nn1 = 255; kk1 = kk + (nn1 - nn);
	alpha_to = (int *) malloc((nn1+1)*sizeof(int));
	index_of = (int *) malloc((nn1+1)*sizeof(int));
	gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
	recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
	data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
	bb = (int *) malloc((nn1-kk1)*sizeof(int));

	//next = cio_tell();

	//printf("COUNT: %d\n",count);
	lepb = cio_read(2);  // legge la lunghezza di EPB..si spera che questo campo non è errato!
	//*printf("LEPB: %x\n",lepb);
	cio_skip(9);  // si posiziona all'inizio del campo dati di EPB
	posdata = cio_tell();
	//printf("data: %x\n",cio_read(2));
	//cio_skip(-2);
	ldata = lepb - 11;  // determina la lunghezza del campo dati
	
	lpar = nn - kk; // determina la lunghezza dei bit di parità utilizzati per correggere la prima parte di EPB
	if (*j2k_state == J2K_STATE_MHSOC)  
	{
		lpar = nbckpar * (nn-kk);
	}
	//if (*j2k_state == J2K_STATE_TPHSOT)
	else
		nbckpar = 1;
	//lbuf = lante + 13 + lpar;  // lpar è la lunghezza dei bit di parità 
	//*printf("lbuf = %d\n",lbuf);
	buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
	          // e i parametri di EPB

	for (i=0; i<nbckpar; i++)
	{
		//buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
	                                           // e i parametri di EPB
		//printf("Ho inizializzato il buffer!\n");
		for (h=0; h<nn1; h++)
			buff[h] = 0; // inizializza il buffer tutto a zero
	
		// Bisognerà copiare tutto il contenuto da questo punto fino alla fine della prima parte dei dati EPB in buff
		// Per come lavora il decoder RS, i bytes di parità vanno posti all'inizio del buffer

		write_buff(buff,posdata+i*(nn-kk),(nn-kk)); // copia nel buffer i byte di parità del campo dati
		//printf("PROVA\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",buff[h]);
		//system("pause");
	
		//printf("nbckpar: %d\n",nbckpar);
		//printf("nn: %d\n",nn);
		cio_seek(next + i*kk);  // si posiziona all'inizio dei dati protetti (SOC,SOT o EPB)
		if (i<(nbckpar -1))
		{
			for (h=(nn-kk); h<nn; h++)
			{
				buff[h] = cio_read(1);  // copia in buff i byte di messaggio (SOC,SIZ,ParEPB)
				//printf(" %x\n",buff[i]);
			}
		}
		else
		{
			if (*j2k_state == J2K_STATE_MHSOC)
			{
				ndata = lmex - ((nbckpar-1) * kk); // l'ultimo blocco dati non è in genere lungo 64!
				for (h=(nn-kk); h<((nn-kk)+ndata); h++)
				{
					buff[h] = cio_read(1);
				}
			}
			else
				for (h=(nn-kk); h<nn; h++)
					buff[h] = cio_read(1);  
		}
		//printf("Eccomi qua-1!\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",buff[h]);
		//system("pause");

		for (h=0; h<nn1; h++)
			recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare

		//printf("Eccomi qua-1!\n");
		//if (*j2k_state == J2K_STATE_MHSOC)
		//if (i==0)
		//{
			
			/*f = fopen("debug","a");
			if (f==NULL)
				printf("Unable to open file!\n");
			fprintf(f,"\n");
			for (h=0; h<nn1; h++)
				fprintf(f,"%x ",recd[h]);
			fprintf(f,"\n");
			fclose(f);*/
		//}
		//else
		//{
		//f = fopen("debug","a");
		//if (f==NULL)
		//	printf("Unable to open file!\n");
		//fprintf(f,"\n");
		//for (h=0; h<nn1; h++)
		//	fprintf(f,"%x ",recd[h]);
		//fprintf(f,"\n");
		//fclose(f);
		//}
		//printf("Eccomi qua-1!\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",recd[h]);
		//system("pause");

		generate_gf(nn1,kk1) ;
		gen_poly(nn1,kk1) ;
		for (h=0; h<nn1; h++)
			recd[h] = index_of[recd[h]] ; // a questo punto recd[] contiene i bytes decodificati
		decode_rs(nn1,kk1,tt); 
		
		if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
		{
			//Inizializzo il buffer in cui vado a copiare la RED
			cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
			cio_seek(redpos);

			//printf("Il blocco corrispondente non è stato decodificato!\n");
			cio_write(next + i*kk,4); // Scrive il byte di start del range considerato	
			redlen += 4;
			if (i<(nbckpar -1))
				cio_write(next + i*kk + kk - 1,4);  // Scrive il byte di end del range
			else
			{
				if (*j2k_state == J2K_STATE_MHSOC)
					cio_write(next + i*kk + ndata - 1,4);  // Scrive il byte di end del range
				else
					cio_write(next + i*kk + kk - 1,4);
			}
			redlen += 4;
			// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
			cio_write(0xFFFF,2);
			redlen += 2;
			if ((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH))
				redlenok+=10;
			//cio_seek(redpos);
			//printf("START: %x\n",cio_read(4));
			//printf("END: %x\n",cio_read(4));
			//printf("VALUE: %x\n",cio_read(2));
			redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
			//printf("ciao\n");
		}

		//printf("Eccomi qua-2!\n");
		//for (i=0; i<nn1; i++)
		//	printf(" %x\n",recd[i]);
		//system("pause");

		// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

		cio_init(cssrc, cslen); //******Aggiunto in questa versione 1.7
		
		cio_seek(posdata+i*(nn-kk)); // si posiziona all'inizio del blocco di parità corrispondente	
		for (h=0; h<(nn-kk); h++)
			cio_write(recd[h],1);  // copia i byte di parità corretti nel campo dati
		cio_seek(next + i*kk);
		//printf("next: %x\n",next);
		if (i<(nbckpar -1))
		{
			for (h=(nn-kk); h<nn; h++)
				cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
		}
		else
		{
			if (*j2k_state == J2K_STATE_MHSOC)
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				{
					cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
				}
			else
				for (h=(nn-kk); h<nn; h++)
				cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
		}
	} // fine ciclo for (i=0; i<nbckpar; i++)

	// A questo punto la codestream è corretta fino alla fine della prima parte dei dati EPB
	// Possiamo leggere i parametri di EPB per condurre la codifica seguente

	cio_seek(pos);  // si posiziona all'inizio di EPB
	//printf("pos: %x\n",cio_tell());
	//printf("pos: %x\n",pos);
	//system("pause");
	temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			//if (temp != JPWL_MS_EPB)
			//{
			//	//*printf("Non ho decodificato l'EPB!\n"); 
			//	// Puo' succedere che l'EPC ha fornito informazione errata: in tal caso il
			//	// processo di decodifica effettuato perde di significato.
			//	// Puo' anche succedere pero' che il codice RS contenuto nell'EPB MS non
			//	// è stato in grado di correggere l'errore sul marker EPB!!
			//	
			//	return 0;
			//	//return;
			//	// Per adesso usciamo dalla procedura, ma la cosa migliore sarebbe
			//	// fare in modo che il decoder vada a cercare l'eventuale EPB successivo
			//}

	//*count++; // se siamo a questo punto vuol dire che è stato letto effettivamente un EPB
	//printf("mark: %x\n",temp);
	cio_skip(2); // ora è all'inizio del campo depb
	depb = cio_read(1); // legge depb
	//printf("depb: %x\n",depb);
	ldpepb = cio_read(4); // legge ldpepb
	//printf("ldpepb: %x\n",ldpepb);
	pepb = cio_read(4); // legge pepb

	/*f = fopen("epb.txt","a");
	fprintf(f,"EPB:   \t%x\n",0xff96);
	fprintf(f,"Lepb:  \t%x\n",lepb);
	fprintf(f,"Depb:  \t%x\n",depb);
	fprintf(f,"LDPepb:\t%x\n",ldpepb);
	fprintf(f,"Pepb:  \t%x\n",pepb);
	fclose(f);*/

	if (nepbrd!=0)
	{
		temp = cio_tell();
		cio_init(epc.tecn[0].pid, epc.tecn[0].lid);
		cio_seek(nepbrd*4);
		if (pepb!=cio_read(4))
		{
			cio_skip(-4);
			pepb=cio_read(4); // Copia nel campo pepb il corrispondente pepc contenuto in EPC
		}
		cio_init(cssrc, cslen);
		cio_seek(temp);
	}
	//*printf("pepb: %x\n",pepb);
	//*printf("ldata1: %d\n",ldata);
	ldata = ldata - nbckpar*(nn-kk);  // lunghezza della porzione rimanente del campo dati
	//*printf("ldata2: %d\n",ldata);
	cio_seek(posdata + nbckpar*(nn-kk)); 
	posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
	if (ldpepb == 0)
		next = cio_tell();
	//printf("pd2: %x\n",posdata2);
	//printf("nbckpar: %d\n",nbckpar);
	//printf("mark: %x\n",cio_read(2));
	//cio_skip(-2);

	if (!((depb >> 6)&1))  // quello corrente non è l'ultimo EPB del tile corrente
		lastepb = 0;
	if ((depb >> 6)&1)  // quello corrente è l'ultimo EPB del tile corrente
		lastepb = 1;
	//printf("lastepb: %d\n",lastepb);
	//printf("pack: %d\n",(depb >> 7)&1);
	if (!((depb >> 7)&1))  // EPB in modalità unpacked
	{
		//printf("Unpacked\n");
		//system("pause");
		if ((!((depb >> 6)&1))&&((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH)))
			*j2k_state = J2K_STATE_MH; // vuol dire che il prossimo EPB è in MH ma non è il primo
		//if (((depb >> 6)&1)&&((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_MHSOC)))
		//	*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
		//if (((depb >> 6)&1)&&((*j2k_state == J2K_STATE_TPH)||(*j2k_state == J2K_STATE_TPHSOT)))
		//	*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
		if ((!((depb >> 6)&1))&&((*j2k_state == J2K_STATE_TPHSOT)||(*j2k_state == J2K_STATE_TPH)))
			*j2k_state = J2K_STATE_TPH; // vuol dire che il prossimo EPB è relativo ad un TPH

		nepbrd++;
		// Ora leggendo pepb il decoder deve capire quale codice applicare per la porzione di dati
		// cui fa riferimento la seconda parte del campo EPBdata

		if (pepb)  // se pepb=0 allora si usano i codici di default precedenti
		{
			if ((pepb>>28)==2)
			{
				// in questo caso deve effettuare la decodifica RS
				/***********/
				// liberiamo gli spazi allocati
				free(alpha_to);
				free(index_of);
				free(gg);
				free(recd);
				free(data);
				free(bb);
				/***********/
				kk = (int) pepb & 0x000000ff;
			    nn = (int) (pepb>>8) & 0x000000ff;
				tt = (int) ceil((double)(nn-kk)/2);
				nn1 = 255; kk1 = kk + (nn1 - nn);
				alpha_to = (int *) malloc((nn1+1)*sizeof(int));
				index_of = (int *) malloc((nn1+1)*sizeof(int));
				gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
				recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
				data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
				bb = (int *) malloc((nn1-kk1)*sizeof(int));
				generate_gf(nn1,kk1) ;
				gen_poly(nn1,kk1) ;
			}
	
			if ((pepb>>28)==1)
			{
				// in questo caso deve effettuare le decodifica CRC
				free(buff);
				buff = (char *) malloc(ldpepb * sizeof(char));
				write_buff(buff,posdata2+ldata,ldpepb);
				if (pepb & 0x00000001)	// vuol dire che bisogna decodificare secondo CRC 32
				{
					/*per fare il crc32 occorre invertire i byte in ingresso, invertire il crc calcolato
				    e farne il complemento a 1*/
					ResetCRC();
					for (i=0; i < ldpepb; i++)
						UpdateCRC32(reflectByte(buff[i]));	
					reflectCRC32();
					crcSum ^= 0xffffffff;	// effettua il complemento a 1	
					cio_seek(posdata2);
					datacrc = cio_read(4);
					//printf("CRCSUM: %x\n",crcSum);
					//if (datacrc == crcSum)
					//	printf("CRC corretto!\n");
					//else
					//	printf("CRC errato!\n");
				}
				else	// vuol dire che bisogna decodificare secondo CRC 16
				{
					ResetCRC();
					for (i=0; i < ldpepb; i++)
						UpdateCRC16(buff[i]);	
					cio_seek(posdata2);
					datacrc = cio_read(2);
					//printf("CRCSUM: %x\n",crcSum);
					//if (datacrc == crcSum)
					//	printf("CRC corretto!\n");
					//else
					//	printf("CRC errato!\n");
				}
				free(buff);
				cio_seek(posdata2 + ldata + ldpepb);
				next = cio_tell();
				//printf("read: %x\n",cio_read(2));
				//cio_skip(-2);

				temp = cio_read(2);
				if (temp == J2K_MS_SOT)
					*j2k_state = J2K_STATE_TPHSOT;
				if (temp == J2K_MS_EOC)
					*j2k_state = J2K_STATE_MT;
				cio_skip(-2);
				//printf("state: %x\n",*j2k_state);

				return 1;
				//return (posdata2 + ldata + ldpepb);  // ritorna la posizione a valle dei dati successivi a EPB
				//return;
			}
	
			if (pepb>=0x30000000)
			{
				// tecniche registrate in RA
				cio_seek(posdata2);
				return 1;
				//return (posdata2 + ldata + ldpepb);
				// Per adesso prevede la semplice uscita dalla funzione
			}
	
			if (pepb==0xffffffff)
			{
				// non sono usati metodi per i dati seguenti
				cio_seek(posdata2);
				return 1;
				//return (posdata2 + ldata + ldpepb);
				//return;
			}
		}// Fine if (pepb)
	
		
	
		/*******************/
		// qui bisogna aggiungere la parte per la gestione della modalità packed/unpacked
		/*******************/
	
		
		//cio_seek(posdata + (nn-kk)); 
		//posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
		
		/********************/
		// Per adesso si suppone che il primo EPB di un header utilizza lo stesso codice
		// di default anche per la seconda parte dei dati...in seguito bisognerà aggiungere
		// la funzionalità che gestisce l'uso dei vari codici in base al campo pepb
		/********************/
	
		// Ora bisogna copiare in buff la seconda parte dei dati di EPB e i dati successivi all'epb
		// per una lunghezza pari a ldpepb
	    
		nblock = ldata / (nn-kk);  // numero di "blocchi di decodifica"
		//printf("nblock = %d\n",nblock);
		//*system("pause");
		//cio_seek(posdata2);  // si posiziona all'inizio della seconda parte dei dati EPB
		free(buff);
		buff = (char *) malloc(nn1 * sizeof(char));
		for (i=0; i<nblock; i++)
		{	
			//free(buff);
			//buff = (char *) malloc(nn1 * sizeof(char));
			for (h=0; h<nn1; h++)
				buff[h] = 0; // inizializza il buffer tutto a zero
			write_buff(buff,posdata2+i*(nn-kk),(nn-kk)); // copia nel buff i bytes di parità
			cio_seek(posdata2+ldata+i*kk); // si posiziona nel blocco dati corrispondente
			
			//if (i==0) {
			//	printf("data: %x\n",cio_read(2));
			//    cio_skip(-2);
			//	system("pause");
			//}
			//pos1 = cio_tell(); // memorizza la posizione del blocco dati corrispondente
			if (i<(nblock-1))
			{
				//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+64; h++)
				for (h=(nn-kk); h<nn; h++)
				{
					buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
					//if (i==1)
					//  printf("Data: %x\n",buff[h]);  /**********/
				}
				//system("pause"); /***********/
			}
			else
			{
				ndata = ldpepb - ((nblock-1) * kk);  // l'ultimo blocco di dati non necessariamente è lungo 64!
				//*printf("ndata: %d\n",ndata);
				//*system("pause");
				//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+ndata; h++)
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				{
					buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
					//printf("Data: %x\n",buff[h]);  /**********/
				}
				//printf("\n");
				//system("pause"); /***********/
				next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
				//printf("next: %x\n",next);
				if (cio_read(2) == 0xffd9)
					*j2k_state = J2K_STATE_MT;
				cio_skip(-2);
			}
			
			for (h=0; h<nn1; h++)
				recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare

			//if (*j2k_state == J2K_STATE_TPHSOT)
			//{
			//	f = fopen("debug","w");
			//	if (f==NULL)
			//		printf("Unable to open file!\n");
			//	fprintf(f,"\n");
			//	for (h=0; h<nn1; h++)
			//		fprintf(f,"%x ",recd[h]);
			//	fprintf(f,"\n");
			//	fclose(f);
			//}
			//else
			//{
			/*f = fopen("debug","a");
			if (f==NULL)
				printf("Unable to open file!\n");
			fprintf(f,"\n");
			for (h=0; h<nn1; h++)
				fprintf(f,"%x ",recd[h]);
			fprintf(f,"\n");
			fclose(f);*/
			//}
			//printf("\n");
			//if (i == (nblock-1))
			// for (h=0; h<nn1; h++)
			//  	printf("mess: %x\n",recd[h]);
			//system("pause");

			//printf("nn1: %d\n",nn1);
			//printf("kk1: %d\n",kk1);
	        
			generate_gf(nn1,kk1) ;
			gen_poly(nn1,kk1) ;
			for (h=0; h<nn1; h++)
				recd[h] = index_of[recd[h]] ;  // a questo punto recd[] contiene i bytes decodificati
			decode_rs(nn1,kk1,tt);  
			if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
			{
				//Inizializzo il buffer in cui vado a copiare la RED
				cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
				cio_seek(redpos);

				//printf("Il blocco corrispondente non è stato decodificato!\n");
				cio_write(posdata2+ldata+i*kk,4); // Scrive il byte di start del range considerato	
				redlen += 4;
				if (i<(nblock -1))
					cio_write(posdata2+ldata+i*kk + kk - 1,4);  // Scrive il byte di end del range
				else
					cio_write(posdata2+ldata+i*kk + ndata - 1,4);  // Scrive il byte di end del range
				redlen += 4;
				// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
				cio_write(0xFFFF,2);
				redlen += 2;
				if ((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_TPHSOT))
					redlenok+=10;
				redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
				//printf("ciao\n");
			}
			if ((redlen==0)&(redmode==1))
				free(red.reddata);
			
			//*printf("nciclo: %d\n\n",i);
			//for (h=0; h<nn1; h++)
			//	printf("mess: %x\n",recd[h]);
			//system("pause");

			// Adesso bisogna ricopiare il contenuto di recd[] nella codestream
			
			cio_init(cssrc, cslen); //*****Aggiunto in questa versione 1.7
			
			cio_seek(posdata2+i*(nn-kk));  // si posiziona all'inizio del blocco di parità corrispondente
			
			for (h=0; h<(nn-kk); h++)
			{
				cio_write(recd[h],1);  // copia nella codestream i bytes di parità corretti
				/*if (i == (nblock-1))
					printf("par: %x\n",recd[h]);
				printf("\n");*/
			}
			//system("pause");
			
			cio_seek(posdata2+ldata+i*kk);
			if (i<(nblock-1))
			{
				//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+64; h++)
				for (h=(nn-kk); h<nn; h++)
					cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
			}
			else
			{
				ndata = ldpepb - (nblock-1) * kk;  // l'ultimo blocco di dati non necessariamente è lungo 64!			
				//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+ndata; h++)
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				{	cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
				//printf("data: %x\n",recd[h]);
				}
				printf("\n");
				/*cio_seek(posdata2+ldata+i*kk);
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
					printf("data: %x\n",cio_read(1));*/
			}
		}//fine ciclo for (i=0; i<nblock; i++)
		temp = cio_read(2);
		if (temp == J2K_MS_SOT)
			*j2k_state = J2K_STATE_TPHSOT;
		if (temp == J2K_MS_EOC)
			*j2k_state = J2K_STATE_MT;
		cio_skip(-2);
		//printf("pos: %x\n",cio_tell());

		//csread += (lepb + ldpepb);

		free(alpha_to);
		free(index_of);
		free(gg);
		free(recd);
		free(data);
		free(bb);
		/***********/
		free(buff);
		return 1;
		//return next; // Ritorna la posizione subito a valle dell'EPB appena letto!!
	}
	else	// Gli EPB sono scritti in modalità packed 
	{	
		if (*j2k_state == J2K_STATE_TPHSOT)
			packall = 1;
		else
			packall = 0;
		//printf("packall: %d\n",packall);
		
		posfirst = pos;
		cio_seek(pos+2); // Si posiziona nel campo lepb del primo EPB packed
		cio_skip(cio_read(2)-2);  // Si posiziona all'inizio del secondo EPB packed
		pos = cio_tell();
		cio_skip(2); // Si posiziona all'inizio del campo lepb del secondo EPB packed
		
		
		//printf("posfirst: %x\n",posfirst);
		//printf("mrk: %x\n",cio_read(2));
		//cio_skip(-2);
		//system("pause");

		//lastepb = 0; // Si suppone che l'EPB corrente non sia l'ultimo di un tile!
		nepbpm = 1;

		free(alpha_to);
		free(index_of);
		free(gg);
		free(recd);
		free(data);
		free(bb);
		nn = 40; kk = 13;
		nn1 = 255; kk1 = kk + (nn1 - nn);
		alpha_to = (int *) malloc((nn1+1)*sizeof(int));
		index_of = (int *) malloc((nn1+1)*sizeof(int));
		gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
		recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
		data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
		bb = (int *) malloc((nn1-kk1)*sizeof(int));

		
		//while ((lastepb == 0)&&(csread < cslen))
		while (lastepb == 0)
		{
			
		lepb = cio_read(2);  // legge la lunghezza di EPB..si spera che questo campo non è errato!
		cio_skip(9);  // si posiziona all'inizio del campo dati di EPB
		posdata = cio_tell();
		ldata = lepb - 11;  // determina la lunghezza del campo dati
		//printf("ldata: %d\n",ldata);
		//printf("lante: %d\n",lante);
		//lbuf = lante + 13 + (nn-kk);  // 2*tt è la lunghezza dei bit di parità 
		lbuf = 13 + (nn-kk);  // 2*tt è la lunghezza dei bit di parità 
		buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
												// e i parametri di EPB
		for (i=0; i<nn1; i++)
			buff[i] = 0; // inizializza il buffer tutto a zero
		
		// Bisognerà copiare tutto il contenuto da questo punto fino alla fine della prima parte dei dati EPB in buff
		// Per come lavora il decoder RS, i bytes di parità vanno posti all'inizio del buffer

		
		write_buff(buff,posdata,(nn-kk)); // copia nel buffer i byte di parità del campo dati
		
		cio_seek(pos);  // si posiziona all'inizio dei dati protetti (SOC,SOT o EPB)
		for (i=(nn-kk); i<lbuf; i++)
		{
			buff[i] = cio_read(1);  // copia in buff i byte di messaggio (SOC,SIZ,ParEPB)
		}

		for (i=0; i<nn1; i++)
			recd[i] = buff[i];  // copia in recd il contenuto di buff da decodificare

		/*f = fopen("debug","a");
		if (f==NULL)
			printf("Unable to open file!\n");
		fprintf(f,"EPB PAR: %d\n",nepbpm);
		for (h=0; h<nn1; h++)
			fprintf(f,"%x ",recd[h]);
		fprintf(f,"\n");
		fclose(f);*/

		generate_gf(nn1,kk1) ;
		gen_poly(nn1,kk1) ;
		for (i=0; i<nn1; i++)
			recd[i] = index_of[recd[i]] ; // a questo punto recd[] contiene i bytes decodificati     
		decode_rs(nn1,kk1,tt);  

		if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
			{
				//Inizializzo il buffer in cui vado a copiare la RED
				cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
				cio_seek(redpos);

				//printf("Il blocco corrispondente non è stato decodificato!\n");
				cio_write(pos,4); // Scrive il byte di start del range considerato	
				cio_write(pos + lbuf - (nn - kk) - 1,4);  // Scrive il byte di end del range
				// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
				cio_write(0xFFFF,2);
				redlen += 10;
				redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
				//printf("ciao\n");
			}
		// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

		cio_init(cssrc, cslen);

		cio_seek(posdata); // si posiziona all'inizio del campo dati della codestream	
		//printf("read: %x\n",cio_read(2));
		//cio_skip(-2);
		//if (packall == 1)
		//	for (i=0; i<(55); i++)
		//		cio_write(recd[i],1);  // copia i byte di parità corretti nel campo dati
		//else
		//if (nepbpm==1)
		//	for (i=0; i<(nn-kk); i++)
		//		printf("%x ",recd[i]);
		for (i=0; i<(nn-kk); i++)
			cio_write(recd[i],1);  // copia i byte di parità corretti nel campo dati
		cio_seek(pos);
		for (i=(nn-kk); i<lbuf; i++)
			cio_write(recd[i],1);  // copia i bytes di messaggio nella codestream
		

		// A questo punto la codestream è corretta fino alla fine della prima parte dei dati EPB
		// Possiamo leggere i parametri di EPB per condurre la codifica seguente

		
		cio_seek(pos);  // si posiziona all'inizio di EPB
		temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
				//if (temp != JPWL_MS_EPB)
				//{
				//	// Puo' succedere che l'EPC ha fornito informazione errata: in tal caso il
				//	// processo di decodifica effettuato perde di significato.
				//	// Puo' anche succedere pero' che il codice RS contenuto nell'EPB MS non
				//	// è stato in grado di correggere l'errore sul marker EPB!!
				//	return 0;
				//	// Per adesso usciamo dalla procedura, ma la cosa migliore sarebbe
				//	// fare in modo che il decoder vada a cercare l'eventuale EPB successivo
				//}

		cio_skip(2); // ora è all'inizio del campo depb
		depb = cio_read(1); // legge depb
		//printf("depb: %x\n",depb);
		//if ((depb >> 6)&1)  // quello corrente è l'ultimo EPB del tile corrente
		//{
		//	lastepb = 1; // l'epb corrente è l'ultimo del tile
			//nepbpm = ((depb << 2) >> 2); // numero di EPB accorpati in modalità packed
		//	nepbpm = (depb & 0x3f); // numero di EPB accorpati in modalità packed
			//printf("nepbpm: %d\n",nepbpm);
		//}
		if (!((depb >> 6)&1))  // quello corrente non è l'ultimo EPB del tile corrente
			nepbpm += 1;
		if ((depb >> 6)&1)  // quello corrente è l'ultimo EPB del tile corrente
		{
			nepbpm += 1;
			lastepb = 1;
		}

		//printf("nepbpm: %d\n",nepbpm);
		//printf("lastepb: %d\n",lastepb);
		//system("pause");

		cio_skip(-3); // si posiziona all'inizio del campo lepb
		cio_skip(cio_read(2)-2);  // si posiziona a valle dell'epb corrente
		pos = cio_tell(); // memorizza la posizione all'inizio dell'EPB successivo
		//printf("pos: %x\n",pos);
		//printf("mrk: %x\n",cio_read(2));
		//cio_skip(-2);
		//system("pause");
		cio_skip(2);

		//conta++;

		//csread += lepb;

		} // Fine while (lastepb == 0)!!!!
		// A questo punto il decoder ha decodificato le porzioni iniziali di tutti gli EPB
		// del tile corrente
		

		// Ora dobbiamo decodificare le porzioni finali di tutti gli EPB!!!

		// pos contiene la posizione a valle dell'ultimo degli EPB packed!!!
		cio_skip(-2);
		posend = cio_tell();
		//printf("posend: %x\n",posend);
		//system("pause");
		lpack = posend-posfirst; // lunghezza totale della catena di EPB
		epb = (EPB_par *) malloc(nepbpm * sizeof(EPB_par));
		cio_seek(posfirst);
		//printf("posfirst: %x\n",posfirst);

		//printf("nepbpm: %d\n",nepbpm);
		for (count=0; count<nepbpm; count++)
		{
			cio_skip(2); // si posiziona all'inizio di lepb
			epb[count].lepb = cio_read(2); // legge lepb
			epb[count].depb = cio_read(1); // legge depb
			epb[count].ldpepb = cio_read(4); // legge ldpepb
			epb[count].pepb = cio_read(4); // legge pepb

			temp = cio_tell();
			cio_init(epc.tecn[0].pid, epc.tecn[0].lid);
			cio_seek((nepbrd+count)*4);
			if (epb[count].pepb!=cio_read(4))
			{
				cio_skip(-4);
				epb[count].pepb=cio_read(4); 
			}
			cio_init(cssrc, cslen);
			cio_seek(temp);

			if ((count == 0)&&(packall == 1))
				epb[count].ldata = (epb[count].lepb - 11) - (80-25);
			else
				epb[count].ldata = (epb[count].lepb - 11) - (nn-kk);  // lunghezza della porzione rimanente del campo dati
			cio_skip(-11); // si posiziona all'inizio di lepb dell'EPB corrente
			cio_skip(epb[count].lepb); // si posiziona a valle dell'EPB corrente
		} // Abbiamo a questo punto memorizzato nella struttura epb i parametri degli EPB packed

		//for (count=0; count<nepbpm; count++)
		//{
		//	printf("EPB[%d]: %x\t%x\t%x\t%x\t%d\n",count,epb[count].lepb,epb[count].depb,
		//		epb[count].ldpepb,epb[count].pepb,epb[count].ldata);
		//}
		
		nepbrd+=nepbpm;

		cio_seek(posfirst);  // si posiziona all'inizio del primo degli EPB packed
		pos = cio_tell();
		ldpread = 0;
		lparity = nn - kk;
		//printf("lparity: %d\n",lparity);
		for (count=0; count<nepbpm; count++)
		{
			cio_seek(pos);
			//printf("mark: %x\n",cio_read(2));
			//printf("count: %d\n",count);
			//cio_skip(-2);
			//system("pause");
			cio_skip(13); // si posiziona all'inizio del campo dati
			posdata = cio_tell();
			//printf("tt: %d\n",nn-kk);
			if ((count == 0)&&(packall == 1))
				cio_seek(posdata + (80 - 25));
			else
				cio_seek(posdata + lparity); // si posiziona all'inizio seconda parte dati EPB corrente
			posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
			//printf("pd2: %x\n",posdata2);
			//system("pause");
			//cio_skip(-2);

			//if ((!((epb[count].depb >> 6)&1))&&((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH)))
			//	*j2k_state = J2K_STATE_MH; // vuol dire che il prossimo EPB è in MH ma non è il primo
			//if (((epb[count].depb >> 6)&1)&&((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_MHSOC)))
			//	*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
			//if (((epb[count].depb >> 6)&1)&&((*j2k_state == J2K_STATE_TPH)||(*j2k_state == J2K_STATE_TPHSOT)))
			//	*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
			//if ((!((epb[count].depb >> 6)&1))&&((*j2k_state == J2K_STATE_TPHSOT)||(*j2k_state == J2K_STATE_TPH)))
			//	*j2k_state = J2K_STATE_TPH; // vuol dire che il prossimo EPB è relativo ad un TPH
			
			// Ora leggendo pepb il decoder deve capire quale codice applicare per la porzione di dati
			// cui fa riferimento la seconda parte del campo EPBdata
			
			if (epb[count].pepb)  // se pepb=0 allora si usano i codici di default precedenti
			{
				if ((epb[count].pepb>>28)==2)
				{	
					// in questo caso deve effettuare la decodifica RS
					/***********/
					// liberiamo gli spazi allocati
					free(alpha_to);
					free(index_of);
					free(gg);
					free(recd);
					free(data);
					free(bb);
					/***********/
					kk = (int) epb[count].pepb & 0x000000ff;
					nn = (int) (epb[count].pepb>>8) & 0x000000ff;
					tt = (int) ceil((double)(nn-kk)/2);
					nn1 = 255; kk1 = kk + (nn1 - nn);
					alpha_to = (int *) malloc((nn1+1)*sizeof(int));
					index_of = (int *) malloc((nn1+1)*sizeof(int));
					gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
					recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
					data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
					bb = (int *) malloc((nn1-kk1)*sizeof(int));
					generate_gf(nn1,kk1) ;
					gen_poly(nn1,kk1) ;
				}

				if ((epb[count].pepb>>28)==1)
				{
					// in questo caso deve effettuare le decodifica CRC
					free(buff);
					buff = (char *) malloc(epb[count].ldpepb * sizeof(char));
					write_buff(buff,posdata2+epb[count].ldata,epb[count].ldpepb);//***Correggi!!!!!!!!!!!
					if (epb[count].pepb & 0x00000001)	// vuol dire che bisogna decodificare secondo CRC 32
					{
						/*per fare il crc32 occorre invertire i byte in ingresso, invertire il crc calcolato
						e farne il complemento a 1*/
						ResetCRC();
						cio_seek(posend+ldpread); // si posiziona nel blocco dati corrispondente
						for (i=0; i < epb[count].ldpepb; i++)
							UpdateCRC32(reflectByte(buff[i]));	
						reflectCRC32();
						if (lastepb==1)
						{
							cio_seek(startsot);
							cio_skip(6);
							psot = cio_read(4);
							next = startsot + psot; // **************Da correggere!!!!
							cio_seek(next);
							//printf("%x\n",cio_read(2));
							//cio_skip(-2);
						}
						if ((cio_read(2) == 0xffd9)||(psot == 0))
							*j2k_state = J2K_STATE_MT;
						cio_skip(-2);
						//else
						//{
						//	next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
						//}
						crcSum ^= 0xffffffff;	// effettua il complemento a 1	
						cio_seek(posdata2);
						datacrc = cio_read(4);
						//if (datacrc == crcSum)
						//	printf("CRC corretto!\n");
						//else
						//	printf("CRC errato!\n");
						
					}
					else	// vuol dire che bisogna decodificare secondo CRC 16
					{
						ResetCRC();
						cio_seek(posend+ldpread); // si posiziona nel blocco dati corrispondente
						for (i=0; i < epb[count].ldpepb; i++)
							UpdateCRC16(buff[i]);
						if (lastepb==1)
						{
							cio_seek(startsot);
							cio_skip(6);
							psot = cio_read(4);
							next = startsot + psot;
							cio_seek(next);
						}
						if ((cio_read(2) == 0xffd9)||(psot == 0))
							*j2k_state = J2K_STATE_MT;
						cio_skip(-2);
						cio_seek(posdata2);
						datacrc = cio_read(2);
						//if (datacrc == crcSum)
						//	printf("CRC corretto!\n");
						//else
						//	printf("CRC errato!\n");
					}
					//free(buff);
				}

				if (epb[count].pepb>=0x30000000)
				{
					next = cio_tell();
					// tecniche registrate in RA
				}

				if (epb[count].pepb==0xffffffff)
				{
					next = cio_tell();
					// non sono usati metodi per i dati seguenti
				}
			}
			
			if (((epb[count].pepb>>28)==2)||(epb[count].pepb==0))  // Vuol dire che si usano codici RS
			{
			// Ora bisogna copiare in buff la seconda parte dei dati di EPB e i dati successivi all'epb
			// per una lunghezza pari a ldpepb
	    
			//printf("count: %d\n",count);
			//printf("ldpread: %d\n",ldpread);
			//system("pause");
			//printf("nn: %d\n",nn);
			//printf("kk: %d\n",kk);
			//system("pause");
			//printf("posiz: %x\n",posdata2 + epb[count].ldata);
			nblock = epb[count].ldata / (nn-kk);  // numero di "blocchi di decodifica"
			//printf("nblock: %d\n",nblock);
			free(buff);
			buff = (char *) malloc(nn1 * sizeof(char));
			cio_seek(startsot);
			cio_skip(6);
			psot = cio_read(4);
			//printf("ldata: %d\n",epb[count].ldata);
			//printf("nblock: %d\n",nblock);
			for (i=0; i<nblock; i++)
			{
				//free(buff);
				//buff = (char *) malloc(nn1 * sizeof(char));
				for (h=0; h<nn1; h++)
					buff[h] = 0; // inizializza il buffer tutto a zero
				write_buff(buff,posdata2+i*(nn-kk),(nn-kk)); // copia nel buff i bytes di parità
				
				//if (i==(nblock-1))
				//if (i==0)
				//{
				//	for (h=0; h<(nn-kk); h++)
				//		printf("%x\n",buff[h]);
				//	//system("pause");
				//}
				cio_seek(posend+ldpread+i*kk); // si posiziona nel blocco dati corrispondente
				if (i<(nblock-1))
				{	//printf("tt: %d\tnn: %d\n",nn-kk,nn);
					for (h=(nn-kk); h<nn; h++)
					{	
						buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
					}
				}
				else
				{
					ndata = epb[count].ldpepb - ((nblock-1) * kk);  // l'ultimo blocco di dati non necessariamente è lungo 64!
					for (h=(nn-kk); h<(nn-kk)+ndata; h++)
					{
						buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
					}
					if (lastepb==1)
					{
						next = cio_tell();
						//next = startsot + psot;
						//cio_seek(next);
					}
					//else
					//{
					//	next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
					//}
					//next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
					if ((cio_read(2) == 0xffd9)||(psot == 0))
						*j2k_state = J2K_STATE_MT;
					cio_skip(-2);
				}
				
				for (h=0; h<nn1; h++)
					recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare
	        
				/*f = fopen("debug","a");
				if (f==NULL)
					printf("Unable to open file!\n");
				fprintf(f,"EPB DATA: %d-%d\n",count,i);
				for (h=0; h<nn1; h++)
					fprintf(f,"%x ",recd[h]);
				fprintf(f,"\n");
				fclose(f);*/
				
				generate_gf(nn1,kk1) ;
				gen_poly(nn1,kk1) ;
				for (h=0; h<nn1; h++)
					recd[h] = index_of[recd[h]] ;// a questo punto recd[] contiene i bytes decodificati
				decode_rs(nn1,kk1,tt);  
				
				if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
				{
					//Inizializzo il buffer in cui vado a copiare la RED
					cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
					cio_seek(redpos);

					//printf("Il blocco corrispondente non è stato decodificato!\n");
					cio_write(posend+ldpread+i*kk,4); // Scrive il byte di start del range considerato	
					//printf("START: %x\n",posend+ldpread+i*kk);
					//printf("END: %x\n",posend+ldpread+i*kk+ndata);

					if (i<(nblock -1))
						cio_write(posend+ldpread+i*kk + kk - 1,4);  // Scrive il byte di end del range
					else
						cio_write(posend+ldpread+i*kk + ndata - 1,4);  // Scrive il byte di end del range
					// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
					cio_write(0xFFFF,2);
					redlen+=10;
					redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
					//printf("ciao\n");
				}

				// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

				cio_init(cssrc, cslen);

				cio_seek(posdata2+i*(nn-kk));  // si posiziona all'inizio del blocco di parità corrispondente
				for (h=0; h<(nn-kk); h++)
					cio_write(recd[h],1);  // copia nella codestream i bytes di parità corretti
			
				//cio_seek(posdata2+epb[count].ldata+i*kk);// si posiziona all'inizio del blocco dati corrispondente
				cio_seek(posend+ldpread+i*kk);// si posiziona all'inizio del blocco dati corrispondente
				if (i<(nblock-1))
				{
					for (h=(nn-kk); h<nn; h++)
						cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
				}
				else
				{
					ndata = epb[count].ldpepb - (nblock-1) * kk;  // l'ultimo blocco di dati non necessariamente è lungo 64!			
					for (h=(nn-kk); h<(nn-kk)+ndata; h++)
						cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
				}
			}//fine ciclo for (i=0; i<nblock; i++)

			} // fine if (!(epb[count]->pepb))
		
		// A questo punto abbiamo corretto anche la parte di dati cui fa riferimento la seconda
		// parte del campo EPBdata

			ldpread += epb[count].ldpepb;
			cio_seek(pos+2);
			cio_skip(epb[count].lepb);
			pos = cio_tell(); // posizione a valle dell'EPB corrente
			
		} // fine for (count=0; count<nepbpm; count++)

		
		cio_seek(next); // si posiziona alla fine dei dati corretti dall'EPB
		//printf("read: %x\n",cio_read(2));
		//cio_skip(-2);
		temp = cio_read(2);
		if (temp == J2K_MS_SOT)
			*j2k_state = J2K_STATE_TPHSOT;
		if (temp == J2K_MS_EOC)
			*j2k_state = J2K_STATE_MT;
		cio_skip(-2);

		//csread += ldpread;
		
		free(alpha_to);
		free(index_of);
		free(gg);
		free(recd);
		free(data);
		free(bb);
		free(buff);
		
		return nepbpm; // Ritorna il numero di EPB letti in modalità packed
	}	
		

}

int read_EPB(int next, int *j2k_state)  // funzione che ritorna la posizione subito a valle dell'EPB letto
//void read_EPB(int *j2k_state)  // funzione che ritorna la posizione subito a valle dell'EPB letto
{
	unsigned int lepb, lsiz, temp, ldata, lsot;
	int posdata, posdata2, nblock, i,h, pos, lante, lpar;
	int nn, kk, tt, nn1, kk1; // parametri per la decodifica RS
	//int pos1, pos2, h; // utili per la gestione della decodifica della seconda parte di EPB
	unsigned long ldpepb, pepb, ndata, datacrc;  // ndata è utile per la decodifica della seconda parte EPB
	unsigned char depb;
	unsigned char *buff;
	int prova;
	//FILE *f;

	//next = 0;
	//cio_seek(next); // si posiziona all'inizio della codestream
	//j2k_state = J2K_STATE_MHSOC;  // ci troviamo nel Main-Header e ci aspettiamo SOC
	//FIRST_epb = 1;  // vuol dire che bisogna usare il codice di default RS(160,64)
    
	//printf("nepb: %d\n",nepb);
    //count = 0;  // ancora non abbiamo letto nessun EPB
	//while (count < nepb)
	//{
	cio_seek(next);
	//next = cio_tell();
		if (*j2k_state == J2K_STATE_MHSOC)  
		{
			// Se siamo giunti a questo punto vuol dire che SOC e i primi due campi di SIZ non sono
			// errati!!...ora ci dobbiamo posizionare subito a valle di SIZ
			//*printf("j2k_state: %x\n",*j2k_state);
			cio_skip(4); // si pone all'inizio del campo Lsiz
			lsiz = cio_read(2);
			cio_skip(lsiz-2); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			//*printf("EPB: %x\n",temp);
			nn = 160; kk = 64; tt = 48;  // inizializzazione per codice RS(160,64)
			lante = lsiz+4; 
			
		} // fine if (j2k_state == J2K_STATE_MHSOC)

		if (*j2k_state == J2K_STATE_TPHSOT)
		{
			
			//*printf("j2k_state: %x\n",*j2k_state);
			startsot = cio_tell(); // memorizza nella variabile globale la posizione di SOT
			cio_skip(2); // si pone all'inizio del campo Lsot
			lsot = cio_read(2);
			cio_skip(2); // si posiziona all'inizio del campo Psot
			psot = cio_read(4); // Legge il campo Psot
			cio_skip(-6); // si riposiziona a valle del campo Lsot
			//*printf("lsot: %d\n",lsot);
			cio_skip(lsot-2); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			//*printf("EPB: %x\n",temp);
			nn = 80; kk = 25; tt = 28;  // inizializzazione per codice RS(80,25)
			lante = lsot+2;
		}

		if ((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_TPH))
		{
			//*printf("j2k_state: %x\n",*j2k_state);
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2); // ci si aspetta qui di trovare il marker EPB
			nn = 40; kk = 13; tt = 14;  // inizializzazione per codice RS(40,13)
			lante = 0;
		}

    // A questo punto possiamo decodificare la prima parte di dati tramite i codici di default

	//printf("nn,kk,tt: %d,%d,%d\n",nn,kk,tt);
	nn1 = 255; kk1 = kk + (nn1 - nn);
	alpha_to = (int *) malloc((nn1+1)*sizeof(int));
	index_of = (int *) malloc((nn1+1)*sizeof(int));
	gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
	recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
	data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
	bb = (int *) malloc((nn1-kk1)*sizeof(int));

	//printf("COUNT: %d\n",count);
	lepb = cio_read(2);  // legge la lunghezza di EPB..si spera che questo campo non è errato!
	//*printf("LEPB: %x\n",lepb);
	cio_skip(9);  // si posiziona all'inizio del campo dati di EPB
	posdata = cio_tell();
	//printf("data: %x\n",cio_read(2));
	//cio_skip(-2);
	ldata = lepb - 11;  // determina la lunghezza del campo dati
	
	lpar = nn - kk; // determina la lunghezza dei bit di parità utilizzati per correggere la prima parte di EPB
	if (*j2k_state == J2K_STATE_MHSOC)  
	{
		lpar = nbckpar * (nn-kk);
	}
	if (*j2k_state == J2K_STATE_TPHSOT)
		nbckpar = 1;
	//lbuf = lante + 13 + lpar;  // lpar è la lunghezza dei bit di parità 
	//*printf("lbuf = %d\n",lbuf);
	buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
	          // e i parametri di EPB

	for (i=0; i<nbckpar; i++)
	{
		//buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
	                                           // e i parametri di EPB
		//printf("Ho inizializzato il buffer!\n");
		for (h=0; h<nn1; h++)
			buff[h] = 0; // inizializza il buffer tutto a zero
	
		// Bisognerà copiare tutto il contenuto da questo punto fino alla fine della prima parte dei dati EPB in buff
		// Per come lavora il decoder RS, i bytes di parità vanno posti all'inizio del buffer

		write_buff(buff,posdata+i*(nn-kk),(nn-kk)); // copia nel buffer i byte di parità del campo dati
		//printf("PROVA\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",buff[h]);
		//system("pause");
	
		//printf("nbckpar: %d\n",nbckpar);
		//printf("nn: %d\n",nn);
		cio_seek(next + i*kk);  // si posiziona all'inizio dei dati protetti (SOC,SOT o EPB)
		if (i<(nbckpar -1))
		{
			for (h=(nn-kk); h<nn; h++)
			{
				buff[h] = cio_read(1);  // copia in buff i byte di messaggio (SOC,SIZ,ParEPB)
				//printf(" %x\n",buff[i]);
			}
		}
		else
		{
			if (*j2k_state == J2K_STATE_MHSOC)
			{
				ndata = lmex - ((nbckpar-1) * kk); // l'ultimo blocco dati non è in genere lungo 64!
				for (h=(nn-kk); h<((nn-kk)+ndata); h++)
				{
					buff[h] = cio_read(1);
				}
			}
			else
				for (h=(nn-kk); h<nn; h++)
					buff[h] = cio_read(1);  
				
			
		}
		//printf("Eccomi qua-1!\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",buff[h]);
		//system("pause");

		for (h=0; h<nn1; h++)
			recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare

		//printf("Eccomi qua-1!\n");
		//if (*j2k_state == J2K_STATE_MHSOC)
		//if (i==0)
		//{
		//	f = fopen("debug","a");
		//	if (f==NULL)
		//		printf("Unable to open file!\n");
		//	fprintf(f,"\n");
		//	for (h=0; h<nn1; h++)
		//		fprintf(f,"%x ",recd[h]);
		//	fprintf(f,"\n");
		//	fclose(f);
		//}
		//else
		//{
		//f = fopen("debug","a");
		//if (f==NULL)
		//	printf("Unable to open file!\n");
		//fprintf(f,"\n");
		//for (h=0; h<nn1; h++)
		//	fprintf(f,"%x ",recd[h]);
		//fprintf(f,"\n");
		//fclose(f);
		//}
		//printf("Eccomi qua-1!\n");
		//for (h=0; h<nn1; h++)
		//	printf(" %x\n",recd[h]);
		//system("pause");

		generate_gf(nn1,kk1) ;
		gen_poly(nn1,kk1) ;
		for (h=0; h<nn1; h++)
			recd[h] = index_of[recd[h]] ; // a questo punto recd[] contiene i bytes decodificati
		decode_rs(nn1,kk1,tt); 

		if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
		{
			//Inizializzo il buffer in cui vado a copiare la RED
			cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
			cio_seek(redpos);

			//printf("Il blocco corrispondente non è stato decodificato!\n");
			cio_write(next + i*kk,4); // Scrive il byte di start del range considerato	
			redlen += 4;
			if (i<(nbckpar -1))
				cio_write(next + i*kk + kk,4);  // Scrive il byte di end del range
			else
			{
				if (*j2k_state == J2K_STATE_MHSOC)
					cio_write(next + i*kk + ndata,4);  // Scrive il byte di end del range
				else
					cio_write(next + i*kk + kk,4);
			}
			redlen += 4;
			// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
			cio_write(0xFFFF,2);
			redlen += 2;
			if ((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH))
				redlenok+=10;
			//cio_seek(redpos);
			//printf("START: %x\n",cio_read(4));
			//printf("END: %x\n",cio_read(4));
			//printf("VALUE: %x\n",cio_read(2));
			redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
			//printf("ciao\n");
		}

		//printf("Eccomi qua-2!\n");
		//for (i=0; i<nn1; i++)
		//	printf(" %x\n",recd[i]);
		//system("pause");

		// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

		cio_init(cssrc, cslen); //******Aggiunto in questa versione 1.7
		
		cio_seek(posdata+i*(nn-kk)); // si posiziona all'inizio del blocco di parità corrispondente	
		for (h=0; h<(nn-kk); h++)
			cio_write(recd[h],1);  // copia i byte di parità corretti nel campo dati
		cio_seek(next + i*kk);
		if (i<(nbckpar -1))
		{
			for (h=(nn-kk); h<nn; h++)
				cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
		}
		else
		{
			if (*j2k_state == J2K_STATE_MHSOC)
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				{
					cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
				}
			else
				for (h=(nn-kk); h<nn; h++)
				cio_write(recd[h],1);  // copia i bytes di messaggio nella codestream
		}
	} // fine ciclo for (i=0; i<nbckpar; i++)

	// A questo punto la codestream è corretta fino alla fine della prima parte dei dati EPB
	// Possiamo leggere i parametri di EPB per condurre la codifica seguente

	
	cio_seek(pos);  // si posiziona all'inizio di EPB
	temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			if (temp != JPWL_MS_EPB)
			{
				//*printf("Non ho decodificato l'EPB!\n"); 
				// Puo' succedere che l'EPC ha fornito informazione errata: in tal caso il
				// processo di decodifica effettuato perde di significato.
				// Puo' anche succedere pero' che il codice RS contenuto nell'EPB MS non
				// è stato in grado di correggere l'errore sul marker EPB!!
				
				return 0;
				//return;
				// Per adesso usciamo dalla procedura, ma la cosa migliore sarebbe
				// fare in modo che il decoder vada a cercare l'eventuale EPB successivo
			}

	//*count++; // se siamo a questo punto vuol dire che è stato letto effettivamente un EPB
	//printf("mark: %x\n",temp);
	cio_skip(2); // ora è all'inizio del campo depb
	depb = cio_read(1); // legge depb
	//*printf("depb: %x\n",depb);
	ldpepb = cio_read(4); // legge ldpepb
	//*printf("ldpepb: %x\n",ldpepb);
	pepb = cio_read(4); // legge pepb
	if (nepbrd!=0)
	{
		temp = cio_tell();
		cio_init(epc.tecn[0].pid, epc.tecn[0].lid);
		cio_seek(nepbrd*4);
		if (pepb!=cio_read(4))
		{
			cio_skip(-4);
			pepb=cio_read(4); // Copia nel campo pepb il corrispondente pepc contenuto in EPC
		}
		cio_init(cssrc, cslen);
		cio_seek(temp);
	}
	//*printf("pepb: %x\n",pepb);
	//*printf("ldata1: %d\n",ldata);
	ldata = ldata - nbckpar*(nn-kk);  // lunghezza della porzione rimanente del campo dati
	//*printf("ldata2: %d\n",ldata);
	cio_seek(posdata + nbckpar*(nn-kk)); 
	posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
	//printf("nbckpar: %d\n",nbckpar);
	//printf("mark: %x\n",cio_read(2));
	//cio_skip(-2);

	if ((!((depb >> 6)&1))&&((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH)))
		*j2k_state = J2K_STATE_MH; // vuol dire che il prossimo EPB è in MH ma non è il primo
	if (((depb >> 6)&1)&&((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_MHSOC)))
		*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
	if (((depb >> 6)&1)&&((*j2k_state == J2K_STATE_TPH)||(*j2k_state == J2K_STATE_TPHSOT)))
		*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
	if ((!((depb >> 6)&1))&&((*j2k_state == J2K_STATE_TPHSOT)||(*j2k_state == J2K_STATE_TPH)))
		*j2k_state = J2K_STATE_TPH; // vuol dire che il prossimo EPB è relativo ad un TPH

	if (!((depb >> 7)&1))
		epbpm = 1; // Gli EPB sono scritti in modalità unpacked (epbpm=0)
	else
		epbpm = 0; // Gli EPB sono scritti in modalità packed (epbpm=1)


	nepbrd++;
	
	// Ora leggendo pepb il decoder deve capire quale codice applicare per la porzione di dati
	// cui fa riferimento la seconda parte del campo EPBdata

	if (pepb)  // se pepb=0 allora si usano i codici di default precedenti
	{
		if ((pepb>>28)==2)
		{
			// in questo caso deve effettuare la decodifica RS
			/***********/
			// liberiamo gli spazi allocati
			free(alpha_to);
			free(index_of);
			free(gg);
			free(recd);
			free(data);
			free(bb);
			/***********/
			kk = (int) pepb & 0x000000ff;
		    nn = (int) (pepb>>8) & 0x000000ff;
			tt = (int) ceil((double)(nn-kk)/2);
			nn1 = 255; kk1 = kk + (nn1 - nn);
			alpha_to = (int *) malloc((nn1+1)*sizeof(int));
			index_of = (int *) malloc((nn1+1)*sizeof(int));
			gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
			recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
			data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
			bb = (int *) malloc((nn1-kk1)*sizeof(int));
			generate_gf(nn1,kk1) ;
			gen_poly(nn1,kk1) ;
		}

		if ((pepb>>28)==1)
		{
			// in questo caso deve effettuare le decodifica CRC
			free(buff);
			buff = (char *) malloc(ldpepb * sizeof(char));
			write_buff(buff,posdata2+ldata,ldpepb);
			if (pepb & 0x00000001)	// vuol dire che bisogna decodificare secondo CRC 32
			{
				/*per fare il crc32 occorre invertire i byte in ingresso, invertire il crc calcolato
			    e farne il complemento a 1*/
				ResetCRC();
				for (i=0; i < ldpepb; i++)
					UpdateCRC32(reflectByte(buff[i]));	
				reflectCRC32();
				crcSum ^= 0xffffffff;	// effettua il complemento a 1	
				cio_seek(posdata2);
				datacrc = cio_read(4);
				if (datacrc == crcSum)
					printf("CRC corretto!\n");
				else
					printf("CRC errato!\n");
			}
			else	// vuol dire che bisogna decodificare secondo CRC 16
			{
				ResetCRC();
				for (i=0; i < ldpepb; i++)
					UpdateCRC16(buff[i]);	
				cio_seek(posdata2);
				datacrc = cio_read(2);
				if (datacrc == crcSum)
					printf("CRC corretto!\n");
				else
					printf("CRC errato!\n");
			}
			free(buff);
			return (posdata2 + ldata + ldpepb);  // ritorna la posizione a valle dei dati successivi a EPB
			//return;
		}

		if (pepb>=0x30000000)
		{
			// tecniche registrate in RA
			return (posdata2 + ldata + ldpepb);
			// Per adesso prevede la semplice uscita dalla funzione
		}

		if (pepb==0xffffffff)
		{
			// non sono usati metodi per i dati seguenti
			return (posdata2 + ldata + ldpepb);
			//return;
		}
	}

	

	/*******************/
	// qui bisogna aggiungere la parte per la gestione della modalità packed/unpacked
	/*******************/

	
	//cio_seek(posdata + (nn-kk)); 
	//posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
	
	/********************/
	// Per adesso si suppone che il primo EPB di un header utilizza lo stesso codice
	// di default anche per la seconda parte dei dati...in seguito bisognerà aggiungere
	// la funzionalità che gestisce l'uso dei vari codici in base al campo pepb
	/********************/

	// Ora bisogna copiare in buff la seconda parte dei dati di EPB e i dati successivi all'epb
	// per una lunghezza pari a ldpepb
    
	nblock = ldata / (nn-kk);  // numero di "blocchi di decodifica"
	//printf("nblock = %d\n",nblock);
	//*system("pause");
	//cio_seek(posdata2);  // si posiziona all'inizio della seconda parte dei dati EPB
	free(buff);
	buff = (char *) malloc(nn1 * sizeof(char));
	for (i=0; i<nblock; i++)
	{
		//free(buff);
		//buff = (char *) malloc(nn1 * sizeof(char));
		for (h=0; h<nn1; h++)
			buff[h] = 0; // inizializza il buffer tutto a zero
		write_buff(buff,posdata2+i*(nn-kk),(nn-kk)); // copia nel buff i bytes di parità
		cio_seek(posdata2+ldata+i*kk); // si posiziona nel blocco dati corrispondente
		
		//if (i==0) {
		//	printf("data: %x\n",cio_read(2));
		//    cio_skip(-2);
		//	system("pause");
		//}
		//pos1 = cio_tell(); // memorizza la posizione del blocco dati corrispondente
		if (i<(nblock-1))
		{
			//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+64; h++)
			for (h=(nn-kk); h<nn; h++)
			{
				buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
				//if (i==1)
				//  printf("Data: %x\n",buff[h]);  /**********/
			}
			//system("pause"); /***********/
		}
		else
		{
			ndata = ldpepb - ((nblock-1) * kk);  // l'ultimo blocco di dati non necessariamente è lungo 64!
			//*printf("ndata: %d\n",ndata);
			//*system("pause");
			//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+ndata; h++)
			for (h=(nn-kk); h<(nn-kk)+ndata; h++)
			{
				buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
				//printf("Data: %x\n",buff[h]);  /**********/
			}
			//system("pause"); /***********/
			next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
			if (cio_read(2) == 0xffd9)
				*j2k_state = J2K_STATE_MT;
			cio_skip(-2);
		}
		
		for (h=0; h<nn1; h++)
			recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare

		//if (*j2k_state == J2K_STATE_TPHSOT)
		//{
		//	f = fopen("debug","w");
		//	if (f==NULL)
		//		printf("Unable to open file!\n");
		//	fprintf(f,"\n");
		//	for (h=0; h<nn1; h++)
		//		fprintf(f,"%x ",recd[h]);
		//	fprintf(f,"\n");
		//	fclose(f);
		//}
		//else
		//{
		//f = fopen("debug","a");
		//if (f==NULL)
		//	printf("Unable to open file!\n");
		//fprintf(f,"\n");
		//for (h=0; h<nn1; h++)
		//	fprintf(f,"%x ",recd[h]);
		//fprintf(f,"\n");
		//fclose(f);
		//}
		//for (h=0; h<nn1; h++)
		//	printf("mess: %x\n",recd[h]);
		//system("pause");

		//printf("nn1: %d\n",nn1);
		//printf("kk1: %d\n",kk1);
        
		generate_gf(nn1,kk1) ;
		gen_poly(nn1,kk1) ;
		for (h=0; h<nn1; h++)
			recd[h] = index_of[recd[h]] ;  // a questo punto recd[] contiene i bytes decodificati
		decode_rs(nn1,kk1,tt);  
		
		if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
		{
			//Inizializzo il buffer in cui vado a copiare la RED
			cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
			cio_seek(redpos);

			//printf("Il blocco corrispondente non è stato decodificato!\n");
			cio_write(posdata2+ldata+i*kk,4); // Scrive il byte di start del range considerato	
			redlen += 4;
			if (i<(nblock -1))
				cio_write(posdata2+ldata+i*kk + kk,4);  // Scrive il byte di end del range
			else
				cio_write(posdata2+ldata+i*kk + ndata,4);  // Scrive il byte di end del range
			redlen += 4;
			// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
			cio_write(0xFFFF,2);
			redlen += 2;
			if ((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_TPHSOT))
				redlenok+=10;
			redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
			//printf("ciao\n");
		}
		if ((redlen==0)&(redmode==1))
			free(red.reddata);
		
		//*printf("nciclo: %d\n\n",i);
		//for (h=0; h<nn1; h++)
		//	printf("mess: %x\n",recd[h]);
		//system("pause");

		// Adesso bisogna ricopiare il contenuto di recd[] nella codestream
		
		cio_init(cssrc, cslen); //*****Aggiunto in questa versione 1.7
		
		cio_seek(posdata2+i*(nn-kk));  // si posiziona all'inizio del blocco di parità corrispondente
		for (h=0; h<(nn-kk); h++)
		{
			cio_write(recd[h],1);  // copia nella codestream i bytes di parità corretti
			//printf("par: %x\n",recd[h]);
		}
		//system("pause");
		
		cio_seek(posdata2+ldata+i*kk);
		if (i<(nblock-1))
		{
			//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+64; h++)
			for (h=(nn-kk); h<nn; h++)
				cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
		}
		else
		{
			ndata = ldpepb - (nblock-1) * kk;  // l'ultimo blocco di dati non necessariamente è lungo 64!			
			//for (h=(posdata2+i*(2*tt)); h<(posdata2+i*(2*tt))+ndata; h++)
			for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
		}
	}//fine ciclo for (i=0; i<nblock; i++)
	

	free(alpha_to);
	free(index_of);
	free(gg);
	free(recd);
	free(data);
	free(bb);
	/***********/

	//} // fine ciclo while iniziale
	free(buff);
	// A questo punto abbiamo corretto anche la parte di dati cui fa riferimento la seconda
	// parte del campo EPBdata

	// Bisogna ora posizionarsi alla fine dei dati corretti
	//next = posdata2 + ldata + ldpepb;
    //cio_seek(next);
	//if (cio_read(2) == 0xffd9)
	//	*j2k_state = J2K_STATE_MT;
	//printf("next: %x\n",cio_read(2));
	//cio_skip(-2);
	
	return next; // Ritorna la posizione subito a valle dell'EPB appena letto!!!
	//return;
	
	//*ltemp=cio_tell();
	//if (cio_read(2)==0xffd9)
	//{
	//	cio_write(0xffd9,2);
	//	cio_skip(-2);
	//}
	//cio_skip(-2);
	//*if (cio_read(2)==0xffd9)
	//*{
	///*	cio_seek(0);
	//	f=fopen("output.txt","wb");
	//*	for (i=0; i<ltemp+2; i++)
	//*		fputc(cio_read(1),f);
    //*    cio_skip(-2);
	//*	printf("EOC: %x\n",cio_read(2));
	//*	fclose(f);
	//*}
	
    //*cio_skip(-2);
	//*printf("next: %x\n",cio_read(2));
	//*cio_skip(-2);
	//*system("pause");
	/***********/
	// liberiamo gli spazi allocati
	
	
	

	//return;
} // fine funzione read_EPB



// La funzione seguente inizializza a zero la struttura relativa ad EPC

//void init_EPC()
//{
//    epc.lepc = 0;
//	epc.pcrc = 0;
//	epc.cl = 0;
//	epc.pepc = 0;
//	epc.tecn = NULL;   
//}

int read_EPB_PM(int *j2k_state)  // Gestisce la lettura degli EPB packed mode
{
	unsigned int lepb, lsiz, temp, ldata, lbuf, lsot;
	int posdata, posdata2, nblock, i,h, pos, lante;
	int lastepb, nepbpm, posfirst, posend, count; // variabili per la gestione modalità packed
	unsigned long lpack, ldpread;	// variabili per la gestione modalità packed
	EPB_par *epb;	// variabili per la gestione modalità packed
	int nn, kk, tt, nn1, kk1; // parametri per la decodifica RS
	unsigned long ldpepb, pepb, ndata, datacrc;  // ndata è utile per la decodifica della seconda parte EPB
	unsigned char depb;
	unsigned char *buff;

	int lparity;
	// int conta;
	//FILE *f;
	
	//next = cio_tell();
	//printf("read: %x\n",cio_read(2));
	//cio_skip(-2);
		if (*j2k_state == J2K_STATE_MHSOC)  
		{
			// Se siamo giunti a questo punto vuol dire che SOC e i primi due campi di SIZ non sono
			// errati!!...ora ci dobbiamo posizionare subito a valle di SIZ
			
			cio_skip(4); // si pone all'inizio del campo Lsiz
			lsiz = cio_read(2);
			cio_skip(lsiz-2); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			nn = 160; kk = 64; tt = 48;  // inizializzazione per codice RS(160,64)
			lante = lsiz+4;
			
		} // fine if (j2k_state == J2K_STATE_MHSOC)

		if (*j2k_state == J2K_STATE_TPHSOT)
		{
			
			cio_skip(2); // si pone all'inizio del campo Lsot
			lsot = cio_read(2);
			cio_skip(lsot-2); // ora siamo all'inizio dell'EPB MS
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			nn = 80; kk = 25; tt = 28;  // inizializzazione per codice RS(80,25)
			lante = lsot+2;
		}

		if ((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_TPH))
		{
			pos = cio_tell(); // memorizza la posizione in cui inizia l'EPB
			temp = cio_read(2); // ci si aspetta qui di trovare il marker EPB
			nn = 40; kk = 13; tt = 14;  // inizializzazione per codice RS(40,13)
			lante = 0;
		}
	// A questo punto possiamo decodificare la prima parte di dati tramite i codici di default

	//printf("state: %x\n",*j2k_state);
	//printf("tt: %d\n",nn-kk);
	posfirst = pos; // memorizza la posizione al'inizio della catena di EPB packed
	nn1 = 255; kk1 = kk + (nn1 - nn);
	alpha_to = (int *) malloc((nn1+1)*sizeof(int));
	index_of = (int *) malloc((nn1+1)*sizeof(int));
	gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
	recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
	data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
	bb = (int *) malloc((nn1-kk1)*sizeof(int));

	lastepb = 0; // Si suppone che l'EPB corrente non sia l'ultimo di un tile!
	nepbpm = 0;
	//conta = 0;

	while (lastepb == 0)
	{

	lepb = cio_read(2);  // legge la lunghezza di EPB..si spera che questo campo non è errato!
	cio_skip(9);  // si posiziona all'inizio del campo dati di EPB
	posdata = cio_tell();
	ldata = lepb - 11;  // determina la lunghezza del campo dati
	//printf("ldata: %d\n",ldata);
	lbuf = lante + 13 + (nn-kk);  // 2*tt è la lunghezza dei bit di parità 
	buff = (char *) malloc(nn1 * sizeof(char)); // buffer che conterrà tutti i dati che precedono EPB
	                                           // e i parametri di EPB
	for (i=0; i<nn1; i++)
		buff[i] = 0; // inizializza il buffer tutto a zero
	
	// Bisognerà copiare tutto il contenuto da questo punto fino alla fine della prima parte dei dati EPB in buff
	// Per come lavora il decoder RS, i bytes di parità vanno posti all'inizio del buffer

	
	write_buff(buff,posdata,(nn-kk)); // copia nel buffer i byte di parità del campo dati
	
	cio_seek(pos);  // si posiziona all'inizio dei dati protetti (SOC,SOT o EPB)
	for (i=(nn-kk); i<lbuf; i++)
	{
		buff[i] = cio_read(1);  // copia in buff i byte di messaggio (SOC,SIZ,ParEPB)
	}

	for (i=0; i<nn1; i++)
		recd[i] = buff[i];  // copia in recd il contenuto di buff da decodificare

	//f = fopen("debug","a");
	//if (f==NULL)
	//	printf("Unable to open file!\n");
	//fprintf(f,"EPB PAR: %d\n",conta);
	//for (h=0; h<nn1; h++)
	//	fprintf(f,"%x ",recd[h]);
	//fprintf(f,"\n");
	//fclose(f);

	generate_gf(nn1,kk1) ;
	gen_poly(nn1,kk1) ;
	for (i=0; i<nn1; i++)
     recd[i] = index_of[recd[i]] ; // a questo punto recd[] contiene i bytes decodificati     
	decode_rs(nn1,kk1,tt);  

	if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
		{
			//Inizializzo il buffer in cui vado a copiare la RED
			cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
			cio_seek(redpos);

			//printf("Il blocco corrispondente non è stato decodificato!\n");
			cio_write(pos,4); // Scrive il byte di start del range considerato	
			cio_write(pos + lbuf - (nn - kk),4);  // Scrive il byte di end del range
			// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
			cio_write(0xFFFF,2);
			redlen += 10;
			redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
			//printf("ciao\n");
		}
	// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

	cio_init(cssrc, cslen);

	cio_seek(posdata); // si posiziona all'inizio del campo dati della codestream	
	for (i=0; i<(nn-kk); i++)
		cio_write(recd[i],1);  // copia i byte di parità corretti nel campo dati
	cio_seek(pos);
	for (i=(nn-kk); i<lbuf; i++)
		cio_write(recd[i],1);  // copia i bytes di messaggio nella codestream

	// A questo punto la codestream è corretta fino alla fine della prima parte dei dati EPB
	// Possiamo leggere i parametri di EPB per condurre la codifica seguente

	
	cio_seek(pos);  // si posiziona all'inizio di EPB
	temp = cio_read(2);  // ci si aspetta qui di trovare il marker EPB
			if (temp != JPWL_MS_EPB)
			{
				// Puo' succedere che l'EPC ha fornito informazione errata: in tal caso il
				// processo di decodifica effettuato perde di significato.
				// Puo' anche succedere pero' che il codice RS contenuto nell'EPB MS non
				// è stato in grado di correggere l'errore sul marker EPB!!
				return 0;
				// Per adesso usciamo dalla procedura, ma la cosa migliore sarebbe
				// fare in modo che il decoder vada a cercare l'eventuale EPB successivo
			}

	cio_skip(2); // ora è all'inizio del campo depb
	depb = cio_read(1); // legge depb
	//if ((depb >> 6)&1)  // quello corrente è l'ultimo EPB del tile corrente
	//{
	//	lastepb = 1; // l'epb corrente è l'ultimo del tile
		//nepbpm = ((depb << 2) >> 2); // numero di EPB accorpati in modalità packed
	//	nepbpm = (depb & 0x3f); // numero di EPB accorpati in modalità packed
		//printf("nepbpm: %d\n",nepbpm);
	//}
	if (!((depb >> 6)&1))  // quello corrente non è l'ultimo EPB del tile corrente
		nepbpm += 1;
	if ((depb >> 6)&1)  // quello corrente è l'ultimo EPB del tile corrente
	{
		nepbpm += 1;
		lastepb = 1;
	}

	cio_skip(-3); // si posiziona all'inizio del campo lepb
	cio_skip(cio_read(2)-2);  // si posiziona a valle dell'epb corrente
	pos = cio_tell(); // memorizza la posizione all'inizio dell'EPB successivo
	cio_skip(2);

	//conta++;

	} // Fine while (lastepb == 0)!!!!
    // A questo punto il decoder ha decodificato le porzioni iniziali di tutti gli EPB
	// del tile corrente
	

	// Ora dobbiamo decodificare le porzioni finali di tutti gli EPB!!!

	// pos contiene la posizione a valle dell'ultimo degli EPB packed!!!
	cio_skip(-2);
	posend = cio_tell();
	lpack = posend-posfirst; // lunghezza totale della catena di EPB
	epb = (EPB_par *) malloc(nepbpm * sizeof(EPB_par));
	cio_seek(posfirst);
	//printf("nepbpm: %d\n",nepbpm);
	for (count=0; count<nepbpm; count++)
	{
		cio_skip(2); // si posiziona all'inizio di lepb
		epb[count].lepb = cio_read(2); // legge lepb
		epb[count].depb = cio_read(1); // legge depb
		epb[count].ldpepb = cio_read(4); // legge ldpepb
		epb[count].pepb = cio_read(4); // legge pepb

		temp = cio_tell();
		cio_init(epc.tecn[0].pid, epc.tecn[0].lid);
		cio_seek((nepbrd+count)*4);
		if (epb[count].pepb!=cio_read(4))
		{
			cio_skip(-4);
			epb[count].pepb=cio_read(4); 
		}
		cio_init(cssrc, cslen);
		cio_seek(temp);

		epb[count].ldata = (epb[count].lepb - 11) - (nn-kk);  // lunghezza della porzione rimanente del campo dati
		cio_skip(-11); // si posiziona all'inizio di lepb dell'EPB corrente
	    cio_skip(epb[count].lepb); // si posiziona a valle dell'EPB corrente
	} // Abbiamo a questo punto memorizzato nella struttura epb i parametri degli EPB packed

	//for (count=0; count<nepbpm; count++)
	//{
	//	printf("EPB[%d]: %x\t%x\t%x\t%x\t%d\n",count,epb[count].lepb,epb[count].depb,
	//		epb[count].ldpepb,epb[count].pepb,epb[count].ldata);
	//}

	nepbrd+=nepbpm;

	cio_seek(posfirst);  // si posiziona all'inizio del primo degli EPB packed
	pos = cio_tell();
	ldpread = 0;
	lparity = nn - kk;
	//printf("lparity: %d\n",lparity);
	for (count=0; count<nepbpm; count++)
	{
		cio_seek(pos);
		//printf("mark: %x\n",cio_read(2));
		//cio_skip(-2);
		cio_skip(13); // si posiziona all'inizio del campo dati
		posdata = cio_tell();
		//printf("tt: %d\n",nn-kk);
		cio_seek(posdata + lparity); // si posiziona all'inizio seconda parte dati EPB corrente
		posdata2 = cio_tell(); // posizione inizio seconda parte dati EPB
		//printf("rd: %x\n",cio_read(2));
		//cio_skip(-2);

		if ((!((epb[count].depb >> 6)&1))&&((*j2k_state == J2K_STATE_MHSOC)||(*j2k_state == J2K_STATE_MH)))
			*j2k_state = J2K_STATE_MH; // vuol dire che il prossimo EPB è in MH ma non è il primo
		if (((epb[count].depb >> 6)&1)&&((*j2k_state == J2K_STATE_MH)||(*j2k_state == J2K_STATE_MHSOC)))
			*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
		if (((epb[count].depb >> 6)&1)&&((*j2k_state == J2K_STATE_TPH)||(*j2k_state == J2K_STATE_TPHSOT)))
			*j2k_state = J2K_STATE_TPHSOT; // vuol dire che il prossimo EPB è il primo di un TPH
		if ((!((epb[count].depb >> 6)&1))&&((*j2k_state == J2K_STATE_TPHSOT)||(*j2k_state == J2K_STATE_TPH)))
			*j2k_state = J2K_STATE_TPH; // vuol dire che il prossimo EPB è relativo ad un TPH
		
		// Ora leggendo pepb il decoder deve capire quale codice applicare per la porzione di dati
		// cui fa riferimento la seconda parte del campo EPBdata
		
		if (epb[count].pepb)  // se pepb=0 allora si usano i codici di default precedenti
		{
			if ((epb[count].pepb>>28)==2)
			{
				// in questo caso deve effettuare la decodifica RS
				/***********/
				// liberiamo gli spazi allocati
				free(alpha_to);
				free(index_of);
				free(gg);
				free(recd);
				free(data);
				free(bb);
				/***********/
				kk = (int) epb[count].pepb & 0x000000ff;
				nn = (int) (epb[count].pepb>>8) & 0x000000ff;
				tt = (int) ceil((double)(nn-kk)/2);
				nn1 = 255; kk1 = kk + (nn1 - nn);
				alpha_to = (int *) malloc((nn1+1)*sizeof(int));
				index_of = (int *) malloc((nn1+1)*sizeof(int));
				gg = (int *) malloc((nn1-kk1+1)*sizeof(int));
				recd = (int *) malloc((nn1)*sizeof(int)); ///forse alcune di queste malloc possono
				data = (int *) malloc((kk1)*sizeof(int)); // essere eliminate, inutili per decodifica!!!
				bb = (int *) malloc((nn1-kk1)*sizeof(int));
				generate_gf(nn1,kk1) ;
				gen_poly(nn1,kk1) ;
			}

			if ((epb[count].pepb>>28)==1)
			{
				// in questo caso deve effettuare le decodifica CRC
				free(buff);
				buff = (char *) malloc(epb[count].ldpepb * sizeof(char));
				write_buff(buff,posdata2+epb[count].ldata,epb[count].ldpepb);
				if (epb[count].pepb & 0x00000001)	// vuol dire che bisogna decodificare secondo CRC 32
				{
					/*per fare il crc32 occorre invertire i byte in ingresso, invertire il crc calcolato
					e farne il complemento a 1*/
					ResetCRC();
					cio_seek(posend+ldpread); // si posiziona nel blocco dati corrispondente
					for (i=0; i < epb[count].ldpepb; i++)
						UpdateCRC32(reflectByte(buff[i]));	
					reflectCRC32();
					if (lastepb==1)
					{
						next = startsot + psot;
						cio_seek(next);
						//printf("%x\n",cio_read(2));
						//cio_skip(-2);
					}
					if ((cio_read(2) == 0xffd9)||(psot == 0))
						*j2k_state = J2K_STATE_MT;
					cio_skip(-2);
					//else
					//{
					//	next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
					//}
					crcSum ^= 0xffffffff;	// effettua il complemento a 1	
					cio_seek(posdata2);
					datacrc = cio_read(4);
					if (datacrc == crcSum)
						printf("CRC corretto!\n");
					else
						printf("CRC errato!\n");
					
				}
				else	// vuol dire che bisogna decodificare secondo CRC 16
				{
					ResetCRC();
					cio_seek(posend+ldpread); // si posiziona nel blocco dati corrispondente
					for (i=0; i < epb[count].ldpepb; i++)
						UpdateCRC16(buff[i]);
					if (lastepb==1)
					{
						next = startsot + psot;
						cio_seek(next);
					}
					if ((cio_read(2) == 0xffd9)||(psot == 0))
						*j2k_state = J2K_STATE_MT;
					cio_skip(-2);
					cio_seek(posdata2);
					datacrc = cio_read(2);
					if (datacrc == crcSum)
						printf("CRC corretto!\n");
					else
						printf("CRC errato!\n");
				}
				//free(buff);
			}

			if (epb[count].pepb>=0x30000000)
			{
				//if (lastepb==1)
				//		next = startsot + psot;
				// tecniche registrate in RA
			}

			if (epb[count].pepb==0xffffffff)
			{
				//if (lastepb==1)
				//		next = startsot + psot;
				// non sono usati metodi per i dati seguenti
			}
		}
		
		if (((epb[count].pepb>>28)==2)||(epb[count].pepb==0))  // Vuol dire che si usano codici RS
		{
		// Ora bisogna copiare in buff la seconda parte dei dati di EPB e i dati successivi all'epb
		// per una lunghezza pari a ldpepb
    
		//printf("posiz: %x\n",posdata2 + epb[count].ldata);
		nblock = epb[count].ldata / (nn-kk);  // numero di "blocchi di decodifica"
		free(buff);
		buff = (char *) malloc(nn1 * sizeof(char));
		//printf("ldata: %d\n",epb[count].ldata);
		//printf("nblock: %d\n",nblock);
		for (i=0; i<nblock; i++)
		{
			//free(buff);
			//buff = (char *) malloc(nn1 * sizeof(char));
			for (h=0; h<nn1; h++)
				buff[h] = 0; // inizializza il buffer tutto a zero
			write_buff(buff,posdata2+i*(nn-kk),(nn-kk)); // copia nel buff i bytes di parità
			//if (i==(nblock-1))
			//{
			//	for (h=0; h<(nn-kk); h++)
			//		printf("%x\n",buff[h]);
			//	system("pause");
			//}
			cio_seek(posend+ldpread+i*kk); // si posiziona nel blocco dati corrispondente
			if (i<(nblock-1))
			{
				for (h=(nn-kk); h<nn; h++)
				{
					buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
				}
			}
			else
			{
				ndata = epb[count].ldpepb - ((nblock-1) * kk);  // l'ultimo blocco di dati non necessariamente è lungo 64!
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
				{
					buff[h] = cio_read(1);  // copia nel buff i bytes di messaggio
				}
				if (lastepb==1)
				{
					next = startsot + psot;
					cio_seek(next);
				}
				//else
				//{
				//	next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
				//}
				//next = cio_tell();  // posizione alla fine dei dati protetti (ldpepb)
				if ((cio_read(2) == 0xffd9)||(psot == 0))
					*j2k_state = J2K_STATE_MT;
				cio_skip(-2);
			}
		
			for (h=0; h<nn1; h++)
				recd[h] = buff[h];  // copia in recd il contenuto di buff da decodificare
        
			//f = fopen("debug","a");
			//if (f==NULL)
			//	printf("Unable to open file!\n");
			//fprintf(f,"EPB DATA: %d-%d\n",count,i);
			//for (h=0; h<nn1; h++)
			//	fprintf(f,"%x ",recd[h]);
			//fprintf(f,"\n");
			//fclose(f);

			generate_gf(nn1,kk1) ;
			gen_poly(nn1,kk1) ;
			for (h=0; h<nn1; h++)
				recd[h] = index_of[recd[h]] ;// a questo punto recd[] contiene i bytes decodificati
			decode_rs(nn1,kk1,tt);  

			if (decodeflag == 0) //*******Aggiunto in questa versione 1.7
			{
				//Inizializzo il buffer in cui vado a copiare la RED
				cio_init(red.reddata,cslen); //*******Aggiunta in questa versione 1.7
				cio_seek(redpos);

				//printf("Il blocco corrispondente non è stato decodificato!\n");
				cio_write(posend+ldpread+i*kk,4); // Scrive il byte di start del range considerato	
				if (i<(nblock -1))
					cio_write(posend+ldpread+i*kk + kk,4);  // Scrive il byte di end del range
				else
					cio_write(posend+ldpread+i*kk + ndata,4);  // Scrive il byte di end del range
				// Adesso segnaliamo la presenza di errori con 0xFFFF!!!
				cio_write(0xFFFF,2);
				redlen+=10;
				redpos = cio_tell(); // Memorizza la posizione attuale del buffer RED
				//printf("ciao\n");
			}

			// Adesso bisogna ricopiare il contenuto di recd[] nella codestream

			cio_init(cssrc, cslen);

			cio_seek(posdata2+i*(nn-kk));  // si posiziona all'inizio del blocco di parità corrispondente
			for (h=0; h<(nn-kk); h++)
				cio_write(recd[h],1);  // copia nella codestream i bytes di parità corretti
		
			//cio_seek(posdata2+epb[count].ldata+i*kk);// si posiziona all'inizio del blocco dati corrispondente
			cio_seek(posend+ldpread+i*kk);// si posiziona all'inizio del blocco dati corrispondente
			if (i<(nblock-1))
			{
				for (h=(nn-kk); h<nn; h++)
					cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
			}
			else
			{
				ndata = epb[count].ldpepb - (nblock-1) * kk;  // l'ultimo blocco di dati non necessariamente è lungo 64!			
				for (h=(nn-kk); h<(nn-kk)+ndata; h++)
					cio_write(recd[h],1);  // copia nella codestream il blocco di dati corretti
			}
		}//fine ciclo for (i=0; i<nblock; i++)

		} // fine if (!(epb[count]->pepb))
	
	// A questo punto abbiamo corretto anche la parte di dati cui fa riferimento la seconda
	// parte del campo EPBdata

		ldpread += epb[count].ldpepb;
		cio_seek(pos+2);
		cio_skip(epb[count].lepb);
		pos = cio_tell(); // posizione a valle dell'EPB corrente

	} // fine for (count=0; count<nepbpm; count++)

	cio_seek(next); // si posiziona alla fine del tile
	//printf("read: %x\n",cio_read(2));
	//cio_skip(-2);
	
	free(alpha_to);
	free(index_of);
	free(gg);
	free(recd);
	free(data);
	free(bb);
	free(buff);
	
	return nepbpm; // Ritorna il numero di EPB letti in modalità packed
	
}

/*******************************************************************/
///////////////FUNZIONE AGGIUNTA IN QUESTA VERSIONE//////////////////
void insert_RED(int pos, int lred, int redlenok)
{
	unsigned long i;
	unsigned char *buff;
	int temp, mem;
	// Buffer in cui verrà salvata la codestream a partire dal primo SOT
	buff = (char *) malloc((epc.cl-pos) * sizeof(char));
	//printf("lung: %d\n",epc.cl-pos);
	for (i=0; i<(epc.cl-pos); i++)
	{
		buff[i] = cio_read(1);
		//printf("i: %d\n",i);
	}
	//printf("fine: %x\n",buff[epc.cl-pos-1]);
	// A questo punto andiamo a scrivere il marker segment RED
	cio_seek(pos);
	//cio_skip(-2);
	//printf("red: %x\n",cio_read(2));
	cio_write(JPWL_MS_RED,2); // Inserisce il marker
	cio_write(red.lred,2); // Inserisce il campo Lred
	cio_write(red.pred,1); // Inserisce il campo Pred
	//printf("redlen: %d\n",redlen);
	temp = cio_tell(); // Memorizza posizione corrente della CS
	
	//printf("redlenok: %d\n",redlenok);
	//for (i=0; i<redlen; i++)
	//	printf("%x",red.reddata[i]);
	//printf("\n");
	//printf("lred: %d\n",lred);
	cio_init(red.reddata,cslen); // Aggiorna le posizioni a causa dell'offset introdotto
	cio_seek(redlenok);			// dall'aggiunta del MS RED
	for (i=0; i<(redlen-redlenok)/10; i++)
	{
		mem = cio_read(4);
		//printf("mem: %x\n",mem);
		cio_skip(-4);
		cio_write(mem + lred,4); // Aggiorna il byte di inizio
		mem = cio_read(4);
		//printf("mem: %x\n",mem);
		cio_skip(-4);
		cio_write(mem + lred,4); // Aggiorna il byte di fine
	}

	cio_init(cssrc,epc.cl+redlen+5);
	cio_seek(temp);

	for (i=0; i<redlen; i++)
		cio_write(red.reddata[i],1); // Copio il buffer reddata nella codestream
	// Adesso andiamo a riaggiungere il resto della codestream
	//printf("cl: %d\n",epc.cl);
	//printf("pos: %d\n",pos);
	//printf("cl-pos: %d\n",epc.cl-pos);
	//printf("fine: %x\n",buff[epc.cl-pos]);
	cio_init(cssrc,epc.cl+redlen+5);
	cio_seek(pos + redlen + 5);
	for (i=0; i<(epc.cl-pos); i++)
	{
		cio_write(buff[i],1);
		//printf("i: %d\n",i);
	}
	cio_skip(-2);
	//printf("fine: %x\n",cio_read(2));
}
/*******************************************************************/

// La funzione seguente legge la codestream a partire da pos e la copia in buff
void write_buff(unsigned char *buff,int pos,long cl)
{
    long i;
	cio_seek(pos);
	for (i=0; i<cl; i++) 
		 buff[i] = cio_read(1);	 
}

// La funzione seguente copia il contenuto di buff a partire dalla posizione della
// stream p
void read_buff(unsigned char *buff,int pos,long cl)
{
	long i;
	cio_seek(pos);
	for (i=0; i<cl; i++)
		cio_write(buff[i],1);
}


void ResetCRC()
{
	crcSum = 0xffffffff;
}


void UpdateCRC16(char x)
{
	int tmp;
	tmp = ((x ^ (crcSum >> 8)) & 0xff);
	crcSum = ((crcSum << 8) ^ CrcT16[tmp]) & 0xffff;
}

void UpdateCRC32(char x)
{
	int tmp;
	tmp = ((x ^ (crcSum >> 24)) & 0xff);
	crcSum = ((crcSum << 8) ^ CrcT32[tmp]);
}
/* funzioni per l'inversione dei byte e del crc32 */

char reflectByte(char inbyte)
{
  // reflect one byte

  unsigned char outbyte=0;
  unsigned char i=0x01;
  unsigned char j;

  for (j=0x080; j; j>>=1) 
  {
    if (inbyte & i) outbyte|=j;
    i<<=1;
  }
  
  return outbyte;
}


void reflectCRC32()
{
 

  unsigned long outcrc=0;
  unsigned long i=0x00000001;
  unsigned long j;

  for (j=0x80000000; j; j>>=1) 
  {
    if (crcSum & i) 
		outcrc|=j;
    i=i<<1;
  }
  crcSum = outcrc;
}

// Codice relativo alla CODIFICA/DECODIFICA RS



//#define nn  255          /* nn=2**mm -1   length of codeword */
//#define tt  48           /* number of errors that can be corrected */
//#define kk  159           /* kk = nn-2*tt  */

//int pp [mm+1] = { 1, 1, 0, 0, 1} ; /* specify irreducible polynomial coeffts */



void generate_gf(int nn, int kk)
/* generate GF(2**mm) from the irreducible polynomial p(X) in pp[0]..pp[mm]
   lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;
                   polynomial form -> index form  index_of[j=alpha**i] = i
   alpha=2 is the primitive element of GF(2**mm)
*/
 {
   register int i, mask ;

  mask = 1 ;
  alpha_to[mm] = 0 ;
  for (i=0; i<mm; i++)
   { alpha_to[i] = mask ;
     index_of[alpha_to[i]] = i ;
     if (pp[i]!=0)
       alpha_to[mm] ^= mask ;
     mask <<= 1 ;
   }
  index_of[alpha_to[mm]] = mm ;
  mask >>= 1 ;
  for (i=mm+1; i<nn; i++)
   { if (alpha_to[i-1] >= mask)
        alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1]^mask)<<1) ;
     else alpha_to[i] = alpha_to[i-1]<<1 ;
     index_of[alpha_to[i]] = i ;
   }
  index_of[0] = -1 ;
 }


void gen_poly(int nn, int kk)
/* Obtain the generator polynomial of the tt-error correcting, length
  nn=(2**mm -1) Reed Solomon code  from the product of (X+alpha**i), i=1..2*tt
*/
 {
   register int i,j ;

   gg[0] = 2 ;    /* primitive element alpha = 2  for GF(2**mm)  */
   gg[1] = 1 ;    /* g(x) = (X+alpha) initially */
   for (i=2; i<=nn-kk; i++)
    { gg[i] = 1 ;
      for (j=i-1; j>0; j--)
        if (gg[j] != 0)  gg[j] = gg[j-1]^ alpha_to[(index_of[gg[j]]+i)%nn] ;
        else gg[j] = gg[j-1] ;
      gg[0] = alpha_to[(index_of[gg[0]]+i)%nn] ;     /* gg[0] can never be zero */
    }
   /* convert gg[] to index form for quicker encoding */
   for (i=0; i<=nn-kk; i++)  gg[i] = index_of[gg[i]] ;
 }


void encode_rs(int nn, int kk, int tt)
/* take the string of symbols in data[i], i=0..(k-1) and encode systematically
   to produce 2*tt parity symbols in bb[0]..bb[2*tt-1]
   data[] is input and bb[] is output in polynomial form.
   Encoding is done by using a feedback shift register with appropriate
   connections specified by the elements of gg[], which was generated above.
   Codeword is   c(X) = data(X)*X**(nn-kk)+ b(X)          */
 {
   register int i,j ;
   int feedback ;

   for (i=0; i<nn-kk; i++)   bb[i] = 0 ;
   for (i=kk-1; i>=0; i--)
    {  feedback = index_of[data[i]^bb[nn-kk-1]] ;
       if (feedback != -1)
        { for (j=nn-kk-1; j>0; j--)
            if (gg[j] != -1)
              bb[j] = bb[j-1]^alpha_to[(gg[j]+feedback)%nn] ;
            else
              bb[j] = bb[j-1] ;
          bb[0] = alpha_to[(gg[0]+feedback)%nn] ;
        }
       else
        { for (j=nn-kk-1; j>0; j--)
            bb[j] = bb[j-1] ;
          bb[0] = 0 ;
        } ;
    } ;
 } ;

// La funzione seguente, leggermente modificata rispetto al sorgente in "eccpage", ritorna
// 1 se è riuscita a correggere gli errori o se non ci sono errori, 0 se il processo di 
// decodifica RS non è stato portato a termine.

void decode_rs(int nn, int kk, int tt)
/* assume we have received bits grouped into mm-bit symbols in recd[i],
   i=0..(nn-1),  and recd[i] is index form (ie as powers of alpha).
   We first compute the 2*tt syndromes by substituting alpha**i into rec(X) and
   evaluating, storing the syndromes in s[i], i=1..2tt (leave s[0] zero) .
   Then we use the Berlekamp iteration to find the error location polynomial
   elp[i].   If the degree of the elp is >tt, we cannot correct all the errors
   and hence just put out the information symbols uncorrected. If the degree of
   elp is <=tt, we substitute alpha**i , i=1..n into the elp to get the roots,
   hence the inverse roots, the error location numbers. If the number of errors
   located does not equal the degree of the elp, we have more than tt errors
   and cannot correct them.  Otherwise, we then solve for the error value at
   the error location and correct the error.  The procedure is that found in
   Lin and Costello. For the cases where the number of errors is known to be too
   large to correct, the information symbols as received are output (the
   advantage of systematic encoding is that hopefully some of the information
   symbols will be okay and that if we are in luck, the errors are in the
   parity part of the transmitted codeword).  Of course, these insoluble cases
   can be returned as error flags to the calling routine if desired.   */
 {
   register int i,j,u,q ;
   //int elp[nn-kk+2][nn-kk], d[nn-kk+2], l[nn-kk+2], u_lu[nn-kk+2], s[nn-kk+1] ;
   //int count=0, syn_error=0, root[tt], loc[tt], z[tt+1], err[nn], reg[tt+1] ;

   
   int **elp, *d, *l, *u_lu, *s;
   int count=0, syn_error=0, *root, *loc, *z, *err, *reg;


   elp = (int **) malloc((nn-kk+2)*sizeof(int));
   for (i=0; i<(nn-kk+2); i++)
	   elp[i] = (int *) malloc((nn-kk)*sizeof(int));
   d = (int *) malloc((nn-kk+2)*sizeof(int));
   l = (int *) malloc((nn-kk+2)*sizeof(int));
   u_lu = (int *) malloc((nn-kk+2)*sizeof(int));
   s = (int *) malloc((nn-kk+2)*sizeof(int));
   root = (int *) malloc(tt*sizeof(int));
   loc = (int *) malloc(tt*sizeof(int));
   z = (int *) malloc((tt+1)*sizeof(int));
   err = (int *) malloc(nn*sizeof(int));
   reg = (int *) malloc((tt+1)*sizeof(int));


/* first form the syndromes */
   for (i=1; i<=nn-kk; i++)
    { s[i] = 0 ;
      for (j=0; j<nn; j++)
        if (recd[j]!=-1)
          s[i] ^= alpha_to[(recd[j]+i*j)%nn] ;      /* recd[j] in index form */
/* convert syndrome from polynomial form to index form  */
      if (s[i]!=0)  syn_error=1 ;        /* set flag if non-zero syndrome => error */
      s[i] = index_of[s[i]] ;
    } ;

   if (syn_error)       /* if errors, try and correct */
    {
/* compute the error location polynomial via the Berlekamp iterative algorithm,
   following the terminology of Lin and Costello :   d[u] is the 'mu'th
   discrepancy, where u='mu'+1 and 'mu' (the Greek letter!) is the step number
   ranging from -1 to 2*tt (see L&C),  l[u] is the
   degree of the elp at that step, and u_l[u] is the difference between the
   step number and the degree of the elp.
*/
/* initialise table entries */
      d[0] = 0 ;           /* index form */
      d[1] = s[1] ;        /* index form */
      elp[0][0] = 0 ;      /* index form */
      elp[1][0] = 1 ;      /* polynomial form */
      for (i=1; i<nn-kk; i++)
        { elp[0][i] = -1 ;   /* index form */
          elp[1][i] = 0 ;   /* polynomial form */
        }
      l[0] = 0 ;
      l[1] = 0 ;
      u_lu[0] = -1 ;
      u_lu[1] = 0 ;
      u = 0 ;

      do
      {
        u++ ;
        if (d[u]==-1)
          { l[u+1] = l[u] ;
            for (i=0; i<=l[u]; i++)
             {  elp[u+1][i] = elp[u][i] ;
                elp[u][i] = index_of[elp[u][i]] ;
             }
          }
        else
/* search for words with greatest u_lu[q] for which d[q]!=0 */
          { q = u-1 ;
            while ((d[q]==-1) && (q>0)) q-- ;
/* have found first non-zero d[q]  */
            if (q>0)
             { j=q ;
               do
               { j-- ;
                 if ((d[j]!=-1) && (u_lu[q]<u_lu[j]))
                   q = j ;
               }while (j>0) ;
             } ;

/* have now found q such that d[u]!=0 and u_lu[q] is maximum */
/* store degree of new elp polynomial */
            if (l[u]>l[q]+u-q)  l[u+1] = l[u] ;
            else  l[u+1] = l[q]+u-q ;

/* form new elp(x) */
            for (i=0; i<nn-kk; i++)    elp[u+1][i] = 0 ;
            for (i=0; i<=l[q]; i++)
              if (elp[q][i]!=-1)
                elp[u+1][i+u-q] = alpha_to[(d[u]+nn-d[q]+elp[q][i])%nn] ;
            for (i=0; i<=l[u]; i++)
              { elp[u+1][i] ^= elp[u][i] ;
                elp[u][i] = index_of[elp[u][i]] ;  /*convert old elp value to index*/
              }
          }
        u_lu[u+1] = u-l[u+1] ;

/* form (u+1)th discrepancy */
        if (u<nn-kk)    /* no discrepancy computed on last iteration */
          {
            if (s[u+1]!=-1)
                   d[u+1] = alpha_to[s[u+1]] ;
            else
              d[u+1] = 0 ;
            for (i=1; i<=l[u+1]; i++)
              if ((s[u+1-i]!=-1) && (elp[u+1][i]!=0))
                d[u+1] ^= alpha_to[(s[u+1-i]+index_of[elp[u+1][i]])%nn] ;
            d[u+1] = index_of[d[u+1]] ;    /* put d[u+1] into index form */
          }
      } while ((u<nn-kk) && (l[u+1]<=tt)) ;

      u++ ;
      if (l[u]<=tt)         /* can correct error */
       {
/* put elp into index form */
         for (i=0; i<=l[u]; i++)   elp[u][i] = index_of[elp[u][i]] ;

/* find roots of the error location polynomial */
         for (i=1; i<=l[u]; i++)
           reg[i] = elp[u][i] ;
         count = 0 ;
         for (i=1; i<=nn; i++)
          {  q = 1 ;
             for (j=1; j<=l[u]; j++)
              if (reg[j]!=-1)
                { reg[j] = (reg[j]+j)%nn ;
                  q ^= alpha_to[reg[j]] ;
                } ;
             if (!q)        /* store root and error location number indices */
              { root[count] = i;
                loc[count] = nn-i ;
                count++ ;
              };
          } ;
         if (count==l[u])    /* no. roots = degree of elp hence <= tt errors */
          {
/* form polynomial z(x) */
           for (i=1; i<=l[u]; i++)        /* Z[0] = 1 always - do not need */
            { if ((s[i]!=-1) && (elp[u][i]!=-1))
                 z[i] = alpha_to[s[i]] ^ alpha_to[elp[u][i]] ;
              else if ((s[i]!=-1) && (elp[u][i]==-1))
                      z[i] = alpha_to[s[i]] ;
                   else if ((s[i]==-1) && (elp[u][i]!=-1))
                          z[i] = alpha_to[elp[u][i]] ;
                        else
                          z[i] = 0 ;
              for (j=1; j<i; j++)
                if ((s[j]!=-1) && (elp[u][i-j]!=-1))
                   z[i] ^= alpha_to[(elp[u][i-j] + s[j])%nn] ;
              z[i] = index_of[z[i]] ;         /* put into index form */
            } ;

  /* evaluate errors at locations given by error location numbers loc[i] */
           for (i=0; i<nn; i++)
             { err[i] = 0 ;
               if (recd[i]!=-1)        /* convert recd[] to polynomial form */
                 recd[i] = alpha_to[recd[i]] ;
               else  recd[i] = 0 ;
             }
           for (i=0; i<l[u]; i++)    /* compute numerator of error term first */
            { err[loc[i]] = 1;       /* accounts for z[0] */
              for (j=1; j<=l[u]; j++)
                if (z[j]!=-1)
                  err[loc[i]] ^= alpha_to[(z[j]+j*root[i])%nn] ;
              if (err[loc[i]]!=0)
               { err[loc[i]] = index_of[err[loc[i]]] ;
                 q = 0 ;     /* form denominator of error term */
                 for (j=0; j<l[u]; j++)
                   if (j!=i)
                     q += index_of[1^alpha_to[(loc[j]+root[i])%nn]] ;
                 q = q % nn ;
                 err[loc[i]] = alpha_to[(err[loc[i]]-q+nn)%nn] ;
                 recd[loc[i]] ^= err[loc[i]] ;  /*recd[i] must be in polynomial form */
               }
            }
			decodeflag = 1;
			//printf("Ho corretto gli errori!\n");
          }
         else    /* no. roots != degree of elp => >tt errors and cannot solve */
		 {  for (i=0; i<nn; i++)        /* could return error flag if desired */
               if (recd[i]!=-1)        /* convert recd[] to polynomial form */
                 recd[i] = alpha_to[recd[i]] ;
               else  recd[i] = 0 ;     /* just output received codeword as is */
			decodeflag = 0;
			//printf("Non ho corretto!\n");
		 }
       }
     else         /* elp has degree has degree >tt hence cannot solve */
	 {  for (i=0; i<nn; i++)       /* could return error flag if desired */
          if (recd[i]!=-1)        /* convert recd[] to polynomial form */
            recd[i] = alpha_to[recd[i]] ;
          else  recd[i] = 0 ;     /* just output received codeword as is */
		decodeflag = 0;
		//printf("Non ho corretto!\n");
	 }
    }
   else       /* no non-zero syndromes => no errors: output received codeword */
   { for (i=0; i<nn; i++)
       if (recd[i]!=-1)        /* convert recd[] to polynomial form */
         recd[i] = alpha_to[recd[i]] ;
       else  recd[i] = 0 ;
	 decodeflag = 1;	
	 //printf("La codestream non contiene errori!\n");
   }

   /******/
	//   int **elp, *d, *l, *u_lu, *s;
   //int count=0, syn_error=0, *root, *loc, *z, *err, *reg;

   //elp = (int *) malloc((nn-kk+2)*sizeof(int));
   
   for (i=0; i<(nn-kk+2); i++)
      free(elp[i]);
   free(elp);
   free(d);
   free(l); 
   free(u_lu);
   free(s);
   free(root);
   free(loc); 
   free(z); 
   free(err);
   free(reg);
 }



