SVN file properties modified
authorFrancois-Olivier Devaux <fodevaux@users.noreply.github.com>
Mon, 4 Dec 2006 16:11:05 +0000 (16:11 +0000)
committerFrancois-Olivier Devaux <fodevaux@users.noreply.github.com>
Mon, 4 Dec 2006 16:11:05 +0000 (16:11 +0000)
jpwl/jpwl_lib.c
jpwl/rs.c
jpwl/rs.h

index 1cf72089919ef4b96af4ad72af9292c12060f936..45bafcc0ed944c21e636cb56a4455b3b0c553de6 100644 (file)
-/*\r
- * Copyright (c) 2001-2003, David Janssens\r
- * Copyright (c) 2002-2003, Yannick Verschueren\r
- * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
- * Copyright (c) 2005, Herv� Drolon, FreeImage Team\r
- * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
- * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
- * POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifdef USE_JPWL\r
-\r
-#include "../libopenjpeg/opj_includes.h"\r
-\r
-/** Minimum and maximum values for the double->pfp conversion */\r
-#define MIN_V1 0.0\r
-#define MAX_V1 17293822569102704640.0\r
-#define MIN_V2 0.000030517578125\r
-#define MAX_V2 131040.0\r
-\r
-/** conversion between a double precision floating point\r
-number and the corresponding pseudo-floating point used \r
-to represent sensitivity values\r
-@param V the double precision value\r
-@param bytes the number of bytes of the representation\r
-@return the pseudo-floating point value (cast accordingly)\r
-*/\r
-unsigned short int jpwl_double_to_pfp(double V, int bytes);\r
-\r
-/** conversion between a pseudo-floating point used \r
-to represent sensitivity values and the corresponding\r
-double precision floating point number  \r
-@param em the pseudo-floating point value (cast accordingly)\r
-@param bytes the number of bytes of the representation\r
-@return the double precision value\r
-*/\r
-double jpwl_pfp_to_double(unsigned short int em, int bytes);\r
-\r
-       /*-------------------------------------------------------------*/\r
-\r
-int jpwl_markcomp(const void *arg1, const void *arg2)\r
-{\r
-   /* Compare the two markers' positions */\r
-   double diff = (((jpwl_marker_t *) arg1)->dpos - ((jpwl_marker_t *) arg2)->dpos);\r
-\r
-   if (diff == 0.0)\r
-          return (0);\r
-   else if (diff < 0)\r
-          return (-1);\r
-   else\r
-          return (+1);\r
-}\r
-\r
-int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,\r
-                                 bool latest, bool packed, bool insideMH, int *idx, int hprot,\r
-                                 double place_pos, int tileno,\r
-                                 unsigned long int pre_len, unsigned long int post_len) {\r
-\r
-       jpwl_epb_ms_t *epb_mark = NULL;\r
-\r
-       int k_pre, k_post, n_pre, n_post;\r
-       \r
-       unsigned long int L1, L2, dL4, max_postlen, epbs_len = 0;\r
-\r
-       /* We find RS(n,k) for EPB parms and pre-data, if any */\r
-       if (insideMH && (*idx == 0)) {\r
-               /* First EPB in MH */ \r
-               k_pre = 64;\r
-               n_pre = 160;\r
-       } else if (!insideMH && (*idx == 0)) {\r
-               /* First EPB in TH */\r
-               k_pre = 25;\r
-               n_pre = 80;\r
-       } else {\r
-               /* Following EPBs in MH or TH */\r
-               k_pre = 13;\r
-               n_pre = 40;\r
-       };\r
-\r
-       /* Find lengths, Figs. B3 and B4 */\r
-       /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */\r
-       L1 = pre_len + 13;\r
-\r
-       /* size of pre-data redundancy */\r
-       /*   (redundancy per codeword)       *     (number of codewords, rounded up)   */\r
-       L2 = (n_pre - k_pre) * (unsigned long int) ceil((double) L1 / (double) k_pre);\r
-\r
-       /* Find protection type for post data and its associated redundancy field length*/\r
-       if ((hprot == 16) || (hprot == 32)) {\r
-               /* there is a CRC for post-data */\r
-               k_post = post_len;\r
-               n_post = post_len + (hprot >> 3);\r
-               /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */\r
-\r
-       } else if ((hprot >= 37) && (hprot <= 128)) {\r
-               /* there is a RS for post-data */\r
-               k_post = 32;\r
-               n_post = hprot;\r
-\r
-       } else {\r
-               /* Use predefined codes */\r
-               n_post = n_pre;\r
-               k_post = k_pre;\r
-       };\r
-\r
-       /* Create the EPB(s) */\r
-       while (post_len > 0) {\r
-\r
-               /* maximum postlen in order to respect EPB size\r
-               (we use 65450 instead of 65535 for keeping room for EPB parms)*/\r
-               /*      (message word size)    *            (number of containable parity words)  */\r
-               max_postlen = k_post * (unsigned long int) floor(65450.0 / (double) (n_post - k_post));\r
-\r
-               /* maximum postlen in order to respect EPB size */\r
-               if (*idx == 0)\r
-                       /* (we use (65500 - L2) instead of 65535 for keeping room for EPB parms + pre-data) */\r
-                       /*      (message word size)    *                   (number of containable parity words)  */\r
-                       max_postlen = k_post * (unsigned long int) floor((double) (65500 - L2) / (double) (n_post - k_post));\r
-\r
-               else\r
-                       /* (we use 65500 instead of 65535 for keeping room for EPB parms) */\r
-                       /*      (message word size)    *            (number of containable parity words)  */\r
-                       max_postlen = k_post * (unsigned long int) floor(65500.0 / (double) (n_post - k_post));\r
-\r
-               /* length to use */\r
-               dL4 = min(max_postlen, post_len);\r
-\r
-               if (epb_mark = jpwl_epb_create(\r
-                       j2k, /* this encoder handle */\r
-                       latest ? (dL4 < max_postlen) : false, /* is it the latest? */\r
-                       packed, /* is it packed? */\r
-                       tileno, /* we are in TPH */\r
-                       *idx, /* its index */\r
-                       hprot, /* protection type parameters of following data */\r
-                       0, /* pre-data: nothing for now */\r
-                       dL4 /* post-data: the stub computed previously */\r
-                       )) {\r
-                       \r
-                       /* Add this marker to the 'insertanda' list */\r
-                       if (*jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
-                               jwmarker[*jwmarker_num].id = J2K_MS_EPB; /* its type */\r
-                               jwmarker[*jwmarker_num].epbmark = epb_mark; /* the EPB */\r
-                               jwmarker[*jwmarker_num].pos = (int) place_pos; /* after SOT */\r
-                               jwmarker[*jwmarker_num].dpos = place_pos + 0.0000001 * (double)(*idx); /* not very first! */\r
-                               jwmarker[*jwmarker_num].len = epb_mark->Lepb; /* its length */\r
-                               jwmarker[*jwmarker_num].len_ready = true; /* ready */\r
-                               jwmarker[*jwmarker_num].pos_ready = true; /* ready */\r
-                               jwmarker[*jwmarker_num].parms_ready = true; /* ready */\r
-                               jwmarker[*jwmarker_num].data_ready = false; /* not ready */\r
-                               (*jwmarker_num)++;\r
-                       }\r
-\r
-                       /* increment epb index */\r
-                       (*idx)++;\r
-\r
-                       /* decrease postlen */\r
-                       post_len -= dL4;\r
-\r
-                       /* increase the total length of EPBs */\r
-                       epbs_len += epb_mark->Lepb + 2;\r
-\r
-               } else {\r
-                       /* ooops, problems */\r
-                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB for UEP in tile %d\n", tileno);                          \r
-               };\r
-       }\r
-\r
-       return epbs_len;\r
-}\r
-\r
-\r
-jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, bool latest, bool packed, int tileno, int idx, int hprot,\r
-                                                 unsigned long int pre_len, unsigned long int post_len) {\r
-\r
-       jpwl_epb_ms_t *epb = NULL;\r
-       unsigned short int data_len = 0;\r
-       unsigned short int L2, L3;\r
-       unsigned long int L1, L4;\r
-       unsigned char *predata_in = NULL;\r
-\r
-       bool insideMH = (tileno == -1);\r
-\r
-       /* Alloc space */\r
-       if (!(epb = (jpwl_epb_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epb_ms_t)))) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for one EPB MS\n");\r
-               return NULL;\r
-       };\r
-\r
-       /* We set RS(n,k) for EPB parms and pre-data, if any */\r
-       if (insideMH && (idx == 0)) {\r
-               /* First EPB in MH */ \r
-               epb->k_pre = 64;\r
-               epb->n_pre = 160;\r
-       } else if (!insideMH && (idx == 0)) {\r
-               /* First EPB in TH */\r
-               epb->k_pre = 25;\r
-               epb->n_pre = 80;\r
-       } else {\r
-               /* Following EPBs in MH or TH */\r
-               epb->k_pre = 13;\r
-               epb->n_pre = 40;\r
-       };\r
-\r
-       /* Find lengths, Figs. B3 and B4 */\r
-       /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */\r
-       L1 = pre_len + 13;\r
-       epb->pre_len = pre_len;\r
-\r
-       /* size of pre-data redundancy */\r
-       /*   (redundancy per codeword)       *               (number of codewords, rounded up)   */\r
-       L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);\r
-\r
-       /* length of post-data */\r
-       L4 = post_len;\r
-       epb->post_len = post_len;\r
-\r
-       /* Find protection type for post data and its associated redundancy field length*/\r
-       if ((hprot == 16) || (hprot == 32)) {\r
-               /* there is a CRC for post-data */\r
-               epb->Pepb = 0x10000000 | ((unsigned long int) hprot >> 5); /* 0=CRC-16, 1=CRC-32 */\r
-               epb->k_post = post_len;\r
-               epb->n_post = post_len + (hprot >> 3);\r
-               /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */\r
-\r
-       } else if ((hprot >= 37) && (hprot <= 128)) {\r
-               /* there is a RS for post-data */\r
-               epb->Pepb = 0x20000020 | (((unsigned long int) hprot & 0x000000FF) << 8);\r
-               epb->k_post = 32;\r
-               epb->n_post = hprot;\r
-\r
-       } else if (hprot == 1) {\r
-               /* Use predefined codes */\r
-               epb->Pepb = (unsigned long int) 0x00000000;\r
-               epb->n_post = epb->n_pre;\r
-               epb->k_post = epb->k_pre;\r
-       \r
-       } else if (hprot == 0) {\r
-               /* Placeholder EPB: only protects its parameters, no protection method */\r
-               epb->Pepb = (unsigned long int) 0xFFFFFFFF;\r
-               epb->n_post = 1;\r
-               epb->k_post = 1;\r
-       \r
-       } else {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Invalid protection value for EPB h = %d\n", hprot);                               \r
-               return NULL;\r
-       }\r
-\r
-       epb->hprot = hprot;\r
-\r
-       /*   (redundancy per codeword)          *                (number of codewords, rounded up) */\r
-       L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);\r
-\r
-       /* private fields */\r
-       epb->tileno = tileno;\r
-\r
-       /* Fill some fields of the EPB */\r
-\r
-       /* total length of the EPB MS (less the EPB marker itself): */\r
-       /* Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) + pre_redundancy + post-redundancy */\r
-       epb->Lepb = 11 + L2 + L3;\r
-\r
-       /* EPB style */\r
-       epb->Depb = ((packed & 0x0001) << 7) | ((latest & 0x0001) << 6) | (idx & 0x003F);\r
-\r
-       /* length of data protected by EPB: */\r
-       epb->LDPepb = L1 + L4;\r
-\r
-       return epb;\r
-}\r
-\r
-void jpwl_epb_write(jpwl_epb_ms_t *epb, unsigned char *buf) {\r
-\r
-       /* Marker */\r
-       *(buf++) = (unsigned char) (J2K_MS_EPB >> 8); \r
-       *(buf++) = (unsigned char) (J2K_MS_EPB >> 0); \r
-\r
-       /* Lepb */\r
-       *(buf++) = (unsigned char) (epb->Lepb >> 8); \r
-       *(buf++) = (unsigned char) (epb->Lepb >> 0); \r
-\r
-       /* Depb */\r
-       *(buf++) = (unsigned char) (epb->Depb >> 0); \r
-\r
-       /* LDPepb */\r
-       *(buf++) = (unsigned char) (epb->LDPepb >> 24); \r
-       *(buf++) = (unsigned char) (epb->LDPepb >> 16); \r
-       *(buf++) = (unsigned char) (epb->LDPepb >> 8); \r
-       *(buf++) = (unsigned char) (epb->LDPepb >> 0); \r
-\r
-       /* Pepb */\r
-       *(buf++) = (unsigned char) (epb->Pepb >> 24); \r
-       *(buf++) = (unsigned char) (epb->Pepb >> 16); \r
-       *(buf++) = (unsigned char) (epb->Pepb >> 8); \r
-       *(buf++) = (unsigned char) (epb->Pepb >> 0); \r
-\r
-       /* Data */\r
-       /*memcpy(buf, epb->data, (size_t) epb->Lepb - 11);*/\r
-       memset(buf, 0, (size_t) epb->Lepb - 11);\r
-};\r
-\r
-\r
-jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, bool esd_on, bool red_on, bool epb_on, bool info_on) {\r
-\r
-       jpwl_epc_ms_t *epc = NULL;\r
-\r
-       /* Alloc space */\r
-       if (!(epc = (jpwl_epc_ms_t *) malloc((size_t) 1 * sizeof (jpwl_epc_ms_t)))) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for EPC MS\n");\r
-               return NULL;\r
-       };\r
-\r
-       /* Set the EPC parameters */\r
-       epc->esd_on = esd_on;\r
-       epc->epb_on = epb_on;\r
-       epc->red_on = red_on;\r
-       epc->info_on = info_on;\r
-\r
-       /* Fill the EPC fields with default values */\r
-       epc->Lepc = 9;\r
-       epc->Pcrc = 0x0000;\r
-       epc->DL = 0x00000000;\r
-       epc->Pepc = ((j2k->cp->esd_on & 0x0001) << 4) | ((j2k->cp->red_on & 0x0001) << 5) |\r
-               ((j2k->cp->epb_on & 0x0001) << 6) | ((j2k->cp->info_on & 0x0001) << 7);\r
-\r
-       return (epc);\r
-}\r
-\r
-bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf, unsigned char *post_buf) {\r
-\r
-       unsigned long int L1, L2, L3, L4;\r
-       int remaining;\r
-       unsigned long int P, NN_P;\r
-\r
-       /* Operating buffer */\r
-       static unsigned char codeword[NN], *parityword;\r
-\r
-       unsigned char *L1_buf, *L2_buf;\r
-       /* these ones are static, since we need to keep memory of\r
-        the exact place from one call to the other */\r
-       static unsigned char *L3_buf, *L4_buf;\r
-\r
-       /* some consistency check */\r
-       if (!buf) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs\n");\r
-               return false;\r
-       }\r
-\r
-       if (!post_buf && !L4_buf) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs data\n");\r
-               return false;\r
-       }\r
-\r
-       /*\r
-        * Compute parity bytes on pre-data, ALWAYS present (at least only for EPB parms)\r
-        */\r
-\r
-       /* Initialize RS structures */\r
-       P = epb->n_pre - epb->k_pre;\r
-       NN_P = NN - P;\r
-       memset(codeword, 0, NN);\r
-       parityword = codeword + NN_P;\r
-       init_rs(NN_P);\r
-\r
-       /* pre-data begins pre_len bytes before of EPB buf */\r
-       L1_buf = buf - epb->pre_len;\r
-       L1 = epb->pre_len + 13;\r
-\r
-       /* redundancy for pre-data begins immediately after EPB parms */\r
-       L2_buf = buf + 13;\r
-       L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);\r
-\r
-       /* post-data\r
-          the position of L4 buffer can be:\r
-            1) passed as a parameter: in that case use it\r
-            2) null: in that case use the previous (static) one\r
-       */\r
-       if (post_buf)\r
-               L4_buf = post_buf;\r
-       L4 = epb->post_len;\r
-\r
-       /* post-data redundancy begins immediately after pre-data redundancy */\r
-       L3_buf = L2_buf + L2;\r
-       L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);\r
-\r
-       /* let's check whether EPB length is sufficient to contain all these data */\r
-       if (epb->Lepb < (11 + L2 + L3))\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no room in EPB data field for writing redundancy data\n");\r
-       /*printf("Env. %d, nec. %d (%d + %d)\n", epb->Lepb - 11, L2 + L3, L2, L3);*/\r
-\r
-       /* Compute redundancy of pre-data message words */\r
-       remaining = L1;\r
-       while (remaining) {\r
-\r
-               /* copy message data into codeword buffer */\r
-               if (remaining < epb->k_pre) {\r
-                       /* the last message word is zero-padded */\r
-                       memset(codeword, 0, NN);\r
-                       memcpy(codeword, L1_buf, remaining);\r
-                       L1_buf += remaining;\r
-                       remaining = 0;\r
-\r
-               } else {\r
-                       memcpy(codeword, L1_buf, epb->k_pre);\r
-                       L1_buf += epb->k_pre;\r
-                       remaining -= epb->k_pre;\r
-\r
-               }\r
-\r
-               /* Encode the buffer and obtain parity bytes */\r
-               if (encode_rs(codeword, parityword))\r
-                       opj_event_msg(j2k->cinfo, EVT_WARNING,\r
-                               "Possible encoding error in codeword @ position #%d\n", (L1_buf - buf) / epb->k_pre);\r
-\r
-               /* copy parity bytes only in redundancy buffer */\r
-               memcpy(L2_buf, parityword, P); \r
-\r
-               /* advance parity buffer */\r
-               L2_buf += P;\r
-       }\r
-\r
-       /*\r
-        * Compute parity bytes on post-data, may be absent if there are no data\r
-        */\r
-       /*printf("Hprot is %d (tileno=%d, k_pre=%d, n_pre=%d, k_post=%d, n_post=%d, pre_len=%d, post_len=%d)\n",\r
-               epb->hprot, epb->tileno, epb->k_pre, epb->n_pre, epb->k_post, epb->n_post, epb->pre_len,\r
-               epb->post_len);*/\r
-       if (epb->hprot < 0) {\r
-\r
-               /* there should be no EPB */\r
-               \r
-       } else if (epb->hprot == 0) {\r
-\r
-               /* no protection for the data */\r
-               /* advance anyway */\r
-               L4_buf += epb->post_len;\r
-\r
-       } else if (epb->hprot == 16) {\r
-\r
-               /* CRC-16 */\r
-               unsigned short int mycrc = 0x0000;\r
-\r
-               /* compute the CRC field (excluding itself) */\r
-               remaining = L4;\r
-               while (remaining--)\r
-                       jpwl_updateCRC16(&mycrc, *(L4_buf++));\r
-\r
-               /* write the CRC field */\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 8);\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 0);\r
-\r
-       } else if (epb->hprot == 32) {\r
-\r
-               /* CRC-32 */\r
-               unsigned long int mycrc = 0x00000000;\r
-\r
-               /* compute the CRC field (excluding itself) */\r
-               remaining = L4;\r
-               while (remaining--)\r
-                       jpwl_updateCRC32(&mycrc, *(L4_buf++));\r
-\r
-               /* write the CRC field */\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 24);\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 16);\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 8);\r
-               *(L3_buf++) = (unsigned char) (mycrc >> 0);\r
-\r
-       } else {\r
-\r
-               /* RS */\r
-\r
-               /* Initialize RS structures */\r
-               P = epb->n_post - epb->k_post;\r
-               NN_P = NN - P;\r
-               memset(codeword, 0, NN);\r
-               parityword = codeword + NN_P;\r
-               init_rs(NN_P);\r
-\r
-               /* Compute redundancy of post-data message words */\r
-               remaining = L4;\r
-               while (remaining) {\r
-\r
-                       /* copy message data into codeword buffer */\r
-                       if (remaining < epb->k_post) {\r
-                               /* the last message word is zero-padded */\r
-                               memset(codeword, 0, NN);\r
-                               memcpy(codeword, L4_buf, remaining);\r
-                               L4_buf += remaining;\r
-                               remaining = 0;\r
-\r
-                       } else {\r
-                               memcpy(codeword, L4_buf, epb->k_post);\r
-                               L4_buf += epb->k_post;\r
-                               remaining -= epb->k_post;\r
-\r
-                       }\r
-\r
-                       /* Encode the buffer and obtain parity bytes */\r
-                       if (encode_rs(codeword, parityword))\r
-                               opj_event_msg(j2k->cinfo, EVT_WARNING,\r
-                                       "Possible encoding error in codeword @ position #%d\n", (L4_buf - buf) / epb->k_post);\r
-\r
-                       /* copy parity bytes only in redundancy buffer */\r
-                       memcpy(L3_buf, parityword, P); \r
-\r
-                       /* advance parity buffer */\r
-                       L3_buf += P;\r
-               }\r
-\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-\r
-bool jpwl_correct(opj_j2k_t *j2k) {\r
-\r
-       opj_cio_t *cio = j2k->cio;\r
-       bool status;\r
-       static bool mh_done = false;\r
-       int mark_pos, id, len, skips, sot_pos;\r
-       unsigned long int Psot = 0;\r
-\r
-       /* go back to marker position */\r
-       mark_pos = cio_tell(cio) - 2;\r
-       cio_seek(cio, mark_pos);\r
-\r
-       if ((j2k->state == J2K_STATE_MHSOC) && !mh_done) {\r
-\r
-               int mark_val = 0, skipnum = 0;\r
-\r
-               /*\r
-                 COLOR IMAGE\r
-                 first thing to do, if we are here, is to look whether\r
-                 51 (skipnum) positions ahead there is an EPB, in case of MH\r
-               */\r
-               /*\r
-                 B/W IMAGE\r
-                 first thing to do, if we are here, is to look whether\r
-                 45 (skipnum) positions ahead there is an EPB, in case of MH\r
-               */\r
-               /*       SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */\r
-               skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;\r
-               if ((cio->bp + skipnum) < cio->end) {\r
-\r
-                       cio_skip(cio, skipnum);\r
-\r
-                       /* check that you are not going beyond the end of codestream */\r
-\r
-                       /* call EPB corrector */\r
-                       status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */\r
-                                                                         cio->bp, /* pointer to EPB in codestream buffer */\r
-                                                                         0,       /* EPB type: MH */\r
-                                                                         skipnum,      /* length of pre-data */\r
-                                                                         -1,      /* length of post-data: -1 means auto */\r
-                                                                         NULL,\r
-                                                                         NULL\r
-                                                                        );\r
-\r
-                       /* read the marker value */\r
-                       mark_val = (*(cio->bp) << 8) | *(cio->bp + 1);\r
-\r
-                       if (status && (mark_val == J2K_MS_EPB)) {\r
-                               /* we found it! */\r
-                               mh_done = true;\r
-                               return true;\r
-                       }\r
-\r
-               }\r
-\r
-       }\r
-\r
-       if (true /*(j2k->state == J2K_STATE_TPHSOT) || (j2k->state == J2K_STATE_TPH)*/) {\r
-               /* else, look if 12 positions ahead there is an EPB, in case of TPH */\r
-               cio_seek(cio, mark_pos);\r
-               if ((cio->bp + 12) < cio->end) {\r
-\r
-                       cio_skip(cio, 12);\r
-\r
-                       /* call EPB corrector */\r
-                       status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */\r
-                                                                         cio->bp, /* pointer to EPB in codestream buffer */\r
-                                                                         1,       /* EPB type: TPH */\r
-                                                                         12,      /* length of pre-data */\r
-                                                                         -1,      /* length of post-data: -1 means auto */\r
-                                                                         NULL,\r
-                                                                         NULL\r
-                                                                        );\r
-                       if (status)\r
-                               /* we found it! */\r
-                               return true;\r
-               }\r
-       }\r
-\r
-       return false;\r
-\r
-       /* for now, don't use this code */\r
-\r
-       /* else, look if here is an EPB, in case of other */\r
-       if (mark_pos > 64) {\r
-               /* it cannot stay before the first MH EPB */\r
-               cio_seek(cio, mark_pos);\r
-               cio_skip(cio, 0);\r
-\r
-               /* call EPB corrector */\r
-               status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */\r
-                                                                 cio->bp, /* pointer to EPB in codestream buffer */\r
-                                                                 2,       /* EPB type: TPH */\r
-                                                                 0,       /* length of pre-data */\r
-                                                                 -1,      /* length of post-data: -1 means auto */\r
-                                                                 NULL,\r
-                                                                 NULL\r
-                                                                );\r
-               if (status)\r
-                       /* we found it! */\r
-                       return true;\r
-       }\r
-\r
-       /* nope, no EPBs probably, or they are so damaged that we can give up */\r
-       return false;\r
-       \r
-       return true;\r
-\r
-       /* AN ATTEMPT OF PARSER */\r
-       /* NOT USED ACTUALLY    */\r
-\r
-       /* go to the beginning of the file */\r
-       cio_seek(cio, 0);\r
-\r
-       /* let's begin */\r
-       j2k->state = J2K_STATE_MHSOC;\r
-\r
-       /* cycle all over the markers */\r
-       while (cio_tell(cio) < cio->length) {\r
-\r
-               /* read the marker */\r
-               mark_pos = cio_tell(cio);\r
-               id = cio_read(cio, 2);\r
-\r
-               /* details */\r
-               printf("Marker@%d: %X\n", cio_tell(cio) - 2, id);\r
-\r
-               /* do an action in response to the read marker */\r
-               switch (id) {\r
-\r
-               /* short markers */\r
-\r
-                       /* SOC */\r
-               case J2K_MS_SOC:\r
-                       j2k->state = J2K_STATE_MHSIZ;\r
-                       len = 0;\r
-                       skips = 0;\r
-                       break;\r
-\r
-                       /* EOC */\r
-               case J2K_MS_EOC:\r
-                       j2k->state = J2K_STATE_MT;\r
-                       len = 0;\r
-                       skips = 0;\r
-                       break;\r
-\r
-                       /* particular case of SOD */\r
-               case J2K_MS_SOD:\r
-                       len = Psot - (mark_pos - sot_pos) - 2;\r
-                       skips = len;\r
-                       break;\r
-\r
-               /* long markers */\r
-\r
-                       /* SOT */\r
-               case J2K_MS_SOT:\r
-                       j2k->state = J2K_STATE_TPH;\r
-                       sot_pos = mark_pos; /* position of SOT */\r
-                       len = cio_read(cio, 2); /* read the length field */\r
-                       cio_skip(cio, 2); /* this field is unnecessary */\r
-                       Psot = cio_read(cio, 4); /* tile length */\r
-                       skips = len - 8;\r
-                       break;\r
-\r
-                       /* remaining */\r
-               case J2K_MS_SIZ:\r
-                       j2k->state = J2K_STATE_MH;\r
-                       /* read the length field */\r
-                       len = cio_read(cio, 2);\r
-                       skips = len - 2;\r
-                       break;\r
-\r
-                       /* remaining */\r
-               default:\r
-                       /* read the length field */\r
-                       len = cio_read(cio, 2);\r
-                       skips = len - 2;\r
-                       break;\r
-\r
-               }\r
-\r
-               /* skip to marker's end */\r
-               cio_skip(cio, skips);   \r
-\r
-       }\r
-\r
-\r
-}\r
-\r
-bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,\r
-                                         unsigned char **L4_bufp) {\r
-\r
-       /* Operating buffer */\r
-       unsigned char codeword[NN], *parityword;\r
-\r
-       unsigned long int P, NN_P;\r
-       unsigned long int L1, L4;\r
-       int remaining, n_pre, k_pre, n_post, k_post;\r
-\r
-       int status, tt;\r
-\r
-       int orig_pos = cio_tell(j2k->cio);\r
-\r
-       unsigned char *L1_buf, *L2_buf;\r
-       unsigned char *L3_buf, *L4_buf;\r
-\r
-       unsigned long int LDPepb, Pepb;\r
-       unsigned short int Lepb;\r
-       unsigned char Depb;\r
-       char str1[25] = "";\r
-       int myconn, errnum = 0;\r
-       bool errflag = false;\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* check for common errors */\r
-       if (!buffer) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "The EPB pointer is a NULL buffer\n");\r
-               return false;\r
-       }\r
-       \r
-       /* set bignesses */\r
-       L1 = pre_len + 13;\r
-\r
-       /* pre-data correction */\r
-       switch (type) {\r
-\r
-       case 0:\r
-               /* MH EPB */\r
-               k_pre = 64;\r
-               n_pre = 160;\r
-               break;\r
-\r
-       case 1:\r
-               /* TPH EPB */\r
-               k_pre = 25;\r
-               n_pre = 80;\r
-               break;\r
-\r
-       case 2:\r
-               /* other EPBs */\r
-               k_pre = 13;\r
-               n_pre = 40;\r
-               break;\r
-\r
-       case 3:\r
-               /* automatic setup */\r
-               break;\r
-\r
-       default:\r
-               /* unknown type */\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Unknown expected EPB type\n");\r
-               return false;\r
-               break;\r
-\r
-       }\r
-\r
-       /* Initialize RS structures */\r
-       P = n_pre - k_pre;\r
-       NN_P = NN - P;\r
-       tt = (int) floor((float) P / 2.0F);\r
-       memset(codeword, 0, NN);\r
-       parityword = codeword + NN_P;\r
-       init_rs(NN_P);\r
-\r
-       /* Correct pre-data message words */\r
-       L1_buf = buffer - pre_len;\r
-       L2_buf = buffer + 13;\r
-       remaining = L1;\r
-       while (remaining) {\r
\r
-               /* always zero-pad codewords */\r
-               /* (this is required, since after decoding the zeros in the long codeword\r
-                   could change, and keep unchanged in subsequent calls) */\r
-               memset(codeword, 0, NN);\r
-\r
-               /* copy codeword buffer into message bytes */\r
-               if (remaining < k_pre)\r
-                       memcpy(codeword, L1_buf, remaining);\r
-               else\r
-                       memcpy(codeword, L1_buf, k_pre);\r
-\r
-               /* copy redundancy buffer in parity bytes */\r
-               memcpy(parityword, L2_buf, P); \r
-\r
-               /* Decode the buffer and possibly obtain corrected bytes */\r
-               status = eras_dec_rs(codeword, NULL, 0);\r
-               if (status == -1) {\r
-                       /*if (conn == NULL)\r
-                               opj_event_msg(j2k->cinfo, EVT_WARNING,\r
-                                       "Possible decoding error in codeword @ position #%d\n", (L1_buf - buffer) / k_pre);*/\r
-                       errflag = true;\r
-                       /* we can try to safely get out from the function:\r
-                         if we are here, either this is not an EPB or the first codeword\r
-                         is too damaged to be helpful */\r
-                       /*return false;*/\r
-\r
-               } else if (status == 0) {\r
-                       /*if (conn == NULL)\r
-                               opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/\r
-\r
-               } else if (status < tt) {\r
-                       /*if (conn == NULL)\r
-                               opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/\r
-                       errnum += status;\r
-\r
-               } else {\r
-                       /*if (conn == NULL)\r
-                               opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");\r
-                       return false;*/\r
-                       errflag = true;\r
-               }\r
-\r
-\r
-               /* advance parity buffer */\r
-               if ((status >= 0) && (status < tt))\r
-                       /* copy back corrected parity only if all is OK */\r
-                       memcpy(L2_buf, parityword, P);\r
-               L2_buf += P;\r
-\r
-               /* advance message buffer */\r
-               if (remaining < k_pre) {\r
-                       if ((status >= 0) && (status < tt))\r
-                               /* copy back corrected data only if all is OK */\r
-                               memcpy(L1_buf, codeword, remaining);\r
-                       L1_buf += remaining;\r
-                       remaining = 0;\r
-\r
-               } else {\r
-                       if ((status >= 0) && (status < tt))\r
-                               /* copy back corrected data only if all is OK */\r
-                               memcpy(L1_buf, codeword, k_pre);\r
-                       L1_buf += k_pre;\r
-                       remaining -= k_pre;\r
-\r
-               }\r
-       }\r
-\r
-       /* print summary */\r
-       if (!conn) {\r
-\r
-               /*if (errnum)\r
-                       opj_event_msg(j2k->cinfo, EVT_INFO, "+ %d symbol errors corrected (Ps=%.1e)\n", errnum,\r
-                               (float) errnum / ((float) n_pre * (float) L1 / (float) k_pre));*/\r
-               if (errflag) {\r
-                       /*opj_event_msg(j2k->cinfo, EVT_INFO, "+ there were unrecoverable errors\n");*/\r
-                       return false;\r
-               }\r
-\r
-       }\r
-\r
-       /* presumably, now, EPB parameters are correct */\r
-       /* let's get them */\r
-\r
-       /* Simply read the EPB parameters */\r
-       if (conn)\r
-               cio->bp = buffer;\r
-       cio_skip(cio, 2); /* the marker */\r
-       Lepb = cio_read(cio, 2);\r
-       Depb = cio_read(cio, 1);\r
-       LDPepb = cio_read(cio, 4);\r
-       Pepb = cio_read(cio, 4);\r
-\r
-       /* What does Pepb tells us about the protection method? */\r
-       if (((Pepb & 0xF0000000) >> 28) == 0)\r
-               sprintf(str1, "pred"); /* predefined */\r
-       else if (((Pepb & 0xF0000000) >> 28) == 1)\r
-               sprintf(str1, "crc-%d", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */\r
-       else if (((Pepb & 0xF0000000) >> 28) == 2)\r
-               sprintf(str1, "rs(%d,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */\r
-       else if (Pepb == 0xFFFFFFFF)\r
-               sprintf(str1, "nometh"); /* RS mode */\r
-       else\r
-               sprintf(str1, "unknown"); /* unknown */\r
-\r
-       /* Now we write them to screen */\r
-       if (!conn && post_len)\r
-               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                       "EPB(%d): (%sl, %sp, %u), %lu, %s\n",\r
-                       cio_tell(cio) - 13,\r
-                       (Depb & 0x40) ? "" : "n", /* latest EPB or not? */\r
-                       (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */\r
-                       (Depb & 0x3F), /* EPB index value */\r
-                       LDPepb, /*length of the data protected by the EPB */\r
-                       str1); /* protection method */\r
-\r
-\r
-       /* well, we need to investigate how long is the connected length of packed EPBs */\r
-       myconn = Lepb + 2;\r
-       if ((Depb & 0x40) == 0) /* not latest in header */\r
-               jpwl_epb_correct(j2k,      /* J2K decompressor handle */\r
-                                            buffer + Lepb + 2,   /* pointer to next EPB in codestream buffer */\r
-                                            2,     /* EPB type: should be of other type */\r
-                                            0,  /* only EPB fields */\r
-                                            0, /* do not look after */\r
-                                                &myconn,\r
-                                                NULL\r
-                                            );\r
-       if (conn)\r
-               *conn += myconn;\r
-\r
-       /*if (!conn)\r
-               printf("connected = %d\n", myconn);*/\r
-\r
-       /*cio_seek(j2k->cio, orig_pos);\r
-       return true;*/\r
-\r
-       /* post-data\r
-          the position of L4 buffer is at the end of currently connected EPBs\r
-       */\r
-       if (!(L4_bufp))\r
-               L4_buf = buffer + myconn;\r
-       else if (!(*L4_bufp))\r
-               L4_buf = buffer + myconn;\r
-       else\r
-               L4_buf = *L4_bufp;\r
-       if (post_len == -1) \r
-               L4 = LDPepb - pre_len - 13;\r
-       else if (post_len == 0)\r
-               L4 = 0;\r
-       else\r
-               L4 = post_len;\r
-\r
-       L3_buf = L2_buf;\r
-\r
-       /* Do a further check here on the read parameters */\r
-       if (L4 > (unsigned long) cio_numbytesleft(j2k->cio))\r
-               /* overflow */\r
-               return false;\r
-\r
-       /* we are ready for decoding the remaining data */\r
-       if (((Pepb & 0xF0000000) >> 28) == 1) {\r
-               /* CRC here */\r
-               if ((16 * ((Pepb & 0x00000001) + 1)) == 16) {\r
-\r
-                       /* CRC-16 */\r
-                       unsigned short int mycrc = 0x0000, filecrc = 0x0000;\r
-\r
-                       /* compute the CRC field */\r
-                       remaining = L4;\r
-                       while (remaining--)\r
-                               jpwl_updateCRC16(&mycrc, *(L4_buf++));\r
-\r
-                       /* read the CRC field */\r
-                       filecrc = *(L3_buf++) << 8;\r
-                       filecrc |= *(L3_buf++);\r
-\r
-                       /* check the CRC field */\r
-                       if (mycrc == filecrc) {\r
-                               if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");\r
-                       } else {\r
-                               if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);\r
-                               errflag = true;\r
-                       }       \r
-               }\r
-\r
-               if ((16 * ((Pepb & 0x00000001) + 1)) == 32) {\r
-\r
-                       /* CRC-32 */\r
-                       unsigned long int mycrc = 0x00000000, filecrc = 0x00000000;\r
-\r
-                       /* compute the CRC field */\r
-                       remaining = L4;\r
-                       while (remaining--)\r
-                               jpwl_updateCRC32(&mycrc, *(L4_buf++));\r
-\r
-                       /* read the CRC field */\r
-                       filecrc = *(L3_buf++) << 24;\r
-                       filecrc |= *(L3_buf++) << 16;\r
-                       filecrc |= *(L3_buf++) << 8;\r
-                       filecrc |= *(L3_buf++);\r
-\r
-                       /* check the CRC field */\r
-                       if (mycrc == filecrc) {\r
-                               if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");\r
-                       } else {\r
-                               if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);\r
-                               errflag = true;\r
-                       }\r
-               }\r
-\r
-       } else if ((((Pepb & 0xF0000000) >> 28) == 2) || (((Pepb & 0xF0000000) >> 28) == 0)) {\r
-               /* RS coding here */\r
-\r
-               if (((Pepb & 0xF0000000) >> 28) == 0) {\r
-\r
-                       k_post = k_pre;\r
-                       n_post = n_pre;\r
-\r
-               } else {\r
-\r
-                       k_post = 32;\r
-                       n_post = (Pepb & 0x0000FF00) >> 8;\r
-               }\r
-\r
-               /* Initialize RS structures */\r
-               P = n_post - k_post;\r
-               NN_P = NN - P;\r
-               tt = (int) floor((float) P / 2.0F);\r
-               memset(codeword, 0, NN);\r
-               parityword = codeword + NN_P;\r
-               init_rs(NN_P);\r
-\r
-               /* Correct post-data message words */\r
-               /*L4_buf = buffer + Lepb + 2;*/\r
-               L3_buf = L2_buf;\r
-               remaining = L4;\r
-               while (remaining) {\r
\r
-                       /* always zero-pad codewords */\r
-                       /* (this is required, since after decoding the zeros in the long codeword\r
-                               could change, and keep unchanged in subsequent calls) */\r
-                       memset(codeword, 0, NN);\r
-\r
-                       /* copy codeword buffer into message bytes */\r
-                       if (remaining < k_post)\r
-                               memcpy(codeword, L4_buf, remaining);\r
-                       else\r
-                               memcpy(codeword, L4_buf, k_post);\r
-\r
-                       /* copy redundancy buffer in parity bytes */\r
-                       memcpy(parityword, L3_buf, P); \r
-\r
-                       /* Decode the buffer and possibly obtain corrected bytes */\r
-                       status = eras_dec_rs(codeword, NULL, 0);\r
-                       if (status == -1) {\r
-                               /*if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_WARNING,\r
-                                               "Possible decoding error in codeword @ position #%d\n", (L4_buf - (buffer + Lepb + 2)) / k_post);*/\r
-                               errflag = true;\r
-\r
-                       } else if (status == 0) {\r
-                               /*if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/\r
-\r
-                       } else if (status < tt) {\r
-                               /*if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/\r
-                               errnum += status;\r
-\r
-                       } else {\r
-                               /*if (conn == NULL)\r
-                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");\r
-                               return false;*/\r
-                               errflag = true;\r
-                       }\r
-\r
-\r
-                       /* advance parity buffer */\r
-                       if ((status >= 0) && (status < tt))\r
-                               /* copy back corrected data only if all is OK */\r
-                               memcpy(L3_buf, parityword, P);\r
-                       L3_buf += P;\r
-\r
-                       /* advance message buffer */\r
-                       if (remaining < k_post) {\r
-                               if ((status >= 0) && (status < tt))\r
-                                       /* copy back corrected data only if all is OK */\r
-                                       memcpy(L4_buf, codeword, remaining);\r
-                               L4_buf += remaining;\r
-                               remaining = 0;\r
-\r
-                       } else {\r
-                               if ((status >= 0) && (status < tt))\r
-                                       /* copy back corrected data only if all is OK */\r
-                                       memcpy(L4_buf, codeword, k_post);\r
-                               L4_buf += k_post;\r
-                               remaining -= k_post;\r
-\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* give back the L4_buf address */\r
-       if (L4_bufp)\r
-               *L4_bufp = L4_buf;\r
-\r
-       /* print summary */\r
-       if (!conn) {\r
-\r
-               if (errnum)\r
-                       opj_event_msg(j2k->cinfo, EVT_INFO, "- %d symbol errors corrected (Ps=%.1e)\n", errnum,\r
-                               (float) errnum / (float) LDPepb);\r
-               if (errflag)\r
-                       opj_event_msg(j2k->cinfo, EVT_INFO, "- there were unrecoverable errors\n");\r
-\r
-       }\r
-\r
-       cio_seek(j2k->cio, orig_pos);\r
-\r
-       return true;\r
-}\r
-\r
-void jpwl_epc_write(jpwl_epc_ms_t *epc, unsigned char *buf) {\r
-\r
-       /* Marker */\r
-       *(buf++) = (unsigned char) (J2K_MS_EPC >> 8); \r
-       *(buf++) = (unsigned char) (J2K_MS_EPC >> 0); \r
-\r
-       /* Lepc */\r
-       *(buf++) = (unsigned char) (epc->Lepc >> 8); \r
-       *(buf++) = (unsigned char) (epc->Lepc >> 0); \r
-\r
-       /* Pcrc */\r
-       *(buf++) = (unsigned char) (epc->Pcrc >> 8); \r
-       *(buf++) = (unsigned char) (epc->Pcrc >> 0);\r
-\r
-       /* DL */\r
-       *(buf++) = (unsigned char) (epc->DL >> 24); \r
-       *(buf++) = (unsigned char) (epc->DL >> 16); \r
-       *(buf++) = (unsigned char) (epc->DL >> 8); \r
-       *(buf++) = (unsigned char) (epc->DL >> 0); \r
-\r
-       /* Pepc */\r
-       *(buf++) = (unsigned char) (epc->Pepc >> 0); \r
-\r
-       /* Data */\r
-       /*memcpy(buf, epc->data, (size_t) epc->Lepc - 9);*/\r
-       memset(buf, 0, (size_t) epc->Lepc - 9);\r
-};\r
-\r
-int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,\r
-                                 int comps, unsigned char addrm, unsigned char ad_size,\r
-                                 unsigned char senst, unsigned char se_size,\r
-                                 double place_pos, int tileno) {\r
-\r
-       return 0;\r
-}\r
-\r
-jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comp, unsigned char addrm, unsigned char ad_size,\r
-                                                               unsigned char senst, unsigned char se_size, int tileno,\r
-                                                               unsigned long int svalnum, void *sensval) {\r
-\r
-       jpwl_esd_ms_t *esd = NULL;\r
-\r
-       /* Alloc space */\r
-       if (!(esd = (jpwl_esd_ms_t *) malloc((size_t) 1 * sizeof (jpwl_esd_ms_t)))) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for ESD MS\n");\r
-               return NULL;\r
-       };\r
-\r
-       /* if relative sensitivity, activate byte range mode */\r
-       if (senst == 0)\r
-               addrm = 1;\r
-\r
-       /* size of sensval's ... */\r
-       if ((ad_size != 0) && (ad_size != 2) && (ad_size != 4)) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address size %d for ESD MS is forbidden\n", ad_size);\r
-               return NULL;\r
-       }\r
-       if ((se_size != 1) && (se_size != 2)) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Sensitivity size %d for ESD MS is forbidden\n", se_size);\r
-               return NULL;\r
-       }\r
-       \r
-       /* ... depends on the addressing mode */\r
-       switch (addrm) {\r
-\r
-       /* packet mode */\r
-       case (0):\r
-               ad_size = 0; /* as per the standard */\r
-               esd->sensval_size = se_size; \r
-               break;\r
-\r
-       /* byte range */\r
-       case (1):\r
-               /* auto sense address size */\r
-               if (ad_size == 0)\r
-                       /* if there are more than 66% of (2^16 - 1) bytes, switch to 4 bytes\r
-                        (we keep space for possible EPBs being inserted) */\r
-                       ad_size = (j2k->image_info->codestream_size > (1 * 65535 / 3)) ? 4 : 2;\r
-               esd->sensval_size = ad_size + ad_size + se_size; \r
-               break;\r
-\r
-       /* packet range */\r
-       case (2):\r
-               /* auto sense address size */\r
-               if (ad_size == 0)\r
-                       /* if there are more than 2^16 - 1 packets, switch to 4 bytes */\r
-                       ad_size = (j2k->image_info->num > 65535) ? 4 : 2;\r
-               esd->sensval_size = ad_size + ad_size + se_size; \r
-               break;\r
-\r
-       case (3):\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is unimplemented\n", addrm);\r
-               return NULL;\r
-\r
-       default:\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is forbidden\n", addrm);\r
-               return NULL;\r
-       }\r
-\r
-       /* set or unset sensitivity values */\r
-       if (svalnum <= 0) {\r
-\r
-               switch (senst) {\r
-\r
-               /* just based on the portions of a codestream */\r
-               case (0):\r
-                       /* MH + no. of THs + no. of packets */\r
-                       svalnum = 1 + (j2k->image_info->tw * j2k->image_info->th) * (1 + j2k->image_info->num);\r
-                       break;\r
-\r
-               /* all the ones that are based on the packets */\r
-               default:\r
-                       if (tileno < 0)\r
-                               /* MH: all the packets and all the tiles info is written */\r
-                               svalnum = j2k->image_info->tw * j2k->image_info->th * j2k->image_info->num;\r
-                       else\r
-                               /* TPH: only that tile info is written */\r
-                               svalnum = j2k->image_info->num;\r
-                       break;\r
-\r
-               }\r
-       }               \r
-\r
-       /* fill private fields */\r
-       esd->senst = senst;\r
-       esd->ad_size = ad_size;\r
-       esd->se_size = se_size;\r
-       esd->addrm = addrm;\r
-       esd->svalnum = svalnum;\r
-       esd->numcomps = j2k->image->numcomps;\r
-       esd->tileno = tileno;\r
-       \r
-       /* Set the ESD parameters */\r
-       /* length, excluding data field */\r
-       if (esd->numcomps < 257)\r
-               esd->Lesd = 4 + (unsigned short int) (esd->svalnum * esd->sensval_size);\r
-       else\r
-               esd->Lesd = 5 + (unsigned short int) (esd->svalnum * esd->sensval_size);\r
-\r
-       /* component data field */\r
-       if (comp >= 0)\r
-               esd->Cesd = comp;\r
-       else\r
-               /* we are averaging */\r
-               esd->Cesd = 0;\r
-\r
-       /* Pesd field */\r
-       esd->Pesd = 0x00;\r
-       esd->Pesd |= (esd->addrm & 0x03) << 6; /* addressing mode */\r
-       esd->Pesd |= (esd->senst & 0x07) << 3; /* sensitivity type */\r
-       esd->Pesd |= ((esd->se_size >> 1) & 0x01) << 2; /* sensitivity size */\r
-       esd->Pesd |= ((esd->ad_size >> 2) & 0x01) << 1; /* addressing size */\r
-       esd->Pesd |= (comp < 0) ? 0x01 : 0x00; /* averaging components */\r
-\r
-       /* if pointer to sensval is NULL, we can fill data field by ourselves */\r
-       if (!sensval) {\r
-\r
-               /* old code moved to jpwl_esd_fill() */\r
-               esd->data = NULL;\r
-\r
-       } else {\r
-                       /* we set the data field as the sensitivity values poinnter passed to the function */\r
-                       esd->data = (unsigned char *) sensval;\r
-       }\r
-\r
-       return (esd);\r
-}\r
-\r
-bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {\r
-\r
-       int i;\r
-       unsigned long int vv;\r
-       unsigned long int addr1, addr2;\r
-       double dvalue, Omax2, tmp, TSE, MSE, oldMSE, PSNR, oldPSNR;\r
-       unsigned short int pfpvalue;\r
-       unsigned long int addrmask = 0x00000000;\r
-       bool doneMH = false, doneTPH = false;\r
-\r
-       /* sensitivity values in image info are as follows:\r
-               - for each tile, distotile is the starting distortion for that tile, sum of all components\r
-               - for each packet in a tile, disto is the distortion reduction caused by that packet to that tile\r
-               - the TSE for a single tile should be given by   distotile - sum(disto)  , for all components\r
-               - the MSE for a single tile is given by     TSE / nbpix    , for all components\r
-               - the PSNR for a single tile is given by   10*log10( Omax^2 / MSE)    , for all components\r
-                 (Omax is given by    2^bpp - 1    for unsigned images and by    2^(bpp - 1) - 1    for signed images\r
-       */\r
-\r
-       /* browse all components and find Omax */\r
-       Omax2 = 0.0;\r
-       for (i = 0; i < j2k->image->numcomps; i++) {\r
-               tmp = pow(2.0, (double) (j2k->image->comps[i].sgnd ?\r
-                       (j2k->image->comps[i].bpp - 1) : (j2k->image->comps[i].bpp))) - 1;\r
-               if (tmp > Omax2)\r
-                       Omax2 = tmp;\r
-       }\r
-       Omax2 = Omax2 * Omax2;\r
-\r
-       /* if pointer of esd->data is not null, simply write down all the values byte by byte */\r
-       if (esd->data) {\r
-               for (i = 0; i < (int) esd->svalnum; i++)\r
-                       *(buf++) = esd->data[i]; \r
-               return true;\r
-       }\r
-\r
-       /* addressing mask */\r
-       if (esd->ad_size == 2)\r
-               addrmask = 0x0000FFFF; /* two bytes */\r
-       else\r
-               addrmask = 0xFFFFFFFF; /* four bytes */\r
-\r
-       /* set on precise point where sensitivity starts */\r
-       if (esd->numcomps < 257)\r
-               buf += 6;\r
-       else\r
-               buf += 7;\r
-\r
-       /* let's fill the data fields */\r
-       for (vv = (esd->tileno < 0) ? 0 : (j2k->image_info->num * esd->tileno); vv < esd->svalnum; vv++) {\r
-\r
-               int thistile = vv / j2k->image_info->num, thispacket = vv % j2k->image_info->num;\r
-\r
-               /* skip for the hack some lines below */\r
-               if (thistile == j2k->image_info->tw * j2k->image_info->th)\r
-                       break;\r
-\r
-               /* starting tile distortion */\r
-               if (thispacket == 0) {\r
-                       TSE = j2k->image_info->tile[thistile].distotile;\r
-                       oldMSE = TSE / j2k->image_info->tile[thistile].nbpix;\r
-                       oldPSNR = 10.0 * log10(Omax2 / oldMSE);\r
-               }\r
-\r
-               /* TSE */\r
-               TSE -= j2k->image_info->tile[thistile].packet[thispacket].disto;\r
-\r
-               /* MSE */\r
-               MSE = TSE / j2k->image_info->tile[thistile].nbpix;\r
-\r
-               /* PSNR */\r
-               PSNR = 10.0 * log10(Omax2 / MSE);\r
-\r
-               /* fill the address range */\r
-               switch (esd->addrm) {\r
-\r
-               /* packet mode */\r
-               case (0):\r
-                       /* nothing, there is none */\r
-                       break;\r
-\r
-               /* byte range */\r
-               case (1):\r
-                       /* start address of packet */\r
-                       addr1 = (j2k->image_info->tile[thistile].packet[thispacket].start_pos) & addrmask;\r
-                       /* end address of packet */\r
-                       addr2 = (j2k->image_info->tile[thistile].packet[thispacket].end_pos) & addrmask;\r
-                       break;\r
-\r
-               /* packet range */\r
-               case (2):\r
-                       /* not implemented here */\r
-                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Addressing mode packet_range is not implemented\n");\r
-                       break;\r
-\r
-               /* unknown addressing method */\r
-               default:\r
-                       /* not implemented here */\r
-                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown addressing mode\n");\r
-                       break;\r
-\r
-               }\r
-\r
-               /* hack for writing relative sensitivity of MH and TPHs */\r
-               if ((esd->senst == 0) && (thispacket == 0)) {\r
-\r
-                       /* possible MH */\r
-                       if ((thistile == 0) && !doneMH) {\r
-                               /* we have to manage MH addresses */\r
-                               addr1 = 0; /* start of MH */\r
-                               addr2 = j2k->image_info->main_head_end; /* end of MH */\r
-                               /* set special dvalue for this MH */\r
-                               dvalue = -10.0;\r
-                               doneMH = true; /* don't come here anymore */\r
-                               vv--; /* wrap back loop counter */\r
-\r
-                       } else if (!doneTPH) {\r
-                               /* we have to manage TPH addresses */\r
-                               addr1 = j2k->image_info->tile[thistile].start_pos;\r
-                               addr2 = j2k->image_info->tile[thistile].end_header;\r
-                               /* set special dvalue for this TPH */\r
-                               dvalue = -1.0;\r
-                               doneTPH = true; /* don't come here till the next tile */\r
-                               vv--; /* wrap back loop counter */\r
-                       }\r
-\r
-               } else\r
-                       doneTPH = false; /* reset TPH counter */\r
-\r
-               /* write the addresses to the buffer */\r
-               switch (esd->ad_size) {\r
-\r
-               case (0):\r
-                       /* do nothing */\r
-                       break;\r
-\r
-               case (2):\r
-                       /* two bytes */\r
-                       *(buf++) = (unsigned char) (addr1 >> 8); \r
-                       *(buf++) = (unsigned char) (addr1 >> 0); \r
-                       *(buf++) = (unsigned char) (addr2 >> 8); \r
-                       *(buf++) = (unsigned char) (addr2 >> 0); \r
-                       break;\r
-\r
-               case (4):\r
-                       /* four bytes */\r
-                       *(buf++) = (unsigned char) (addr1 >> 24); \r
-                       *(buf++) = (unsigned char) (addr1 >> 16); \r
-                       *(buf++) = (unsigned char) (addr1 >> 8); \r
-                       *(buf++) = (unsigned char) (addr1 >> 0); \r
-                       *(buf++) = (unsigned char) (addr2 >> 24); \r
-                       *(buf++) = (unsigned char) (addr2 >> 16); \r
-                       *(buf++) = (unsigned char) (addr2 >> 8); \r
-                       *(buf++) = (unsigned char) (addr2 >> 0); \r
-                       break;\r
-\r
-               default:\r
-                       /* do nothing */\r
-                       break;\r
-               }\r
-\r
-\r
-               /* let's fill the value field */\r
-               switch (esd->senst) {\r
-\r
-               /* relative sensitivity */\r
-               case (0):\r
-                       /* we just write down the packet ordering */\r
-                       if (dvalue == -10)\r
-                               /* MH */\r
-                               dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */\r
-                       else if (dvalue == -1)\r
-                               /* TPH */\r
-                               dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */\r
-                       else\r
-                               /* packet: first is most important, and then in decreasing order\r
-                               down to the last, which counts for 1 */\r
-                               dvalue = jpwl_pfp_to_double(j2k->image_info->num - thispacket, esd->se_size);\r
-                       break;\r
-\r
-               /* MSE */\r
-               case (1):\r
-                       /* !!! WRONG: let's put here disto field of packets !!! */\r
-                       dvalue = MSE;\r
-                       break;\r
-\r
-               /* MSE reduction */\r
-               case (2):\r
-                       dvalue = oldMSE - MSE;\r
-                       oldMSE = MSE;\r
-                       break;\r
-\r
-               /* PSNR */\r
-               case (3):\r
-                       dvalue = PSNR;\r
-                       break;\r
-\r
-               /* PSNR increase */\r
-               case (4):\r
-                       dvalue = PSNR - oldPSNR;\r
-                       oldPSNR = PSNR;\r
-                       break;\r
-\r
-               /* MAXERR */\r
-               case (5):\r
-                       dvalue = 0.0;\r
-                       opj_event_msg(j2k->cinfo, EVT_WARNING, "MAXERR sensitivity mode is not implemented\n");\r
-                       break;\r
-\r
-               /* TSE */\r
-               case (6):\r
-                       dvalue = TSE;\r
-                       break;\r
-\r
-               /* reserved */\r
-               case (7):\r
-                       dvalue = 0.0;\r
-                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Reserved sensitivity mode is not implemented\n");\r
-                       break;\r
-\r
-               default:\r
-                       dvalue = 0.0;\r
-                       break;\r
-               }\r
-\r
-               /* compute the pseudo-floating point value */\r
-               pfpvalue = jpwl_double_to_pfp(dvalue, esd->se_size);\r
-\r
-               /* write the pfp value to the buffer */\r
-               switch (esd->se_size) {\r
-\r
-               case (1):\r
-                       /* one byte */\r
-                       *(buf++) = (unsigned char) (pfpvalue >> 0); \r
-                       break;\r
-\r
-               case (2):\r
-                       /* two bytes */\r
-                       *(buf++) = (unsigned char) (pfpvalue >> 8); \r
-                       *(buf++) = (unsigned char) (pfpvalue >> 0); \r
-                       break;\r
-               }\r
-\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-void jpwl_esd_write(jpwl_esd_ms_t *esd, unsigned char *buf) {\r
-\r
-       /* Marker */\r
-       *(buf++) = (unsigned char) (J2K_MS_ESD >> 8); \r
-       *(buf++) = (unsigned char) (J2K_MS_ESD >> 0); \r
-\r
-       /* Lesd */\r
-       *(buf++) = (unsigned char) (esd->Lesd >> 8); \r
-       *(buf++) = (unsigned char) (esd->Lesd >> 0); \r
-\r
-       /* Cesd */\r
-       if (esd->numcomps >= 257)\r
-               *(buf++) = (unsigned char) (esd->Cesd >> 8); \r
-       *(buf++) = (unsigned char) (esd->Cesd >> 0); \r
-\r
-       /* Pesd */\r
-       *(buf++) = (unsigned char) (esd->Pesd >> 0); \r
-\r
-       /* Data */\r
-       if (esd->numcomps < 257)\r
-               memset(buf, 0xAA, (size_t) esd->Lesd - 4);\r
-               /*memcpy(buf, esd->data, (size_t) esd->Lesd - 4);*/\r
-       else\r
-               memset(buf, 0xAA, (size_t) esd->Lesd - 5);\r
-               /*memcpy(buf, esd->data, (size_t) esd->Lesd - 5);*/\r
-}\r
-\r
-unsigned short int jpwl_double_to_pfp(double V, int bytes) {\r
-\r
-       unsigned short int em, e, m;\r
-\r
-       switch (bytes) {\r
-\r
-       case (1):\r
-\r
-               if (V < MIN_V1) {\r
-                       e = 0x0000;\r
-                       m = 0x0000;\r
-               } else if (V > MAX_V1) {\r
-                       e = 0x000F;\r
-                       m = 0x000F;\r
-               } else {\r
-                       e = (unsigned short int) (floor(log(V) * 1.44269504088896) / 4.0);\r
-                       m = (unsigned short int) (0.5 + (V / (pow(2.0, (double) (4 * e)))));\r
-               }\r
-               em = ((e & 0x000F) << 4) + (m & 0x000F);                \r
-               break;\r
-\r
-       case (2):\r
-\r
-               if (V < MIN_V2) {\r
-                       e = 0x0000;\r
-                       m = 0x0000;\r
-               } else if (V > MAX_V2) {\r
-                       e = 0x001F;\r
-                       m = 0x07FF;\r
-               } else {\r
-                       e = (unsigned short int) floor(log(V) * 1.44269504088896) + 15;\r
-                       m = (unsigned short int) (0.5 + 2048.0 * ((V / (pow(2.0, (double) e - 15.0))) - 1.0));\r
-               }\r
-               em = ((e & 0x001F) << 11) + (m & 0x07FF);\r
-               break;\r
-\r
-       default:\r
-\r
-               em = 0x0000;\r
-               break;\r
-       };\r
-\r
-       return em;\r
-}\r
-\r
-double jpwl_pfp_to_double(unsigned short int em, int bytes) {\r
-\r
-       double V;\r
-\r
-       switch (bytes) {\r
-\r
-       case 1:\r
-               V = (double) (em & 0x0F) * pow(2.0, (double) (em & 0xF0));\r
-               break;\r
-\r
-       case 2:\r
-\r
-               V = pow(2.0, (double) ((em & 0xF800) >> 11) - 15.0) * (1.0 + (double) (em & 0x07FF) / 2048.0);\r
-               break;\r
-\r
-       default:\r
-               V = 0.0;\r
-               break;\r
-\r
-       }\r
-\r
-       return V;\r
-\r
-}\r
-\r
-bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num) {\r
-\r
-       int mm;\r
-       unsigned long int addlen;\r
-\r
-       opj_image_info_t *info = j2k->image_info;\r
-       int tileno, packno, numtiles = info->th * info->tw, numpacks = info->num;\r
-\r
-       if (!j2k || !jwmarker ) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "J2K handle or JPWL markers list badly allocated\n");\r
-               return false;\r
-       }\r
-\r
-       /* main_head_end: how many markers are there before? */\r
-       addlen = 0;\r
-       for (mm = 0; mm < jwmarker_num; mm++)\r
-               if (jwmarker[mm].pos < (unsigned long int) info->main_head_end)\r
-                       addlen += jwmarker[mm].len + 2;\r
-       info->main_head_end += addlen;\r
-\r
-       /* codestream_size: always increment with all markers */\r
-       addlen = 0;\r
-       for (mm = 0; mm < jwmarker_num; mm++)\r
-               addlen += jwmarker[mm].len + 2;\r
-       info->codestream_size += addlen;\r
-\r
-       /* navigate through all the tiles */\r
-       for (tileno = 0; tileno < numtiles; tileno++) {\r
-\r
-               /* start_pos: increment with markers before SOT */\r
-               addlen = 0;\r
-               for (mm = 0; mm < jwmarker_num; mm++)\r
-                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].start_pos)\r
-                               addlen += jwmarker[mm].len + 2;\r
-               info->tile[tileno].start_pos += addlen;\r
-\r
-               /* end_header: increment with markers before of it */\r
-               addlen = 0;\r
-               for (mm = 0; mm < jwmarker_num; mm++)\r
-                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_header)\r
-                               addlen += jwmarker[mm].len + 2;\r
-               info->tile[tileno].end_header += addlen;\r
-\r
-               /* end_pos: increment with markers before the end of this tile */\r
-               /* code is disabled, since according to JPWL no markers can be beyond TPH */\r
-               /*addlen = 0;\r
-               for (mm = 0; mm < jwmarker_num; mm++)\r
-                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_pos)\r
-                               addlen += jwmarker[mm].len + 2;*/\r
-               info->tile[tileno].end_pos += addlen;\r
-\r
-               /* navigate through all the packets in this tile */\r
-               for (packno = 0; packno < numpacks; packno++) {\r
-                       \r
-                       /* start_pos: increment with markers before the packet */\r
-                       /* disabled for the same reason as before */\r
-                       /*addlen = 0;\r
-                       for (mm = 0; mm < jwmarker_num; mm++)\r
-                               if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].start_pos)\r
-                                       addlen += jwmarker[mm].len + 2;*/\r
-                       info->tile[tileno].packet[packno].start_pos += addlen;\r
-\r
-                       /* end_pos: increment if marker is before the end of packet */\r
-                       /* disabled for the same reason as before */\r
-                       /*addlen = 0;\r
-                       for (mm = 0; mm < jwmarker_num; mm++)\r
-                               if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_pos)\r
-                                       addlen += jwmarker[mm].len + 2;*/\r
-                       info->tile[tileno].packet[packno].end_pos += addlen;\r
-\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef USE_JPWL
+
+#include "../libopenjpeg/opj_includes.h"
+
+/** Minimum and maximum values for the double->pfp conversion */
+#define MIN_V1 0.0
+#define MAX_V1 17293822569102704640.0
+#define MIN_V2 0.000030517578125
+#define MAX_V2 131040.0
+
+/** conversion between a double precision floating point
+number and the corresponding pseudo-floating point used 
+to represent sensitivity values
+@param V the double precision value
+@param bytes the number of bytes of the representation
+@return the pseudo-floating point value (cast accordingly)
+*/
+unsigned short int jpwl_double_to_pfp(double V, int bytes);
+
+/** conversion between a pseudo-floating point used 
+to represent sensitivity values and the corresponding
+double precision floating point number  
+@param em the pseudo-floating point value (cast accordingly)
+@param bytes the number of bytes of the representation
+@return the double precision value
+*/
+double jpwl_pfp_to_double(unsigned short int em, int bytes);
+
+       /*-------------------------------------------------------------*/
+
+int jpwl_markcomp(const void *arg1, const void *arg2)
+{
+   /* Compare the two markers' positions */
+   double diff = (((jpwl_marker_t *) arg1)->dpos - ((jpwl_marker_t *) arg2)->dpos);
+
+   if (diff == 0.0)
+          return (0);
+   else if (diff < 0)
+          return (-1);
+   else
+          return (+1);
+}
+
+int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+                                 bool latest, bool packed, bool insideMH, int *idx, int hprot,
+                                 double place_pos, int tileno,
+                                 unsigned long int pre_len, unsigned long int post_len) {
+
+       jpwl_epb_ms_t *epb_mark = NULL;
+
+       int k_pre, k_post, n_pre, n_post;
+       
+       unsigned long int L1, L2, dL4, max_postlen, epbs_len = 0;
+
+       /* We find RS(n,k) for EPB parms and pre-data, if any */
+       if (insideMH && (*idx == 0)) {
+               /* First EPB in MH */ 
+               k_pre = 64;
+               n_pre = 160;
+       } else if (!insideMH && (*idx == 0)) {
+               /* First EPB in TH */
+               k_pre = 25;
+               n_pre = 80;
+       } else {
+               /* Following EPBs in MH or TH */
+               k_pre = 13;
+               n_pre = 40;
+       };
+
+       /* Find lengths, Figs. B3 and B4 */
+       /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+       L1 = pre_len + 13;
+
+       /* size of pre-data redundancy */
+       /*   (redundancy per codeword)       *     (number of codewords, rounded up)   */
+       L2 = (n_pre - k_pre) * (unsigned long int) ceil((double) L1 / (double) k_pre);
+
+       /* Find protection type for post data and its associated redundancy field length*/
+       if ((hprot == 16) || (hprot == 32)) {
+               /* there is a CRC for post-data */
+               k_post = post_len;
+               n_post = post_len + (hprot >> 3);
+               /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+       } else if ((hprot >= 37) && (hprot <= 128)) {
+               /* there is a RS for post-data */
+               k_post = 32;
+               n_post = hprot;
+
+       } else {
+               /* Use predefined codes */
+               n_post = n_pre;
+               k_post = k_pre;
+       };
+
+       /* Create the EPB(s) */
+       while (post_len > 0) {
+
+               /* maximum postlen in order to respect EPB size
+               (we use 65450 instead of 65535 for keeping room for EPB parms)*/
+               /*      (message word size)    *            (number of containable parity words)  */
+               max_postlen = k_post * (unsigned long int) floor(65450.0 / (double) (n_post - k_post));
+
+               /* maximum postlen in order to respect EPB size */
+               if (*idx == 0)
+                       /* (we use (65500 - L2) instead of 65535 for keeping room for EPB parms + pre-data) */
+                       /*      (message word size)    *                   (number of containable parity words)  */
+                       max_postlen = k_post * (unsigned long int) floor((double) (65500 - L2) / (double) (n_post - k_post));
+
+               else
+                       /* (we use 65500 instead of 65535 for keeping room for EPB parms) */
+                       /*      (message word size)    *            (number of containable parity words)  */
+                       max_postlen = k_post * (unsigned long int) floor(65500.0 / (double) (n_post - k_post));
+
+               /* length to use */
+               dL4 = min(max_postlen, post_len);
+
+               if (epb_mark = jpwl_epb_create(
+                       j2k, /* this encoder handle */
+                       latest ? (dL4 < max_postlen) : false, /* is it the latest? */
+                       packed, /* is it packed? */
+                       tileno, /* we are in TPH */
+                       *idx, /* its index */
+                       hprot, /* protection type parameters of following data */
+                       0, /* pre-data: nothing for now */
+                       dL4 /* post-data: the stub computed previously */
+                       )) {
+                       
+                       /* Add this marker to the 'insertanda' list */
+                       if (*jwmarker_num < JPWL_MAX_NO_MARKERS) {
+                               jwmarker[*jwmarker_num].id = J2K_MS_EPB; /* its type */
+                               jwmarker[*jwmarker_num].epbmark = epb_mark; /* the EPB */
+                               jwmarker[*jwmarker_num].pos = (int) place_pos; /* after SOT */
+                               jwmarker[*jwmarker_num].dpos = place_pos + 0.0000001 * (double)(*idx); /* not very first! */
+                               jwmarker[*jwmarker_num].len = epb_mark->Lepb; /* its length */
+                               jwmarker[*jwmarker_num].len_ready = true; /* ready */
+                               jwmarker[*jwmarker_num].pos_ready = true; /* ready */
+                               jwmarker[*jwmarker_num].parms_ready = true; /* ready */
+                               jwmarker[*jwmarker_num].data_ready = false; /* not ready */
+                               (*jwmarker_num)++;
+                       }
+
+                       /* increment epb index */
+                       (*idx)++;
+
+                       /* decrease postlen */
+                       post_len -= dL4;
+
+                       /* increase the total length of EPBs */
+                       epbs_len += epb_mark->Lepb + 2;
+
+               } else {
+                       /* ooops, problems */
+                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB for UEP in tile %d\n", tileno);                          
+               };
+       }
+
+       return epbs_len;
+}
+
+
+jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, bool latest, bool packed, int tileno, int idx, int hprot,
+                                                 unsigned long int pre_len, unsigned long int post_len) {
+
+       jpwl_epb_ms_t *epb = NULL;
+       unsigned short int data_len = 0;
+       unsigned short int L2, L3;
+       unsigned long int L1, L4;
+       unsigned char *predata_in = NULL;
+
+       bool insideMH = (tileno == -1);
+
+       /* Alloc space */
+       if (!(epb = (jpwl_epb_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epb_ms_t)))) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for one EPB MS\n");
+               return NULL;
+       };
+
+       /* We set RS(n,k) for EPB parms and pre-data, if any */
+       if (insideMH && (idx == 0)) {
+               /* First EPB in MH */ 
+               epb->k_pre = 64;
+               epb->n_pre = 160;
+       } else if (!insideMH && (idx == 0)) {
+               /* First EPB in TH */
+               epb->k_pre = 25;
+               epb->n_pre = 80;
+       } else {
+               /* Following EPBs in MH or TH */
+               epb->k_pre = 13;
+               epb->n_pre = 40;
+       };
+
+       /* Find lengths, Figs. B3 and B4 */
+       /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+       L1 = pre_len + 13;
+       epb->pre_len = pre_len;
+
+       /* size of pre-data redundancy */
+       /*   (redundancy per codeword)       *               (number of codewords, rounded up)   */
+       L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+       /* length of post-data */
+       L4 = post_len;
+       epb->post_len = post_len;
+
+       /* Find protection type for post data and its associated redundancy field length*/
+       if ((hprot == 16) || (hprot == 32)) {
+               /* there is a CRC for post-data */
+               epb->Pepb = 0x10000000 | ((unsigned long int) hprot >> 5); /* 0=CRC-16, 1=CRC-32 */
+               epb->k_post = post_len;
+               epb->n_post = post_len + (hprot >> 3);
+               /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+       } else if ((hprot >= 37) && (hprot <= 128)) {
+               /* there is a RS for post-data */
+               epb->Pepb = 0x20000020 | (((unsigned long int) hprot & 0x000000FF) << 8);
+               epb->k_post = 32;
+               epb->n_post = hprot;
+
+       } else if (hprot == 1) {
+               /* Use predefined codes */
+               epb->Pepb = (unsigned long int) 0x00000000;
+               epb->n_post = epb->n_pre;
+               epb->k_post = epb->k_pre;
+       
+       } else if (hprot == 0) {
+               /* Placeholder EPB: only protects its parameters, no protection method */
+               epb->Pepb = (unsigned long int) 0xFFFFFFFF;
+               epb->n_post = 1;
+               epb->k_post = 1;
+       
+       } else {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Invalid protection value for EPB h = %d\n", hprot);                               
+               return NULL;
+       }
+
+       epb->hprot = hprot;
+
+       /*   (redundancy per codeword)          *                (number of codewords, rounded up) */
+       L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+       /* private fields */
+       epb->tileno = tileno;
+
+       /* Fill some fields of the EPB */
+
+       /* total length of the EPB MS (less the EPB marker itself): */
+       /* Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) + pre_redundancy + post-redundancy */
+       epb->Lepb = 11 + L2 + L3;
+
+       /* EPB style */
+       epb->Depb = ((packed & 0x0001) << 7) | ((latest & 0x0001) << 6) | (idx & 0x003F);
+
+       /* length of data protected by EPB: */
+       epb->LDPepb = L1 + L4;
+
+       return epb;
+}
+
+void jpwl_epb_write(jpwl_epb_ms_t *epb, unsigned char *buf) {
+
+       /* Marker */
+       *(buf++) = (unsigned char) (J2K_MS_EPB >> 8); 
+       *(buf++) = (unsigned char) (J2K_MS_EPB >> 0); 
+
+       /* Lepb */
+       *(buf++) = (unsigned char) (epb->Lepb >> 8); 
+       *(buf++) = (unsigned char) (epb->Lepb >> 0); 
+
+       /* Depb */
+       *(buf++) = (unsigned char) (epb->Depb >> 0); 
+
+       /* LDPepb */
+       *(buf++) = (unsigned char) (epb->LDPepb >> 24); 
+       *(buf++) = (unsigned char) (epb->LDPepb >> 16); 
+       *(buf++) = (unsigned char) (epb->LDPepb >> 8); 
+       *(buf++) = (unsigned char) (epb->LDPepb >> 0); 
+
+       /* Pepb */
+       *(buf++) = (unsigned char) (epb->Pepb >> 24); 
+       *(buf++) = (unsigned char) (epb->Pepb >> 16); 
+       *(buf++) = (unsigned char) (epb->Pepb >> 8); 
+       *(buf++) = (unsigned char) (epb->Pepb >> 0); 
+
+       /* Data */
+       /*memcpy(buf, epb->data, (size_t) epb->Lepb - 11);*/
+       memset(buf, 0, (size_t) epb->Lepb - 11);
+};
+
+
+jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, bool esd_on, bool red_on, bool epb_on, bool info_on) {
+
+       jpwl_epc_ms_t *epc = NULL;
+
+       /* Alloc space */
+       if (!(epc = (jpwl_epc_ms_t *) malloc((size_t) 1 * sizeof (jpwl_epc_ms_t)))) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for EPC MS\n");
+               return NULL;
+       };
+
+       /* Set the EPC parameters */
+       epc->esd_on = esd_on;
+       epc->epb_on = epb_on;
+       epc->red_on = red_on;
+       epc->info_on = info_on;
+
+       /* Fill the EPC fields with default values */
+       epc->Lepc = 9;
+       epc->Pcrc = 0x0000;
+       epc->DL = 0x00000000;
+       epc->Pepc = ((j2k->cp->esd_on & 0x0001) << 4) | ((j2k->cp->red_on & 0x0001) << 5) |
+               ((j2k->cp->epb_on & 0x0001) << 6) | ((j2k->cp->info_on & 0x0001) << 7);
+
+       return (epc);
+}
+
+bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf, unsigned char *post_buf) {
+
+       unsigned long int L1, L2, L3, L4;
+       int remaining;
+       unsigned long int P, NN_P;
+
+       /* Operating buffer */
+       static unsigned char codeword[NN], *parityword;
+
+       unsigned char *L1_buf, *L2_buf;
+       /* these ones are static, since we need to keep memory of
+        the exact place from one call to the other */
+       static unsigned char *L3_buf, *L4_buf;
+
+       /* some consistency check */
+       if (!buf) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs\n");
+               return false;
+       }
+
+       if (!post_buf && !L4_buf) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs data\n");
+               return false;
+       }
+
+       /*
+        * Compute parity bytes on pre-data, ALWAYS present (at least only for EPB parms)
+        */
+
+       /* Initialize RS structures */
+       P = epb->n_pre - epb->k_pre;
+       NN_P = NN - P;
+       memset(codeword, 0, NN);
+       parityword = codeword + NN_P;
+       init_rs(NN_P);
+
+       /* pre-data begins pre_len bytes before of EPB buf */
+       L1_buf = buf - epb->pre_len;
+       L1 = epb->pre_len + 13;
+
+       /* redundancy for pre-data begins immediately after EPB parms */
+       L2_buf = buf + 13;
+       L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+       /* post-data
+          the position of L4 buffer can be:
+            1) passed as a parameter: in that case use it
+            2) null: in that case use the previous (static) one
+       */
+       if (post_buf)
+               L4_buf = post_buf;
+       L4 = epb->post_len;
+
+       /* post-data redundancy begins immediately after pre-data redundancy */
+       L3_buf = L2_buf + L2;
+       L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+       /* let's check whether EPB length is sufficient to contain all these data */
+       if (epb->Lepb < (11 + L2 + L3))
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no room in EPB data field for writing redundancy data\n");
+       /*printf("Env. %d, nec. %d (%d + %d)\n", epb->Lepb - 11, L2 + L3, L2, L3);*/
+
+       /* Compute redundancy of pre-data message words */
+       remaining = L1;
+       while (remaining) {
+
+               /* copy message data into codeword buffer */
+               if (remaining < epb->k_pre) {
+                       /* the last message word is zero-padded */
+                       memset(codeword, 0, NN);
+                       memcpy(codeword, L1_buf, remaining);
+                       L1_buf += remaining;
+                       remaining = 0;
+
+               } else {
+                       memcpy(codeword, L1_buf, epb->k_pre);
+                       L1_buf += epb->k_pre;
+                       remaining -= epb->k_pre;
+
+               }
+
+               /* Encode the buffer and obtain parity bytes */
+               if (encode_rs(codeword, parityword))
+                       opj_event_msg(j2k->cinfo, EVT_WARNING,
+                               "Possible encoding error in codeword @ position #%d\n", (L1_buf - buf) / epb->k_pre);
+
+               /* copy parity bytes only in redundancy buffer */
+               memcpy(L2_buf, parityword, P); 
+
+               /* advance parity buffer */
+               L2_buf += P;
+       }
+
+       /*
+        * Compute parity bytes on post-data, may be absent if there are no data
+        */
+       /*printf("Hprot is %d (tileno=%d, k_pre=%d, n_pre=%d, k_post=%d, n_post=%d, pre_len=%d, post_len=%d)\n",
+               epb->hprot, epb->tileno, epb->k_pre, epb->n_pre, epb->k_post, epb->n_post, epb->pre_len,
+               epb->post_len);*/
+       if (epb->hprot < 0) {
+
+               /* there should be no EPB */
+               
+       } else if (epb->hprot == 0) {
+
+               /* no protection for the data */
+               /* advance anyway */
+               L4_buf += epb->post_len;
+
+       } else if (epb->hprot == 16) {
+
+               /* CRC-16 */
+               unsigned short int mycrc = 0x0000;
+
+               /* compute the CRC field (excluding itself) */
+               remaining = L4;
+               while (remaining--)
+                       jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+               /* write the CRC field */
+               *(L3_buf++) = (unsigned char) (mycrc >> 8);
+               *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+       } else if (epb->hprot == 32) {
+
+               /* CRC-32 */
+               unsigned long int mycrc = 0x00000000;
+
+               /* compute the CRC field (excluding itself) */
+               remaining = L4;
+               while (remaining--)
+                       jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+               /* write the CRC field */
+               *(L3_buf++) = (unsigned char) (mycrc >> 24);
+               *(L3_buf++) = (unsigned char) (mycrc >> 16);
+               *(L3_buf++) = (unsigned char) (mycrc >> 8);
+               *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+       } else {
+
+               /* RS */
+
+               /* Initialize RS structures */
+               P = epb->n_post - epb->k_post;
+               NN_P = NN - P;
+               memset(codeword, 0, NN);
+               parityword = codeword + NN_P;
+               init_rs(NN_P);
+
+               /* Compute redundancy of post-data message words */
+               remaining = L4;
+               while (remaining) {
+
+                       /* copy message data into codeword buffer */
+                       if (remaining < epb->k_post) {
+                               /* the last message word is zero-padded */
+                               memset(codeword, 0, NN);
+                               memcpy(codeword, L4_buf, remaining);
+                               L4_buf += remaining;
+                               remaining = 0;
+
+                       } else {
+                               memcpy(codeword, L4_buf, epb->k_post);
+                               L4_buf += epb->k_post;
+                               remaining -= epb->k_post;
+
+                       }
+
+                       /* Encode the buffer and obtain parity bytes */
+                       if (encode_rs(codeword, parityword))
+                               opj_event_msg(j2k->cinfo, EVT_WARNING,
+                                       "Possible encoding error in codeword @ position #%d\n", (L4_buf - buf) / epb->k_post);
+
+                       /* copy parity bytes only in redundancy buffer */
+                       memcpy(L3_buf, parityword, P); 
+
+                       /* advance parity buffer */
+                       L3_buf += P;
+               }
+
+       }
+
+       return true;
+}
+
+
+bool jpwl_correct(opj_j2k_t *j2k) {
+
+       opj_cio_t *cio = j2k->cio;
+       bool status;
+       static bool mh_done = false;
+       int mark_pos, id, len, skips, sot_pos;
+       unsigned long int Psot = 0;
+
+       /* go back to marker position */
+       mark_pos = cio_tell(cio) - 2;
+       cio_seek(cio, mark_pos);
+
+       if ((j2k->state == J2K_STATE_MHSOC) && !mh_done) {
+
+               int mark_val = 0, skipnum = 0;
+
+               /*
+                 COLOR IMAGE
+                 first thing to do, if we are here, is to look whether
+                 51 (skipnum) positions ahead there is an EPB, in case of MH
+               */
+               /*
+                 B/W IMAGE
+                 first thing to do, if we are here, is to look whether
+                 45 (skipnum) positions ahead there is an EPB, in case of MH
+               */
+               /*       SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */
+               skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;
+               if ((cio->bp + skipnum) < cio->end) {
+
+                       cio_skip(cio, skipnum);
+
+                       /* check that you are not going beyond the end of codestream */
+
+                       /* call EPB corrector */
+                       status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */
+                                                                         cio->bp, /* pointer to EPB in codestream buffer */
+                                                                         0,       /* EPB type: MH */
+                                                                         skipnum,      /* length of pre-data */
+                                                                         -1,      /* length of post-data: -1 means auto */
+                                                                         NULL,
+                                                                         NULL
+                                                                        );
+
+                       /* read the marker value */
+                       mark_val = (*(cio->bp) << 8) | *(cio->bp + 1);
+
+                       if (status && (mark_val == J2K_MS_EPB)) {
+                               /* we found it! */
+                               mh_done = true;
+                               return true;
+                       }
+
+               }
+
+       }
+
+       if (true /*(j2k->state == J2K_STATE_TPHSOT) || (j2k->state == J2K_STATE_TPH)*/) {
+               /* else, look if 12 positions ahead there is an EPB, in case of TPH */
+               cio_seek(cio, mark_pos);
+               if ((cio->bp + 12) < cio->end) {
+
+                       cio_skip(cio, 12);
+
+                       /* call EPB corrector */
+                       status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */
+                                                                         cio->bp, /* pointer to EPB in codestream buffer */
+                                                                         1,       /* EPB type: TPH */
+                                                                         12,      /* length of pre-data */
+                                                                         -1,      /* length of post-data: -1 means auto */
+                                                                         NULL,
+                                                                         NULL
+                                                                        );
+                       if (status)
+                               /* we found it! */
+                               return true;
+               }
+       }
+
+       return false;
+
+       /* for now, don't use this code */
+
+       /* else, look if here is an EPB, in case of other */
+       if (mark_pos > 64) {
+               /* it cannot stay before the first MH EPB */
+               cio_seek(cio, mark_pos);
+               cio_skip(cio, 0);
+
+               /* call EPB corrector */
+               status = jpwl_epb_correct(j2k,     /* J2K decompressor handle */
+                                                                 cio->bp, /* pointer to EPB in codestream buffer */
+                                                                 2,       /* EPB type: TPH */
+                                                                 0,       /* length of pre-data */
+                                                                 -1,      /* length of post-data: -1 means auto */
+                                                                 NULL,
+                                                                 NULL
+                                                                );
+               if (status)
+                       /* we found it! */
+                       return true;
+       }
+
+       /* nope, no EPBs probably, or they are so damaged that we can give up */
+       return false;
+       
+       return true;
+
+       /* AN ATTEMPT OF PARSER */
+       /* NOT USED ACTUALLY    */
+
+       /* go to the beginning of the file */
+       cio_seek(cio, 0);
+
+       /* let's begin */
+       j2k->state = J2K_STATE_MHSOC;
+
+       /* cycle all over the markers */
+       while (cio_tell(cio) < cio->length) {
+
+               /* read the marker */
+               mark_pos = cio_tell(cio);
+               id = cio_read(cio, 2);
+
+               /* details */
+               printf("Marker@%d: %X\n", cio_tell(cio) - 2, id);
+
+               /* do an action in response to the read marker */
+               switch (id) {
+
+               /* short markers */
+
+                       /* SOC */
+               case J2K_MS_SOC:
+                       j2k->state = J2K_STATE_MHSIZ;
+                       len = 0;
+                       skips = 0;
+                       break;
+
+                       /* EOC */
+               case J2K_MS_EOC:
+                       j2k->state = J2K_STATE_MT;
+                       len = 0;
+                       skips = 0;
+                       break;
+
+                       /* particular case of SOD */
+               case J2K_MS_SOD:
+                       len = Psot - (mark_pos - sot_pos) - 2;
+                       skips = len;
+                       break;
+
+               /* long markers */
+
+                       /* SOT */
+               case J2K_MS_SOT:
+                       j2k->state = J2K_STATE_TPH;
+                       sot_pos = mark_pos; /* position of SOT */
+                       len = cio_read(cio, 2); /* read the length field */
+                       cio_skip(cio, 2); /* this field is unnecessary */
+                       Psot = cio_read(cio, 4); /* tile length */
+                       skips = len - 8;
+                       break;
+
+                       /* remaining */
+               case J2K_MS_SIZ:
+                       j2k->state = J2K_STATE_MH;
+                       /* read the length field */
+                       len = cio_read(cio, 2);
+                       skips = len - 2;
+                       break;
+
+                       /* remaining */
+               default:
+                       /* read the length field */
+                       len = cio_read(cio, 2);
+                       skips = len - 2;
+                       break;
+
+               }
+
+               /* skip to marker's end */
+               cio_skip(cio, skips);   
+
+       }
+
+
+}
+
+bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,
+                                         unsigned char **L4_bufp) {
+
+       /* Operating buffer */
+       unsigned char codeword[NN], *parityword;
+
+       unsigned long int P, NN_P;
+       unsigned long int L1, L4;
+       int remaining, n_pre, k_pre, n_post, k_post;
+
+       int status, tt;
+
+       int orig_pos = cio_tell(j2k->cio);
+
+       unsigned char *L1_buf, *L2_buf;
+       unsigned char *L3_buf, *L4_buf;
+
+       unsigned long int LDPepb, Pepb;
+       unsigned short int Lepb;
+       unsigned char Depb;
+       char str1[25] = "";
+       int myconn, errnum = 0;
+       bool errflag = false;
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* check for common errors */
+       if (!buffer) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "The EPB pointer is a NULL buffer\n");
+               return false;
+       }
+       
+       /* set bignesses */
+       L1 = pre_len + 13;
+
+       /* pre-data correction */
+       switch (type) {
+
+       case 0:
+               /* MH EPB */
+               k_pre = 64;
+               n_pre = 160;
+               break;
+
+       case 1:
+               /* TPH EPB */
+               k_pre = 25;
+               n_pre = 80;
+               break;
+
+       case 2:
+               /* other EPBs */
+               k_pre = 13;
+               n_pre = 40;
+               break;
+
+       case 3:
+               /* automatic setup */
+               break;
+
+       default:
+               /* unknown type */
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Unknown expected EPB type\n");
+               return false;
+               break;
+
+       }
+
+       /* Initialize RS structures */
+       P = n_pre - k_pre;
+       NN_P = NN - P;
+       tt = (int) floor((float) P / 2.0F);
+       memset(codeword, 0, NN);
+       parityword = codeword + NN_P;
+       init_rs(NN_P);
+
+       /* Correct pre-data message words */
+       L1_buf = buffer - pre_len;
+       L2_buf = buffer + 13;
+       remaining = L1;
+       while (remaining) {
+               /* always zero-pad codewords */
+               /* (this is required, since after decoding the zeros in the long codeword
+                   could change, and keep unchanged in subsequent calls) */
+               memset(codeword, 0, NN);
+
+               /* copy codeword buffer into message bytes */
+               if (remaining < k_pre)
+                       memcpy(codeword, L1_buf, remaining);
+               else
+                       memcpy(codeword, L1_buf, k_pre);
+
+               /* copy redundancy buffer in parity bytes */
+               memcpy(parityword, L2_buf, P); 
+
+               /* Decode the buffer and possibly obtain corrected bytes */
+               status = eras_dec_rs(codeword, NULL, 0);
+               if (status == -1) {
+                       /*if (conn == NULL)
+                               opj_event_msg(j2k->cinfo, EVT_WARNING,
+                                       "Possible decoding error in codeword @ position #%d\n", (L1_buf - buffer) / k_pre);*/
+                       errflag = true;
+                       /* we can try to safely get out from the function:
+                         if we are here, either this is not an EPB or the first codeword
+                         is too damaged to be helpful */
+                       /*return false;*/
+
+               } else if (status == 0) {
+                       /*if (conn == NULL)
+                               opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+               } else if (status < tt) {
+                       /*if (conn == NULL)
+                               opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+                       errnum += status;
+
+               } else {
+                       /*if (conn == NULL)
+                               opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+                       return false;*/
+                       errflag = true;
+               }
+
+
+               /* advance parity buffer */
+               if ((status >= 0) && (status < tt))
+                       /* copy back corrected parity only if all is OK */
+                       memcpy(L2_buf, parityword, P);
+               L2_buf += P;
+
+               /* advance message buffer */
+               if (remaining < k_pre) {
+                       if ((status >= 0) && (status < tt))
+                               /* copy back corrected data only if all is OK */
+                               memcpy(L1_buf, codeword, remaining);
+                       L1_buf += remaining;
+                       remaining = 0;
+
+               } else {
+                       if ((status >= 0) && (status < tt))
+                               /* copy back corrected data only if all is OK */
+                               memcpy(L1_buf, codeword, k_pre);
+                       L1_buf += k_pre;
+                       remaining -= k_pre;
+
+               }
+       }
+
+       /* print summary */
+       if (!conn) {
+
+               /*if (errnum)
+                       opj_event_msg(j2k->cinfo, EVT_INFO, "+ %d symbol errors corrected (Ps=%.1e)\n", errnum,
+                               (float) errnum / ((float) n_pre * (float) L1 / (float) k_pre));*/
+               if (errflag) {
+                       /*opj_event_msg(j2k->cinfo, EVT_INFO, "+ there were unrecoverable errors\n");*/
+                       return false;
+               }
+
+       }
+
+       /* presumably, now, EPB parameters are correct */
+       /* let's get them */
+
+       /* Simply read the EPB parameters */
+       if (conn)
+               cio->bp = buffer;
+       cio_skip(cio, 2); /* the marker */
+       Lepb = cio_read(cio, 2);
+       Depb = cio_read(cio, 1);
+       LDPepb = cio_read(cio, 4);
+       Pepb = cio_read(cio, 4);
+
+       /* What does Pepb tells us about the protection method? */
+       if (((Pepb & 0xF0000000) >> 28) == 0)
+               sprintf(str1, "pred"); /* predefined */
+       else if (((Pepb & 0xF0000000) >> 28) == 1)
+               sprintf(str1, "crc-%d", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
+       else if (((Pepb & 0xF0000000) >> 28) == 2)
+               sprintf(str1, "rs(%d,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
+       else if (Pepb == 0xFFFFFFFF)
+               sprintf(str1, "nometh"); /* RS mode */
+       else
+               sprintf(str1, "unknown"); /* unknown */
+
+       /* Now we write them to screen */
+       if (!conn && post_len)
+               opj_event_msg(j2k->cinfo, EVT_INFO,
+                       "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
+                       cio_tell(cio) - 13,
+                       (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
+                       (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
+                       (Depb & 0x3F), /* EPB index value */
+                       LDPepb, /*length of the data protected by the EPB */
+                       str1); /* protection method */
+
+
+       /* well, we need to investigate how long is the connected length of packed EPBs */
+       myconn = Lepb + 2;
+       if ((Depb & 0x40) == 0) /* not latest in header */
+               jpwl_epb_correct(j2k,      /* J2K decompressor handle */
+                                            buffer + Lepb + 2,   /* pointer to next EPB in codestream buffer */
+                                            2,     /* EPB type: should be of other type */
+                                            0,  /* only EPB fields */
+                                            0, /* do not look after */
+                                                &myconn,
+                                                NULL
+                                            );
+       if (conn)
+               *conn += myconn;
+
+       /*if (!conn)
+               printf("connected = %d\n", myconn);*/
+
+       /*cio_seek(j2k->cio, orig_pos);
+       return true;*/
+
+       /* post-data
+          the position of L4 buffer is at the end of currently connected EPBs
+       */
+       if (!(L4_bufp))
+               L4_buf = buffer + myconn;
+       else if (!(*L4_bufp))
+               L4_buf = buffer + myconn;
+       else
+               L4_buf = *L4_bufp;
+       if (post_len == -1) 
+               L4 = LDPepb - pre_len - 13;
+       else if (post_len == 0)
+               L4 = 0;
+       else
+               L4 = post_len;
+
+       L3_buf = L2_buf;
+
+       /* Do a further check here on the read parameters */
+       if (L4 > (unsigned long) cio_numbytesleft(j2k->cio))
+               /* overflow */
+               return false;
+
+       /* we are ready for decoding the remaining data */
+       if (((Pepb & 0xF0000000) >> 28) == 1) {
+               /* CRC here */
+               if ((16 * ((Pepb & 0x00000001) + 1)) == 16) {
+
+                       /* CRC-16 */
+                       unsigned short int mycrc = 0x0000, filecrc = 0x0000;
+
+                       /* compute the CRC field */
+                       remaining = L4;
+                       while (remaining--)
+                               jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+                       /* read the CRC field */
+                       filecrc = *(L3_buf++) << 8;
+                       filecrc |= *(L3_buf++);
+
+                       /* check the CRC field */
+                       if (mycrc == filecrc) {
+                               if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+                       } else {
+                               if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+                               errflag = true;
+                       }       
+               }
+
+               if ((16 * ((Pepb & 0x00000001) + 1)) == 32) {
+
+                       /* CRC-32 */
+                       unsigned long int mycrc = 0x00000000, filecrc = 0x00000000;
+
+                       /* compute the CRC field */
+                       remaining = L4;
+                       while (remaining--)
+                               jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+                       /* read the CRC field */
+                       filecrc = *(L3_buf++) << 24;
+                       filecrc |= *(L3_buf++) << 16;
+                       filecrc |= *(L3_buf++) << 8;
+                       filecrc |= *(L3_buf++);
+
+                       /* check the CRC field */
+                       if (mycrc == filecrc) {
+                               if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+                       } else {
+                               if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+                               errflag = true;
+                       }
+               }
+
+       } else if ((((Pepb & 0xF0000000) >> 28) == 2) || (((Pepb & 0xF0000000) >> 28) == 0)) {
+               /* RS coding here */
+
+               if (((Pepb & 0xF0000000) >> 28) == 0) {
+
+                       k_post = k_pre;
+                       n_post = n_pre;
+
+               } else {
+
+                       k_post = 32;
+                       n_post = (Pepb & 0x0000FF00) >> 8;
+               }
+
+               /* Initialize RS structures */
+               P = n_post - k_post;
+               NN_P = NN - P;
+               tt = (int) floor((float) P / 2.0F);
+               memset(codeword, 0, NN);
+               parityword = codeword + NN_P;
+               init_rs(NN_P);
+
+               /* Correct post-data message words */
+               /*L4_buf = buffer + Lepb + 2;*/
+               L3_buf = L2_buf;
+               remaining = L4;
+               while (remaining) {
+                       /* always zero-pad codewords */
+                       /* (this is required, since after decoding the zeros in the long codeword
+                               could change, and keep unchanged in subsequent calls) */
+                       memset(codeword, 0, NN);
+
+                       /* copy codeword buffer into message bytes */
+                       if (remaining < k_post)
+                               memcpy(codeword, L4_buf, remaining);
+                       else
+                               memcpy(codeword, L4_buf, k_post);
+
+                       /* copy redundancy buffer in parity bytes */
+                       memcpy(parityword, L3_buf, P); 
+
+                       /* Decode the buffer and possibly obtain corrected bytes */
+                       status = eras_dec_rs(codeword, NULL, 0);
+                       if (status == -1) {
+                               /*if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_WARNING,
+                                               "Possible decoding error in codeword @ position #%d\n", (L4_buf - (buffer + Lepb + 2)) / k_post);*/
+                               errflag = true;
+
+                       } else if (status == 0) {
+                               /*if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+                       } else if (status < tt) {
+                               /*if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+                               errnum += status;
+
+                       } else {
+                               /*if (conn == NULL)
+                                       opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+                               return false;*/
+                               errflag = true;
+                       }
+
+
+                       /* advance parity buffer */
+                       if ((status >= 0) && (status < tt))
+                               /* copy back corrected data only if all is OK */
+                               memcpy(L3_buf, parityword, P);
+                       L3_buf += P;
+
+                       /* advance message buffer */
+                       if (remaining < k_post) {
+                               if ((status >= 0) && (status < tt))
+                                       /* copy back corrected data only if all is OK */
+                                       memcpy(L4_buf, codeword, remaining);
+                               L4_buf += remaining;
+                               remaining = 0;
+
+                       } else {
+                               if ((status >= 0) && (status < tt))
+                                       /* copy back corrected data only if all is OK */
+                                       memcpy(L4_buf, codeword, k_post);
+                               L4_buf += k_post;
+                               remaining -= k_post;
+
+                       }
+               }
+       }
+
+       /* give back the L4_buf address */
+       if (L4_bufp)
+               *L4_bufp = L4_buf;
+
+       /* print summary */
+       if (!conn) {
+
+               if (errnum)
+                       opj_event_msg(j2k->cinfo, EVT_INFO, "- %d symbol errors corrected (Ps=%.1e)\n", errnum,
+                               (float) errnum / (float) LDPepb);
+               if (errflag)
+                       opj_event_msg(j2k->cinfo, EVT_INFO, "- there were unrecoverable errors\n");
+
+       }
+
+       cio_seek(j2k->cio, orig_pos);
+
+       return true;
+}
+
+void jpwl_epc_write(jpwl_epc_ms_t *epc, unsigned char *buf) {
+
+       /* Marker */
+       *(buf++) = (unsigned char) (J2K_MS_EPC >> 8); 
+       *(buf++) = (unsigned char) (J2K_MS_EPC >> 0); 
+
+       /* Lepc */
+       *(buf++) = (unsigned char) (epc->Lepc >> 8); 
+       *(buf++) = (unsigned char) (epc->Lepc >> 0); 
+
+       /* Pcrc */
+       *(buf++) = (unsigned char) (epc->Pcrc >> 8); 
+       *(buf++) = (unsigned char) (epc->Pcrc >> 0);
+
+       /* DL */
+       *(buf++) = (unsigned char) (epc->DL >> 24); 
+       *(buf++) = (unsigned char) (epc->DL >> 16); 
+       *(buf++) = (unsigned char) (epc->DL >> 8); 
+       *(buf++) = (unsigned char) (epc->DL >> 0); 
+
+       /* Pepc */
+       *(buf++) = (unsigned char) (epc->Pepc >> 0); 
+
+       /* Data */
+       /*memcpy(buf, epc->data, (size_t) epc->Lepc - 9);*/
+       memset(buf, 0, (size_t) epc->Lepc - 9);
+};
+
+int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+                                 int comps, unsigned char addrm, unsigned char ad_size,
+                                 unsigned char senst, unsigned char se_size,
+                                 double place_pos, int tileno) {
+
+       return 0;
+}
+
+jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comp, unsigned char addrm, unsigned char ad_size,
+                                                               unsigned char senst, unsigned char se_size, int tileno,
+                                                               unsigned long int svalnum, void *sensval) {
+
+       jpwl_esd_ms_t *esd = NULL;
+
+       /* Alloc space */
+       if (!(esd = (jpwl_esd_ms_t *) malloc((size_t) 1 * sizeof (jpwl_esd_ms_t)))) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for ESD MS\n");
+               return NULL;
+       };
+
+       /* if relative sensitivity, activate byte range mode */
+       if (senst == 0)
+               addrm = 1;
+
+       /* size of sensval's ... */
+       if ((ad_size != 0) && (ad_size != 2) && (ad_size != 4)) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address size %d for ESD MS is forbidden\n", ad_size);
+               return NULL;
+       }
+       if ((se_size != 1) && (se_size != 2)) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Sensitivity size %d for ESD MS is forbidden\n", se_size);
+               return NULL;
+       }
+       
+       /* ... depends on the addressing mode */
+       switch (addrm) {
+
+       /* packet mode */
+       case (0):
+               ad_size = 0; /* as per the standard */
+               esd->sensval_size = se_size; 
+               break;
+
+       /* byte range */
+       case (1):
+               /* auto sense address size */
+               if (ad_size == 0)
+                       /* if there are more than 66% of (2^16 - 1) bytes, switch to 4 bytes
+                        (we keep space for possible EPBs being inserted) */
+                       ad_size = (j2k->image_info->codestream_size > (1 * 65535 / 3)) ? 4 : 2;
+               esd->sensval_size = ad_size + ad_size + se_size; 
+               break;
+
+       /* packet range */
+       case (2):
+               /* auto sense address size */
+               if (ad_size == 0)
+                       /* if there are more than 2^16 - 1 packets, switch to 4 bytes */
+                       ad_size = (j2k->image_info->num > 65535) ? 4 : 2;
+               esd->sensval_size = ad_size + ad_size + se_size; 
+               break;
+
+       case (3):
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is unimplemented\n", addrm);
+               return NULL;
+
+       default:
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is forbidden\n", addrm);
+               return NULL;
+       }
+
+       /* set or unset sensitivity values */
+       if (svalnum <= 0) {
+
+               switch (senst) {
+
+               /* just based on the portions of a codestream */
+               case (0):
+                       /* MH + no. of THs + no. of packets */
+                       svalnum = 1 + (j2k->image_info->tw * j2k->image_info->th) * (1 + j2k->image_info->num);
+                       break;
+
+               /* all the ones that are based on the packets */
+               default:
+                       if (tileno < 0)
+                               /* MH: all the packets and all the tiles info is written */
+                               svalnum = j2k->image_info->tw * j2k->image_info->th * j2k->image_info->num;
+                       else
+                               /* TPH: only that tile info is written */
+                               svalnum = j2k->image_info->num;
+                       break;
+
+               }
+       }               
+
+       /* fill private fields */
+       esd->senst = senst;
+       esd->ad_size = ad_size;
+       esd->se_size = se_size;
+       esd->addrm = addrm;
+       esd->svalnum = svalnum;
+       esd->numcomps = j2k->image->numcomps;
+       esd->tileno = tileno;
+       
+       /* Set the ESD parameters */
+       /* length, excluding data field */
+       if (esd->numcomps < 257)
+               esd->Lesd = 4 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+       else
+               esd->Lesd = 5 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+
+       /* component data field */
+       if (comp >= 0)
+               esd->Cesd = comp;
+       else
+               /* we are averaging */
+               esd->Cesd = 0;
+
+       /* Pesd field */
+       esd->Pesd = 0x00;
+       esd->Pesd |= (esd->addrm & 0x03) << 6; /* addressing mode */
+       esd->Pesd |= (esd->senst & 0x07) << 3; /* sensitivity type */
+       esd->Pesd |= ((esd->se_size >> 1) & 0x01) << 2; /* sensitivity size */
+       esd->Pesd |= ((esd->ad_size >> 2) & 0x01) << 1; /* addressing size */
+       esd->Pesd |= (comp < 0) ? 0x01 : 0x00; /* averaging components */
+
+       /* if pointer to sensval is NULL, we can fill data field by ourselves */
+       if (!sensval) {
+
+               /* old code moved to jpwl_esd_fill() */
+               esd->data = NULL;
+
+       } else {
+                       /* we set the data field as the sensitivity values poinnter passed to the function */
+                       esd->data = (unsigned char *) sensval;
+       }
+
+       return (esd);
+}
+
+bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+       int i;
+       unsigned long int vv;
+       unsigned long int addr1, addr2;
+       double dvalue, Omax2, tmp, TSE, MSE, oldMSE, PSNR, oldPSNR;
+       unsigned short int pfpvalue;
+       unsigned long int addrmask = 0x00000000;
+       bool doneMH = false, doneTPH = false;
+
+       /* sensitivity values in image info are as follows:
+               - for each tile, distotile is the starting distortion for that tile, sum of all components
+               - for each packet in a tile, disto is the distortion reduction caused by that packet to that tile
+               - the TSE for a single tile should be given by   distotile - sum(disto)  , for all components
+               - the MSE for a single tile is given by     TSE / nbpix    , for all components
+               - the PSNR for a single tile is given by   10*log10( Omax^2 / MSE)    , for all components
+                 (Omax is given by    2^bpp - 1    for unsigned images and by    2^(bpp - 1) - 1    for signed images
+       */
+
+       /* browse all components and find Omax */
+       Omax2 = 0.0;
+       for (i = 0; i < j2k->image->numcomps; i++) {
+               tmp = pow(2.0, (double) (j2k->image->comps[i].sgnd ?
+                       (j2k->image->comps[i].bpp - 1) : (j2k->image->comps[i].bpp))) - 1;
+               if (tmp > Omax2)
+                       Omax2 = tmp;
+       }
+       Omax2 = Omax2 * Omax2;
+
+       /* if pointer of esd->data is not null, simply write down all the values byte by byte */
+       if (esd->data) {
+               for (i = 0; i < (int) esd->svalnum; i++)
+                       *(buf++) = esd->data[i]; 
+               return true;
+       }
+
+       /* addressing mask */
+       if (esd->ad_size == 2)
+               addrmask = 0x0000FFFF; /* two bytes */
+       else
+               addrmask = 0xFFFFFFFF; /* four bytes */
+
+       /* set on precise point where sensitivity starts */
+       if (esd->numcomps < 257)
+               buf += 6;
+       else
+               buf += 7;
+
+       /* let's fill the data fields */
+       for (vv = (esd->tileno < 0) ? 0 : (j2k->image_info->num * esd->tileno); vv < esd->svalnum; vv++) {
+
+               int thistile = vv / j2k->image_info->num, thispacket = vv % j2k->image_info->num;
+
+               /* skip for the hack some lines below */
+               if (thistile == j2k->image_info->tw * j2k->image_info->th)
+                       break;
+
+               /* starting tile distortion */
+               if (thispacket == 0) {
+                       TSE = j2k->image_info->tile[thistile].distotile;
+                       oldMSE = TSE / j2k->image_info->tile[thistile].nbpix;
+                       oldPSNR = 10.0 * log10(Omax2 / oldMSE);
+               }
+
+               /* TSE */
+               TSE -= j2k->image_info->tile[thistile].packet[thispacket].disto;
+
+               /* MSE */
+               MSE = TSE / j2k->image_info->tile[thistile].nbpix;
+
+               /* PSNR */
+               PSNR = 10.0 * log10(Omax2 / MSE);
+
+               /* fill the address range */
+               switch (esd->addrm) {
+
+               /* packet mode */
+               case (0):
+                       /* nothing, there is none */
+                       break;
+
+               /* byte range */
+               case (1):
+                       /* start address of packet */
+                       addr1 = (j2k->image_info->tile[thistile].packet[thispacket].start_pos) & addrmask;
+                       /* end address of packet */
+                       addr2 = (j2k->image_info->tile[thistile].packet[thispacket].end_pos) & addrmask;
+                       break;
+
+               /* packet range */
+               case (2):
+                       /* not implemented here */
+                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Addressing mode packet_range is not implemented\n");
+                       break;
+
+               /* unknown addressing method */
+               default:
+                       /* not implemented here */
+                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown addressing mode\n");
+                       break;
+
+               }
+
+               /* hack for writing relative sensitivity of MH and TPHs */
+               if ((esd->senst == 0) && (thispacket == 0)) {
+
+                       /* possible MH */
+                       if ((thistile == 0) && !doneMH) {
+                               /* we have to manage MH addresses */
+                               addr1 = 0; /* start of MH */
+                               addr2 = j2k->image_info->main_head_end; /* end of MH */
+                               /* set special dvalue for this MH */
+                               dvalue = -10.0;
+                               doneMH = true; /* don't come here anymore */
+                               vv--; /* wrap back loop counter */
+
+                       } else if (!doneTPH) {
+                               /* we have to manage TPH addresses */
+                               addr1 = j2k->image_info->tile[thistile].start_pos;
+                               addr2 = j2k->image_info->tile[thistile].end_header;
+                               /* set special dvalue for this TPH */
+                               dvalue = -1.0;
+                               doneTPH = true; /* don't come here till the next tile */
+                               vv--; /* wrap back loop counter */
+                       }
+
+               } else
+                       doneTPH = false; /* reset TPH counter */
+
+               /* write the addresses to the buffer */
+               switch (esd->ad_size) {
+
+               case (0):
+                       /* do nothing */
+                       break;
+
+               case (2):
+                       /* two bytes */
+                       *(buf++) = (unsigned char) (addr1 >> 8); 
+                       *(buf++) = (unsigned char) (addr1 >> 0); 
+                       *(buf++) = (unsigned char) (addr2 >> 8); 
+                       *(buf++) = (unsigned char) (addr2 >> 0); 
+                       break;
+
+               case (4):
+                       /* four bytes */
+                       *(buf++) = (unsigned char) (addr1 >> 24); 
+                       *(buf++) = (unsigned char) (addr1 >> 16); 
+                       *(buf++) = (unsigned char) (addr1 >> 8); 
+                       *(buf++) = (unsigned char) (addr1 >> 0); 
+                       *(buf++) = (unsigned char) (addr2 >> 24); 
+                       *(buf++) = (unsigned char) (addr2 >> 16); 
+                       *(buf++) = (unsigned char) (addr2 >> 8); 
+                       *(buf++) = (unsigned char) (addr2 >> 0); 
+                       break;
+
+               default:
+                       /* do nothing */
+                       break;
+               }
+
+
+               /* let's fill the value field */
+               switch (esd->senst) {
+
+               /* relative sensitivity */
+               case (0):
+                       /* we just write down the packet ordering */
+                       if (dvalue == -10)
+                               /* MH */
+                               dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+                       else if (dvalue == -1)
+                               /* TPH */
+                               dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+                       else
+                               /* packet: first is most important, and then in decreasing order
+                               down to the last, which counts for 1 */
+                               dvalue = jpwl_pfp_to_double(j2k->image_info->num - thispacket, esd->se_size);
+                       break;
+
+               /* MSE */
+               case (1):
+                       /* !!! WRONG: let's put here disto field of packets !!! */
+                       dvalue = MSE;
+                       break;
+
+               /* MSE reduction */
+               case (2):
+                       dvalue = oldMSE - MSE;
+                       oldMSE = MSE;
+                       break;
+
+               /* PSNR */
+               case (3):
+                       dvalue = PSNR;
+                       break;
+
+               /* PSNR increase */
+               case (4):
+                       dvalue = PSNR - oldPSNR;
+                       oldPSNR = PSNR;
+                       break;
+
+               /* MAXERR */
+               case (5):
+                       dvalue = 0.0;
+                       opj_event_msg(j2k->cinfo, EVT_WARNING, "MAXERR sensitivity mode is not implemented\n");
+                       break;
+
+               /* TSE */
+               case (6):
+                       dvalue = TSE;
+                       break;
+
+               /* reserved */
+               case (7):
+                       dvalue = 0.0;
+                       opj_event_msg(j2k->cinfo, EVT_WARNING, "Reserved sensitivity mode is not implemented\n");
+                       break;
+
+               default:
+                       dvalue = 0.0;
+                       break;
+               }
+
+               /* compute the pseudo-floating point value */
+               pfpvalue = jpwl_double_to_pfp(dvalue, esd->se_size);
+
+               /* write the pfp value to the buffer */
+               switch (esd->se_size) {
+
+               case (1):
+                       /* one byte */
+                       *(buf++) = (unsigned char) (pfpvalue >> 0); 
+                       break;
+
+               case (2):
+                       /* two bytes */
+                       *(buf++) = (unsigned char) (pfpvalue >> 8); 
+                       *(buf++) = (unsigned char) (pfpvalue >> 0); 
+                       break;
+               }
+
+       }
+
+       return true;
+}
+
+void jpwl_esd_write(jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+       /* Marker */
+       *(buf++) = (unsigned char) (J2K_MS_ESD >> 8); 
+       *(buf++) = (unsigned char) (J2K_MS_ESD >> 0); 
+
+       /* Lesd */
+       *(buf++) = (unsigned char) (esd->Lesd >> 8); 
+       *(buf++) = (unsigned char) (esd->Lesd >> 0); 
+
+       /* Cesd */
+       if (esd->numcomps >= 257)
+               *(buf++) = (unsigned char) (esd->Cesd >> 8); 
+       *(buf++) = (unsigned char) (esd->Cesd >> 0); 
+
+       /* Pesd */
+       *(buf++) = (unsigned char) (esd->Pesd >> 0); 
+
+       /* Data */
+       if (esd->numcomps < 257)
+               memset(buf, 0xAA, (size_t) esd->Lesd - 4);
+               /*memcpy(buf, esd->data, (size_t) esd->Lesd - 4);*/
+       else
+               memset(buf, 0xAA, (size_t) esd->Lesd - 5);
+               /*memcpy(buf, esd->data, (size_t) esd->Lesd - 5);*/
+}
+
+unsigned short int jpwl_double_to_pfp(double V, int bytes) {
+
+       unsigned short int em, e, m;
+
+       switch (bytes) {
+
+       case (1):
+
+               if (V < MIN_V1) {
+                       e = 0x0000;
+                       m = 0x0000;
+               } else if (V > MAX_V1) {
+                       e = 0x000F;
+                       m = 0x000F;
+               } else {
+                       e = (unsigned short int) (floor(log(V) * 1.44269504088896) / 4.0);
+                       m = (unsigned short int) (0.5 + (V / (pow(2.0, (double) (4 * e)))));
+               }
+               em = ((e & 0x000F) << 4) + (m & 0x000F);                
+               break;
+
+       case (2):
+
+               if (V < MIN_V2) {
+                       e = 0x0000;
+                       m = 0x0000;
+               } else if (V > MAX_V2) {
+                       e = 0x001F;
+                       m = 0x07FF;
+               } else {
+                       e = (unsigned short int) floor(log(V) * 1.44269504088896) + 15;
+                       m = (unsigned short int) (0.5 + 2048.0 * ((V / (pow(2.0, (double) e - 15.0))) - 1.0));
+               }
+               em = ((e & 0x001F) << 11) + (m & 0x07FF);
+               break;
+
+       default:
+
+               em = 0x0000;
+               break;
+       };
+
+       return em;
+}
+
+double jpwl_pfp_to_double(unsigned short int em, int bytes) {
+
+       double V;
+
+       switch (bytes) {
+
+       case 1:
+               V = (double) (em & 0x0F) * pow(2.0, (double) (em & 0xF0));
+               break;
+
+       case 2:
+
+               V = pow(2.0, (double) ((em & 0xF800) >> 11) - 15.0) * (1.0 + (double) (em & 0x07FF) / 2048.0);
+               break;
+
+       default:
+               V = 0.0;
+               break;
+
+       }
+
+       return V;
+
+}
+
+bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num) {
+
+       int mm;
+       unsigned long int addlen;
+
+       opj_image_info_t *info = j2k->image_info;
+       int tileno, packno, numtiles = info->th * info->tw, numpacks = info->num;
+
+       if (!j2k || !jwmarker ) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "J2K handle or JPWL markers list badly allocated\n");
+               return false;
+       }
+
+       /* main_head_end: how many markers are there before? */
+       addlen = 0;
+       for (mm = 0; mm < jwmarker_num; mm++)
+               if (jwmarker[mm].pos < (unsigned long int) info->main_head_end)
+                       addlen += jwmarker[mm].len + 2;
+       info->main_head_end += addlen;
+
+       /* codestream_size: always increment with all markers */
+       addlen = 0;
+       for (mm = 0; mm < jwmarker_num; mm++)
+               addlen += jwmarker[mm].len + 2;
+       info->codestream_size += addlen;
+
+       /* navigate through all the tiles */
+       for (tileno = 0; tileno < numtiles; tileno++) {
+
+               /* start_pos: increment with markers before SOT */
+               addlen = 0;
+               for (mm = 0; mm < jwmarker_num; mm++)
+                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].start_pos)
+                               addlen += jwmarker[mm].len + 2;
+               info->tile[tileno].start_pos += addlen;
+
+               /* end_header: increment with markers before of it */
+               addlen = 0;
+               for (mm = 0; mm < jwmarker_num; mm++)
+                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_header)
+                               addlen += jwmarker[mm].len + 2;
+               info->tile[tileno].end_header += addlen;
+
+               /* end_pos: increment with markers before the end of this tile */
+               /* code is disabled, since according to JPWL no markers can be beyond TPH */
+               /*addlen = 0;
+               for (mm = 0; mm < jwmarker_num; mm++)
+                       if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_pos)
+                               addlen += jwmarker[mm].len + 2;*/
+               info->tile[tileno].end_pos += addlen;
+
+               /* navigate through all the packets in this tile */
+               for (packno = 0; packno < numpacks; packno++) {
+                       
+                       /* start_pos: increment with markers before the packet */
+                       /* disabled for the same reason as before */
+                       /*addlen = 0;
+                       for (mm = 0; mm < jwmarker_num; mm++)
+                               if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].start_pos)
+                                       addlen += jwmarker[mm].len + 2;*/
+                       info->tile[tileno].packet[packno].start_pos += addlen;
+
+                       /* end_pos: increment if marker is before the end of packet */
+                       /* disabled for the same reason as before */
+                       /*addlen = 0;
+                       for (mm = 0; mm < jwmarker_num; mm++)
+                               if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_pos)
+                                       addlen += jwmarker[mm].len + 2;*/
+                       info->tile[tileno].packet[packno].end_pos += addlen;
+
+               }
+       }
+
+       return true;
+}
+
 #endif /* USE_JPWL */
