Logo Search packages:      
Sourcecode: gdcm version File versions

jpw.c

// 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);
 }




Generated by  Doxygen 1.6.0   Back to index