Logo Search packages:      
Sourcecode: gdcm version File versions

jpw.c

/*
 * Copyright 2004-2005 Andrea Betti and Michele Massarelli
 * Copyright 2004-2005 DIEI, University of Perugia
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */


/* questa è un' estensione della libreria dell'openjpeg in grado di implementare
 * la parte 11 dello standard JPEG2000 ossia il JPWL
 */

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

// JPWL MARKERS 
#define JPWL_MS_EPC 0xff68
#define JPWL_MS_EPB 0xff66
#define JPWL_MS_ESD 0xff67
#define JPWL_MS_RED 0xff69


//stati del codec
#define J2K_STATE_MHSOC 0x0001
#define J2K_STATE_MHSIZ 0x0002
#define J2K_STATE_MH 0x0004
#define J2K_STATE_TPHSOT 0x0008
#define J2K_STATE_TPH 0x0010
#define J2K_STATE_MT 0x0020
#define J2K_STATE_NEOC 0x0040
#define J2K_STATE_MHEPB 0x0080
#define J2K_STATE_TPHEPB 0x0100

//carica la struttura relativa ai parametri JPWL
extern JPWL_cp_t jpwl_cp;
extern int j2k_state;
extern j2k_cp_t *j2k_cp;
extern info_image info_IM;

static long crcSum;
static long pepbs[1000];
static int cont_epb=0;
static int scavalcato=0;

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


/* inizializza i parametri relativi al JPWL *
 * disabilitando le funzionalità            */

void jpwl_cp_init(JPWL_cp_t *jpwl_cp){
      jpwl_cp->JPWL_on = 0;
      jpwl_cp->EPB_on = 0;
      jpwl_cp->ESD_on = 0;
      jpwl_cp->RED_on = 0;
      jpwl_cp->info_tech_on = 0;
}

/****************************************************************************************
 *                                                                                                                                  *
 *                                                  Marker JPWL                                                               *
 *                                                                                                                                  *
 ****************************************************************************************/

/* Scrive il marker segment EPC
   version 0.1: in questa prima fase questo andrà subito dopo il SIZ */

void jpwl_write_EPC(){
      int lenp, len, i;
      char c, P_EPC = 0;
      cio_write(JPWL_MS_EPC, 2);
      lenp = cio_tell();
      cio_skip(2);
      // calcola il crc
      cio_skip(2);
      // per adesso lascio uno spazio vuoto (16 bit)
      // CL settore di 32bit che indica la lungheza della codestream:
      // per ora metto tutto uguale a zero (info non disponibile)
      cio_write(0, 4);
      // P_EPC indica se nella codestream saranno usati gli altri 
      // marker segment oppure tecniche informative aggiuntive 
      if (jpwl_cp.ESD_on)
            P_EPC += 0x10;
      if (jpwl_cp.RED_on)
            P_EPC += 0x20;
      if (jpwl_cp.EPB_on)
            P_EPC += 0x40;
      if (jpwl_cp.info_tech_on)
            P_EPC += 0x80;
      cio_write(P_EPC, 1);
      //scrivo i Pepb

      if(jpwl_cp.EPB_on)
            JPWL_write_Pepbs(NULL,0);




      /* Al momento non esistono tecniche informative aggiuntive per richiamarle
       * opereremo in questo modo:
       * 0) dovrò inserire nella struttura jpwl_cp_t un campo contenente un puntatore
       *    ad un array che conterrà gli ID delle tecniche informative da usare;
       * 1) conrollo il campo info_tech_on;
       * 2) eseguo delle funzioni da inserire nel file jpw.c e jpw.h relative alle 
       *    tecniche informative desiderate; tali funzioni dovranno preoccuparsi di
       *    creare i campi corretti nel marker segment.
       *  if( jpwl_cp->info_tech_on){
       *      qui inserirò i comandi desiderati
       *  }
       */
    len = cio_tell() - lenp;
      cio_seek(lenp);
      cio_write(len, 2);
      // calcola il crc
      cio_skip(-4);
      ResetCRC();
      for (i=0; i<4; i++){
            c = cio_read(1);
            UpdateCRC16(c);   
      }
      cio_skip(2);
      for (i=6; i<(len + 2); i++){
            c = cio_read(1);
            UpdateCRC16(c);   
      }
      cio_seek(lenp + 2);
      cio_write(crcSum, 2);
      cio_seek(lenp + len);

}


void jpwl_write_EPC_fin(unsigned long CL, long *pepbs, int num_epb){
      int lenp, len, i;
      unsigned long len_codestr;
      char c, P_EPC = 0;
      cio_write(JPWL_MS_EPC, 2);
      lenp = cio_tell();
      cio_skip(2);
      // calcola il crc
      cio_skip(2);
      // per adesso lascio uno spazio vuoto (16 bit)
      // CL settore di 32bit che indica la lungheza della codestream:
      // per ora metto tutto uguale a zero (info non disponibile)
      cio_write(0, 4);
      // P_EPC indica se nella codestream saranno usati gli altri 
      // marker segment oppure tecniche informative aggiuntive 
      if (jpwl_cp.ESD_on)
            P_EPC += 0x10;
      if (jpwl_cp.RED_on)
            P_EPC += 0x20;
      if (jpwl_cp.EPB_on)
            P_EPC += 0x40;
      if (jpwl_cp.info_tech_on)
            P_EPC += 0x80;
      cio_write(P_EPC, 1);
      //scrivo i Pepb

      if(jpwl_cp.EPB_on)
            JPWL_write_Pepbs(pepbs, num_epb);




      /* Al momento non esistono tecniche informative aggiuntive per richiamarle
       * opereremo in questo modo:
       * 0) dovrò inserire nella struttura jpwl_cp_t un campo contenente un puntatore
       *    ad un array che conterrà gli ID delle tecniche informative da usare;
       * 1) conrollo il campo info_tech_on;
       * 2) eseguo delle funzioni da inserire nel file jpw.c e jpw.h relative alle 
       *    tecniche informative desiderate; tali funzioni dovranno preoccuparsi di
       *    creare i campi corretti nel marker segment.
       *  if( jpwl_cp->info_tech_on){
       *      qui inserirò i comandi desiderati
       *  }
       */
    len = cio_tell() - lenp;
      cio_seek(lenp);
      cio_write(len, 2);
      //scrivo la lunghezza della codestream
      cio_skip(2);
      len_codestr = CL + len + 2;
      cio_write(len_codestr, 4);
      // calcola il crc
      cio_skip(-10);
      ResetCRC();
      for (i=0; i<4; i++){
            c = cio_read(1);
            UpdateCRC16(c);   
      }
      cio_skip(2);
      for (i=6; i<(len + 2); i++){
            c = cio_read(1);
            UpdateCRC16(c);   
      }
      cio_seek(lenp + 2);
      cio_write(crcSum, 2);
      cio_seek(lenp + len);

}