\ No newline at end of file
index ea26e325f107a917ab8f74354678c5c978c33f69..bf37d4115485922f13fd356c064051b62dc59b8d 100644 (file)
--- a/jpwl/rs.c
+++ b/jpwl/rs.c
- /*\r
- * Copyright (c) 2001-2003, David Janssens\r
- * Copyright (c) 2002-2003, Yannick Verschueren\r
- * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
- * Copyright (c) 2005, Herv� Drolon, FreeImage Team\r
- * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
- * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
- * POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifdef USE_JPWL\r
-\r
-/**\r
-@file rs.c\r
-@brief Functions used to compute the Reed-Solomon parity and check of byte arrays\r
-\r
-*/\r
-\r
-/**\r
- * Reed-Solomon coding and decoding\r
- * Phil Karn (karn@ka9q.ampr.org) September 1996\r
- * \r
- * This file is derived from the program "new_rs_erasures.c" by Robert\r
- * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy\r
- * (harit@spectra.eng.hawaii.edu), Aug 1995\r
- *\r
- * I've made changes to improve performance, clean up the code and make it\r
- * easier to follow. Data is now passed to the encoding and decoding functions\r
- * through arguments rather than in global arrays. The decode function returns\r
- * the number of corrected symbols, or -1 if the word is uncorrectable.\r
- *\r
- * This code supports a symbol size from 2 bits up to 16 bits,\r
- * implying a block size of 3 2-bit symbols (6 bits) up to 65535\r
- * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h.\r
- *\r
- * Note that if symbols larger than 8 bits are used, the type of each\r
- * data array element switches from unsigned char to unsigned int. The\r
- * caller must ensure that elements larger than the symbol range are\r
- * not passed to the encoder or decoder.\r
- *\r
- */\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include "rs.h"\r
-\r
-/* This defines the type used to store an element of the Galois Field\r
- * used by the code. Make sure this is something larger than a char if\r
- * if anything larger than GF(256) is used.\r
- *\r
- * Note: unsigned char will work up to GF(256) but int seems to run\r
- * faster on the Pentium.\r
- */\r
-typedef int gf;\r
-\r
-/* Primitive polynomials - see Lin & Costello, Appendix A,\r
- * and  Lee & Messerschmitt, p. 453.\r
- */\r
-#if(MM == 2)/* Admittedly silly */\r
-int Pp[MM+1] = { 1, 1, 1 };\r
-\r
-#elif(MM == 3)\r
-/* 1 + x + x^3 */\r
-int Pp[MM+1] = { 1, 1, 0, 1 };\r
-\r
-#elif(MM == 4)\r
-/* 1 + x + x^4 */\r
-int Pp[MM+1] = { 1, 1, 0, 0, 1 };\r
-\r
-#elif(MM == 5)\r
-/* 1 + x^2 + x^5 */\r
-int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };\r
-\r
-#elif(MM == 6)\r
-/* 1 + x + x^6 */\r
-int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 7)\r
-/* 1 + x^3 + x^7 */\r
-int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 8)\r
-/* 1+x^2+x^3+x^4+x^8 */\r
-int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 9)\r
-/* 1+x^4+x^9 */\r
-int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 10)\r
-/* 1+x^3+x^10 */\r
-int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 11)\r
-/* 1+x^2+x^11 */\r
-int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 12)\r
-/* 1+x+x^4+x^6+x^12 */\r
-int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 13)\r
-/* 1+x+x^3+x^4+x^13 */\r
-int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 14)\r
-/* 1+x+x^6+x^10+x^14 */\r
-int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 15)\r
-/* 1+x+x^15 */\r
-int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
-\r
-#elif(MM == 16)\r
-/* 1+x+x^3+x^12+x^16 */\r
-int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };\r
-\r
-#else\r
-#error "MM must be in range 2-16"\r
-#endif\r
-\r
-/* Alpha exponent for the first root of the generator polynomial */\r
-#define B0     0  /* Different from the default 1 */\r
-\r
-/* index->polynomial form conversion table */\r
-gf Alpha_to[NN + 1];\r
-\r
-/* Polynomial->index form conversion table */\r
-gf Index_of[NN + 1];\r
-\r
-/* No legal value in index form represents zero, so\r
- * we need a special value for this purpose\r
- */\r
-#define A0     (NN)\r
-\r
-/* Generator polynomial g(x)\r
- * Degree of g(x) = 2*TT\r
- * has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)\r
- */\r
-/*gf Gg[NN - KK + 1];*/\r
-gf             Gg[NN - 1];\r
-\r
-/* Compute x % NN, where NN is 2**MM - 1,\r
- * without a slow divide\r
- */\r
-static /*inline*/ gf\r
-modnn(int x)\r
-{\r
-       while (x >= NN) {\r
-               x -= NN;\r
-               x = (x >> MM) + (x & NN);\r
-       }\r
-       return x;\r
-}\r
-\r
-/*#define      min(a,b)        ((a) < (b) ? (a) : (b))*/\r
-\r
-#define        CLEAR(a,n) {\\r
-       int ci;\\r
-       for(ci=(n)-1;ci >=0;ci--)\\r
-               (a)[ci] = 0;\\r
-       }\r
-\r
-#define        COPY(a,b,n) {\\r
-       int ci;\\r
-       for(ci=(n)-1;ci >=0;ci--)\\r
-               (a)[ci] = (b)[ci];\\r
-       }\r
-#define        COPYDOWN(a,b,n) {\\r
-       int ci;\\r
-       for(ci=(n)-1;ci >=0;ci--)\\r
-               (a)[ci] = (b)[ci];\\r
-       }\r
-\r
-void init_rs(int k)\r
-{\r
-       KK = k;\r
-       if (KK >= NN) {\r
-               printf("KK must be less than 2**MM - 1\n");\r
-               exit(1);\r
-       }\r
-       \r
-       generate_gf();\r
-       gen_poly();\r
-}\r
-\r
-/* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]\r
-   lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;\r
-                   polynomial form -> index form  index_of[j=alpha**i] = i\r
-   alpha=2 is the primitive element of GF(2**m)\r
-   HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:\r
-        Let @ represent the primitive element commonly called "alpha" that\r
-   is the root of the primitive polynomial p(x). Then in GF(2^m), for any\r
-   0 <= i <= 2^m-2,\r
-        @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)\r
-   where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation\r
-   of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for\r
-   example the polynomial representation of @^5 would be given by the binary\r
-   representation of the integer "alpha_to[5]".\r
-                   Similarily, index_of[] can be used as follows:\r
-        As above, let @ represent the primitive element of GF(2^m) that is\r
-   the root of the primitive polynomial p(x). In order to find the power\r
-   of @ (alpha) that has the polynomial representation\r
-        a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)\r
-   we consider the integer "i" whose binary representation with a(0) being LSB\r
-   and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry\r
-   "index_of[i]". Now, @^index_of[i] is that element whose polynomial \r
-    representation is (a(0),a(1),a(2),...,a(m-1)).\r
-   NOTE:\r
-        The element alpha_to[2^m-1] = 0 always signifying that the\r
-   representation of "@^infinity" = 0 is (0,0,0,...,0).\r
-        Similarily, the element index_of[0] = A0 always signifying\r
-   that the power of alpha which has the polynomial representation\r
-   (0,0,...,0) is "infinity".\r
\r
-*/\r
-\r
-void\r
-generate_gf(void)\r
-{\r
-       register int i, mask;\r
-\r
-       mask = 1;\r
-       Alpha_to[MM] = 0;\r
-       for (i = 0; i < MM; i++) {\r
-               Alpha_to[i] = mask;\r
-               Index_of[Alpha_to[i]] = i;\r
-               /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */\r
-               if (Pp[i] != 0)\r
-                       Alpha_to[MM] ^= mask;   /* Bit-wise EXOR operation */\r
-               mask <<= 1;     /* single left-shift */\r
-       }\r
-       Index_of[Alpha_to[MM]] = MM;\r
-       /*\r
-        * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by\r
-        * poly-repr of @^i shifted left one-bit and accounting for any @^MM\r
-        * term that may occur when poly-repr of @^i is shifted.\r
-        */\r
-       mask >>= 1;\r
-       for (i = MM + 1; i < NN; i++) {\r
-               if (Alpha_to[i - 1] >= mask)\r
-                       Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);\r
-               else\r
-                       Alpha_to[i] = Alpha_to[i - 1] << 1;\r
-               Index_of[Alpha_to[i]] = i;\r
-       }\r
-       Index_of[0] = A0;\r
-       Alpha_to[NN] = 0;\r
-}\r
-\r
-\r
-/*\r
- * Obtain the generator polynomial of the TT-error correcting, length\r
- * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,\r
- * ... ,(2*TT-1)\r
- *\r
- * Examples:\r
- *\r
- * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.\r
- * g(x) = (x+@) (x+@**2)\r
- *\r
- * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.\r
- * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)\r
- */\r
-void\r
-gen_poly(void)\r
-{\r
-       register int i, j;\r
-\r
-       Gg[0] = Alpha_to[B0];\r
-       Gg[1] = 1;              /* g(x) = (X+@**B0) initially */\r
-       for (i = 2; i <= NN - KK; i++) {\r
-               Gg[i] = 1;\r
-               /*\r
-                * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by\r
-                * (@**(B0+i-1) + x)\r
-                */\r
-               for (j = i - 1; j > 0; j--)\r
-                       if (Gg[j] != 0)\r
-                               Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];\r
-                       else\r
-                               Gg[j] = Gg[j - 1];\r
-               /* Gg[0] can never be zero */\r
-               Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];\r
-       }\r
-       /* convert Gg[] to index form for quicker encoding */\r
-       for (i = 0; i <= NN - KK; i++)\r
-               Gg[i] = Index_of[Gg[i]];\r
-}\r
-\r
-\r
-/*\r
- * take the string of symbols in data[i], i=0..(k-1) and encode\r
- * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[]\r
- * is input and bb[] is output in polynomial form. Encoding is done by using\r
- * a feedback shift register with appropriate connections specified by the\r
- * elements of Gg[], which was generated above. Codeword is   c(X) =\r
- * data(X)*X**(NN-KK)+ b(X)\r
- */\r
-int\r
-encode_rs(dtype *data, dtype *bb)\r
-{\r
-       register int i, j;\r
-       gf feedback;\r
-\r
-       CLEAR(bb,NN-KK);\r
-       for (i = KK - 1; i >= 0; i--) {\r
-#if (MM != 8)\r
-               if(data[i] > NN)\r
-                       return -1;      /* Illegal symbol */\r
-#endif\r
-               feedback = Index_of[data[i] ^ bb[NN - KK - 1]];\r
-               if (feedback != A0) {   /* feedback term is non-zero */\r
-                       for (j = NN - KK - 1; j > 0; j--)\r
-                               if (Gg[j] != A0)\r
-                                       bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];\r
-                               else\r
-                                       bb[j] = bb[j - 1];\r
-                       bb[0] = Alpha_to[modnn(Gg[0] + feedback)];\r
-               } else {        /* feedback term is zero. encoder becomes a\r
-                                * single-byte shifter */\r
-                       for (j = NN - KK - 1; j > 0; j--)\r
-                               bb[j] = bb[j - 1];\r
-                       bb[0] = 0;\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-/*\r
- * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,\r
- * writes the codeword into data[] itself. Otherwise data[] is unaltered.\r
- *\r
- * Return number of symbols corrected, or -1 if codeword is illegal\r
- * or uncorrectable.\r
- * \r
- * First "no_eras" erasures are declared by the calling program. Then, the\r
- * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).\r
- * If the number of channel errors is not greater than "t_after_eras" the\r
- * transmitted codeword will be recovered. Details of algorithm can be found\r
- * in R. Blahut's "Theory ... of Error-Correcting Codes".\r
- */\r
-int\r
-eras_dec_rs(dtype *data, int *eras_pos, int no_eras)\r
-{\r
-       int deg_lambda, el, deg_omega;\r
-       int i, j, r;\r
-       gf u,q,tmp,num1,num2,den,discr_r;\r
-       gf recd[NN];\r
-       /* Err+Eras Locator poly and syndrome poly */\r
-       /*gf lambda[NN-KK + 1], s[NN-KK + 1];   \r
-       gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];\r
-       gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];*/\r
-       gf lambda[NN + 1], s[NN + 1];   \r
-       gf b[NN + 1], t[NN + 1], omega[NN + 1];\r
-       gf root[NN], reg[NN + 1], loc[NN];\r
-       int syn_error, count;\r
-\r
-       /* data[] is in polynomial form, copy and convert to index form */\r
-       for (i = NN-1; i >= 0; i--){\r
-#if (MM != 8)\r
-               if(data[i] > NN)\r
-                       return -1;      /* Illegal symbol */\r
-#endif\r
-               recd[i] = Index_of[data[i]];\r
-       }\r
-       /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)\r
-        * namely @**(B0+i), i = 0, ... ,(NN-KK-1)\r
-        */\r
-       syn_error = 0;\r
-       for (i = 1; i <= NN-KK; i++) {\r
-               tmp = 0;\r
-               for (j = 0; j < NN; j++)\r
-                       if (recd[j] != A0)      /* recd[j] in index form */\r
-                               tmp ^= Alpha_to[modnn(recd[j] + (B0+i-1)*j)];\r
-               syn_error |= tmp;       /* set flag if non-zero syndrome =>\r
-                                        * error */\r
-               /* store syndrome in index form  */\r
-               s[i] = Index_of[tmp];\r
-       }\r
-       if (!syn_error) {\r
-               /*\r
-                * if syndrome is zero, data[] is a codeword and there are no\r
-                * errors to correct. So return data[] unmodified\r
-                */\r
-               return 0;\r
-       }\r
-       CLEAR(&lambda[1],NN-KK);\r
-       lambda[0] = 1;\r
-       if (no_eras > 0) {\r
-               /* Init lambda to be the erasure locator polynomial */\r
-               lambda[1] = Alpha_to[eras_pos[0]];\r
-               for (i = 1; i < no_eras; i++) {\r
-                       u = eras_pos[i];\r
-                       for (j = i+1; j > 0; j--) {\r
-                               tmp = Index_of[lambda[j - 1]];\r
-                               if(tmp != A0)\r
-                                       lambda[j] ^= Alpha_to[modnn(u + tmp)];\r
-                       }\r
-               }\r
-#ifdef ERASURE_DEBUG\r
-               /* find roots of the erasure location polynomial */\r
-               for(i=1;i<=no_eras;i++)\r
-                       reg[i] = Index_of[lambda[i]];\r
-               count = 0;\r
-               for (i = 1; i <= NN; i++) {\r
-                       q = 1;\r
-                       for (j = 1; j <= no_eras; j++)\r
-                               if (reg[j] != A0) {\r
-                                       reg[j] = modnn(reg[j] + j);\r
-                                       q ^= Alpha_to[reg[j]];\r
-                               }\r
-                       if (!q) {\r
-                               /* store root and error location\r
-                                * number indices\r
-                                */\r
-                               root[count] = i;\r
-                               loc[count] = NN - i;\r
-                               count++;\r
-                       }\r
-               }\r
-               if (count != no_eras) {\r
-                       printf("\n lambda(x) is WRONG\n");\r
-                       return -1;\r
-               }\r
-#ifndef NO_PRINT\r
-               printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");\r
-               for (i = 0; i < count; i++)\r
-                       printf("%d ", loc[i]);\r
-               printf("\n");\r
-#endif\r
-#endif\r
-       }\r
-       for(i=0;i<NN-KK+1;i++)\r
-               b[i] = Index_of[lambda[i]];\r
-\r
-       /*\r
-        * Begin Berlekamp-Massey algorithm to determine error+erasure\r
-        * locator polynomial\r
-        */\r
-       r = no_eras;\r
-       el = no_eras;\r
-       while (++r <= NN-KK) {  /* r is the step number */\r
-               /* Compute discrepancy at the r-th step in poly-form */\r
-               discr_r = 0;\r
-               for (i = 0; i < r; i++){\r
-                       if ((lambda[i] != 0) && (s[r - i] != A0)) {\r
-                               discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];\r
-                       }\r
-               }\r
-               discr_r = Index_of[discr_r];    /* Index form */\r
-               if (discr_r == A0) {\r
-                       /* 2 lines below: B(x) <-- x*B(x) */\r
-                       COPYDOWN(&b[1],b,NN-KK);\r
-                       b[0] = A0;\r
-               } else {\r
-                       /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */\r
-                       t[0] = lambda[0];\r
-                       for (i = 0 ; i < NN-KK; i++) {\r
-                               if(b[i] != A0)\r
-                                       t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];\r
-                               else\r
-                                       t[i+1] = lambda[i+1];\r
-                       }\r
-                       if (2 * el <= r + no_eras - 1) {\r
-                               el = r + no_eras - el;\r
-                               /*\r
-                                * 2 lines below: B(x) <-- inv(discr_r) *\r
-                                * lambda(x)\r
-                                */\r
-                               for (i = 0; i <= NN-KK; i++)\r
-                                       b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);\r
-                       } else {\r
-                               /* 2 lines below: B(x) <-- x*B(x) */\r
-                               COPYDOWN(&b[1],b,NN-KK);\r
-                               b[0] = A0;\r
-                       }\r
-                       COPY(lambda,t,NN-KK+1);\r
-               }\r
-       }\r
-\r
-       /* Convert lambda to index form and compute deg(lambda(x)) */\r
-       deg_lambda = 0;\r
-       for(i=0;i<NN-KK+1;i++){\r
-               lambda[i] = Index_of[lambda[i]];\r
-               if(lambda[i] != A0)\r
-                       deg_lambda = i;\r
-       }\r
-       /*\r
-        * Find roots of the error+erasure locator polynomial. By Chien\r
-        * Search\r
-        */\r
-       COPY(&reg[1],&lambda[1],NN-KK);\r
-       count = 0;              /* Number of roots of lambda(x) */\r
-       for (i = 1; i <= NN; i++) {\r
-               q = 1;\r
-               for (j = deg_lambda; j > 0; j--)\r
-                       if (reg[j] != A0) {\r
-                               reg[j] = modnn(reg[j] + j);\r
-                               q ^= Alpha_to[reg[j]];\r
-                       }\r
-               if (!q) {\r
-                       /* store root (index-form) and error location number */\r
-                       root[count] = i;\r
-                       loc[count] = NN - i;\r
-                       count++;\r
-               }\r
-       }\r
-\r
-#ifdef DEBUG\r
-       printf("\n Final error positions:\t");\r
-       for (i = 0; i < count; i++)\r
-               printf("%d ", loc[i]);\r
-       printf("\n");\r
-#endif\r
-       if (deg_lambda != count) {\r
-               /*\r
-                * deg(lambda) unequal to number of roots => uncorrectable\r
-                * error detected\r
-                */\r
-               return -1;\r
-       }\r
-       /*\r
-        * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo\r
-        * x**(NN-KK)). in index form. Also find deg(omega).\r
-        */\r
-       deg_omega = 0;\r
-       for (i = 0; i < NN-KK;i++){\r
-               tmp = 0;\r
-               j = (deg_lambda < i) ? deg_lambda : i;\r
-               for(;j >= 0; j--){\r
-                       if ((s[i + 1 - j] != A0) && (lambda[j] != A0))\r
-                               tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];\r
-               }\r
-               if(tmp != 0)\r
-                       deg_omega = i;\r
-               omega[i] = Index_of[tmp];\r
-       }\r
-       omega[NN-KK] = A0;\r
-\r
-       /*\r
-        * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =\r
-        * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form\r
-        */\r
-       for (j = count-1; j >=0; j--) {\r
-               num1 = 0;\r
-               for (i = deg_omega; i >= 0; i--) {\r
-                       if (omega[i] != A0)\r
-                               num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];\r
-               }\r
-               num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];\r
-               den = 0;\r
-\r
-               /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */\r
-               for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {\r
-                       if(lambda[i+1] != A0)\r
-                               den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];\r
-               }\r
-               if (den == 0) {\r
-#ifdef DEBUG\r
-                       printf("\n ERROR: denominator = 0\n");\r
-#endif\r
-                       return -1;\r
-               }\r
-               /* Apply error to data */\r
-               if (num1 != 0) {\r
-                       data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];\r
-               }\r
-       }\r
-       return count;\r
-}\r
-\r
-\r
+ /*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef USE_JPWL
+
+/**
+@file rs.c
+@brief Functions used to compute the Reed-Solomon parity and check of byte arrays
+
+*/
+
+/**
+ * Reed-Solomon coding and decoding
+ * Phil Karn (karn@ka9q.ampr.org) September 1996
+ * 
+ * This file is derived from the program "new_rs_erasures.c" by Robert
+ * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy
+ * (harit@spectra.eng.hawaii.edu), Aug 1995
+ *
+ * I've made changes to improve performance, clean up the code and make it
+ * easier to follow. Data is now passed to the encoding and decoding functions
+ * through arguments rather than in global arrays. The decode function returns
+ * the number of corrected symbols, or -1 if the word is uncorrectable.
+ *
+ * This code supports a symbol size from 2 bits up to 16 bits,
+ * implying a block size of 3 2-bit symbols (6 bits) up to 65535
+ * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h.
+ *
+ * Note that if symbols larger than 8 bits are used, the type of each
+ * data array element switches from unsigned char to unsigned int. The
+ * caller must ensure that elements larger than the symbol range are
+ * not passed to the encoder or decoder.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "rs.h"
+
+/* This defines the type used to store an element of the Galois Field
+ * used by the code. Make sure this is something larger than a char if
+ * if anything larger than GF(256) is used.
+ *
+ * Note: unsigned char will work up to GF(256) but int seems to run
+ * faster on the Pentium.
+ */
+typedef int gf;
+
+/* Primitive polynomials - see Lin & Costello, Appendix A,
+ * and  Lee & Messerschmitt, p. 453.
+ */
+#if(MM == 2)/* Admittedly silly */
+int Pp[MM+1] = { 1, 1, 1 };
+
+#elif(MM == 3)
+/* 1 + x + x^3 */
+int Pp[MM+1] = { 1, 1, 0, 1 };
+
+#elif(MM == 4)
+/* 1 + x + x^4 */
+int Pp[MM+1] = { 1, 1, 0, 0, 1 };
+
+#elif(MM == 5)
+/* 1 + x^2 + x^5 */
+int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };
+
+#elif(MM == 6)
+/* 1 + x + x^6 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };
+
+#elif(MM == 7)
+/* 1 + x^3 + x^7 */
+int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };
+
+#elif(MM == 8)
+/* 1+x^2+x^3+x^4+x^8 */
+int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };
+
+#elif(MM == 9)
+/* 1+x^4+x^9 */
+int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
+
+#elif(MM == 10)
+/* 1+x^3+x^10 */
+int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 11)
+/* 1+x^2+x^11 */
+int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 12)
+/* 1+x+x^4+x^6+x^12 */
+int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 13)
+/* 1+x+x^3+x^4+x^13 */
+int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 14)
+/* 1+x+x^6+x^10+x^14 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+
+#elif(MM == 15)
+/* 1+x+x^15 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 16)
+/* 1+x+x^3+x^12+x^16 */
+int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
+
+#else
+#error "MM must be in range 2-16"
+#endif
+
+/* Alpha exponent for the first root of the generator polynomial */
+#define B0     0  /* Different from the default 1 */
+
+/* index->polynomial form conversion table */
+gf Alpha_to[NN + 1];
+
+/* Polynomial->index form conversion table */
+gf Index_of[NN + 1];
+
+/* No legal value in index form represents zero, so
+ * we need a special value for this purpose
+ */
+#define A0     (NN)
+
+/* Generator polynomial g(x)
+ * Degree of g(x) = 2*TT
+ * has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)
+ */
+/*gf Gg[NN - KK + 1];*/
+gf             Gg[NN - 1];
+
+/* Compute x % NN, where NN is 2**MM - 1,
+ * without a slow divide
+ */
+static /*inline*/ gf
+modnn(int x)
+{
+       while (x >= NN) {
+               x -= NN;
+               x = (x >> MM) + (x & NN);
+       }
+       return x;
+}
+
+/*#define      min(a,b)        ((a) < (b) ? (a) : (b))*/
+
+#define        CLEAR(a,n) {\
+       int ci;\
+       for(ci=(n)-1;ci >=0;ci--)\
+               (a)[ci] = 0;\
+       }
+
+#define        COPY(a,b,n) {\
+       int ci;\
+       for(ci=(n)-1;ci >=0;ci--)\
+               (a)[ci] = (b)[ci];\
+       }
+#define        COPYDOWN(a,b,n) {\
+       int ci;\
+       for(ci=(n)-1;ci >=0;ci--)\
+               (a)[ci] = (b)[ci];\
+       }
+
+void init_rs(int k)
+{
+       KK = k;
+       if (KK >= NN) {
+               printf("KK must be less than 2**MM - 1\n");
+               exit(1);
+       }
+       
+       generate_gf();
+       gen_poly();
+}
+
+/* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
+   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**m)
+   HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
+        Let @ represent the primitive element commonly called "alpha" that
+   is the root of the primitive polynomial p(x). Then in GF(2^m), for any
+   0 <= i <= 2^m-2,
+        @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+   where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
+   of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
+   example the polynomial representation of @^5 would be given by the binary
+   representation of the integer "alpha_to[5]".
+                   Similarily, index_of[] can be used as follows:
+        As above, let @ represent the primitive element of GF(2^m) that is
+   the root of the primitive polynomial p(x). In order to find the power
+   of @ (alpha) that has the polynomial representation
+        a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+   we consider the integer "i" whose binary representation with a(0) being LSB
+   and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
+   "index_of[i]". Now, @^index_of[i] is that element whose polynomial 
+    representation is (a(0),a(1),a(2),...,a(m-1)).
+   NOTE:
+        The element alpha_to[2^m-1] = 0 always signifying that the
+   representation of "@^infinity" = 0 is (0,0,0,...,0).
+        Similarily, the element index_of[0] = A0 always signifying
+   that the power of alpha which has the polynomial representation
+   (0,0,...,0) is "infinity".
+*/
+
+void
+generate_gf(void)
+{
+       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] == 1 then, term @^i occurs in poly-repr of @^MM */
+               if (Pp[i] != 0)
+                       Alpha_to[MM] ^= mask;   /* Bit-wise EXOR operation */
+               mask <<= 1;     /* single left-shift */
+       }
+       Index_of[Alpha_to[MM]] = MM;
+       /*
+        * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
+        * poly-repr of @^i shifted left one-bit and accounting for any @^MM
+        * term that may occur when poly-repr of @^i is shifted.
+        */
+       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] = A0;
+       Alpha_to[NN] = 0;
+}
+
+
+/*
+ * Obtain the generator polynomial of the TT-error correcting, length
+ * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,
+ * ... ,(2*TT-1)
+ *
+ * Examples:
+ *
+ * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.
+ * g(x) = (x+@) (x+@**2)
+ *
+ * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.
+ * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)
+ */
+void
+gen_poly(void)
+{
+       register int i, j;
+
+       Gg[0] = Alpha_to[B0];
+       Gg[1] = 1;              /* g(x) = (X+@**B0) initially */
+       for (i = 2; i <= NN - KK; i++) {
+               Gg[i] = 1;
+               /*
+                * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
+                * (@**(B0+i-1) + x)
+                */
+               for (j = i - 1; j > 0; j--)
+                       if (Gg[j] != 0)
+                               Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];
+                       else
+                               Gg[j] = Gg[j - 1];
+               /* Gg[0] can never be zero */
+               Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];
+       }
+       /* convert Gg[] to index form for quicker encoding */
+       for (i = 0; i <= NN - KK; i++)
+               Gg[i] = Index_of[Gg[i]];
+}
+
+
+/*
+ * take the string of symbols in data[i], i=0..(k-1) and encode
+ * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-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)
+ */
+int
+encode_rs(dtype *data, dtype *bb)
+{
+       register int i, j;
+       gf feedback;
+
+       CLEAR(bb,NN-KK);
+       for (i = KK - 1; i >= 0; i--) {
+#if (MM != 8)
+               if(data[i] > NN)
+                       return -1;      /* Illegal symbol */
+#endif
+               feedback = Index_of[data[i] ^ bb[NN - KK - 1]];
+               if (feedback != A0) {   /* feedback term is non-zero */
+                       for (j = NN - KK - 1; j > 0; j--)
+                               if (Gg[j] != A0)
+                                       bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];
+                               else
+                                       bb[j] = bb[j - 1];
+                       bb[0] = Alpha_to[modnn(Gg[0] + feedback)];
+               } else {        /* feedback term is zero. encoder becomes a
+                                * single-byte shifter */
+                       for (j = NN - KK - 1; j > 0; j--)
+                               bb[j] = bb[j - 1];
+                       bb[0] = 0;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,
+ * writes the codeword into data[] itself. Otherwise data[] is unaltered.
+ *
+ * Return number of symbols corrected, or -1 if codeword is illegal
+ * or uncorrectable.
+ * 
+ * First "no_eras" erasures are declared by the calling program. Then, the
+ * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
+ * If the number of channel errors is not greater than "t_after_eras" the
+ * transmitted codeword will be recovered. Details of algorithm can be found
+ * in R. Blahut's "Theory ... of Error-Correcting Codes".
+ */
+int
+eras_dec_rs(dtype *data, int *eras_pos, int no_eras)
+{
+       int deg_lambda, el, deg_omega;
+       int i, j, r;
+       gf u,q,tmp,num1,num2,den,discr_r;
+       gf recd[NN];
+       /* Err+Eras Locator poly and syndrome poly */
+       /*gf lambda[NN-KK + 1], s[NN-KK + 1];   
+       gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
+       gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];*/
+       gf lambda[NN + 1], s[NN + 1];   
+       gf b[NN + 1], t[NN + 1], omega[NN + 1];
+       gf root[NN], reg[NN + 1], loc[NN];
+       int syn_error, count;
+
+       /* data[] is in polynomial form, copy and convert to index form */
+       for (i = NN-1; i >= 0; i--){
+#if (MM != 8)
+               if(data[i] > NN)
+                       return -1;      /* Illegal symbol */
+#endif
+               recd[i] = Index_of[data[i]];
+       }
+       /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)
+        * namely @**(B0+i), i = 0, ... ,(NN-KK-1)
+        */
+       syn_error = 0;
+       for (i = 1; i <= NN-KK; i++) {
+               tmp = 0;
+               for (j = 0; j < NN; j++)
+                       if (recd[j] != A0)      /* recd[j] in index form */
+                               tmp ^= Alpha_to[modnn(recd[j] + (B0+i-1)*j)];
+               syn_error |= tmp;       /* set flag if non-zero syndrome =>
+                                        * error */
+               /* store syndrome in index form  */
+               s[i] = Index_of[tmp];
+       }
+       if (!syn_error) {
+               /*
+                * if syndrome is zero, data[] is a codeword and there are no
+                * errors to correct. So return data[] unmodified
+                */
+               return 0;
+       }
+       CLEAR(&lambda[1],NN-KK);
+       lambda[0] = 1;
+       if (no_eras > 0) {
+               /* Init lambda to be the erasure locator polynomial */
+               lambda[1] = Alpha_to[eras_pos[0]];
+               for (i = 1; i < no_eras; i++) {
+                       u = eras_pos[i];
+                       for (j = i+1; j > 0; j--) {
+                               tmp = Index_of[lambda[j - 1]];
+                               if(tmp != A0)
+                                       lambda[j] ^= Alpha_to[modnn(u + tmp)];
+                       }
+               }
+#ifdef ERASURE_DEBUG
+               /* find roots of the erasure location polynomial */
+               for(i=1;i<=no_eras;i++)
+                       reg[i] = Index_of[lambda[i]];
+               count = 0;
+               for (i = 1; i <= NN; i++) {
+                       q = 1;
+                       for (j = 1; j <= no_eras; j++)
+                               if (reg[j] != A0) {
+                                       reg[j] = modnn(reg[j] + j);
+                                       q ^= Alpha_to[reg[j]];
+                               }
+                       if (!q) {
+                               /* store root and error location
+                                * number indices
+                                */
+                               root[count] = i;
+                               loc[count] = NN - i;
+                               count++;
+                       }
+               }
+               if (count != no_eras) {
+                       printf("\n lambda(x) is WRONG\n");
+                       return -1;
+               }
+#ifndef NO_PRINT
+               printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
+               for (i = 0; i < count; i++)
+                       printf("%d ", loc[i]);
+               printf("\n");
+#endif
+#endif
+       }
+       for(i=0;i<NN-KK+1;i++)
+               b[i] = Index_of[lambda[i]];
+
+       /*
+        * Begin Berlekamp-Massey algorithm to determine error+erasure
+        * locator polynomial
+        */
+       r = no_eras;
+       el = no_eras;
+       while (++r <= NN-KK) {  /* r is the step number */
+               /* Compute discrepancy at the r-th step in poly-form */
+               discr_r = 0;
+               for (i = 0; i < r; i++){
+                       if ((lambda[i] != 0) && (s[r - i] != A0)) {
+                               discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
+                       }
+               }
+               discr_r = Index_of[discr_r];    /* Index form */
+               if (discr_r == A0) {
+                       /* 2 lines below: B(x) <-- x*B(x) */
+                       COPYDOWN(&b[1],b,NN-KK);
+                       b[0] = A0;
+               } else {
+                       /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+                       t[0] = lambda[0];
+                       for (i = 0 ; i < NN-KK; i++) {
+                               if(b[i] != A0)
+                                       t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
+                               else
+                                       t[i+1] = lambda[i+1];
+                       }
+                       if (2 * el <= r + no_eras - 1) {
+                               el = r + no_eras - el;
+                               /*
+                                * 2 lines below: B(x) <-- inv(discr_r) *
+                                * lambda(x)
+                                */
+                               for (i = 0; i <= NN-KK; i++)
+                                       b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
+                       } else {
+                               /* 2 lines below: B(x) <-- x*B(x) */
+                               COPYDOWN(&b[1],b,NN-KK);
+                               b[0] = A0;
+                       }
+                       COPY(lambda,t,NN-KK+1);
+               }
+       }
+
+       /* Convert lambda to index form and compute deg(lambda(x)) */
+       deg_lambda = 0;
+       for(i=0;i<NN-KK+1;i++){
+               lambda[i] = Index_of[lambda[i]];
+               if(lambda[i] != A0)
+                       deg_lambda = i;
+       }
+       /*
+        * Find roots of the error+erasure locator polynomial. By Chien
+        * Search
+        */
+       COPY(&reg[1],&lambda[1],NN-KK);
+       count = 0;              /* Number of roots of lambda(x) */
+       for (i = 1; i <= NN; i++) {
+               q = 1;
+               for (j = deg_lambda; j > 0; j--)
+                       if (reg[j] != A0) {
+                               reg[j] = modnn(reg[j] + j);
+                               q ^= Alpha_to[reg[j]];
+                       }
+               if (!q) {
+                       /* store root (index-form) and error location number */
+                       root[count] = i;
+                       loc[count] = NN - i;
+                       count++;
+               }
+       }
+
+#ifdef DEBUG
+       printf("\n Final error positions:\t");
+       for (i = 0; i < count; i++)
+               printf("%d ", loc[i]);
+       printf("\n");
+#endif
+       if (deg_lambda != count) {
+               /*
+                * deg(lambda) unequal to number of roots => uncorrectable
+                * error detected
+                */
+               return -1;
+       }
+       /*
+        * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+        * x**(NN-KK)). in index form. Also find deg(omega).
+        */
+       deg_omega = 0;
+       for (i = 0; i < NN-KK;i++){
+               tmp = 0;
+               j = (deg_lambda < i) ? deg_lambda : i;
+               for(;j >= 0; j--){
+                       if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
+                               tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
+               }
+               if(tmp != 0)
+                       deg_omega = i;
+               omega[i] = Index_of[tmp];
+       }
+       omega[NN-KK] = A0;
+
+       /*
+        * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+        * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
+        */
+       for (j = count-1; j >=0; j--) {
+               num1 = 0;
+               for (i = deg_omega; i >= 0; i--) {
+                       if (omega[i] != A0)
+                               num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];
+               }
+               num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
+               den = 0;
+
+               /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+               for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
+                       if(lambda[i+1] != A0)
+                               den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
+               }
+               if (den == 0) {
+#ifdef DEBUG
+                       printf("\n ERROR: denominator = 0\n");
+#endif
+                       return -1;
+               }
+               /* Apply error to data */
+               if (num1 != 0) {
+                       data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
+               }
+       }
+       return count;
+}
+
+
 #endif /* USE_JPWL */
