remove deprecated v1 style function j2k_add_mhmarker; rename j2k_add_mhmarker_v2...
[openjpeg.git] / libopenjpeg / jpwl / jpwl.c
index 707e46fd37f6d0e466ffe9f0e78f2ddcdc0d6978..db8cfa3f7b997831998a63505e8aa6a10b832175 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, Herve 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
-#include "opj_includes.h"\r
-\r
-#ifdef USE_JPWL\r
-\r
-/** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */\r
-/*@{*/\r
-\r
-/** @name Local static variables */\r
-/*@{*/\r
-\r
-/** number of JPWL prepared markers */\r
-static int jwmarker_num;\r
-/** properties of JPWL markers to insert */\r
-static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS]; \r
-\r
-/*@}*/\r
-\r
-/*@}*/\r
-\r
-/** @name Local static functions */\r
-/*@{*/\r
-\r
-/** create an EPC marker segment\r
-@param j2k J2K compressor handle\r
-@param esd_on true if ESD is activated\r
-@param red_on true if RED is activated\r
-@param epb_on true if EPB is activated\r
-@param info_on true if informative techniques are activated\r
-@return returns the freshly created EPC\r
-*/\r
-jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on);\r
-\r
-/*@}*/\r
-\r
-/** create an EPC marker segment\r
-@param j2k J2K compressor handle\r
-@param comps considered component (-1=average, 0/1/2/...=component no.)\r
-@param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)\r
-@param ad_size size of addresses (2/4 bytes)\r
-@param senst sensitivity type\r
-@param se_size sensitivity values size (1/2 bytes)\r
-@param tileno tile where this ESD lies (-1 means MH)\r
-@param svalnum number of sensitivity values (if 0, they will be automatically filled)\r
-@param sensval pointer to an array of sensitivity values (if NULL, they will be automatically filled)\r
-@return returns the freshly created ESD\r
-*/\r
-jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comps, unsigned char addrm, unsigned char ad_size,\r
-                                                               unsigned char senst, int se_size, int tileno,\r
-                                                               unsigned long int svalnum, void *sensval);\r
-                       \r
-/** this function is used to compare two JPWL markers based on\r
-their relevant wishlist position\r
-@param arg1 pointer to first marker\r
-@param arg2 pointer to second marker\r
-@return 1 if arg1>arg2, 0 if arg1=arg2, -1 if arg1<arg2\r
-*/\r
-int jpwl_markcomp(const void *arg1, const void *arg2);\r
-\r
-/** write an EPB MS to a buffer\r
-@param j2k J2K compressor handle\r
-@param epbmark pointer to the EPB MS\r
-@param buf pointer to the memory buffer\r
-*/\r
-void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf);\r
-\r
-/** write an EPC MS to a buffer\r
-@param j2k J2K compressor handle\r
-@param epcmark pointer to the EPC MS\r
-@param buf pointer to the memory buffer\r
-*/\r
-void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epcmark, unsigned char *buf);\r
-\r
-/** write an ESD MS to a buffer\r
-@param j2k J2K compressor handle\r
-@param esdmark pointer to the ESD MS\r
-@param buf pointer to the memory buffer\r
-*/\r
-void jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);\r
-\r
-/*-----------------------------------------------------------------*/\r
-\r
-void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
-\r
-       int mm;\r
-\r
-       /* let's reset some settings */\r
-\r
-       /* clear the existing markers */\r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-\r
-               switch (jwmarker[mm].id) {\r
-\r
-               case J2K_MS_EPB:\r
-                       opj_free(jwmarker[mm].m.epbmark);\r
-                       break;\r
-\r
-               case J2K_MS_EPC:\r
-                       opj_free(jwmarker[mm].m.epcmark);\r
-                       break;\r
-\r
-               case J2K_MS_ESD:\r
-                       opj_free(jwmarker[mm].m.esdmark);\r
-                       break;\r
-\r
-               case J2K_MS_RED:\r
-                       opj_free(jwmarker[mm].m.redmark);\r
-                       break;\r
-\r
-               default:\r
-                       break;\r
-               }\r
-       }\r
-\r
-       /* clear the marker structure array */\r
-       memset(jwmarker, 0, sizeof(jpwl_marker_t) * JPWL_MAX_NO_MARKERS);\r
-\r
-       /* no more markers in the list */\r
-       jwmarker_num = 0;\r
-\r
-       /* let's begin creating a marker list, according to user wishes */\r
-       jpwl_prepare_marks(j2k, cio, image);\r
-\r
-       /* now we dump the JPWL markers on the codestream */\r
-       jpwl_dump_marks(j2k, cio, image);\r
-\r
-       /* do not know exactly what is this for,\r
-       but it gets called during index creation */\r
-       j2k->pos_correction = 0;\r
-\r
-}\r
-\r
-void j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {\r
-\r
-       if (!cstr_info)\r
-               return;\r
-\r
-       /* expand the list? */\r
-       if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {\r
-               cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F);\r
-               cstr_info->marker = opj_realloc(cstr_info->marker, cstr_info->maxmarknum);\r
-       }\r
-\r
-       /* add the marker */\r
-       cstr_info->marker[cstr_info->marknum].type = type;\r
-       cstr_info->marker[cstr_info->marknum].pos = pos;\r
-       cstr_info->marker[cstr_info->marknum].len = len;\r
-       cstr_info->marknum++;\r
-\r
-}\r
-\r
-void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
-\r
-       unsigned short int socsiz_len = 0;\r
-       int ciopos = cio_tell(cio), soc_pos = j2k->cstr_info->main_head_start;\r
-       unsigned char *socp = NULL;\r
-\r
-       int tileno, acc_tpno, tpno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;\r
-\r
-       jpwl_epb_ms_t *epb_mark;\r
-       jpwl_epc_ms_t *epc_mark;\r
-       jpwl_esd_ms_t *esd_mark;\r
-\r
-       /* find (SOC + SIZ) length */\r
-       /* I assume SIZ is always the first marker after SOC */\r
-       cio_seek(cio, soc_pos + 4);\r
-       socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */\r
-       cio_seek(cio, soc_pos + 0);\r
-       socp = cio_getbp(cio); /* pointer to SOC */\r
-\r
-       /* \r
-        EPC MS for Main Header: if we are here it's required\r
-       */\r
-       /* create the EPC */\r
-       if ((epc_mark = jpwl_epc_create(\r
-                       j2k,\r
-                       j2k->cp->esd_on, /* is ESD present? */\r
-                       j2k->cp->red_on, /* is RED present? */\r
-                       j2k->cp->epb_on, /* is EPB present? */\r
-                       OPJ_FALSE /* are informative techniques present? */\r
-               ))) {\r
-\r
-               /* Add this marker to the 'insertanda' list */\r
-               if (epc_mark) {\r
-                       jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */\r
-                       jwmarker[jwmarker_num].m.epcmark = epc_mark; /* the EPC */\r
-                       jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */\r
-                       jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */\r
-                       jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */\r
-                       jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
-                       jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
-                       jwmarker[jwmarker_num].parms_ready = OPJ_FALSE; /* not ready */\r
-                       jwmarker[jwmarker_num].data_ready = OPJ_TRUE; /* ready */\r
-                       jwmarker_num++;\r
-               };\r
-\r
-               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                       "MH  EPC : setting %s%s%s\n",\r
-                       j2k->cp->esd_on ? "ESD, " : "",\r
-                       j2k->cp->red_on ? "RED, " : "",\r
-                       j2k->cp->epb_on ? "EPB, " : ""\r
-                       );\r
-\r
-       } else {\r
-               /* ooops, problems */\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");                              \r
-       };\r
-\r
-       /* \r
-        ESD MS for Main Header\r
-       */\r
-       /* first of all, must MH have an ESD MS? */\r
-       if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {\r
-\r
-               /* Create the ESD */\r
-               if ((esd_mark = jpwl_esd_create(\r
-                       j2k, /* this encoder handle */\r
-                       -1, /* we are averaging over all components */\r
-                       (unsigned char) j2k->cp->sens_range, /* range method */\r
-                       (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */\r
-                       (unsigned char) j2k->cp->sens_MH, /* sensitivity method */\r
-                       j2k->cp->sens_size, /* sensitivity size */\r
-                       -1, /* this ESD is in main header */\r
-                       0 /*j2k->cstr_info->num*/, /* number of packets in codestream */\r
-                       NULL /*sensval*/ /* pointer to sensitivity data of packets */\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_ESD; /* its type */\r
-                               jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */\r
-                               jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* we choose to place it after SIZ */\r
-                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
-                               jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
-                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* not ready, yet */\r
-                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
-                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */\r
-                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
-                               jwmarker_num++;\r
-                       }\r
-\r
-                       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                               "MH  ESDs: method %d\n",\r
-                               j2k->cp->sens_MH\r
-                               );\r
-\r
-               } else {\r
-                       /* ooops, problems */\r
-                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");                              \r
-               };\r
-\r
-       }\r
-\r
-       /* \r
-        ESD MSs for Tile Part Headers \r
-       */\r
-       /* cycle through tiles */\r
-       sens = -1; /* default spec: no ESD */\r
-       tilespec = 0; /* first tile spec */\r
-       acc_tpno = 0;\r
-       for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {\r
-\r
-               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                       "Tile %d has %d tile part(s)\n",\r
-                       tileno, j2k->cstr_info->tile[tileno].num_tps\r
-                       );\r
-\r
-               /* for every tile part in the tile */\r
-               for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {\r
-       \r
-                       int sot_len, Psot, Psotp, mm;\r
-                       unsigned long sot_pos, post_sod_pos;\r
-\r
-                       unsigned long int left_THmarks_len;\r
-\r
-                       /******* sot_pos = j2k->cstr_info->tile[tileno].start_pos; */\r
-                       sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;\r
-                       cio_seek(cio, sot_pos + 2); \r
-                       sot_len = cio_read(cio, 2); /* SOT Len */\r
-                       cio_skip(cio, 2);\r
-                       Psotp = cio_tell(cio);\r
-                       Psot = cio_read(cio, 4); /* tile length */\r
-\r
-                       /******* post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */\r
-                       post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;\r
-                       left_THmarks_len = post_sod_pos - sot_pos;\r
-\r
-                       /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */\r
-                       for (mm = 0; mm < jwmarker_num; mm++) {\r
-                               if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
-                                       if (jwmarker[mm].len_ready)\r
-                                               left_THmarks_len += jwmarker[mm].len + 2;\r
-                                       else {\r
-                                               opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
-                                                       jwmarker[mm].id, jwmarker[mm].dpos);                            \r
-                                               exit(1);\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       /******* if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno)) */\r
-                       if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == acc_tpno))\r
-                               /* we got a specification from this tile onwards */\r
-                               sens = j2k->cp->sens_TPH[tilespec++];\r
-               \r
-                       /* must this TPH have an ESD MS? */\r
-                       if (j2k->cp->esd_on && (sens >= 0)) {\r
-\r
-                               /* Create the ESD */\r
-                               if ((esd_mark = jpwl_esd_create(\r
-                                       j2k, /* this encoder handle */\r
-                                       -1, /* we are averaging over all components */\r
-                                       (unsigned char) j2k->cp->sens_range, /* range method */\r
-                                       (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */\r
-                                       (unsigned char) sens, /* sensitivity method */\r
-                                       j2k->cp->sens_size, /* sensitivity value size */\r
-                                       tileno, /* this ESD is in a tile */\r
-                                       0, /* number of packets in codestream */\r
-                                       NULL /* pointer to sensitivity data of packets */\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_ESD; /* its type */\r
-                                               jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */\r
-                                               /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */\r
-                                               jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */\r
-                                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
-                                               jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
-                                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready, yet */\r
-                                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
-                                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */\r
-                                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* ready */\r
-                                               jwmarker_num++;\r
-                                       }\r
-\r
-                                       /* update Psot of the tile  */\r
-                                       cio_seek(cio, Psotp);\r
-                                       cio_write(cio, Psot + esd_mark->Lesd + 2, 4);\r
-\r
-                                       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                                               /******* "TPH ESDs: tile %02d, method %d\n", */\r
-                                               "TPH ESDs: tile %02d, part %02d, method %d\n",\r
-                                               /******* tileno, */\r
-                                               tileno, tpno,\r
-                                               sens\r
-                                               );\r
-\r
-                               } else {\r
-                                       /* ooops, problems */\r
-                                       /***** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno); */\r
-                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d,%d\n", tileno, tpno);\r
-                               };\r
-\r
-                       }\r
-                       \r
-               }\r
-       \r
-       };\r
-\r
-       /* \r
-        EPB MS for Main Header\r
-       */\r
-       /* first of all, must MH have an EPB MS? */\r
-       if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {\r
-\r
-               int mm;\r
-\r
-               /* position of SOT */\r
-               unsigned int sot_pos = j2k->cstr_info->main_head_end + 1;\r
-\r
-               /* how much space is there between end of SIZ and beginning of SOT? */\r
-               int left_MHmarks_len = sot_pos - socsiz_len;\r
-\r
-               /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */\r
-               for (mm = 0; mm < jwmarker_num; mm++) {\r
-                       if ((jwmarker[mm].pos >=0) && (jwmarker[mm].pos < sot_pos)) {\r
-                               if (jwmarker[mm].len_ready)\r
-                                       left_MHmarks_len += jwmarker[mm].len + 2;\r
-                               else {\r
-                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",\r
-                                               jwmarker[mm].id, jwmarker[mm].dpos);                            \r
-                                       exit(1);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               /* Create the EPB */\r
-               if ((epb_mark = jpwl_epb_create(\r
-                       j2k, /* this encoder handle */\r
-                       OPJ_TRUE, /* is it the latest? */\r
-                       OPJ_TRUE, /* is it packed? not for now */\r
-                       -1, /* we are in main header */\r
-                       0, /* its index is 0 (first) */\r
-                       j2k->cp->hprot_MH, /* protection type parameters of data */\r
-                       socsiz_len, /* pre-data: only SOC+SIZ */\r
-                       left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */\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].m.epbmark = epb_mark; /* the EPB */\r
-                               jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */\r
-                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
-                               jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
-                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
-                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
-                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */\r
-                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
-                               jwmarker_num++;\r
-                       }\r
-\r
-                       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                               "MH  EPB : prot. %d\n",\r
-                               j2k->cp->hprot_MH\r
-                               );\r
-\r
-               } else {\r
-                       /* ooops, problems */\r
-                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");                              \r
-               };\r
-       }\r
-\r
-       /* \r
-        EPB MSs for Tile Parts\r
-       */\r
-       /* cycle through TPHs */\r
-       hprot = j2k->cp->hprot_MH; /* default spec */\r
-       tilespec = 0; /* first tile spec */\r
-       lastileno = 0;\r
-       packspec = 0;\r
-       pprot = -1;\r
-       acc_tpno = 0;\r
-       for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {\r
-\r
-               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                       "Tile %d has %d tile part(s)\n",\r
-                       tileno, j2k->cstr_info->tile[tileno].num_tps\r
-                       );\r
-\r
-               /* for every tile part in the tile */\r
-               for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) { \r
-               \r
-                       int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;\r
-                       unsigned long sot_pos, post_sod_pos;\r
-                       unsigned long int left_THmarks_len/*, epbs_len = 0*/;\r
-                       int startpack = 0, stoppack = j2k->cstr_info->packno;\r
-                       int first_tp_pack, last_tp_pack;\r
-                       jpwl_epb_ms_t *tph_epb = NULL;\r
-\r
-                       /****** sot_pos = j2k->cstr_info->tile[tileno].start_pos; */\r
-                       sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;\r
-                       cio_seek(cio, sot_pos + 2); \r
-                       sot_len = cio_read(cio, 2); /* SOT Len */\r
-                       cio_skip(cio, 2);\r
-                       Psotp = cio_tell(cio);\r
-                       Psot = cio_read(cio, 4); /* tile length */\r
-\r
-                       /* a-priori length of the data dwelling between SOT and SOD */\r
-                       /****** post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */\r
-                       post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;\r
-                       left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);\r
-\r
-                       /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */\r
-                       for (mm = 0; mm < jwmarker_num; mm++) {\r
-                               if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
-                                       if (jwmarker[mm].len_ready)\r
-                                               left_THmarks_len += jwmarker[mm].len + 2;\r
-                                       else {\r
-                                               opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
-                                                       jwmarker[mm].id, jwmarker[mm].dpos);                            \r
-                                               exit(1);\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       /****** if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno)) */\r
-                       if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == acc_tpno))\r
-                               /* we got a specification from this tile part onwards */\r
-                               hprot = j2k->cp->hprot_TPH[tilespec++];\r
-               \r
-                       /* must this TPH have an EPB MS? */\r
-                       if (j2k->cp->epb_on && (hprot > 0)) {\r
-\r
-                               /* Create the EPB */\r
-                               if ((epb_mark = jpwl_epb_create(\r
-                                       j2k, /* this encoder handle */\r
-                                       OPJ_FALSE, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */\r
-                                       OPJ_TRUE, /* is it packed? yes for now */\r
-                                       tileno, /* we are in TPH */\r
-                                       epb_index++, /* its index is 0 (first) */\r
-                                       hprot, /* protection type parameters of following data */\r
-                                       sot_len + 2, /* pre-data length: only SOT */\r
-                                       left_THmarks_len /* post-data length: from SOT end to SOD inclusive */\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].m.epbmark = epb_mark; /* the EPB */\r
-                                               /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */\r
-                                               jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */\r
-                                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
-                                               jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
-                                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
-                                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
-                                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */\r
-                                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
-                                               jwmarker_num++;\r
-                                       }\r
-\r
-                                       /* update Psot of the tile  */\r
-                                       Psot += epb_mark->Lepb + 2;\r
-\r
-                                       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                                               /***** "TPH EPB : tile %02d, prot. %d\n", */\r
-                                               "TPH EPB : tile %02d, part %02d, prot. %d\n",\r
-                                               /***** tileno, */\r
-                                               tileno, tpno,\r
-                                               hprot\r
-                                               );\r
-\r
-                                       /* save this TPH EPB address */\r
-                                       tph_epb = epb_mark;\r
-\r
-                               } else {\r
-                                       /* ooops, problems */\r
-                                       /****** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno); */\r
-                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB in #%d,d\n", tileno, tpno);\r
-                               };\r
-\r
-                       }                               \r
-               \r
-                       startpack = 0;\r
-                       /* EPB MSs for UEP packet data protection in Tile Parts */\r
-                       /****** for (packno = 0; packno < j2k->cstr_info->num; packno++) { */\r
-                       /*first_tp_pack = (tpno > 0) ? (first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno - 1].tp_numpacks) : 0;*/\r
-                       first_tp_pack = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pack;\r
-                       last_tp_pack = first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks - 1;\r
-                       for (packno = 0; packno < j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks; packno++) {\r
-\r
-                               /******** if ((packspec < JPWL_MAX_NO_PACKSPECS) &&\r
-                                       (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) { */\r
-                               if ((packspec < JPWL_MAX_NO_PACKSPECS) &&\r
-                                       (j2k->cp->pprot_tileno[packspec] == acc_tpno) && (j2k->cp->pprot_packno[packspec] == packno)) {\r
-\r
-                                       /* we got a specification from this tile and packet onwards */\r
-                                       /* print the previous spec */\r
-                                       if (packno > 0) {\r
-                                               stoppack = packno - 1;                          \r
-                                               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                                                       /***** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */\r
-                                                       "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
-                                                       /***** tileno, */\r
-                                                       tileno, tpno,\r
-                                                       startpack,\r
-                                                       stoppack,\r
-                                                       /***** j2k->cstr_info->tile[tileno].packet[startpack].start_pos, */\r
-                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,\r
-                                                       /***** j2k->cstr_info->tile[tileno].packet[stoppack].end_pos, */\r
-                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,\r
-                                                       pprot);\r
-\r
-                                               /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
-                                                       j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */\r
-                                               prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -\r
-                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;\r
-\r
-                                               /*\r
-                                                 particular case: if this is the last header and the last packet,\r
-                                                 then it is better to protect even the EOC marker\r
-                                               */\r
-                                               /****** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
-                                                       (stoppack == (j2k->cstr_info->num - 1))) */\r
-                                               if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
-                                                       (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&\r
-                                                       (stoppack == last_tp_pack))\r
-                                                       /* add the EOC len */\r
-                                                       prot_len += 2;\r
-\r
-                                               /* let's add the EPBs */\r
-                                               Psot += jpwl_epbs_add(\r
-                                                       j2k, /* J2K handle */\r
-                                                       jwmarker, /* pointer to JPWL markers list */\r
-                                                       &jwmarker_num, /* pointer to the number of current markers */\r
-                                                       OPJ_FALSE, /* latest */\r
-                                                       OPJ_TRUE, /* packed */\r
-                                                       OPJ_FALSE, /* inside MH */\r
-                                                       &epb_index, /* pointer to EPB index */\r
-                                                       pprot, /* protection type */\r
-                                                       /****** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, */ /* position */\r
-                                                       (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */\r
-                                                       tileno, /* number of tile */\r
-                                                       0, /* length of pre-data */\r
-                                                       prot_len /*4000*/ /* length of post-data */\r
-                                                       );\r
-                                       }\r
-\r
-                                       startpack = packno;\r
-                                       pprot = j2k->cp->pprot[packspec++];\r
-                               }\r
-\r
-                               //printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);\r
-               \r
-                       }\r
-\r
-                       /* we are at the end: print the remaining spec */\r
-                       stoppack = packno - 1;\r
-                       if (pprot >= 0) {\r
-\r
-                               opj_event_msg(j2k->cinfo, EVT_INFO,\r
-                                       /**** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */\r
-                                       "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
-                                       /**** tileno, */\r
-                                       tileno, tpno,\r
-                                       startpack,\r
-                                       stoppack,\r
-                                       /***** j2k->image_info->tile[tileno].packet[startpack].start_pos,\r
-                                       j2k->image_info->tile[tileno].packet[stoppack].end_pos, */\r
-                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,\r
-                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,\r
-                                       pprot);\r
-\r
-                               /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
-                                       j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */\r
-                               prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -\r
-                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;\r
-\r
-                               /*\r
-                                 particular case: if this is the last header and the last packet,\r
-                                 then it is better to protect even the EOC marker\r
-                               */\r
-                               /***** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
-                                       (stoppack == (j2k->cstr_info->num - 1))) */\r
-                               if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
-                                       (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&\r
-                                       (stoppack == last_tp_pack))\r
-                                       /* add the EOC len */\r
-                                       prot_len += 2;\r
-\r
-                               /* let's add the EPBs */\r
-                               Psot += jpwl_epbs_add(\r
-                                                       j2k, /* J2K handle */\r
-                                                       jwmarker, /* pointer to JPWL markers list */\r
-                                                       &jwmarker_num, /* pointer to the number of current markers */\r
-                                                       OPJ_TRUE, /* latest */\r
-                                                       OPJ_TRUE, /* packed */\r
-                                                       OPJ_FALSE, /* inside MH */\r
-                                                       &epb_index, /* pointer to EPB index */\r
-                                                       pprot, /* protection type */\r
-                                                       /***** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001,*/ /* position */\r
-                                                       (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */\r
-                                                       tileno, /* number of tile */\r
-                                                       0, /* length of pre-data */\r
-                                                       prot_len /*4000*/ /* length of post-data */\r
-                                                       );\r
-                       }\r
-\r
-                       /* we can now check if the TPH EPB was really the last one */\r
-                       if (tph_epb && (epb_index == 1)) {\r
-                               /* set the TPH EPB to be the last one in current header */\r
-                               tph_epb->Depb |= (unsigned char) ((OPJ_TRUE & 0x0001) << 6);\r
-                               tph_epb = NULL;\r
-                       }\r
-\r
-                       /* write back Psot */\r
-                       cio_seek(cio, Psotp);\r
-                       cio_write(cio, Psot, 4);\r
-               \r
-               }\r
-\r
-       };\r
-\r
-       /* reset the position */\r
-       cio_seek(cio, ciopos);\r
-\r
-}\r
-\r
-void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
-\r
-       int mm;\r
-       unsigned long int old_size = j2k->cstr_info->codestream_size;\r
-       unsigned long int new_size = old_size;\r
-       int /*ciopos = cio_tell(cio),*/ soc_pos = j2k->cstr_info->main_head_start;\r
-       unsigned char *jpwl_buf, *orig_buf;\r
-       unsigned long int orig_pos;\r
-       double epbcoding_time = 0.0, esdcoding_time = 0.0;\r
-\r
-       /* Order JPWL markers according to their wishlist position */\r
-       qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);\r
-\r
-       /* compute markers total size */ \r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-               /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,\r
-                       jwmarker[mm].dpos, jwmarker[mm].len);*/\r
-               new_size += jwmarker[mm].len + 2;\r
-       }\r
-\r
-       /* allocate a new buffer of proper size */\r
-       if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) (new_size + soc_pos) * sizeof(unsigned char)))) {\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL codestream buffer\n");\r
-               exit(1);\r
-       };\r
-\r
-       /* copy the jp2 part, if any */\r
-       orig_buf = jpwl_buf;\r
-       memcpy(jpwl_buf, cio->buffer, soc_pos);\r
-       jpwl_buf += soc_pos;\r
-\r
-       /* cycle through markers */\r
-       orig_pos = soc_pos + 0; /* start from the beginning */\r
-       cio_seek(cio, soc_pos + 0); /* rewind the original */\r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-\r
-               /*\r
-               need to copy a piece of the original codestream\r
-               if there is such\r
-               */\r
-               memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);\r
-               jpwl_buf += jwmarker[mm].pos - orig_pos;\r
-               orig_pos = jwmarker[mm].pos;\r
-               cio_seek(cio, orig_pos);\r
-\r
-               /*\r
-               then write down the marker\r
-               */\r
-               switch (jwmarker[mm].id) {\r
-\r
-               case J2K_MS_EPB:\r
-                       jpwl_epb_write(j2k, jwmarker[mm].m.epbmark, jpwl_buf);\r
-                       break;\r
-\r
-               case J2K_MS_EPC:\r
-                       jpwl_epc_write(j2k, jwmarker[mm].m.epcmark, jpwl_buf);\r
-                       break;\r
-\r
-               case J2K_MS_ESD:\r
-                       jpwl_esd_write(j2k, jwmarker[mm].m.esdmark, jpwl_buf);\r
-                       break;\r
-\r
-               case J2K_MS_RED:\r
-                       memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */\r
-                       break;\r
-\r
-               default:\r
-                       break;\r
-               };\r
-\r
-               /* we update the markers struct */\r
-               if (j2k->cstr_info)\r
-                       j2k->cstr_info->marker[j2k->cstr_info->marknum - 1].pos = (jpwl_buf - orig_buf);\r
-               \r
-               /* we set the marker dpos to the new position in the JPWL codestream */\r
-               jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);\r
-\r
-               /* advance JPWL buffer position */\r
-               jpwl_buf += jwmarker[mm].len + 2;\r
-\r
-       }\r
-\r
-       /* finish remaining original codestream */\r
-       memcpy(jpwl_buf, cio_getbp(cio), old_size - (orig_pos - soc_pos));\r
-       jpwl_buf += old_size - (orig_pos - soc_pos);\r
-       cio_seek(cio, soc_pos + old_size);\r
-       \r
-       /*\r
-       update info file based on added markers\r
-       */\r
-       if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))\r
-               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ cstr_info structure\n");\r
-\r
-       /* now we need to repass some markers and fill their data fields */\r
-       \r
-       /* first of all, DL and Pcrc in EPCs */ \r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-\r
-               /* find the EPCs */\r
-               if (jwmarker[mm].id == J2K_MS_EPC) {\r
-\r
-                       int epc_pos = (int) jwmarker[mm].dpos, pp;\r
-                       unsigned short int mycrc = 0x0000;\r
-\r
-                       /* fix and fill the DL field */\r
-                       jwmarker[mm].m.epcmark->DL = new_size;\r
-                       orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 24);\r
-                       orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 16);\r
-                       orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 8);\r
-                       orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 0);\r
-\r
-                       /* compute the CRC field (excluding itself) */\r
-                       for (pp = 0; pp < 4; pp++)\r
-                               jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
-                       for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)\r
-                               jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
-\r
-                       /* fix and fill the CRC */\r
-                       jwmarker[mm].m.epcmark->Pcrc = mycrc;\r
-                       orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 8);\r
-                       orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 0);\r
-\r
-               }\r
-       }\r
-\r
-       /* then, sensitivity data in ESDs */ \r
-       esdcoding_time = opj_clock();\r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-\r
-               /* find the ESDs */\r
-               if (jwmarker[mm].id == J2K_MS_ESD) {\r
-\r
-                       /* remember that they are now in a new position (dpos) */\r
-                       int esd_pos = (int) jwmarker[mm].dpos;\r
-\r
-                       jpwl_esd_fill(j2k, jwmarker[mm].m.esdmark, &orig_buf[esd_pos]);\r
-               \r
-               }\r
-\r
-       }\r
-       esdcoding_time = opj_clock() - esdcoding_time;\r
-       if (j2k->cp->esd_on)\r
-               opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);\r
-\r
-       /* finally, RS or CRC parity in EPBs */ \r
-       epbcoding_time = opj_clock();\r
-       for (mm = 0; mm < jwmarker_num; mm++) {\r
-\r
-               /* find the EPBs */\r
-               if (jwmarker[mm].id == J2K_MS_EPB) {\r
-\r
-                       /* remember that they are now in a new position (dpos) */\r
-                       int nn, accum_len;\r
-\r
-                       /* let's see how many EPBs are following this one, included itself */\r
-                       /* for this to work, we suppose that the markers are correctly ordered */\r
-                       /* and, overall, that they are in packed mode inside headers */\r
-                       accum_len = 0;\r
-                       for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
-                               (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
-                               accum_len += jwmarker[nn].m.epbmark->Lepb + 2;\r
-\r
-                       /* fill the current (first) EPB with post-data starting from the computed position */\r
-                       jpwl_epb_fill(j2k, jwmarker[mm].m.epbmark, &orig_buf[(int) jwmarker[mm].dpos],\r
-                               &orig_buf[(int) jwmarker[mm].dpos + accum_len]);\r
-               \r
-                       /* fill the remaining EPBs in the header with post-data starting from the last position */\r
-                       for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
-                               (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
-                               jpwl_epb_fill(j2k, jwmarker[nn].m.epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);\r
-\r
-                       /* skip all the processed EPBs */\r
-                       mm = nn - 1;\r
-               }\r
-\r
-       }\r
-       epbcoding_time = opj_clock() - epbcoding_time;\r
-       if (j2k->cp->epb_on)\r
-               opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);\r
-\r
-       /* free original cio buffer and set it to the JPWL one */\r
-       opj_free(cio->buffer);\r
-       cio->cinfo = cio->cinfo; /* no change */\r
-       cio->openmode = cio->openmode; /* no change */\r
-       cio->buffer = orig_buf;\r
-       cio->length = new_size + soc_pos;\r
-       cio->start = cio->buffer;\r
-       cio->end = cio->buffer + cio->length;\r
-       cio->bp = cio->buffer;\r
-       cio_seek(cio, soc_pos + new_size);\r
-\r
-}\r
-\r
-\r
-void j2k_read_epc(opj_j2k_t *j2k) {\r
-       unsigned long int DL, Lepcp, Pcrcp, l;\r
-       unsigned short int Lepc, Pcrc = 0x0000;\r
-       unsigned char Pepc;     \r
-       opj_cio_t *cio = j2k->cio;\r
-       char *ans1;\r
-\r
-       /* Simply read the EPC parameters */\r
-       Lepcp = cio_tell(cio);\r
-       Lepc = cio_read(cio, 2);\r
-       Pcrcp = cio_tell(cio);\r
-       cio_skip(cio, 2); /* Pcrc */\r
-       DL = cio_read(cio, 4);\r
-       Pepc = cio_read(cio, 1);\r
-\r
-       /* compute Pcrc */\r
-       cio_seek(cio, Lepcp - 2);\r
-\r
-               /* Marker */\r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* Length */\r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* skip Pcrc */\r
-               cio_skip(cio, 2);\r
-\r
-               /* read all remaining */\r
-               for (l = 4; l < Lepc; l++)\r
-                       jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* check Pcrc with the result */\r
-               cio_seek(cio, Pcrcp);\r
-               ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";\r
-\r
-       /* now we write them to screen */\r
-       opj_event_msg(j2k->cinfo, EVT_INFO, \r
-               "EPC(%u,%d): %s, DL=%d%s %s %s\n",\r
-               Lepcp - 2,\r
-               Lepc,\r
-               ans1,\r
-               DL, /* data length this EPC is referring to */\r
-               (Pepc & 0x10) ? ", esd" : "", /* ESD is present */\r
-               (Pepc & 0x20) ? ", red" : "", /* RED is present */\r
-               (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */\r
-\r
-       cio_seek(cio, Lepcp + Lepc);  \r
-}\r
-\r
-void j2k_write_epc(opj_j2k_t *j2k) {\r
-\r
-       unsigned long int DL, Lepcp, Pcrcp, l;\r
-       unsigned short int Lepc, Pcrc;\r
-       unsigned char Pepc;     \r
-\r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       cio_write(cio, J2K_MS_EPC, 2);  /* EPC */\r
-       Lepcp = cio_tell(cio);\r
-       cio_skip(cio, 2);\r
-\r
-       /* CRC-16 word of the EPC */\r
-       Pcrc = 0x0000; /* initialize */\r
-       Pcrcp = cio_tell(cio);\r
-       cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/\r
-\r
-       /* data length of the EPC protection domain */\r
-       DL = 0x00000000; /* we leave this set to 0, as if the information is not available */\r
-       cio_write(cio, DL, 4);   /* DL */\r
-\r
-       /* jpwl capabilities */\r
-       Pepc = 0x00;\r
-       cio_write(cio, Pepc, 1); /* Pepc */\r
-\r
-       /* ID section */\r
-       /* no ID's, as of now */\r
-\r
-       Lepc = (unsigned short) (cio_tell(cio) - Lepcp);\r
-       cio_seek(cio, Lepcp);\r
-       cio_write(cio, Lepc, 2); /* Lepc */\r
-\r
-       /* compute Pcrc */\r
-       cio_seek(cio, Lepcp - 2);\r
-\r
-               /* Marker */\r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* Length */\r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* skip Pcrc */\r
-               cio_skip(cio, 2);\r
-\r
-               /* read all remaining */\r
-               for (l = 4; l < Lepc; l++)\r
-                       jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
-\r
-               /* fill Pcrc with the result */\r
-               cio_seek(cio, Pcrcp);\r
-               cio_write(cio, Pcrc, 2);\r
-\r
-       cio_seek(cio, Lepcp + Lepc);\r
-\r
-       /* marker struct update */\r
-       j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, Lepcp - 2, Lepc + 2);\r
-\r
-}\r
-\r
-void j2k_read_epb(opj_j2k_t *j2k) {\r
-       unsigned long int LDPepb, Pepb;\r
-       unsigned short int Lepb;\r
-       unsigned char Depb;\r
-       char str1[25] = "";\r
-       opj_bool status;\r
-       static opj_bool first_in_tph = OPJ_TRUE;\r
-       int type, pre_len, post_len;\r
-       static unsigned char *redund = NULL;\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* B/W = 45, RGB = 51 */\r
-       /*           SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */\r
-       int skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;\r
-\r
-       if (j2k->cp->correct) {\r
-\r
-               /* go back to EPB marker value */\r
-               cio_seek(cio, cio_tell(cio) - 2);\r
-\r
-               /* we need to understand where we are */\r
-               if (j2k->state == J2K_STATE_MH) {\r
-                       /* we are in MH */\r
-                       type = 0; /* MH */\r
-                       pre_len = skipnum; /* SOC+SIZ */\r
-                       post_len = -1; /* auto */\r
-\r
-               } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {\r
-                       /* we are in TPH */\r
-                       type = 1; /* TPH */\r
-                       pre_len = 12; /* SOC+SIZ */\r
-                       first_in_tph = OPJ_FALSE;\r
-                       post_len = -1; /* auto */\r
-\r
-               } else {\r
-                       /* we are elsewhere */\r
-                       type = 2; /* other */\r
-                       pre_len = 0; /* nada */\r
-                       post_len = -1; /* auto */\r
-\r
-               }\r
-\r
-               /* call EPB corrector */\r
-               /*printf("before %x, ", redund);*/\r
-               status = jpwl_epb_correct(j2k,      /* J2K decompressor handle */\r
-                                                                 cio->bp,  /* pointer to EPB in codestream buffer */\r
-                                                                 type,     /* EPB type: MH */\r
-                                                                 pre_len,  /* length of pre-data */\r
-                                                                 post_len, /* length of post-data: -1 means auto */\r
-                                                                 NULL,     /* do everything auto */\r
-                                                                 &redund\r
-                                                                );\r
-               /*printf("after %x\n", redund);*/\r
-\r
-               /* Read the (possibly corrected) EPB parameters */\r
-               cio_skip(cio, 2);\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
-               if (!status) {\r
-\r
-                       opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");\r
-\r
-                       /* advance to EPB endpoint */\r
-                       cio_skip(cio, Lepb + 2);  \r
-\r
-                       return;\r
-               }\r
-\r
-               /* last in current header? */\r
-               if (Depb & 0x40) {\r
-                       redund = NULL; /* reset the pointer to L4 buffer */\r
-                       first_in_tph = OPJ_TRUE;\r
-               }\r
-\r
-               /* advance to EPB endpoint */\r
-               cio_skip(cio, Lepb - 11);  \r
-\r
-       } else {\r
-\r
-               /* Simply read the EPB parameters */\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-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */\r
-               else if (((Pepb & 0xF0000000) >> 28) == 2)\r
-                       sprintf(str1, "rs(%lu,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
-               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
-               cio_skip(cio, Lepb - 11);  \r
-       }\r
-}\r
-\r
-void j2k_write_epb(opj_j2k_t *j2k) {\r
-       unsigned long int LDPepb, Pepb, Lepbp;\r
-       unsigned short int Lepb;\r
-       unsigned char Depb;\r
-\r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       cio_write(cio, J2K_MS_EPB, 2);  /* EPB */\r
-       Lepbp = cio_tell(cio);\r
-       cio_skip(cio, 2);\r
-\r
-       /* EPB style */\r
-       Depb = 0x00; /* test */\r
-       cio_write(cio, Depb, 1);   /* Depb */\r
-\r
-       /* length of the data to be protected by this EPB */\r
-       LDPepb = 0x00000000; /* test */\r
-       cio_write(cio, LDPepb, 4);   /* LDPepb */\r
-\r
-       /* next error correction tool */\r
-       Pepb = 0x00000000; /* test */\r
-       cio_write(cio, Pepb, 4);   /* Pepb */\r
-\r
-       /* EPB data */\r
-       /* no data, as of now */\r
-\r
-       Lepb = (unsigned short) (cio_tell(cio) - Lepbp);\r
-       cio_seek(cio, Lepbp);\r
-       cio_write(cio, Lepb, 2);                /* Lepb */\r
-\r
-       cio_seek(cio, Lepbp + Lepb);\r
-\r
-       /* marker struct update */\r
-       j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, Lepbp - 2, Lepb + 2);\r
-}\r
-\r
-void j2k_read_esd(opj_j2k_t *j2k) {\r
-       unsigned short int Lesd, Cesd;\r
-       unsigned char Pesd;\r
-\r
-       int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;\r
-\r
-       char str1[4][4] = {"p", "br", "pr", "res"};\r
-       char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* Simply read the ESD parameters */\r
-       Lesd = cio_read(cio, 2);\r
-       Cesd = cio_read(cio, cesdsize);\r
-       Pesd = cio_read(cio, 1);\r
-\r
-       /* Now we write them to screen */\r
-       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-               "ESD(%d): c%d, %s, %s, %s, %s, %s\n",\r
-               cio_tell(cio) - (5 + cesdsize),\r
-               Cesd, /* component number for this ESD */\r
-               str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
-               str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */\r
-               ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",\r
-               ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",\r
-               (Pesd & (unsigned char) 0x01) ? "avgc" : "");\r
-\r
-       cio_skip(cio, Lesd - (3 + cesdsize));  \r
-}\r
-\r
-void j2k_read_red(opj_j2k_t *j2k) {\r
-       unsigned short int Lred;\r
-       unsigned char Pred;\r
-       char str1[4][4] = {"p", "br", "pr", "res"};\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* Simply read the RED parameters */\r
-       Lred = cio_read(cio, 2);\r
-       Pred = cio_read(cio, 1);\r
-\r
-       /* Now we write them to screen */\r
-       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-               "RED(%d): %s, %dc, %s, %s\n",\r
-               cio_tell(cio) - 5,\r
-               str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
-               (Pred & (unsigned char) 0x38) >> 3, /* corruption level */\r
-               ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */\r
-               (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */\r
-\r
-       cio_skip(cio, Lred - 3);  \r
-}\r
-\r
-opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {\r
-\r
-#ifdef oerhgierhgvhreit4u\r
-       /*\r
-          we navigate through the tile and find possible invalid parameters:\r
-       this saves a lot of crashes!!!!!\r
-        */\r
-       int compno, resno, precno, /*layno,*/ bandno, blockno;\r
-       int numprecincts, numblocks;\r
-\r
-       /* this is the selected tile */\r
-       opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);\r
-\r
-       /* will keep the component */\r
-       opj_tcd_tilecomp_t *comp = NULL;\r
-\r
-       /* will keep the resolution */\r
-       opj_tcd_resolution_t *res;\r
-\r
-       /* will keep the subband */\r
-       opj_tcd_band_t *band; \r
-\r
-       /* will keep the precinct */\r
-       opj_tcd_precinct_t *prec; \r
-\r
-       /* will keep the codeblock */\r
-       opj_tcd_cblk_t *block;\r
-\r
-       /* check all tile components */\r
-       for (compno = 0; compno < tile->numcomps; compno++) {\r
-               comp = &(tile->comps[compno]);\r
-\r
-               /* check all component resolutions */\r
-               for (resno = 0; resno < comp->numresolutions; resno++) {\r
-                       res = &(comp->resolutions[resno]);\r
-                       numprecincts = res->pw * res->ph;\r
-\r
-                       /* check all the subbands */\r
-                       for (bandno = 0; bandno < res->numbands; bandno++) {\r
-                               band = &(res->bands[bandno]);\r
-\r
-                               /* check all the precincts */\r
-                               for (precno = 0; precno < numprecincts; precno++) {\r
-                                       prec = &(band->precincts[precno]);\r
-                                       numblocks = prec->ch * prec->cw;\r
-\r
-                                       /* check all the codeblocks */\r
-                                       for (blockno = 0; blockno < numblocks; blockno++) {\r
-                                               block = &(prec->cblks[blockno]);\r
-\r
-                                               /* x-origin is invalid */\r
-                                               if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {\r
-                                                       opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,\r
-                                                               "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",\r
-                                                               block->x0, prec->x0, prec->x1);\r
-                                                       if (!JPWL_ASSUME || JPWL_ASSUME)\r
-                                                               return OPJ_FALSE;\r
-                                               };\r
-                                       }\r
-                               }                               \r
-                       }\r
-               }\r
-       }\r
-\r
-#endif\r
-\r
-       return OPJ_TRUE;\r
-}\r
-\r
-/*@}*/\r
-\r
-#endif /* USE_JPWL */\r
-\r
-\r
-#ifdef USE_JPSEC\r
-\r
-/** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */\r
-/*@{*/\r
-\r
-\r
-/** @name Local static functions */\r
-/*@{*/\r
-\r
-void j2k_read_sec(opj_j2k_t *j2k) {\r
-       unsigned short int Lsec;\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* Simply read the SEC length */\r
-       Lsec = cio_read(cio, 2);\r
-\r
-       /* Now we write them to screen */\r
-       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-               "SEC(%d)\n",\r
-               cio_tell(cio) - 2\r
-               );\r
-\r
-       cio_skip(cio, Lsec - 2);  \r
-}\r
-\r
-void j2k_write_sec(opj_j2k_t *j2k) {\r
-       unsigned short int Lsec = 24;\r
-       int i;\r
-\r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       cio_write(cio, J2K_MS_SEC, 2);  /* SEC */\r
-       cio_write(cio, Lsec, 2);\r
-\r
-       /* write dummy data */\r
-       for (i = 0; i < Lsec - 2; i++)\r
-               cio_write(cio, 0, 1);\r
-}\r
-\r
-void j2k_read_insec(opj_j2k_t *j2k) {\r
-       unsigned short int Linsec;\r
-       \r
-       opj_cio_t *cio = j2k->cio;\r
-\r
-       /* Simply read the INSEC length */\r
-       Linsec = cio_read(cio, 2);\r
-\r
-       /* Now we write them to screen */\r
-       opj_event_msg(j2k->cinfo, EVT_INFO,\r
-               "INSEC(%d)\n",\r
-               cio_tell(cio) - 2\r
-               );\r
-\r
-       cio_skip(cio, Linsec - 2);  \r
-}\r
-\r
-\r
-/*@}*/\r
-\r
-/*@}*/\r
-\r
-#endif /* USE_JPSEC */\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, Herve 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.
+ */
+
+#include "opj_includes.h"
+
+#ifdef USE_JPWL
+
+/** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */
+/*@{*/
+
+/** @name Local static variables */
+/*@{*/
+
+/** number of JPWL prepared markers */
+static int jwmarker_num;
+/** properties of JPWL markers to insert */
+static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS]; 
+
+/*@}*/
+
+/*@}*/
+
+/** @name Local static functions */
+/*@{*/
+
+/** create an EPC marker segment
+@param j2k J2K compressor handle
+@param esd_on true if ESD is activated
+@param red_on true if RED is activated
+@param epb_on true if EPB is activated
+@param info_on true if informative techniques are activated
+@return returns the freshly created EPC
+*/
+jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on);
+
+/*@}*/
+
+/** create an EPC marker segment
+@param j2k J2K compressor handle
+@param comps considered component (-1=average, 0/1/2/...=component no.)
+@param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)
+@param ad_size size of addresses (2/4 bytes)
+@param senst sensitivity type
+@param se_size sensitivity values size (1/2 bytes)
+@param tileno tile where this ESD lies (-1 means MH)
+@param svalnum number of sensitivity values (if 0, they will be automatically filled)
+@param sensval pointer to an array of sensitivity values (if NULL, they will be automatically filled)
+@return returns the freshly created ESD
+*/
+jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comps, 
+       unsigned char addrm, unsigned char ad_size,
+       unsigned char senst, int se_size, int tileno,
+       unsigned long int svalnum, void *sensval);
+                       
+/** this function is used to compare two JPWL markers based on
+their relevant wishlist position
+@param arg1 pointer to first marker
+@param arg2 pointer to second marker
+@return 1 if arg1>arg2, 0 if arg1=arg2, -1 if arg1<arg2
+*/
+int jpwl_markcomp(const void *arg1, const void *arg2);
+
+/** write an EPB MS to a buffer
+@param j2k J2K compressor handle
+@param epbmark pointer to the EPB MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf);
+
+/** write an EPC MS to a buffer
+@param j2k J2K compressor handle
+@param epcmark pointer to the EPC MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epcmark, unsigned char *buf);
+
+/** write an ESD MS to a buffer
+@param j2k J2K compressor handle
+@param esdmark pointer to the ESD MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);
+
+/*-----------------------------------------------------------------*/
+
+void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+       int mm;
+
+       /* let's reset some settings */
+
+       /* clear the existing markers */
+       for (mm = 0; mm < jwmarker_num; mm++) {
+
+               switch (jwmarker[mm].id) {
+
+               case J2K_MS_EPB:
+                       opj_free(jwmarker[mm].m.epbmark);
+                       break;
+
+               case J2K_MS_EPC:
+                       opj_free(jwmarker[mm].m.epcmark);
+                       break;
+
+               case J2K_MS_ESD:
+                       opj_free(jwmarker[mm].m.esdmark);
+                       break;
+
+               case J2K_MS_RED:
+                       opj_free(jwmarker[mm].m.redmark);
+                       break;
+
+               default:
+                       break;
+               }
+       }
+
+       /* clear the marker structure array */
+       memset(jwmarker, 0, sizeof(jpwl_marker_t) * JPWL_MAX_NO_MARKERS);
+
+       /* no more markers in the list */
+       jwmarker_num = 0;
+
+       /* let's begin creating a marker list, according to user wishes */
+       jpwl_prepare_marks(j2k, cio, image);
+
+       /* now we dump the JPWL markers on the codestream */
+       jpwl_dump_marks(j2k, cio, image);
+
+       /* do not know exactly what is this for,
+       but it gets called during index creation */
+       j2k->pos_correction = 0;
+
+}
+
+void j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
+
+       if (!cstr_info)
+               return;
+
+       /* expand the list? */
+       if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {
+               cstr_info->maxmarknum += 100;
+               cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum * sizeof(opj_marker_info_t));
+       }
+
+       /* add the marker */
+       cstr_info->marker[cstr_info->marknum].type = type;
+       cstr_info->marker[cstr_info->marknum].pos = pos;
+       cstr_info->marker[cstr_info->marknum].len = len;
+       cstr_info->marknum++;
+
+}
+
+void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+       unsigned short int socsiz_len = 0;
+       int ciopos = cio_tell(cio), soc_pos = j2k->cstr_info->main_head_start;
+       unsigned char *socp = NULL;
+
+       int tileno, acc_tpno, tpno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;
+
+       jpwl_epb_ms_t *epb_mark;
+       jpwl_epc_ms_t *epc_mark;
+       jpwl_esd_ms_t *esd_mark;
+  (void)image;
+
+       /* find (SOC + SIZ) length */
+       /* I assume SIZ is always the first marker after SOC */
+       cio_seek(cio, soc_pos + 4);
+       socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */
+       cio_seek(cio, soc_pos + 0);
+       socp = cio_getbp(cio); /* pointer to SOC */
+
+       /* 
+        EPC MS for Main Header: if we are here it's required
+       */
+       /* create the EPC */
+       if ((epc_mark = jpwl_epc_create(
+                       j2k,
+                       j2k->cp->esd_on, /* is ESD present? */
+                       j2k->cp->red_on, /* is RED present? */
+                       j2k->cp->epb_on, /* is EPB present? */
+                       OPJ_FALSE /* are informative techniques present? */
+               ))) {
+
+               /* Add this marker to the 'insertanda' list */
+               if (epc_mark) {
+                       jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */
+                       jwmarker[jwmarker_num].m.epcmark = epc_mark; /* the EPC */
+                       jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
+                       jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */
+                       jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */
+                       jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+                       jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+                       jwmarker[jwmarker_num].parms_ready = OPJ_FALSE; /* not ready */
+                       jwmarker[jwmarker_num].data_ready = OPJ_TRUE; /* ready */
+                       jwmarker_num++;
+               };
+
+               opj_event_msg(j2k->cinfo, EVT_INFO,
+                       "MH  EPC : setting %s%s%s\n",
+                       j2k->cp->esd_on ? "ESD, " : "",
+                       j2k->cp->red_on ? "RED, " : "",
+                       j2k->cp->epb_on ? "EPB, " : ""
+                       );
+
+       } else {
+               /* ooops, problems */
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");                              
+       };
+
+       /* 
+        ESD MS for Main Header
+       */
+       /* first of all, must MH have an ESD MS? */
+       if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {
+
+               /* Create the ESD */
+               if ((esd_mark = jpwl_esd_create(
+                       j2k, /* this encoder handle */
+                       -1, /* we are averaging over all components */
+                       (unsigned char) j2k->cp->sens_range, /* range method */
+                       (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */
+                       (unsigned char) j2k->cp->sens_MH, /* sensitivity method */
+                       j2k->cp->sens_size, /* sensitivity size */
+                       -1, /* this ESD is in main header */
+                       0 /*j2k->cstr_info->num*/, /* number of packets in codestream */
+                       NULL /*sensval*/ /* pointer to sensitivity data of packets */
+                       ))) {
+                       
+                       /* Add this marker to the 'insertanda' list */
+                       if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+                               jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
+                               jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
+                               jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* we choose to place it after SIZ */
+                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
+                               jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
+                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* not ready, yet */
+                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
+                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+                               jwmarker_num++;
+                       }
+
+                       opj_event_msg(j2k->cinfo, EVT_INFO,
+                               "MH  ESDs: method %d\n",
+                               j2k->cp->sens_MH
+                               );
+
+               } else {
+                       /* ooops, problems */
+                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");                              
+               };
+
+       }
+
+       /* 
+        ESD MSs for Tile Part Headers 
+       */
+       /* cycle through tiles */
+       sens = -1; /* default spec: no ESD */
+       tilespec = 0; /* first tile spec */
+       acc_tpno = 0;
+       for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
+
+               opj_event_msg(j2k->cinfo, EVT_INFO,
+                       "Tile %d has %d tile part(s)\n",
+                       tileno, j2k->cstr_info->tile[tileno].num_tps
+                       );
+
+               /* for every tile part in the tile */
+               for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {
+       
+                       int sot_len, Psot, Psotp, mm;
+                       unsigned long sot_pos, post_sod_pos;
+
+                       unsigned long int left_THmarks_len;
+
+                       /******* sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
+                       sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
+                       cio_seek(cio, sot_pos + 2); 
+                       sot_len = cio_read(cio, 2); /* SOT Len */
+                       cio_skip(cio, 2);
+                       Psotp = cio_tell(cio);
+                       Psot = cio_read(cio, 4); /* tile length */
+
+                       /******* post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
+                       post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
+                       left_THmarks_len = post_sod_pos - sot_pos;
+
+                       /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */
+                       for (mm = 0; mm < jwmarker_num; mm++) {
+                               if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
+                                       if (jwmarker[mm].len_ready)
+                                               left_THmarks_len += jwmarker[mm].len + 2;
+                                       else {
+                                               opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
+                                                       jwmarker[mm].id, jwmarker[mm].dpos);                            
+                                               exit(1);
+                                       }
+                               }
+                       }
+
+                       /******* if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno)) */
+                       if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == acc_tpno))
+                               /* we got a specification from this tile onwards */
+                               sens = j2k->cp->sens_TPH[tilespec++];
+               
+                       /* must this TPH have an ESD MS? */
+                       if (j2k->cp->esd_on && (sens >= 0)) {
+
+                               /* Create the ESD */
+                               if ((esd_mark = jpwl_esd_create(
+                                       j2k, /* this encoder handle */
+                                       -1, /* we are averaging over all components */
+                                       (unsigned char) j2k->cp->sens_range, /* range method */
+                                       (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */
+                                       (unsigned char) sens, /* sensitivity method */
+                                       j2k->cp->sens_size, /* sensitivity value size */
+                                       tileno, /* this ESD is in a tile */
+                                       0, /* number of packets in codestream */
+                                       NULL /* pointer to sensitivity data of packets */
+                                       ))) {
+                                       
+                                       /* Add this marker to the 'insertanda' list */
+                                       if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+                                               jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
+                                               jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
+                                               /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
+                                               jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
+                                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
+                                               jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
+                                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready, yet */
+                                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+                                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
+                                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* ready */
+                                               jwmarker_num++;
+                                       }
+
+                                       /* update Psot of the tile  */
+                                       cio_seek(cio, Psotp);
+                                       cio_write(cio, Psot + esd_mark->Lesd + 2, 4);
+
+                                       opj_event_msg(j2k->cinfo, EVT_INFO,
+                                               /******* "TPH ESDs: tile %02d, method %d\n", */
+                                               "TPH ESDs: tile %02d, part %02d, method %d\n",
+                                               /******* tileno, */
+                                               tileno, tpno,
+                                               sens
+                                               );
+
+                               } else {
+                                       /* ooops, problems */
+                                       /***** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno); */
+                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d,%d\n", tileno, tpno);
+                               };
+
+                       }
+                       
+               }
+       
+       };
+
+       /* 
+        EPB MS for Main Header
+       */
+       /* first of all, must MH have an EPB MS? */
+       if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {
+
+               int mm;
+
+               /* position of SOT */
+               unsigned int sot_pos = j2k->cstr_info->main_head_end + 1;
+
+               /* how much space is there between end of SIZ and beginning of SOT? */
+               int left_MHmarks_len = sot_pos - socsiz_len;
+
+               /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */
+               for (mm = 0; mm < jwmarker_num; mm++) {
+                       if ( jwmarker[mm].pos < sot_pos) { /* jwmarker[mm].pos >=0 since ulong */
+                               if (jwmarker[mm].len_ready)
+                                       left_MHmarks_len += jwmarker[mm].len + 2;
+                               else {
+                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",
+                                               jwmarker[mm].id, jwmarker[mm].dpos);                            
+                                       exit(1);
+                               }
+                       }
+               }
+
+               /* Create the EPB */
+               if ((epb_mark = jpwl_epb_create(
+                       j2k, /* this encoder handle */
+                       OPJ_TRUE, /* is it the latest? */
+                       OPJ_TRUE, /* is it packed? not for now */
+                       -1, /* we are in main header */
+                       0, /* its index is 0 (first) */
+                       j2k->cp->hprot_MH, /* protection type parameters of data */
+                       socsiz_len, /* pre-data: only SOC+SIZ */
+                       left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */
+                       ))) {
+                       
+                       /* 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].m.epbmark = epb_mark; /* the EPB */
+                               jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
+                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
+                               jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
+                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
+                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+                               jwmarker_num++;
+                       }
+
+                       opj_event_msg(j2k->cinfo, EVT_INFO,
+                               "MH  EPB : prot. %d\n",
+                               j2k->cp->hprot_MH
+                               );
+
+               } else {
+                       /* ooops, problems */
+                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");                              
+               };
+       }
+
+       /* 
+        EPB MSs for Tile Parts
+       */
+       /* cycle through TPHs */
+       hprot = j2k->cp->hprot_MH; /* default spec */
+       tilespec = 0; /* first tile spec */
+       lastileno = 0;
+       packspec = 0;
+       pprot = -1;
+       acc_tpno = 0;
+       for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
+
+               opj_event_msg(j2k->cinfo, EVT_INFO,
+                       "Tile %d has %d tile part(s)\n",
+                       tileno, j2k->cstr_info->tile[tileno].num_tps
+                       );
+
+               /* for every tile part in the tile */
+               for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) { 
+               
+                       int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;
+                       unsigned long sot_pos, post_sod_pos;
+                       unsigned long int left_THmarks_len/*, epbs_len = 0*/;
+                       int startpack = 0, stoppack = j2k->cstr_info->packno;
+                       int first_tp_pack, last_tp_pack;
+                       jpwl_epb_ms_t *tph_epb = NULL;
+
+                       /****** sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
+                       sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
+                       cio_seek(cio, sot_pos + 2); 
+                       sot_len = cio_read(cio, 2); /* SOT Len */
+                       cio_skip(cio, 2);
+                       Psotp = cio_tell(cio);
+                       Psot = cio_read(cio, 4); /* tile length */
+
+                       /* a-priori length of the data dwelling between SOT and SOD */
+                       /****** post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
+                       post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
+                       left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);
+
+                       /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */
+                       for (mm = 0; mm < jwmarker_num; mm++) {
+                               if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
+                                       if (jwmarker[mm].len_ready)
+                                               left_THmarks_len += jwmarker[mm].len + 2;
+                                       else {
+                                               opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
+                                                       jwmarker[mm].id, jwmarker[mm].dpos);                            
+                                               exit(1);
+                                       }
+                               }
+                       }
+
+                       /****** if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno)) */
+                       if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == acc_tpno))
+                               /* we got a specification from this tile part onwards */
+                               hprot = j2k->cp->hprot_TPH[tilespec++];
+               
+                       /* must this TPH have an EPB MS? */
+                       if (j2k->cp->epb_on && (hprot > 0)) {
+
+                               /* Create the EPB */
+                               if ((epb_mark = jpwl_epb_create(
+                                       j2k, /* this encoder handle */
+                                       OPJ_FALSE, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */
+                                       OPJ_TRUE, /* is it packed? yes for now */
+                                       tileno, /* we are in TPH */
+                                       epb_index++, /* its index is 0 (first) */
+                                       hprot, /* protection type parameters of following data */
+                                       sot_len + 2, /* pre-data length: only SOT */
+                                       left_THmarks_len /* post-data length: from SOT end to SOD inclusive */
+                                       ))) {
+                                       
+                                       /* 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].m.epbmark = epb_mark; /* the EPB */
+                                               /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
+                                               jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
+                                               jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
+                                               jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
+                                               jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+                                               jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+                                               jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
+                                               jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+                                               jwmarker_num++;
+                                       }
+
+                                       /* update Psot of the tile  */
+                                       Psot += epb_mark->Lepb + 2;
+
+                                       opj_event_msg(j2k->cinfo, EVT_INFO,
+                                               /***** "TPH EPB : tile %02d, prot. %d\n", */
+                                               "TPH EPB : tile %02d, part %02d, prot. %d\n",
+                                               /***** tileno, */
+                                               tileno, tpno,
+                                               hprot
+                                               );
+
+                                       /* save this TPH EPB address */
+                                       tph_epb = epb_mark;
+
+                               } else {
+                                       /* ooops, problems */
+                                       /****** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno); */
+                                       opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB in #%d,d\n", tileno, tpno);
+                               };
+
+                       }                               
+               
+                       startpack = 0;
+                       /* EPB MSs for UEP packet data protection in Tile Parts */
+                       /****** for (packno = 0; packno < j2k->cstr_info->num; packno++) { */
+                       /*first_tp_pack = (tpno > 0) ? (first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno - 1].tp_numpacks) : 0;*/
+                       first_tp_pack = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pack;
+                       last_tp_pack = first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks - 1;
+                       for (packno = 0; packno < j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks; packno++) {
+
+                               /******** if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
+                                       (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) { */
+                               if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
+                                       (j2k->cp->pprot_tileno[packspec] == acc_tpno) && (j2k->cp->pprot_packno[packspec] == packno)) {
+
+                                       /* we got a specification from this tile and packet onwards */
+                                       /* print the previous spec */
+                                       if (packno > 0) {
+                                               stoppack = packno - 1;                          
+                                               opj_event_msg(j2k->cinfo, EVT_INFO,
+                                                       /***** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
+                                                       "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
+                                                       /***** tileno, */
+                                                       tileno, tpno,
+                                                       startpack,
+                                                       stoppack,
+                                                       /***** j2k->cstr_info->tile[tileno].packet[startpack].start_pos, */
+                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
+                                                       /***** j2k->cstr_info->tile[tileno].packet[stoppack].end_pos, */
+                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
+                                                       pprot);
+
+                                               /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
+                                                       j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
+                                               prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
+                                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
+
+                                               /*
+                                                 particular case: if this is the last header and the last packet,
+                                                 then it is better to protect even the EOC marker
+                                               */
+                                               /****** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+                                                       (stoppack == (j2k->cstr_info->num - 1))) */
+                                               if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+                                                       (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
+                                                       (stoppack == last_tp_pack))
+                                                       /* add the EOC len */
+                                                       prot_len += 2;
+
+                                               /* let's add the EPBs */
+                                               Psot += jpwl_epbs_add(
+                                                       j2k, /* J2K handle */
+                                                       jwmarker, /* pointer to JPWL markers list */
+                                                       &jwmarker_num, /* pointer to the number of current markers */
+                                                       OPJ_FALSE, /* latest */
+                                                       OPJ_TRUE, /* packed */
+                                                       OPJ_FALSE, /* inside MH */
+                                                       &epb_index, /* pointer to EPB index */
+                                                       pprot, /* protection type */
+                                                       /****** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, */ /* position */
+                                                       (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
+                                                       tileno, /* number of tile */
+                                                       0, /* length of pre-data */
+                                                       prot_len /*4000*/ /* length of post-data */
+                                                       );
+                                       }
+
+                                       startpack = packno;
+                                       pprot = j2k->cp->pprot[packspec++];
+                               }
+
+                               /*printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);*/
+               
+                       }
+
+                       /* we are at the end: print the remaining spec */
+                       stoppack = packno - 1;
+                       if (pprot >= 0) {
+
+                               opj_event_msg(j2k->cinfo, EVT_INFO,
+                                       /**** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
+                                       "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
+                                       /**** tileno, */
+                                       tileno, tpno,
+                                       startpack,
+                                       stoppack,
+                                       /***** j2k->image_info->tile[tileno].packet[startpack].start_pos,
+                                       j2k->image_info->tile[tileno].packet[stoppack].end_pos, */
+                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
+                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
+                                       pprot);
+
+                               /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
+                                       j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
+                               prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
+                                       j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
+
+                               /*
+                                 particular case: if this is the last header and the last packet,
+                                 then it is better to protect even the EOC marker
+                               */
+                               /***** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+                                       (stoppack == (j2k->cstr_info->num - 1))) */
+                               if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+                                       (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
+                                       (stoppack == last_tp_pack))
+                                       /* add the EOC len */
+                                       prot_len += 2;
+
+                               /* let's add the EPBs */
+                               Psot += jpwl_epbs_add(
+                                                       j2k, /* J2K handle */
+                                                       jwmarker, /* pointer to JPWL markers list */
+                                                       &jwmarker_num, /* pointer to the number of current markers */
+                                                       OPJ_TRUE, /* latest */
+                                                       OPJ_TRUE, /* packed */
+                                                       OPJ_FALSE, /* inside MH */
+                                                       &epb_index, /* pointer to EPB index */
+                                                       pprot, /* protection type */
+                                                       /***** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001,*/ /* position */
+                                                       (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
+                                                       tileno, /* number of tile */
+                                                       0, /* length of pre-data */
+                                                       prot_len /*4000*/ /* length of post-data */
+                                                       );
+                       }
+
+                       /* we can now check if the TPH EPB was really the last one */
+                       if (tph_epb && (epb_index == 1)) {
+                               /* set the TPH EPB to be the last one in current header */
+                               tph_epb->Depb |= (unsigned char) ((OPJ_TRUE & 0x0001) << 6);
+                               tph_epb = NULL;
+                       }
+
+                       /* write back Psot */
+                       cio_seek(cio, Psotp);
+                       cio_write(cio, Psot, 4);
+               
+               }
+
+       };
+
+       /* reset the position */
+       cio_seek(cio, ciopos);
+
+}
+
+void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+       int mm;
+       unsigned long int old_size = j2k->cstr_info->codestream_size;
+       unsigned long int new_size = old_size;
+       int /*ciopos = cio_tell(cio),*/ soc_pos = j2k->cstr_info->main_head_start;
+       unsigned char *jpwl_buf, *orig_buf;
+       unsigned long int orig_pos;
+       double epbcoding_time = 0.0, esdcoding_time = 0.0;
+  (void)image;
+
+       /* Order JPWL markers according to their wishlist position */
+       qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);
+
+       /* compute markers total size */ 
+       for (mm = 0; mm < jwmarker_num; mm++) {
+               /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,
+                       jwmarker[mm].dpos, jwmarker[mm].len);*/
+               new_size += jwmarker[mm].len + 2;
+       }
+
+       /* allocate a new buffer of proper size */
+       if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) (new_size + soc_pos) * sizeof(unsigned char)))) {
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL codestream buffer\n");
+               exit(1);
+       };
+
+       /* copy the jp2 part, if any */
+       orig_buf = jpwl_buf;
+       memcpy(jpwl_buf, cio->buffer, soc_pos);
+       jpwl_buf += soc_pos;
+
+       /* cycle through markers */
+       orig_pos = soc_pos + 0; /* start from the beginning */
+       cio_seek(cio, soc_pos + 0); /* rewind the original */
+       for (mm = 0; mm < jwmarker_num; mm++) {
+
+               /*
+               need to copy a piece of the original codestream
+               if there is such
+               */
+               memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);
+               jpwl_buf += jwmarker[mm].pos - orig_pos;
+               orig_pos = jwmarker[mm].pos;
+               cio_seek(cio, orig_pos);
+
+               /*
+               then write down the marker
+               */
+               switch (jwmarker[mm].id) {
+
+               case J2K_MS_EPB:
+                       jpwl_epb_write(j2k, jwmarker[mm].m.epbmark, jpwl_buf);
+                       break;
+
+               case J2K_MS_EPC:
+                       jpwl_epc_write(j2k, jwmarker[mm].m.epcmark, jpwl_buf);
+                       break;
+
+               case J2K_MS_ESD:
+                       jpwl_esd_write(j2k, jwmarker[mm].m.esdmark, jpwl_buf);
+                       break;
+
+               case J2K_MS_RED:
+                       memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */
+                       break;
+
+               default:
+                       break;
+               };
+
+               /* we update the markers struct */
+               if (j2k->cstr_info)
+                       j2k->cstr_info->marker[j2k->cstr_info->marknum - 1].pos = (jpwl_buf - orig_buf);
+               
+               /* we set the marker dpos to the new position in the JPWL codestream */
+               jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);
+
+               /* advance JPWL buffer position */
+               jpwl_buf += jwmarker[mm].len + 2;
+
+       }
+
+       /* finish remaining original codestream */
+       memcpy(jpwl_buf, cio_getbp(cio), old_size - (orig_pos - soc_pos));
+       jpwl_buf += old_size - (orig_pos - soc_pos);
+       cio_seek(cio, soc_pos + old_size);
+       
+       /*
+       update info file based on added markers
+       */
+       if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))
+               opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ cstr_info structure\n");
+
+       /* now we need to repass some markers and fill their data fields */
+       
+       /* first of all, DL and Pcrc in EPCs */ 
+       for (mm = 0; mm < jwmarker_num; mm++) {
+
+               /* find the EPCs */
+               if (jwmarker[mm].id == J2K_MS_EPC) {
+
+                       int epc_pos = (int) jwmarker[mm].dpos, pp;
+                       unsigned short int mycrc = 0x0000;
+
+                       /* fix and fill the DL field */
+                       jwmarker[mm].m.epcmark->DL = new_size;
+                       orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 24);
+                       orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 16);
+                       orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 8);
+                       orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 0);
+
+                       /* compute the CRC field (excluding itself) */
+                       for (pp = 0; pp < 4; pp++)
+                               jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
+                       for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)
+                               jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
+
+                       /* fix and fill the CRC */
+                       jwmarker[mm].m.epcmark->Pcrc = mycrc;
+                       orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 8);
+                       orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 0);
+
+               }
+       }
+
+       /* then, sensitivity data in ESDs */ 
+       esdcoding_time = opj_clock();
+       for (mm = 0; mm < jwmarker_num; mm++) {
+
+               /* find the ESDs */
+               if (jwmarker[mm].id == J2K_MS_ESD) {
+
+                       /* remember that they are now in a new position (dpos) */
+                       int esd_pos = (int) jwmarker[mm].dpos;
+
+                       jpwl_esd_fill(j2k, jwmarker[mm].m.esdmark, &orig_buf[esd_pos]);
+               
+               }
+
+       }
+       esdcoding_time = opj_clock() - esdcoding_time;
+       if (j2k->cp->esd_on)
+               opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);
+
+       /* finally, RS or CRC parity in EPBs */ 
+       epbcoding_time = opj_clock();
+       for (mm = 0; mm < jwmarker_num; mm++) {
+
+               /* find the EPBs */
+               if (jwmarker[mm].id == J2K_MS_EPB) {
+
+                       /* remember that they are now in a new position (dpos) */
+                       int nn, accum_len;
+
+                       /* let's see how many EPBs are following this one, included itself */
+                       /* for this to work, we suppose that the markers are correctly ordered */
+                       /* and, overall, that they are in packed mode inside headers */
+                       accum_len = 0;
+                       for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
+                               (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
+                               accum_len += jwmarker[nn].m.epbmark->Lepb + 2;
+
+                       /* fill the current (first) EPB with post-data starting from the computed position */
+                       jpwl_epb_fill(j2k, jwmarker[mm].m.epbmark, &orig_buf[(int) jwmarker[mm].dpos],
+                               &orig_buf[(int) jwmarker[mm].dpos + accum_len]);
+               
+                       /* fill the remaining EPBs in the header with post-data starting from the last position */
+                       for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
+                               (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
+                               jpwl_epb_fill(j2k, jwmarker[nn].m.epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);
+
+                       /* skip all the processed EPBs */
+                       mm = nn - 1;
+               }
+
+       }
+       epbcoding_time = opj_clock() - epbcoding_time;
+       if (j2k->cp->epb_on)
+               opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);
+
+       /* free original cio buffer and set it to the JPWL one */
+       opj_free(cio->buffer);
+       cio->cinfo = cio->cinfo; /* no change */
+       cio->openmode = cio->openmode; /* no change */
+       cio->buffer = orig_buf;
+       cio->length = new_size + soc_pos;
+       cio->start = cio->buffer;
+       cio->end = cio->buffer + cio->length;
+       cio->bp = cio->buffer;
+       cio_seek(cio, soc_pos + new_size);
+
+}
+
+
+void j2k_read_epc(opj_j2k_t *j2k) {
+       unsigned long int DL, Lepcp, Pcrcp, l;
+       unsigned short int Lepc, Pcrc = 0x0000;
+       unsigned char Pepc;     
+       opj_cio_t *cio = j2k->cio;
+       const char *ans1;
+
+       /* Simply read the EPC parameters */
+       Lepcp = cio_tell(cio);
+       Lepc = cio_read(cio, 2);
+       Pcrcp = cio_tell(cio);
+       cio_skip(cio, 2); /* Pcrc */
+       DL = cio_read(cio, 4);
+       Pepc = cio_read(cio, 1);
+
+       /* compute Pcrc */
+       cio_seek(cio, Lepcp - 2);
+
+               /* Marker */
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* Length */
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* skip Pcrc */
+               cio_skip(cio, 2);
+
+               /* read all remaining */
+               for (l = 4; l < Lepc; l++)
+                       jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* check Pcrc with the result */
+               cio_seek(cio, Pcrcp);
+               ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";
+
+       /* now we write them to screen */
+       opj_event_msg(j2k->cinfo, EVT_INFO, 
+               "EPC(%u,%d): %s, DL=%d%s %s %s\n",
+               Lepcp - 2,
+               Lepc,
+               ans1,
+               DL, /* data length this EPC is referring to */
+               (Pepc & 0x10) ? ", esd" : "", /* ESD is present */
+               (Pepc & 0x20) ? ", red" : "", /* RED is present */
+               (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */
+
+       cio_seek(cio, Lepcp + Lepc);  
+}
+
+#if 0
+void j2k_write_epc(opj_j2k_t *j2k) {
+
+       unsigned long int DL, Lepcp, Pcrcp, l;
+       unsigned short int Lepc, Pcrc;
+       unsigned char Pepc;     
+
+       opj_cio_t *cio = j2k->cio;
+
+       cio_write(cio, J2K_MS_EPC, 2);  /* EPC */
+       Lepcp = cio_tell(cio);
+       cio_skip(cio, 2);
+
+       /* CRC-16 word of the EPC */
+       Pcrc = 0x0000; /* initialize */
+       Pcrcp = cio_tell(cio);
+       cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/
+
+       /* data length of the EPC protection domain */
+       DL = 0x00000000; /* we leave this set to 0, as if the information is not available */
+       cio_write(cio, DL, 4);   /* DL */
+
+       /* jpwl capabilities */
+       Pepc = 0x00;
+       cio_write(cio, Pepc, 1); /* Pepc */
+
+       /* ID section */
+       /* no ID's, as of now */
+
+       Lepc = (unsigned short) (cio_tell(cio) - Lepcp);
+       cio_seek(cio, Lepcp);
+       cio_write(cio, Lepc, 2); /* Lepc */
+
+       /* compute Pcrc */
+       cio_seek(cio, Lepcp - 2);
+
+               /* Marker */
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* Length */
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+               jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* skip Pcrc */
+               cio_skip(cio, 2);
+
+               /* read all remaining */
+               for (l = 4; l < Lepc; l++)
+                       jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
+
+               /* fill Pcrc with the result */
+               cio_seek(cio, Pcrcp);
+               cio_write(cio, Pcrc, 2);
+
+       cio_seek(cio, Lepcp + Lepc);
+
+       /* marker struct update */
+       j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, Lepcp - 2, Lepc + 2);
+
+}
+#endif
+
+void j2k_read_epb(opj_j2k_t *j2k) {
+       unsigned long int LDPepb, Pepb;
+       unsigned short int Lepb;
+       unsigned char Depb;
+       char str1[25] = "";
+       opj_bool status;
+       static opj_bool first_in_tph = OPJ_TRUE;
+       int type, pre_len, post_len;
+       static unsigned char *redund = NULL;
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* B/W = 45, RGB = 51 */
+       /*           SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */
+       int skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;
+
+       if (j2k->cp->correct) {
+
+               /* go back to EPB marker value */
+               cio_seek(cio, cio_tell(cio) - 2);
+
+               /* we need to understand where we are */
+               if (j2k->state == J2K_STATE_MH) {
+                       /* we are in MH */
+                       type = 0; /* MH */
+                       pre_len = skipnum; /* SOC+SIZ */
+                       post_len = -1; /* auto */
+
+               } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {
+                       /* we are in TPH */
+                       type = 1; /* TPH */
+                       pre_len = 12; /* SOC+SIZ */
+                       first_in_tph = OPJ_FALSE;
+                       post_len = -1; /* auto */
+
+               } else {
+                       /* we are elsewhere */
+                       type = 2; /* other */
+                       pre_len = 0; /* nada */
+                       post_len = -1; /* auto */
+
+               }
+
+               /* call EPB corrector */
+               /*printf("before %x, ", redund);*/
+               status = jpwl_epb_correct(j2k,      /* J2K decompressor handle */
+                                                                 cio->bp,  /* pointer to EPB in codestream buffer */
+                                                                 type,     /* EPB type: MH */
+                                                                 pre_len,  /* length of pre-data */
+                                                                 post_len, /* length of post-data: -1 means auto */
+                                                                 NULL,     /* do everything auto */
+                                                                 &redund
+                                                                );
+               /*printf("after %x\n", redund);*/
+
+               /* Read the (possibly corrected) EPB parameters */
+               cio_skip(cio, 2);
+               Lepb = cio_read(cio, 2);
+               Depb = cio_read(cio, 1);
+               LDPepb = cio_read(cio, 4);
+               Pepb = cio_read(cio, 4);
+
+               if (!status) {
+
+                       opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");
+
+                       /* advance to EPB endpoint */
+                       cio_skip(cio, Lepb + 2);  
+
+                       return;
+               }
+
+               /* last in current header? */
+               if (Depb & 0x40) {
+                       redund = NULL; /* reset the pointer to L4 buffer */
+                       first_in_tph = OPJ_TRUE;
+               }
+
+               /* advance to EPB endpoint */
+               cio_skip(cio, Lepb - 11);  
+
+       } else {
+
+               /* Simply read the EPB parameters */
+               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-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
+               else if (((Pepb & 0xF0000000) >> 28) == 2)
+                       sprintf(str1, "rs(%lu,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 */
+               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 */
+
+               cio_skip(cio, Lepb - 11);  
+       }
+}
+
+void j2k_write_epb(opj_j2k_t *j2k) {
+       unsigned long int LDPepb, Pepb, Lepbp;
+       unsigned short int Lepb;
+       unsigned char Depb;
+
+       opj_cio_t *cio = j2k->cio;
+
+       cio_write(cio, J2K_MS_EPB, 2);  /* EPB */
+       Lepbp = cio_tell(cio);
+       cio_skip(cio, 2);
+
+       /* EPB style */
+       Depb = 0x00; /* test */
+       cio_write(cio, Depb, 1);   /* Depb */
+
+       /* length of the data to be protected by this EPB */
+       LDPepb = 0x00000000; /* test */
+       cio_write(cio, LDPepb, 4);   /* LDPepb */
+
+       /* next error correction tool */
+       Pepb = 0x00000000; /* test */
+       cio_write(cio, Pepb, 4);   /* Pepb */
+
+       /* EPB data */
+       /* no data, as of now */
+
+       Lepb = (unsigned short) (cio_tell(cio) - Lepbp);
+       cio_seek(cio, Lepbp);
+       cio_write(cio, Lepb, 2);                /* Lepb */
+
+       cio_seek(cio, Lepbp + Lepb);
+
+       /* marker struct update */
+       j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, Lepbp - 2, Lepb + 2);
+}
+
+void j2k_read_esd(opj_j2k_t *j2k) {
+       unsigned short int Lesd, Cesd;
+       unsigned char Pesd;
+
+       int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;
+
+       char str1[4][4] = {"p", "br", "pr", "res"};
+       char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* Simply read the ESD parameters */
+       Lesd = cio_read(cio, 2);
+       Cesd = cio_read(cio, cesdsize);
+       Pesd = cio_read(cio, 1);
+
+       /* Now we write them to screen */
+       opj_event_msg(j2k->cinfo, EVT_INFO,
+               "ESD(%d): c%d, %s, %s, %s, %s, %s\n",
+               cio_tell(cio) - (5 + cesdsize),
+               Cesd, /* component number for this ESD */
+               str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */
+               str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */
+               ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",
+               ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",
+               (Pesd & (unsigned char) 0x01) ? "avgc" : "");
+
+       cio_skip(cio, Lesd - (3 + cesdsize));  
+}
+
+void j2k_read_red(opj_j2k_t *j2k) {
+       unsigned short int Lred;
+       unsigned char Pred;
+       char str1[4][4] = {"p", "br", "pr", "res"};
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* Simply read the RED parameters */
+       Lred = cio_read(cio, 2);
+       Pred = cio_read(cio, 1);
+
+       /* Now we write them to screen */
+       opj_event_msg(j2k->cinfo, EVT_INFO,
+               "RED(%d): %s, %dc, %s, %s\n",
+               cio_tell(cio) - 5,
+               str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */
+               (Pred & (unsigned char) 0x38) >> 3, /* corruption level */
+               ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */
+               (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */
+
+       cio_skip(cio, Lred - 3);  
+}
+
+opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {
+
+#ifdef oerhgierhgvhreit4u
+       /*
+          we navigate through the tile and find possible invalid parameters:
+       this saves a lot of crashes!!!!!
+        */
+       int compno, resno, precno, /*layno,*/ bandno, blockno;
+       int numprecincts, numblocks;
+
+       /* this is the selected tile */
+       opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);
+
+       /* will keep the component */
+       opj_tcd_tilecomp_t *comp = NULL;
+
+       /* will keep the resolution */
+       opj_tcd_resolution_t *res;
+
+       /* will keep the subband */
+       opj_tcd_band_t *band; 
+
+       /* will keep the precinct */
+       opj_tcd_precinct_t *prec; 
+
+       /* will keep the codeblock */
+       opj_tcd_cblk_t *block;
+
+       /* check all tile components */
+       for (compno = 0; compno < tile->numcomps; compno++) {
+               comp = &(tile->comps[compno]);
+
+               /* check all component resolutions */
+               for (resno = 0; resno < comp->numresolutions; resno++) {
+                       res = &(comp->resolutions[resno]);
+                       numprecincts = res->pw * res->ph;
+
+                       /* check all the subbands */
+                       for (bandno = 0; bandno < res->numbands; bandno++) {
+                               band = &(res->bands[bandno]);
+
+                               /* check all the precincts */
+                               for (precno = 0; precno < numprecincts; precno++) {
+                                       prec = &(band->precincts[precno]);
+                                       numblocks = prec->ch * prec->cw;
+
+                                       /* check all the codeblocks */
+                                       for (blockno = 0; blockno < numblocks; blockno++) {
+                                               block = &(prec->cblks[blockno]);
+
+                                               /* x-origin is invalid */
+                                               if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {
+                                                       opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+                                                               "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",
+                                                               block->x0, prec->x0, prec->x1);
+                                                       if (!JPWL_ASSUME || JPWL_ASSUME)
+                                                               return OPJ_FALSE;
+                                               };
+                                       }
+                               }                               
+                       }
+               }
+       }
+
+#else
+  (void)j2k;
+  (void)tcd;
+  (void)tileno;
+#endif
+
+       return OPJ_TRUE;
+}
+
+/*@}*/
+
+#endif /* USE_JPWL */
+
+
+#ifdef USE_JPSEC
+
+/** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */
+/*@{*/
+
+
+/** @name Local static functions */
+/*@{*/
+
+void j2k_read_sec(opj_j2k_t *j2k) {
+       unsigned short int Lsec;
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* Simply read the SEC length */
+       Lsec = cio_read(cio, 2);
+
+       /* Now we write them to screen */
+       opj_event_msg(j2k->cinfo, EVT_INFO,
+               "SEC(%d)\n",
+               cio_tell(cio) - 2
+               );
+
+       cio_skip(cio, Lsec - 2);  
+}
+
+void j2k_write_sec(opj_j2k_t *j2k) {
+       unsigned short int Lsec = 24;
+       int i;
+
+       opj_cio_t *cio = j2k->cio;
+
+       cio_write(cio, J2K_MS_SEC, 2);  /* SEC */
+       cio_write(cio, Lsec, 2);
+
+       /* write dummy data */
+       for (i = 0; i < Lsec - 2; i++)
+               cio_write(cio, 0, 1);
+}
+
+void j2k_read_insec(opj_j2k_t *j2k) {
+       unsigned short int Linsec;
+       
+       opj_cio_t *cio = j2k->cio;
+
+       /* Simply read the INSEC length */
+       Linsec = cio_read(cio, 2);
+
+       /* Now we write them to screen */
+       opj_event_msg(j2k->cinfo, EVT_INFO,
+               "INSEC(%d)\n",
+               cio_tell(cio) - 2
+               );
+
+       cio_skip(cio, Linsec - 2);  
+}
+
+
+/*@}*/
+
+/*@}*/
+
+#endif /* USE_JPSEC */
+