void JPWL_write_EPB(char *buf, unsigned long LDPepb, unsigned long Pepb, unsigned char Depb){
      int *alpha_to, *index_of, *gg, *data_, *bb;
      unsigned long i=0;
      unsigned int len = 11, lenp, scrivi_pb, cont, leggi, tenta=0;
      char pos_epb;
      unsigned data_unprot = 0, RS = 0;
      int n1, n2, k1, k2, j, n=255, k, CRC = 0, go_back;      // 0 = disabilitato, 1 = CRC CCITT 16 bit, 2 = Ethernet CRC 32 bit 
      //prova
      /*FILE *f;
      FILE *fp;*/


      cio_write(JPWL_MS_EPB, 2);
      lenp = cio_tell();
      /* determino len_epb e i parametri di codifica*/
      pos_epb= Depb & 0x3F;
      if ((j2k_state == J2K_STATE_MH) && !(pos_epb)){  // sto scrivendo il primo epb del mh
            
            n1=160;
            k1=64;
            go_back =lenp + 11;
            len += (n1 - k1)*(unsigned int)ceil((double)go_back/k1);
      } else {if ((j2k_state == J2K_STATE_TPH) && !(pos_epb)&& !(scavalcato)){            // primo epb di un tph
                        n1=80;
                        k1=go_back=25;
                        len += 55;
                        
                  } else {                    // altro epb
                        n1=40;
                        k1=go_back=13;
                        len += 27;
                        //tenta=1;
                  }
      }
      if (!Pepb) {               // per codificare i dati seguenti uso lo stesso codice di prima
            RS = 1;
            n2 = n1;
            k2 = k1;
          len +=(unsigned int) ceil((double)LDPepb/k2)*(n2 - k2);

      } else{
            if (Pepb == 0xffffffff)    
                  data_unprot=1;
            else {if ((Pepb >> 28)== 1){
                        if ((Pepb & 0x00000001)){
                              CRC = 2;
                              len += 4;
                        } else {
                              CRC = 1;
                              len +=2;
                        }
                  } else {if ((Pepb >> 28)== 2){
                                    n2 = ((Pepb & 0x0000ff00)>> 8);
                                    k2 = (Pepb & 0x000000ff);
                                    RS = 1;
                                    len +=(unsigned int) ceil((double)LDPepb/k2)*(n2 - k2);
                                    }
                              }
                  }
      }
      cio_write(len, 2);    // Lepb
      cio_write(Depb, 1);           //Depb
      cio_write((LDPepb & 0xffff0000) >> 16, 2);  //LDPepb
    cio_write((LDPepb & 0x0000ffff), 2);
      cio_write((Pepb & 0xffff0000) >> 16, 2);  //Pepb
    cio_write((Pepb & 0x0000ffff), 2);
      //printf("start\n");

      // devi implementare il codice rs per la protezione dell'epb
      // cio_write(0, (int) ceil((lenp+11)*(n1 - k1)/k1));
      if(!(alpha_to=(int *) calloc(256,sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma1\n ");

    if(!(index_of=(int *) calloc(256,sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma2\n ");
      
      if(!(gg=(int *) calloc((n1 - k1 +1),sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma3\n ");
      
      k = 255-(n1-k1);

      if(!(data_=(int *) calloc(k, sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma4\n ");

      if(!(bb=(int *) calloc((n1 - k1),sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma5\n ");
      
      generate_gf(alpha_to, index_of);

      gen_poly(k, alpha_to, index_of, gg);

      scrivi_pb = cio_tell();

      //prova
      

      cio_skip(-go_back);
      for (cont = 0; cont < (unsigned int) ceil((double)go_back/k1); cont++) {
            for (j=0; j<k1; j++){
                  if (j+(cont*k1) <(unsigned int) go_back)
                        data_[j]= cio_read(1);
                  else data_[j] = 0;            //padding
            }
            for (j=k1; j<k; j++) data_[j] = 0; // padding per la gestione di codici "accorciati"
            
            leggi = cio_tell();
            encode_rs(k,alpha_to, index_of, gg, bb, data_);
            
            cio_seek(scrivi_pb);
            for (j=0; j<(n1-k1); j++)
                  cio_write(bb[j], 1);
            scrivi_pb = cio_tell();
            cio_seek(leggi);
      }
      cio_seek(scrivi_pb);
      
      free(alpha_to);
      free(index_of);
      free(gg);
      free(data_);
      free(bb);

      /* protezione dei dati seguenti */
      
      
      if (!data_unprot) {
            if (CRC == 1){                //crc ccitt 16 bit questo è l'algo
                  ResetCRC();
                  for (i=0; i < LDPepb; i++){
                        UpdateCRC16(buf[i]);    
                  }
                  cio_write(crcSum & 0xffff, 2);
        }
            if (CRC == 2){  
                  /*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(buf[i]));   
                  }
                  reflectCRC32();
                  crcSum ^= 0xffffffff;         
            cio_write((crcSum & 0xffff0000) >> 16, 2);
                  cio_write((crcSum & 0x0000ffff), 2);
        } 
            if (RS) {
                  //printf("n2, k2: %d %d\n", n2, k2);
                  k = 255-(n2-k2);

                  if(!(alpha_to=(int *) malloc(256*sizeof(int))))
                        printf("Non può essere allocata memoria per eseguire il programma1\n ");

                  if(!(index_of=(int *) malloc(256*sizeof(int))))
                        printf("Non può essere allocata memoria per eseguire il programma2\n ");
      
                  if(!(gg=(int *) malloc((n2 - k2 +1)*sizeof(int))))
                        printf("Non può essere allocata memoria per eseguire il programma3\n ");      
                        
                  if(!(data_=(int *) malloc(k*sizeof(int))))
                        printf("Non può essere allocata memoria per eseguire il programma4\n ");

                  if(!(bb=(int *) malloc((n2 - k2)*sizeof(int))))
                        printf("Non può essere allocata memoria per eseguire il programma5\n ");
                  
                  generate_gf(alpha_to, index_of);

                  gen_poly(k, alpha_to, index_of, gg);
                  //printf("num blocchi: %f\n", ceil((double)LDPepb/k2));
                  //printf("resto: %d\n", LDPepb%k2);

                  for (cont = 0; cont < (unsigned int)ceil((double)LDPepb/k2); cont++) {

                        for (j=0; j<k2; j++){
                              if (j+(cont*k2) < LDPepb)
                                    data_[j]= 0x000000ff & buf[j+(cont*k2)];  //qualcuno dovrà spiegarmi il perchè!!!!
                              else data_[j] = 0;            //padding
                        }
                        
                        for (j=k2; j<k; j++) data_[j] = 0; // padding per la gestione di codici "accorciati"
                        //prova
                        /*if ((cont==(unsigned int)ceil((double)LDPepb/k2)-1)&&(tenta)){
                              f=fopen("data.txt","wb");
                              for(j=0; j<k; j++) fputc(data_[j], f);
                              fclose(f);
                        }*/
                        
                        encode_rs(k, alpha_to, index_of, gg, bb, data_);
                        //prova
                        /*if ((cont==(unsigned int)ceil((double)LDPepb/k2)-1)&&(tenta)){
                              fp=fopen("parity.txt","wb");
                              for(j=0; j<(n2-k2); j++) fputc(bb[j], fp);
                              fclose(fp);
                        }*/
                        
                        for (j=0; j<(n2-k2); j++){
                              cio_write(bb[j], 1);
                              }
                        
                  }

                  free(alpha_to);
                  free(index_of);
                  free(gg);
                  free(data_);
                  free(bb);

                  

                  
            }
      }
}


void jpwl_write_ESD(char Pesd, int notil){
      int i, ult, set, nb_pos, nb_sv, metric, mode, cont=0, npix, lev, start, end, temp, len, npack;
      double **dMSE, **dPSNR, maxMSE, **PSNR, M, val, x;

      //nuova versione!!
      cio_write(JPWL_MS_ESD,2);
      set = cio_tell();
      cio_skip(2);   //len
      // faccio solo un esd medio relativo a tutte le componenti
      if(info_IM.Comp < 257)
            cio_write(0,1);         //Cesd
      else cio_write(0x0000,2);
      cio_write(Pesd,1);
      //determino i parametri per scrivere i dati dell'esd
      nb_pos = (((Pesd & 0x02)>>1)==0) ? 2 : 4;
      nb_sv = (((Pesd & 0x04)>>2)==0) ? 1 : 2;
      metric = ((Pesd & 0x38)>>3);
      mode = ((Pesd & 0xC0)>>6);
      M = 65025;
      // creo le matrici che conterranno i valori di deltaMSE e deltaPSNR
      // in realtà spreco un po' di memoria nel caso in cui la scrivo nei tile...
      dMSE = (double **) malloc(j2k_cp->th * j2k_cp->tw * sizeof(double));
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            dMSE[i]=(double*) malloc(info_IM.num *sizeof(double));
      dPSNR = (double **) malloc(j2k_cp->th * j2k_cp->tw * sizeof(double));
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            dPSNR[i]=(double*) malloc(info_IM.num *sizeof(double));
      PSNR = (double **) malloc(j2k_cp->th * j2k_cp->tw * sizeof(double));
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            PSNR[i]=(double*) malloc(info_IM.num * sizeof(double));

      // a questo punto se notil=0 vuol dire che scrivo l'esd nel main header
      // altrimenti notil indica il tile a cui mi riferisco
      ult = (notil == 0) ? j2k_cp->th * j2k_cp->tw : notil;
      if (notil != 0) notil--; 
      
      // calcolo di dPSNR, dMSE e PSNR 
      // nuova routine più snella!!
      for (i = notil; i < ult; i++){
            val = 0;
            npix = info_IM.tile[i].nbpix;
            maxMSE = info_IM.tile[i].distotile / npix;
            for(npack=0; npack < (info_IM.num); npack++){
                  dMSE[i][npack] = info_IM.tile[i].packet[npack].disto / npix;
                  if (dMSE[i][npack]!=0){
                        val += dMSE[i][npack];
                        PSNR[i][npack] = (10 * log10(M/(maxMSE - val)));
                        x = (npack==0) ? 0 : PSNR[i][npack-1];
                        dPSNR[i][npack] = PSNR[i][npack] - x;
                  }
                  else {
                        dPSNR[i][npack] = 0;
                        PSNR[i][npack] = PSNR[i][npack-1];
                  }
            } 
      }
      
      //ora scrivo i valori di sensibilità in base alla metrica scelta
      switch (metric){
                  case 0:
                        //relative error sensitivity: i lvelli di sensibilità coincidono con i layer (livello 0 = header) 
                        //uso sette livelli di sensibilità relativa
                        switch (mode){
                              case 0:
                                    //packet mode
                                    
                                    for (i = notil; i < ult; i++){
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                if (dPSNR[i][npack]>10)
                                                      cio_write(1, 1);
                                                else if ((dPSNR[i][npack]<=10)&&(dPSNR[i][npack]>8))
                                                      cio_write(2,1);
                                                else if ((dPSNR[i][npack]<=8)&&(dPSNR[i][npack]>6))
                                                      cio_write(3,1);
                                                else if ((dPSNR[i][npack]<=6)&&(dPSNR[i][npack]> 4.5))
                                                      cio_write(4,1);
                                                else if ((dPSNR[i][npack]<=4.5)&&(dPSNR[i][npack]>3))
                                                      cio_write(5,1);
                                                else if ((dPSNR[i][npack]<=3)&&(dPSNR[i][npack]>1.7))
                                                      cio_write(6,1);
                                                else
                                                      //(dPSNR[i][npack]<=1.7)
                                                      cio_write(7,1);
                                          }     
                                    }

                                    break;

                              case 1:
                                    //byte range mode
                                    for (i = notil; i < ult; i++){
                                          //inizializzazioni
                                          lev = 0;
                                          start = 0;
                                          end = 1;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                temp=lev;
                                                //determinazione dei livelli 
                                                if (dPSNR[i][npack]>10)
                                                      lev = 1;
                                                else if ((dPSNR[i][npack]<=10)&&(dPSNR[i][npack]>8))
                                                      lev = 2;
                                                else if ((dPSNR[i][npack]<=8)&&(dPSNR[i][npack]>6))
                                                      lev = 3;
                                                else if ((dPSNR[i][npack]<=6)&&(dPSNR[i][npack]> 4.5))
                                                      lev = 4;
                                                else if ((dPSNR[i][npack]<=4.5)&&(dPSNR[i][npack]>3))
                                                      lev = 5;
                                                else if ((dPSNR[i][npack]<=3)&&(dPSNR[i][npack]>1.7))
                                                      lev = 6;
                                                else 
                                                      //(dPSNR[i][npack]<=1.7)
                                                      lev = 7;
                                                if (lev == temp){
                                                      end++;
                                                      continue;
                                                } else {
                                                      cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                      cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                                      cio_write(lev, nb_sv);
                                                      start = end;
                                                      end++;
                                                }
                                          }
                                          cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                          cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                          cio_write(lev, nb_sv);
                                    } 
                                    break;

                              case 2:
                                    //packet range mode
                                    for (i = notil; i < ult; i++){
                                          //inizializzazioni
                                          lev = 0;
                                          start = 0;
                                          end = 1;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                temp=lev;
                                                //determinazione dei livelli (catena di if-else-if)
                                                if (dPSNR[i][npack]>10)
                                                      lev = 1;
                                                else if ((dPSNR[i][npack]<=10)&&(dPSNR[i][npack]>8))
                                                      lev = 2;
                                                else if ((dPSNR[i][npack]<=8)&&(dPSNR[i][npack]>6))
                                                      lev = 3;
                                                else if ((dPSNR[i][npack]<=6)&&(dPSNR[i][npack]> 4.5))
                                                      lev = 4;
                                                else if ((dPSNR[i][npack]<=4.5)&&(dPSNR[i][npack]>3))
                                                      lev = 5;
                                                else if ((dPSNR[i][npack]<=3)&&(dPSNR[i][npack]>1.7))
                                                      lev = 6;
                                                else 
                                                      //(dPSNR[i][npack]<=1.7)
                                                      lev = 7;
                                                if (lev == temp){
                                                      end++;
                                                      continue;
                                                } else {
                                                      cio_write(start, nb_pos);
                                                      cio_write(end-1, nb_pos);
                                                      cio_write(lev, nb_sv);
                                                      start = end;
                                                      end++;
                                                }
                                          }
                                          cio_write(start, nb_pos);
                                          cio_write(end - 1, nb_pos);
                                          cio_write(lev, nb_sv);
                                    } 
                                    
                                    break;
                              default:
                                    printf("errore\n");
                        }
                        break;
                  case 1:
                        // MSE
                        switch (mode){
                              case 0:
                                    //packet mode
                                    for (i = notil; i < ult; i++){
                                          npix = info_IM.tile[i].nbpix;
                                          val = info_IM.tile[i].distotile / npix;
                                          cio_write(d2pfp(val), nb_sv);
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val -= dMSE[i][npack];
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              case 1:
                                    //byte range mode
                                    //divido in blocchi da 10 pacchetti (l'ultimo blocco dipende da quanti pacchetti restano
                                    for (i = notil; i < ult; i++){
                                          npix = info_IM.tile[i].nbpix;
                                          val = info_IM.tile[i].distotile / npix;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val -= dMSE[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                      cio_write(info_IM.tile[i].packet[end].end_pos, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }

                                    break;
                              case 2:
                                    //packet range mode
                                    //divido in blocchi da 10 pacchetti (l'ultimo blocco dipende da quanti pacchetti restano
                                    for (i = notil; i < ult; i++){
                                          npix = info_IM.tile[i].nbpix;
                                          val = info_IM.tile[i].distotile / npix;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val -= dMSE[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      cio_write(start, nb_pos);
                                                      cio_write(end, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                cio_write(start, nb_pos);
                                                cio_write(end-1, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              default:
                                    printf("errore\n");
                        }

                        break;
                  case 2:
                        // MSE reduction
                        switch (mode){
                              case 0:
                                    //packet mode
                                    for (i = notil; i < ult; i++)
                                          for (npack=0; npack < (info_IM.num); npack++)
                                                cio_write(d2pfp(dMSE[i][npack]), nb_sv);
                                    
                                    break;
                              case 1:
                                    //byte range mode
                                    //scrivo la mse reduction media relativa ad un blocco di dieci pacchetti
                                    for (i = notil; i < ult; i++){
                                          val = 0;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val += dMSE[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      val /= 10;
                                                      cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                      cio_write(info_IM.tile[i].packet[end].end_pos, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                      val = 0;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                val /= npack%10;
                                                cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              case 2:
                                    //packet range mode
                                    //scrivo la mse reduction media relativa ad un blocco di dieci pacchetti
                                    for (i = notil; i < ult; i++){
                                          val = 0;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val += dMSE[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      val /= 10;
                                                      cio_write(start, nb_pos);
                                                      cio_write(end, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                      val = 0;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                val /= npack%10;
                                                cio_write(start, nb_pos);
                                                cio_write(end-1, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              default:
                                    printf("errore\n");
                        }

                        break;
                  case 3:
                        //PSNR

                        switch (mode){
                              case 0:
                                    //packet mode     
                                    for (i = notil; i < ult; i++)
                                          for (npack=0; npack < (info_IM.num); npack++)
                                                cio_write(d2pfp(PSNR[i][npack]),nb_sv);
                                    break;
                              case 1:
                                    //byte range mode
                                    //divido in blocchi da 10 pacchetti (l'ultimo blocco dipende da quanti pacchetti restano
                                    for (i = notil; i < ult; i++){
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                if (((npack+1) % 10)==0){
                                                      cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                      //printf("start: %d\n",info_IM.tile[i].packet[start].start_pos);
                                                      cio_write(info_IM.tile[i].packet[end].end_pos, nb_pos);
                                                      //printf("end: %d\n", info_IM.tile[i].packet[end].end_pos);
                                                      cio_write(d2pfp(PSNR[i][npack]), nb_sv);
                                                      start = end+1;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                //printf("start: %d\n",info_IM.tile[i].packet[start].start_pos);
                                                cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                                //printf("end: %d\n", info_IM.tile[i].packet[end-1].end_pos);
                                                cio_write(d2pfp(PSNR[i][end-1]), nb_sv);
                                          }
                                    }
                                    break;
                              case 2:
                                    //packet range mode
                                    //divido in blocchi da 10 pacchetti (l'ultimo blocco dipende da quanti pacchetti restano
                                    for (i = notil; i < ult; i++){
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                if (((npack+1) % 10)==0){
                                                      cio_write(start, nb_pos);
                                                      cio_write(end, nb_pos);
                                                      cio_write(d2pfp(PSNR[i][npack]), nb_sv);
                                                      start = end+1;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                cio_write(start, nb_pos);
                                                cio_write(end-1, nb_pos);
                                                cio_write(d2pfp(PSNR[i][end-1]), nb_sv);
                                          }
                                    }

                                    break;
                              default:
                                    printf("errore\n");
                        }

                        break;
                  case 4:
                        //PSNR increases

                        switch (mode){
                              case 0:
                                    //packet mode
                                    for (i = notil; i < ult; i++)
                                          for (npack=0; npack < (info_IM.num); npack++)
                                                cio_write(d2pfp(dPSNR[i][npack]), nb_sv);
                                    break;
                              case 1:
                                    //byte range mode
                                    //scrivo il psnr increase medio relativo ad un blocco di dieci pacchetti
                                    for (i = notil; i < ult; i++){
                                          val = 0;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val += dPSNR[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      val /= 10;
                                                      cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                      cio_write(info_IM.tile[i].packet[end].end_pos, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                      val = 0;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                val /= npack%10;
                                                cio_write(info_IM.tile[i].packet[start].start_pos, nb_pos);
                                                cio_write(info_IM.tile[i].packet[end-1].end_pos, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              case 2:
                                    //packet range mode
                                    //scrivo il psnr increase medio relativo ad un blocco di dieci pacchetti
                                    for (i = notil; i < ult; i++){
                                          val = 0;
                                          start = 0;
                                          end = 0;
                                          for (npack=0; npack < (info_IM.num); npack++){
                                                val += dPSNR[i][npack];
                                                if (((npack+1) % 10)==0){
                                                      val /= 10;
                                                      cio_write(start, nb_pos);
                                                      cio_write(end, nb_pos);
                                                      cio_write(d2pfp(val), nb_sv);
                                                      start = end+1;
                                                      val = 0;
                                                }
                                                end++;
                                          }
                                          if (start != end){
                                                val /= npack%10;
                                                cio_write(start, nb_pos);
                                                cio_write(end-1, nb_pos);
                                                cio_write(d2pfp(val), nb_sv);
                                          }
                                    }
                                    break;
                              default:
                                    printf("errore\n");
                        }

                        break;
                  case 5:
                        //MAXERR
                        printf("Opzione MAXERR non supportata\n");
                        break;
                  default:
                        printf("opzione riservata per uso futuro\n");
            }
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            free(PSNR[i]);
      free(PSNR);
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            free(dPSNR[i]);
      free(dPSNR);
      for (i=0; i<j2k_cp->th * j2k_cp->tw; i++)
            free(dMSE[i]);
      free(dMSE);

      len = cio_tell() - set;
      cio_seek(set);
      cio_write(len, 2);
      cio_skip(len - 2);
}


int JPWL_len_EPB(unsigned int LDPepb, unsigned int Pepb, unsigned char Depb){
      unsigned int len = 11, n1, n2, k1, k2, lenp;
      char pos_epb;
      
      
      lenp = cio_tell();
      /* determino len_epb e i parametri di codifica*/
      pos_epb= Depb & 0x3F;
      if ((j2k_state == J2K_STATE_MH) && !(pos_epb)){  // sto scrivendo il primo epb del mh
            n1=160;
            k1=64;
            len += (n1 - k1)*(unsigned int)ceil((double)(lenp + 11)/k1);
      } else {if ((j2k_state == J2K_STATE_TPH) && !(pos_epb)){          // primo epb di un tph
                        n1=80;
                        k1=25;
                        len += 55;
                  } else {                    // altro epb
                        n1=40;
                        k1=13;
                        len += 27;
                  }
      }
      if (!Pepb) {               // per codificare i dati seguenti uso lo stesso codice di prima
            n2 = n1;
            k2 = k1;
          len +=(unsigned int) ceil((double)LDPepb/k2)*(n2 - k2);

      } else{
            if (Pepb == 0xffffffff)   
                  1;

            else {if ((Pepb >> 28)== 1){
                        if ((Pepb & 0x00000001)){
                              len += 4;
                        } else {
                              len +=2;
                        }
                  } else {if ((Pepb >> 28)== 2){
                                    n2 = ((Pepb & 0x0000ff00)>> 8);
                                    k2 = (Pepb & 0x000000ff);
                                    len +=(unsigned int) ceil((double)LDPepb/k2)*(n2 - k2);
                                    }
                              }
                  }
      }

      
      return len;

}

void jpwl_write_RED(){
      //questa funzione scrive un marker RED di test vuoto
      cio_write(JPWL_MS_RED,2);
      //già scrivo la len(non metto informazioni nel marker, poichè la codestream sarà corretta)
      cio_write(3,2);
      cio_write(jpwl_cp.pred,1);
}





void JPWL_write_Pepbs(long *pepbs, int num_epb){
      int i, lenp, pos;
      
      cio_write(0,2);               // id relativo all'uso degli epb
      cio_skip(2);
      lenp=cio_tell();
      /*
            Qui in base a come deciderò di far operare l'encoder dovrò trovare il modo di inserire
            i Pepb relativi alla struttura; In questo caso uso una struttura fissa che prevede un 
            solo epb nel main header che usa lo stesso codice relativo al primo epb e più epb per 
            ogni tile part header, il primo che protegge tutto il tph con lo stesso codice relativo 
            al primo epb del tile part,  gli altri a protezione dei dati con un codice rs specificato
      */
      for (i=0; i<num_epb; i++)
            cio_write(pepbs[i],4);
      // scrivo la Lid
      pos=cio_tell();
      cio_seek(lenp-2);
      cio_write(pos-lenp,2);
      cio_seek(pos);
}

void correggi_esd(int offset, int len_esd, int Pesd){
      //nel caso in cui i dati dell'esd sono posti in byte range mode, devo correggere con l'offset
      //pari alla somma della lunghezza del primo epb e dell'epc
      int nb_pos, nb_sv, start, end, set, p;
      p=cio_tell();
      //mi metto all'inizio dei dati dell'esd
      cio_skip(6);
      //printf("marker: %x\n", cio_read(2));
      //printf("len: %x\n", cio_read(2));
      //printf("info: %x\n", cio_read(2));
      //determino i parametri con cui sono scritti i dati
      nb_pos = (((Pesd & 0x02)>>1)==0) ? 2 : 4;
      nb_sv = (((Pesd & 0x04)>>2)==0) ? 1 : 2;
      //printf("offset: %x\n",offset);
      //printf("len_esd: %d\n", len_esd);
      //procedo alla correzione
      while ((cio_tell()-p)<len_esd) {
            set=cio_tell();
            start = cio_read(nb_pos);
            //printf("start: %d\n", start);
            end = cio_read(nb_pos);
            //printf("end: %d\n", end);
            cio_seek(set);
            cio_write(start + offset, nb_pos);
            cio_write(end + offset, nb_pos);
            cio_skip(nb_sv);
            //printf("pos: %d\n", cio_tell());
      }

}

int pianifica_epb(unsigned int LDPepb, unsigned int Pepb, int *n_epb ){
      int len_max, *num_epb, n2, k2;
      //serve per pianificare il numero di epb necessari per proteggere i dati
      num_epb = n_epb;
      if ((Pepb >> 28)== 2){
            n2 = ((Pepb & 0x0000ff00)>> 8);
            k2 = (Pepb & 0x000000ff);
            len_max = 0xFF80 * k2 / (n2 - k2);
            *num_epb = (int) ceil((double) LDPepb / len_max);
      } else if (!Pepb){
            n2 = 40;
            k2 = 13;
            len_max = 0xFF80 * k2 / (n2 - k2);
            *num_epb = (int) ceil((double) LDPepb / len_max);
      } else {
            *num_epb = 1;
            len_max = LDPepb+2;
      }
      return len_max;
}



int uep(int notil, char *bs, char *header, int len_header){
      //questa funzione ritorna il valore di psot_corr
      double maxMSE, val, dMSE, M;
      int depb, mask, corr=0, len_til, npix, lung=0, i, h=0, k, l=0, npack, start[6], end[6], fa=0, pkt=0, Psot_cor=0, lmax[6], no_epb[6], len[6], set, cont, tot_epb=0;
      char *data;
      double *PSNR; 
      
      PSNR = (double *) malloc(info_IM.num*sizeof(double));
      //printf("uep\n");

      //mi piazzo alla fine di SOT
      set=cio_tell();

      //determino il psnr che si raggiunge con ogni pacchetto
      M = 65025;
      //printf("M: %f\n",M);
      val = 0;
      npix = info_IM.tile[notil-1].nbpix;
      maxMSE = info_IM.tile[notil-1].distotile / npix;
      //printf("max mse:%f\n", maxMSE);
      for(npack=0; npack < (info_IM.num); npack++){
            dMSE = info_IM.tile[notil-1].packet[npack].disto / npix;
            //printf("dmse: %f\n", dMSE);
            if (dMSE!=0){
                  val += dMSE;
                  PSNR[npack] = (10 * log10(M/(maxMSE - val)));   
            }
            else {
                  PSNR[npack] = PSNR[npack-1];
            }
            printf("psnr %d: %f\n ", npack, PSNR[npack] );
      }
      
      //a questo punto determino le fasce
      npack=0;
      
      //inizializzo le posizioni
      for (i=0;i<6;i++){
            start[i]=-1;
            end[i]=-1;
      }
      start[0]=0;
      while (npack<info_IM.num){
            //printf("conta: %d\n", npack);
            if (PSNR[npack]<20){
                  npack++;
            }
            else if ((PSNR[npack]>=20)&&(PSNR[npack]<23)){
                  if (fa!=1){
                        fa=1;
                        end[0]=npack++;
                        start[1]=npack;
                  }
                  else
                        npack++;
            
            }
            else if ((PSNR[npack]>=23)&&(PSNR[npack]<26)){
                  if (fa!=2){
                        end[fa]=npack++;
                        start[2]=npack;
                        fa=2;
                  }
                  else
                        npack++;
            
            }
            else if ((PSNR[npack]>=26)&&(PSNR[npack]<35)){
                  if (fa!=3){
                        end[fa]=npack++;
                        start[3]=npack;
                        fa=3;
                  }
                  else
                        npack++;
            
            }
            else if ((PSNR[npack]>=35)&&(PSNR[npack]<37)){
                  if (fa!=4){
                        end[fa]=npack++;
                        start[4]=npack;
                        fa=4;
                  }
                  else
                        npack++;

            }
            else{
                  end[fa]=info_IM.num-1;
                  npack=info_IM.num;
                  fa=5;
            
            }
      
      }
      // devo mettere la fine all'ultima fascia abilitata
      if (fa!=5){
            //risolvo un bug!!
            if(start[fa] == info_IM.num){
                  //disattivo l'ultima fascia se non correttamente abilitata
                  start[fa] = -1;
                  fa--;
            }
            else
                  end[fa]=info_IM.num-1;
      }
      printf("livello   start    end\n");
      for (i=0;i<6;i++)
            printf("%d\t%d\t%d\n", i, start[i], end[i]);

      for (i=0;i<6;i++)
            printf("pepb[%d]: %x\n", i, jpwl_cp.pepb[i]);

      //determino anticipatamente le lunghezze degli epb
      if (len_header)
            Psot_cor += JPWL_len_EPB((len_header), jpwl_cp.pepb[0], 0) + 2;
      fa=0;
      //devo calcolare le lunghezze degli epb necessari per ogni fascia
      for(i=0;i<5;i++){
            len[i]=0;
            if ((start[i]!=-1)&&(end[i]!=-1)){
                  len[i]= (info_IM.tile[notil-1].packet[end[i]].end_pos) - info_IM.tile[notil-1].packet[start[i]].start_pos +1;
                  /*printf("len[%d]: %d\n",i, len[i]); */
                  if (i==0)
                        //poichè non viene considerato il marker SOD
                        len[i]+=2;
                  lmax[i] = pianifica_epb(len[i], jpwl_cp.pepb[i+1], &no_epb[i]);
                  /*printf("lmax[%d]: %d\n", i, lmax[i]);*/
                  tot_epb+=no_epb[i];
                  /*printf("num epb[%d]: %d\n",i, no_epb[i]);*/
                  if(no_epb[i] > 1){
                        if ((!(len_header))&&(i==1))
                              Psot_cor += JPWL_len_EPB(lmax[i], jpwl_cp.pepb[i+1], 0) + (no_epb[i]-2)*JPWL_len_EPB((lmax[i]), jpwl_cp.pepb[i+1], 0x41) + JPWL_len_EPB((len[i] % lmax[i]), jpwl_cp.pepb[i+1], 0x41);
                        else
                              Psot_cor += (no_epb[i]-1)*JPWL_len_EPB((lmax[i]), jpwl_cp.pepb[i+1], 0x41) + JPWL_len_EPB((len[i] % lmax[i]), jpwl_cp.pepb[i+1], 0x41);
                  }
                  else{
                        if ((!(len_header))&&(i==1))
                              Psot_cor += JPWL_len_EPB((len[i]), jpwl_cp.pepb[i+1], 0x0);
                        else
                              Psot_cor += JPWL_len_EPB((len[i]), jpwl_cp.pepb[i+1], 0x41);
                  }

                  Psot_cor += 2*(no_epb[i]);
                  fa=i;


            }
      }
      /*printf("fa: %d\n", fa);
      printf("psot_cor: %d\n", Psot_cor);
      printf("tot_epb: %d\n", tot_epb);*/
      /*len[5]=0;
      for(i=0;i<5;i++){
            len[5]+=len[i];
      }*/
      /*printf("lendata: %d\n", len[5]);*/
      cio_seek(set - 6);
      len_til=cio_read(4);
      cio_skip(-4);
      cio_write(Psot_cor + len_til,4);

      cio_seek(set);
      //correzione index
      if (info_IM.index_on){
            corr += Psot_cor;
            info_IM.tile[notil-1].end_header += corr;
            info_IM.tile[notil-1].end_pos += corr;
            if (notil < j2k_cp->tw * j2k_cp->th)
                  info_IM.tile[notil].start_pos += corr;
            pack_corr(corr, notil-1);
      }
      //scrivo gli EPB e riporto i buffer
      if (len_header){
            JPWL_write_EPB(header, len_header, jpwl_cp.pepb[0], 0);
            h=1;
            pepbs[cont_epb++]=jpwl_cp.pepb[0];
      }
      for (i = 0; i < len_header; i++)
            cio_write(header[i],1);
      free(header);
      mask = (tot_epb == 1) ? 0x40 : 0x80;
      for(i=0;i<5;i++){
            if ((start[i]!=-1)&&(end[i]!=-1)){
                  data = (unsigned char *)malloc(lmax[i]*sizeof(unsigned char));
                  for (k=0; k < no_epb[i]; k++){
                        cont=0;
                        depb = mask | ((l+h)&0x3F);
                        
                        while (((cont + k*lmax[i])< len[i])&&(cont < lmax[i])){
                              data[cont] = bs[cont + k*lmax[i] + lung];
                              cont++;
                        }
                        if ((cont < lmax[i])&&(i==fa))
                              depb |= 0x40;
                        /*printf("depb[%d]: %x\n",i, depb);*/
                        JPWL_write_EPB(data, cont, jpwl_cp.pepb[i+1], depb);
                        pepbs[cont_epb++]=jpwl_cp.pepb[i+1];
                        if (l==1)
                              scavalcato=1;
                        l++;
                  }
                  free(data);
                  lung+=len[i];
            }
      }

      /*printf("lung: %d\n", lung );*/
      return Psot_cor;

}



int uep_lay(int notil, char *bs, char *header, int len_header){
      //questa funzione ritorna il valore di psot_corr
      int depb, mask, corr=0, len_til, n_lay, lung=0, i, h=0, k, l=0, npack, Psot_cor=0, set, cont, tot_epb=0;
      char *data;
      int *lmax, *no_epb, *len;
      
      //determino il numero dei layer
      n_lay = info_IM.Layer;

      //determino il numero di pacchetti per layer
      npack = info_IM.num / n_lay;

      //preparo i vettori necessari

      if(!(lmax=(int *) malloc(n_lay * sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma3\n ");
      if(!(no_epb=(int *) malloc(n_lay * sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma3\n ");
      if(!(len=(int *) malloc(n_lay * sizeof(int))))
           printf("Non può essere allocata memoria per eseguire il programma3\n ");

      //mi piazzo alla fine di SOT
      set=cio_tell();


      //determino anticipatamente le lunghezze degli epb
      if (len_header)
            Psot_cor += JPWL_len_EPB((len_header), jpwl_cp.pepb[0], 0) + 2;

      //devo calcolare le lunghezze degli epb necessari per ogni fascia
      for(i=0;i<n_lay;i++){
            //determino le lunghezze dei layer
            len[i] = (info_IM.tile[notil-1].packet[((i+1) * npack) - 1].end_pos) - info_IM.tile[notil-1].packet[i * npack].start_pos +1;
            /*printf("len[%d]: %d\n",i, len[i]); */
            if (i==0)
                  //poichè non viene considerato il marker SOD
                  len[i]+=2;
            lmax[i] = pianifica_epb(len[i], jpwl_cp.pepb[i+1], &no_epb[i]);
            /*printf("lmax[%d]: %d\n", i, lmax[i]);*/
            tot_epb+=no_epb[i];
            /*printf("num epb[%d]: %d\n",i, no_epb[i]);*/
            if(no_epb[i] > 1){
                  if ((!(len_header))&&(i==1))
                        Psot_cor += JPWL_len_EPB(lmax[i], jpwl_cp.pepb[i+1], 0) + (no_epb[i]-2)*JPWL_len_EPB((lmax[i]), jpwl_cp.pepb[i+1], 0x41) + JPWL_len_EPB((len[i] % lmax[i]), jpwl_cp.pepb[i+1], 0x41);
                  else
                        Psot_cor += (no_epb[i]-1)*JPWL_len_EPB((lmax[i]), jpwl_cp.pepb[i+1], 0x41) + JPWL_len_EPB((len[i] % lmax[i]), jpwl_cp.pepb[i+1], 0x41);
            }
            else{
                  if ((!(len_header))&&(i==1))
                        Psot_cor += JPWL_len_EPB((len[i]), jpwl_cp.pepb[i+1], 0x0);
                  else
                        Psot_cor += JPWL_len_EPB((len[i]), jpwl_cp.pepb[i+1], 0x41);
            }

            Psot_cor += 2*(no_epb[i]);
      }

      //correzione di psot
      cio_seek(set - 6);
      len_til=cio_read(4);
      cio_skip(-4);
      cio_write(Psot_cor + len_til,4);
      cio_seek(set);

      //correzione index
      if (info_IM.index_on){
            corr += Psot_cor;
            info_IM.tile[notil-1].end_header += corr;
            info_IM.tile[notil-1].end_pos += corr;
            if (notil < j2k_cp->tw * j2k_cp->th)
                  info_IM.tile[notil].start_pos += corr;
            pack_corr(corr, notil-1);
      }

      //scrivo gli EPB e riporto i buffer
      if (len_header){
            JPWL_write_EPB(header, len_header, jpwl_cp.pepb[0], 0);
            h=1;
            pepbs[cont_epb++]=jpwl_cp.pepb[0];
      }
      for (i = 0; i < len_header; i++)
            cio_write(header[i],1);
      free(header);

      //EPB a protezione della bitstream
      mask = (tot_epb == 1) ? 0x40 : 0x80;
      for(i=0;i<n_lay;i++){
            //preparo il buffer con i dati da proteggere
            data = (unsigned char *)malloc(lmax[i]*sizeof(unsigned char));
            for (k=0; k < no_epb[i]; k++){
                  cont=0;
                  depb = mask | ((l+h)&0x3F);
                  
                  while (((cont + k*lmax[i])< len[i])&&(cont < lmax[i])){
                        data[cont] = bs[cont + k*lmax[i] + lung];
                        cont++;
                  }
                  if ((cont < lmax[i]) && (i == (n_lay-1)))
                        depb |= 0x40;
                  /*printf("depb[%d]: %x\n",i, depb);*/
                  JPWL_write_EPB(data, cont, jpwl_cp.pepb[i+1], depb);
                  pepbs[cont_epb++]=jpwl_cp.pepb[i+1];
                  if (l==1)
                        scavalcato=1;
                  l++;
            }
            free(data);
            lung+=len[i];
            
      }
      free(len);
      free(no_epb);
      free(lmax);
      /*printf("lung: %d\n", lung );*/
      return Psot_cor;

}


int jpwl_encode(char *input, char * output, unsigned long CL){
      long len_tot, len_primo_epb, len_til, Psot_cor;
      unsigned char *buf1, *buf2, *buf3, *data;
      int h=0,pos, end_siz, i, depb, len_SIZ, notil, len_mar, len_red, mark, set, end_tph, len_data1, len_data2, len_data3, cur_pos, fine_mh, len_epc, corr=0, len_esd=0, lmax, no_epb, cont, mask;
      
      
      // controllo se devo usare gli epb
      if (jpwl_cp.EPB_on){
            
            //parser, serve a determinare le lunghezze degli epb e scrivere quelli nei tile part
            cio_init(input, CL*4);
            len_tot=CL;
            cio_skip(4);
            len_mar = cio_read(2);
            cio_skip(len_mar-2);
            end_siz=cio_tell();
            j2k_state = J2K_STATE_MH;
            mark = cio_read(2);
            //printf("mark: %x\n",mark);
            while (mark!=0xff90){
                  len_mar = cio_read(2);
                  cio_skip(len_mar-2);
                  mark = cio_read(2);
                  //printf("mark: %x\n",mark);
            }
            fine_mh=cio_tell()-2;
            cont_epb=1;
            pepbs[0]=jpwl_cp.pepb[0];

            j2k_state = J2K_STATE_TPH;
            for (notil=1; notil <= j2k_cp->tw * j2k_cp->th; notil++){
                  Psot_cor = 0;
                  //trucco per non fare sbagliare nella scrittura di più di 64 epb
                  scavalcato=0;
                  cio_skip(4);
                  len_til = cio_read(4);
                  cio_skip(2);
                  set = cio_tell();
                  mark = cio_read(2);
                  //printf("mark: %x\n",mark);
                  while (mark!=0xff93){
                        len_mar = cio_read(2);
                        cio_skip(len_mar-2);
                        mark = cio_read(2);
                        //printf("mark: %x\n",mark);
                  }
                  end_tph = cio_tell()-2;
                  len_data1= end_tph - set;
                  len_data2= len_til+set-end_tph-12;
                  /*printf("lendata2: %d\n",len_data2);*/
                  buf1 = (unsigned char *) malloc(len_data1*sizeof(unsigned char));
                  buf2 = (unsigned char *) malloc(len_data2*sizeof(unsigned char));
                cio_seek(set);
                  for (i=0; i<len_data1; i++)
                        buf1[i]=cio_read(1);
                  for (i=0; i<len_data2; i++)
                        buf2[i]=cio_read(1);
                  cur_pos=cio_tell();
                  len_data3 = len_tot-cur_pos;
                  buf3 = (unsigned char *) malloc((len_data3)*sizeof(unsigned char));
                  for (i=0; i< len_data3; i++)
                        buf3[i]=cio_read(1);
                  //uep
                  if (jpwl_cp.UEP_on){
                        cio_seek(set);
                        Psot_cor=uep_lay(notil,buf2,buf1,len_data1);
                        //free(buf1);
                        len_tot += Psot_cor;
                  }
                  else{
                        //correzione Psot
                        if (len_data1)
                              Psot_cor += JPWL_len_EPB((len_data1), jpwl_cp.pepb[0], 0) + 2;
                        lmax = pianifica_epb(len_data2, jpwl_cp.pepb[1], &no_epb);
                        //printf("num epb: %d\n", no_epb);
                        if(no_epb > 1){
                              if (len_data1)
                                    Psot_cor += (no_epb-1)*JPWL_len_EPB((lmax), jpwl_cp.pepb[1], 0x41) + JPWL_len_EPB((len_data2 % lmax), jpwl_cp.pepb[1], 0x41);
                              else
                                    Psot_cor += JPWL_len_EPB(lmax, jpwl_cp.pepb[1], 0) + (no_epb-2)*JPWL_len_EPB((lmax), jpwl_cp.pepb[1], 0x41) + JPWL_len_EPB((len_data2 % lmax), jpwl_cp.pepb[1], 0x41);
                        }
                        else{
                              if (len_data1)
                                    Psot_cor += JPWL_len_EPB((len_data2), jpwl_cp.pepb[1], 0x41);
                              else
                                    Psot_cor += JPWL_len_EPB((len_data2), jpwl_cp.pepb[1], 0x0);
                        }
                        Psot_cor += 2*(no_epb);
                        len_tot += Psot_cor;
                        //Psot_cor += len_til;
                        cio_seek(set - 6);
                        cio_write(Psot_cor + len_til,4);

                        cio_seek(set);
                        //correzione index
                        if (info_IM.index_on){
                              corr += Psot_cor;
                              info_IM.tile[notil-1].end_header += corr;
                              info_IM.tile[notil-1].end_pos += corr;
                              if (notil < j2k_cp->tw * j2k_cp->th)
                                    info_IM.tile[notil].start_pos += corr;
                              pack_corr(corr, notil-1);
                        }
                        //scrivo gli EPB e riporto i buffer
                        if (len_data1){
                              JPWL_write_EPB(buf1, len_data1, jpwl_cp.pepb[0], 0);
                              h=1;
                              pepbs[cont_epb++]=jpwl_cp.pepb[0];
                        }
                        for (i = 0; i < len_data1; i++)
                              cio_write(buf1[i],1);
                        free(buf1);
                        mask = (no_epb == 1) ? 0x40 : 0x80;
                        data = (unsigned char *)malloc(lmax*sizeof(unsigned char));
                        for (i=0; i < no_epb; i++){
                              cont=0;
                              depb = mask | ((i+h)&0x3F);
                              while (((cont + i*lmax)< len_data2)&&(cont < lmax)){
                                    data[cont] = buf2[cont + i*lmax];
                                    cont++;
                              }
                              if (cont < lmax)
                                    depb |= 0x40;
                              JPWL_write_EPB(data, cont, jpwl_cp.pepb[1], depb);
                              pepbs[cont_epb++]=jpwl_cp.pepb[1];
                              if (i==1)
                                    scavalcato=1;
                        }
                        free(data);
                  }
                  for (i = 0; i < len_data2; i++)
                        cio_write(buf2[i],1);
                  cur_pos=cio_tell();
                  free(buf2);
                  for (i=0; i < len_data3; i++)
                        cio_write(buf3[i],1);
                  free(buf3);
                  cio_seek(cur_pos);
                  mark = cio_read(2);

            }

            //ora mi trovo alla fine della codestream
            len_tot=cio_tell();
            // controllo se devo inserire l'esd (non lo devo inserire qui se è attivo il packet range mode)
            if ((jpwl_cp.ESD_on)&(!(((jpwl_cp.pesd & 0xC0)>>6)==2))){
                  cio_seek(end_siz);
                  len_data1 = len_tot - end_siz;
                  buf1 = (unsigned char *) malloc(len_data1 * sizeof(unsigned char));
                  for (i = 0; i < len_data1; i++){
                        buf1[i] = cio_read(1);
                  }
                  //printf("%x%x\n", buf1[len_tot - set - 2], buf1[len_tot - set -1]);
                  cio_seek(end_siz);
                  jpwl_write_ESD(jpwl_cp.pesd, 0);
                  len_esd = cio_tell() - end_siz;
                  //printf("len esd: %d\n",len_esd);
                  len_tot += len_esd;
                  for (i = 0; i < len_data1; i++){
                        cio_write(buf1[i],1);
                  }
                  free(buf1);
            }

            //scrivo l'epc ed il primo epb
            cio_init(output, len_tot*2);
            j2k_state = J2K_STATE_MH;
            for (i=0; i< 6; i++){
                  output[i]=input[i];
            }
            cio_skip(4);
            len_SIZ = cio_read(2);
            for (i=6; i< 4+len_SIZ; i++){
            output[i]=input[i];
            }
            cio_skip(len_SIZ-2);
            set = cio_tell();
            len_epc = 15 + cont_epb*4;
            len_primo_epb=JPWL_len_EPB(fine_mh - set + len_epc, jpwl_cp.pepb[0], 0);
            len_red=(jpwl_cp.RED_on)? 5 : 0; 
            if (info_IM.index_on){
                  corr=len_epc + len_primo_epb + 2 + len_esd + len_red;
                  info_IM.Main_head_end += corr;
                  //printf("fine_mh: %d\n",info_IM.Main_head_end);
                  //printf("%d\n", info_IM.tile[0].start_pos);
                  info_IM.tile[0].start_pos += corr;
                  for (i=0; i < j2k_cp->th * j2k_cp->tw; i++){
                        info_IM.tile[i].end_header += corr;
                        info_IM.tile[i].end_pos += corr;
                        if (i <  j2k_cp->tw * j2k_cp->th)
                              info_IM.tile[i+1].start_pos += corr;
                        pack_corr(corr, i);
                  } 
            } 

            jpwl_write_EPC_fin(len_tot+len_primo_epb+2+len_esd+len_red, pepbs, cont_epb);
            //controllo se devo inserire la red (solo test)
            if (jpwl_cp.RED_on) 
                  jpwl_write_RED();
            pos=cio_tell();
            //scrivo da input il main header
            for (i=4+len_SIZ; i<fine_mh+len_esd; i++){
                  cio_write(input[i],1);
            }
            cur_pos = cio_tell();
            //se l'esd è presente ed è in byte range mode devo correggere la posizioni
            if (jpwl_cp.ESD_on && (((jpwl_cp.pesd & 0xC0)>>6)==1) ){
                  cio_seek(pos);
                  correggi_esd(corr, len_esd, jpwl_cp.pesd);
            }
            
            len_data1=cur_pos-set;
            buf1= (unsigned char *) malloc((len_data1)*sizeof(unsigned char));
            cio_seek(set);
            for (i=0; i< len_data1; i++){
                  buf1[i]=cio_read(1);
            }
            cio_seek(set);
            JPWL_write_EPB(buf1, len_data1, jpwl_cp.pepb[0], 0x40);
            for (i = 0; i < len_data1; i++)
                  cio_write(buf1[i],1);
            free(buf1);
            for (i = fine_mh+len_esd; i < len_tot; i++)
                  cio_write(input[i],1);
            
            
      }
      
      
      // se devo inserire l'epc da solo lo posiziono subito dopo SIZ
      else {
            len_esd=0;
            cio_init(output, CL*2);
            for (i=0; i< 6; i++){
                  output[i]=input[i];
            }
            cio_skip(4);
            len_SIZ = cio_read(2);
            for (i=6; i< 4+len_SIZ; i++){
                  output[i]=input[i];
            }
            cio_skip(len_SIZ-2);
            set = cio_tell();
            // controllo se devo inserire l'esd 
            if ((jpwl_cp.ESD_on)&(!(((jpwl_cp.pesd & 0xC0)>>6)==2))){
                  jpwl_write_ESD(jpwl_cp.pesd, 0);
                  len_esd = cio_tell() - set;
                  cio_seek(set);
                  buf1 = (unsigned char *) malloc(len_esd * sizeof(unsigned char));
                  for (i = 0; i < len_esd; i++){
                        buf1[i] = cio_read(1);
                  }
                  cio_seek(set);
                  len_red=(jpwl_cp.RED_on)? 5 : 0;
                  corr=len_esd+11+len_red;
                  //correzione delle posizioni dei pack nella struttura info image da fare nel caso di esd nel main header
                  if (info_IM.index_on){
                        info_IM.Main_head_end += corr;
                        //printf("fine_mh: %d\n",info_IM.Main_head_end);
                        info_IM.tile[0].start_pos += corr;
                        for (i=0; i < j2k_cp->th * j2k_cp->tw; i++){
                              info_IM.tile[i].end_header += corr;
                              info_IM.tile[i].end_pos += corr;
                              if (i <  j2k_cp->tw * j2k_cp->th)
                                    info_IM.tile[i+1].start_pos += corr;
                              pack_corr(corr, i);
                        } 
                  } 
            }
            jpwl_write_EPC_fin(CL + len_esd, NULL, 0);
            //controllo se devo inserire la red (solo test)
            if (jpwl_cp.RED_on) 
                  jpwl_write_RED();
            set=cio_tell();
            if (jpwl_cp.ESD_on){
                  for (i = 0; i < len_esd; i++){
                              cio_write(buf1[i],1);
                        }
                  free(buf1);
                  if (((jpwl_cp.pesd & 0xC0)>>6)==1) {
                        cio_seek(set);
                        correggi_esd(corr, len_esd, jpwl_cp.pesd);
                  }
            }
            for (i=4+len_SIZ; i < CL; i++){
                  cio_write(input[i],1);
            }
      }

      
      return cio_tell();

}

void get_jpwl_cp(j2k_cp_t *cp){
      char risp, scelta,choose;
      int out = 0;
      unsigned long n;
      j2k_cp_t *param;
      
      param = cp;
      printf("You have chosen to activate JPWL techniques. EPC will be inserted\n");
      if (param->intermed_file){
            printf("Since intermed file option is active, EPC will not contain any information on the");
            printf("codestream length: eventual ESDs will be written in tile part headers.\n\n\n");
      }
      printf("Do you want to use EPBs (y/n)?: ");
      risp = (char) _getche();
      printf("\n\n\n");
      do {
            switch (risp){
                  case 'y':
                        jpwl_cp.EPB_on = 1;
                        do{
                              printf("UEP or EEP (u,e)?: ");
                              choose = (char) _getche();
                              printf("\n\n\n");
                        }while(!strchr("ue",choose));
                        if (choose=='e'){
                                    do{
                                          printf("Header protecting EPBs settings\n");
                                          printf("1) Adopt the same RS code used for the EPB;\n");
                                          printf("2) Enter a RS(n,32) code;\n");
                                          printf("3) Use CRC-16(CCITT);\n");
                                          printf("4) Use CRC-32(ETHERNET);\n");
                                          printf("5) No protection at all.\n\n\n");
                                          scelta = (char) _getche();
                                          printf("\n\n");
                                    }while(!strchr("12345",scelta));
                                    if (scelta == '1')
                                          jpwl_cp.pepb[0]=0x00000000;
                                    if (scelta == '2'){
                                          do {
                                          printf("Enter the desired n value (k=32 as standard; n between 37 and 128): ");
                                          scanf("%d", &n);
                                          printf("\n\n\n");
                                          } while ((n<37)||(n>128));
                                          jpwl_cp.pepb[0] = ( n & 0x000000FF)<<8;
                                          jpwl_cp.pepb[0] |= 0x20000020;
                                    }
                                    if (scelta == '3')
                                          jpwl_cp.pepb[0] = 0x10000000;
                                    if (scelta == '4')
                                          jpwl_cp.pepb[0] = 0x10000001;
                                    if (scelta == '5')
                                          jpwl_cp.pepb[0] = 0xFFFFFFFF;
                                    printf("pepb1: %x\n", jpwl_cp.pepb[0]);
                                    do{
                                          printf("Data protecting EPBs settings\n");
                                          printf("1) Adopt the same RS code used for the EPB;\n");
                                          printf("2) Enter a RS(n,32) code;\n");
                                          printf("3) Use CRC-16(CCITT);\n");
                                          printf("4) Use CRC-32(ETHERNET);\n");
                                          printf("5) No protection at all.\n\n\n");
                                          scelta = (char) _getche();
                                          printf("\n\n");
                                    }while(!strchr("12345",scelta));
                                    if (scelta == '1')
                                          jpwl_cp.pepb[1]=0x00000000;
                                    if (scelta == '2'){
                                          do {
                                                printf("Enter the desired n value (k=32 as standard; n between 37 and 128): ");
                                          scanf("%d", &n);
                                          printf("\n\n\n");
                                          } while ((n<37)||(n>128));
                                          jpwl_cp.pepb[1] = ( n & 0x000000FF)<<8;
                                          jpwl_cp.pepb[1] |= 0x20000020;
                                    }
                                    if (scelta == '3')
                                          jpwl_cp.pepb[1] = 0x10000000;
                                    if (scelta == '4')
                                          jpwl_cp.pepb[1] = 0x10000001;
                                    if (scelta == '5')
                                          jpwl_cp.pepb[1] = 0xFFFFFFFF;
                                    printf("pepb2: %x\n", jpwl_cp.pepb[1]);
                                    out=1;
                        }
                        if (choose=='u'){
                              printf("N.B.: layer number must be less than or equal to five\n");
                              param->index_on = 1;
                              jpwl_cp.UEP_on = 1;
                              jpwl_cp.pepb[0] = 0x20008020;
                              jpwl_cp.pepb[1] = 0x20005520;
                              jpwl_cp.pepb[2] = 0x20004B20;
                              jpwl_cp.pepb[3] = 0x20002520;
                              jpwl_cp.pepb[4] = 0x20002520;
                              jpwl_cp.pepb[5] = 0x20002520;
                              out=1;
                        }

                        break;
                  case 'n':
                        out=1;
                        break;
                  default:
                        printf("Error in answer.\n");
                        printf("Do you want to use EPBs (y/n)?: ");
                        risp = (char) _getche();
                        printf("\n\n\n");
            }
      }while (!out);
      out = 0;
      printf("Do you want to use ESD (y/n)?: ");
      risp = (char) _getche();
      printf("\n\n\n");
      do {
            switch(risp){
                  case 'y':
                        jpwl_cp.ESD_on = 1;
                        param->index_on = 1;
                        jpwl_cp.pesd = 0x01;
                        do{
                              printf("Enter representation mode:\n");
                              printf("1) Packet mode;\n");
                              printf("2) Byte range mode;\n");
                              printf("3) Packet range mode.\n");
                              scelta = (char) _getche();
                              printf("\n\n");
                        }while(!strchr("123",scelta));
                        if (scelta =='1')
                              jpwl_cp.pesd |= 0x00;
                        if (scelta =='2')
                              jpwl_cp.pesd |= 0x42;
                        if (scelta =='3')
                              jpwl_cp.pesd |= 0x80;
                        do{
                              printf("Enter metrics:\n");
                              printf("1) Relative error sensitivity;\n");
                              printf("2) MSE;\n");
                              printf("3) MSE reduction;\n");
                              printf("4) PSNR;\n");
                              printf("5) PSNR increase.\n");
                              scelta = (char) _getche();
                              printf("\n\n");
                        }while(!strchr("12345",scelta));
                        if (scelta =='1')
                              jpwl_cp.pesd |= 0x00;
                        if (scelta =='2')
                              jpwl_cp.pesd |= 0x0C;
                        if (scelta =='3')
                              jpwl_cp.pesd |= 0x14;
                        if (scelta =='4')
                              jpwl_cp.pesd |= 0x1C;
                        if (scelta =='5')
                              jpwl_cp.pesd |= 0x24;
                        printf("pesd: %x\n", jpwl_cp.pesd);
                        out=1;
                        break;
                  case 'n':
                        out=1;
                        break;
                  default:
                        printf("Error entering the answer.\n");
                        printf("Do you want to use ESD (y/n)?: ");
                        risp = (char) _getche();
                        printf("\n\n\n");
            }
      }while (!out);
      out = 0;
      printf("Do you want to use RED (y/n)?: ");
      risp = (char) _getche();
      printf("\n\n\n");
      do {
            switch(risp){
                  case 'y':
                        jpwl_cp.RED_on = 1;
                        //suppongo che la codestream sia corretta => b0=0 e b5b4b3=000
                        jpwl_cp.pred = 0x00;
                        do{
                              printf("Enter representation mode:\n");
                              printf("1) Packet mode;\n");
                              printf("2) Byte range mode;\n");
                              printf("3) Packet range mode.\n");
                              scelta = (char) _getche();
                              printf("\n\n");
                        }while(!strchr("123",scelta));
                        if (scelta =='1')
                              jpwl_cp.pred |= 0x00;
                        if (scelta =='2')
                              jpwl_cp.pred |= 0x42;
                        if (scelta =='3')
                              jpwl_cp.pred |= 0x80;
                        printf("pred: %x\n", jpwl_cp.pred);
                        out=1;
                        break;
                  case 'n':
                        out=1;
                        break;
                  default:
                        printf("Error entering the answer.\n");
                        printf("Do you want to use RED (y/n)?: ");
                        risp = (char) _getche();
                        printf("\n\n\n");
            }
      }while (!out);

}



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

/*
int crc_ccitt(char *buffer, int len){
      char c;
      int i;
      ResetCRC();
      for (i=0; i<len; i++) {
            c= *buffer;
            UpdateCRC(c);
            buffer++;
      }
      return crcSum;
}

*/


//funzioni di conversione allo pseudo floating point format 
short int d2pfp(double in){
      long *punt, data;
      short int mant, ex, out;
      punt = &in;
      punt++;
      data = *punt;
      mant = (data>>9) & 0x07FF;
      ex = (data>>20) & 0x07FF;
      out = ex+15;
      out = out << 11;
      out &= 0x0000F800;
      out |= mant;
      return out;
}


double pfp2d(short int in){
      double out;
      short int ex, mant;
      mant = in & 0x07FF;
      ex = (in >> 11) & 0x001F;
      out = pow(2,ex-15)*(1+(mant/pow(2,11)));
      return out;
}

Generated by  Doxygen 1.6.0   Back to index