\ No newline at end of file
index 9c2e9a9b4d572dae80ff751d2cc6f9a63433871a..b303af79daf01ea2d44161edb339e6edc3d22cb6 100644 (file)
--- a/jpwl/rs.h
+++ b/jpwl/rs.h
-/*\r
- * Copyright (c) 2001-2003, David Janssens\r
- * Copyright (c) 2002-2003, Yannick Verschueren\r
- * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
- * Copyright (c) 2005, Herv� Drolon, FreeImage Team\r
- * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
- * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- *    notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- *    notice, this list of conditions and the following disclaimer in the\r
- *    documentation and/or other materials provided with the distribution.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
- * POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifdef USE_JPWL\r
-\r
-/**\r
-@file rs.h\r
-@brief Functions used to compute Reed-Solomon parity and check of byte arrays\r
-\r
-*/\r
-\r
-#ifndef __RS_HEADER__\r
-#define __RS_HEADER__\r
-\r
-/** Global definitions for Reed-Solomon encoder/decoder\r
- * Phil Karn KA9Q, September 1996\r
- *\r
- * The parameters MM and KK specify the Reed-Solomon code parameters.\r
- *\r
- * Set MM to be the size of each code symbol in bits. The Reed-Solomon\r
- * block size will then be NN = 2**M - 1 symbols. Supported values are\r
- * defined in rs.c.\r
- *\r
- * Set KK to be the number of data symbols in each block, which must be\r
- * less than the block size. The code will then be able to correct up\r
- * to NN-KK erasures or (NN-KK)/2 errors, or combinations thereof with\r
- * each error counting as two erasures.\r
- */\r
-#define MM  8          /* RS code over GF(2**MM) - change to suit */\r
-static int     KK;\r
-\r
-/* Original code */\r
-/*#define KK  239*/            /* KK = number of information symbols */\r
-\r
-#define        NN ((1 << MM) - 1)\r
-\r
-#if (MM <= 8)\r
-typedef unsigned char dtype;\r
-#else\r
-typedef unsigned int dtype;\r
-#endif\r
-\r
-/** Initialization function */\r
-void init_rs(int);\r
-\r
-/** These two functions *must* be called in this order (e.g.,\r
- * by init_rs()) before any encoding/decoding\r
- */\r
-void generate_gf(void);        /* Generate Galois Field */\r
-void gen_poly(void);   /* Generate generator polynomial */\r
-\r
-/** Reed-Solomon encoding\r
- * data[] is the input block, parity symbols are placed in bb[]\r
- * bb[] may lie past the end of the data, e.g., for (255,223):\r
- *     encode_rs(&data[0],&data[223]);\r
- */\r
-int encode_rs(dtype data[], dtype bb[]);\r
-\r
-/** Reed-Solomon erasures-and-errors decoding\r
- * The received block goes into data[], and a list of zero-origin\r
- * erasure positions, if any, goes in eras_pos[] with a count in no_eras.\r
- *\r
- * The decoder corrects the symbols in place, if possible and returns\r
- * the number of corrected symbols. If the codeword is illegal or\r
- * uncorrectible, the data array is unchanged and -1 is returned\r
- */\r
-int eras_dec_rs(dtype data[], int eras_pos[], int no_eras);\r
-\r
-\r
-#endif /* __CRC32_HEADER__ */\r
-\r
-\r
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef USE_JPWL
+
+/**
+@file rs.h
+@brief Functions used to compute Reed-Solomon parity and check of byte arrays
+
+*/
+
+#ifndef __RS_HEADER__
+#define __RS_HEADER__
+
+/** Global definitions for Reed-Solomon encoder/decoder
+ * Phil Karn KA9Q, September 1996
+ *
+ * The parameters MM and KK specify the Reed-Solomon code parameters.
+ *
+ * Set MM to be the size of each code symbol in bits. The Reed-Solomon
+ * block size will then be NN = 2**M - 1 symbols. Supported values are
+ * defined in rs.c.
+ *
+ * Set KK to be the number of data symbols in each block, which must be
+ * less than the block size. The code will then be able to correct up
+ * to NN-KK erasures or (NN-KK)/2 errors, or combinations thereof with
+ * each error counting as two erasures.
+ */
+#define MM  8          /* RS code over GF(2**MM) - change to suit */
+static int     KK;
+
+/* Original code */
+/*#define KK  239*/            /* KK = number of information symbols */
+
+#define        NN ((1 << MM) - 1)
+
+#if (MM <= 8)
+typedef unsigned char dtype;
+#else
+typedef unsigned int dtype;
+#endif
+
+/** Initialization function */
+void init_rs(int);
+
+/** These two functions *must* be called in this order (e.g.,
+ * by init_rs()) before any encoding/decoding
+ */
+void generate_gf(void);        /* Generate Galois Field */
+void gen_poly(void);   /* Generate generator polynomial */
+
+/** Reed-Solomon encoding
+ * data[] is the input block, parity symbols are placed in bb[]
+ * bb[] may lie past the end of the data, e.g., for (255,223):
+ *     encode_rs(&data[0],&data[223]);
+ */
+int encode_rs(dtype data[], dtype bb[]);
+
+/** Reed-Solomon erasures-and-errors decoding
+ * The received block goes into data[], and a list of zero-origin
+ * erasure positions, if any, goes in eras_pos[] with a count in no_eras.
+ *
+ * The decoder corrects the symbols in place, if possible and returns
+ * the number of corrected symbols. If the codeword is illegal or
+ * uncorrectible, the data array is unchanged and -1 is returned
+ */
+int eras_dec_rs(dtype data[], int eras_pos[], int no_eras);
+
+
+#endif /* __CRC32_HEADER__ */
+
+
 #endif /* USE_JPWL */
\ No newline at end of file