-/*\r
- * Copyright (c) 2001-2003, David Janssens\r
- * Copyright (c) 2002-2003, Yannick Verschueren\r
- * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
- * Copyright (c) 2005, Herv� Drolon, FreeImage Team\r
- * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
- * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
- * All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions\r
- * are met:\r
- * 1. Redistributions of source code must retain the above copyright\r
- * notice, this list of conditions and the following disclaimer.\r
- * 2. Redistributions in binary form must reproduce the above copyright\r
- * notice, this list of conditions and the following disclaimer in the\r
- * documentation and/or other materials provided with the distribution.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
- * POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-#ifdef USE_JPWL\r
-\r
-#include "../libopenjpeg/opj_includes.h"\r
-\r
-/** Minimum and maximum values for the double->pfp conversion */\r
-#define MIN_V1 0.0\r
-#define MAX_V1 17293822569102704640.0\r
-#define MIN_V2 0.000030517578125\r
-#define MAX_V2 131040.0\r
-\r
-/** conversion between a double precision floating point\r
-number and the corresponding pseudo-floating point used \r
-to represent sensitivity values\r
-@param V the double precision value\r
-@param bytes the number of bytes of the representation\r
-@return the pseudo-floating point value (cast accordingly)\r
-*/\r
-unsigned short int jpwl_double_to_pfp(double V, int bytes);\r
-\r
-/** conversion between a pseudo-floating point used \r
-to represent sensitivity values and the corresponding\r
-double precision floating point number \r
-@param em the pseudo-floating point value (cast accordingly)\r
-@param bytes the number of bytes of the representation\r
-@return the double precision value\r
-*/\r
-double jpwl_pfp_to_double(unsigned short int em, int bytes);\r
-\r
- /*-------------------------------------------------------------*/\r
-\r
-int jpwl_markcomp(const void *arg1, const void *arg2)\r
-{\r
- /* Compare the two markers' positions */\r
- double diff = (((jpwl_marker_t *) arg1)->dpos - ((jpwl_marker_t *) arg2)->dpos);\r
-\r
- if (diff == 0.0)\r
- return (0);\r
- else if (diff < 0)\r
- return (-1);\r
- else\r
- return (+1);\r
-}\r
-\r
-int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,\r
- bool latest, bool packed, bool insideMH, int *idx, int hprot,\r
- double place_pos, int tileno,\r
- unsigned long int pre_len, unsigned long int post_len) {\r
-\r
- jpwl_epb_ms_t *epb_mark = NULL;\r
-\r
- int k_pre, k_post, n_pre, n_post;\r
- \r
- unsigned long int L1, L2, dL4, max_postlen, epbs_len = 0;\r
-\r
- /* We find RS(n,k) for EPB parms and pre-data, if any */\r
- if (insideMH && (*idx == 0)) {\r
- /* First EPB in MH */ \r
- k_pre = 64;\r
- n_pre = 160;\r
- } else if (!insideMH && (*idx == 0)) {\r
- /* First EPB in TH */\r
- k_pre = 25;\r
- n_pre = 80;\r
- } else {\r
- /* Following EPBs in MH or TH */\r
- k_pre = 13;\r
- n_pre = 40;\r
- };\r
-\r
- /* Find lengths, Figs. B3 and B4 */\r
- /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */\r
- L1 = pre_len + 13;\r
-\r
- /* size of pre-data redundancy */\r
- /* (redundancy per codeword) * (number of codewords, rounded up) */\r
- L2 = (n_pre - k_pre) * (unsigned long int) ceil((double) L1 / (double) k_pre);\r
-\r
- /* Find protection type for post data and its associated redundancy field length*/\r
- if ((hprot == 16) || (hprot == 32)) {\r
- /* there is a CRC for post-data */\r
- k_post = post_len;\r
- n_post = post_len + (hprot >> 3);\r
- /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */\r
-\r
- } else if ((hprot >= 37) && (hprot <= 128)) {\r
- /* there is a RS for post-data */\r
- k_post = 32;\r
- n_post = hprot;\r
-\r
- } else {\r
- /* Use predefined codes */\r
- n_post = n_pre;\r
- k_post = k_pre;\r
- };\r
-\r
- /* Create the EPB(s) */\r
- while (post_len > 0) {\r
-\r
- /* maximum postlen in order to respect EPB size\r
- (we use 65450 instead of 65535 for keeping room for EPB parms)*/\r
- /* (message word size) * (number of containable parity words) */\r
- max_postlen = k_post * (unsigned long int) floor(65450.0 / (double) (n_post - k_post));\r
-\r
- /* maximum postlen in order to respect EPB size */\r
- if (*idx == 0)\r
- /* (we use (65500 - L2) instead of 65535 for keeping room for EPB parms + pre-data) */\r
- /* (message word size) * (number of containable parity words) */\r
- max_postlen = k_post * (unsigned long int) floor((double) (65500 - L2) / (double) (n_post - k_post));\r
-\r
- else\r
- /* (we use 65500 instead of 65535 for keeping room for EPB parms) */\r
- /* (message word size) * (number of containable parity words) */\r
- max_postlen = k_post * (unsigned long int) floor(65500.0 / (double) (n_post - k_post));\r
-\r
- /* length to use */\r
- dL4 = min(max_postlen, post_len);\r
-\r
- if (epb_mark = jpwl_epb_create(\r
- j2k, /* this encoder handle */\r
- latest ? (dL4 < max_postlen) : false, /* is it the latest? */\r
- packed, /* is it packed? */\r
- tileno, /* we are in TPH */\r
- *idx, /* its index */\r
- hprot, /* protection type parameters of following data */\r
- 0, /* pre-data: nothing for now */\r
- dL4 /* post-data: the stub computed previously */\r
- )) {\r
- \r
- /* Add this marker to the 'insertanda' list */\r
- if (*jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
- jwmarker[*jwmarker_num].id = J2K_MS_EPB; /* its type */\r
- jwmarker[*jwmarker_num].epbmark = epb_mark; /* the EPB */\r
- jwmarker[*jwmarker_num].pos = (int) place_pos; /* after SOT */\r
- jwmarker[*jwmarker_num].dpos = place_pos + 0.0000001 * (double)(*idx); /* not very first! */\r
- jwmarker[*jwmarker_num].len = epb_mark->Lepb; /* its length */\r
- jwmarker[*jwmarker_num].len_ready = true; /* ready */\r
- jwmarker[*jwmarker_num].pos_ready = true; /* ready */\r
- jwmarker[*jwmarker_num].parms_ready = true; /* ready */\r
- jwmarker[*jwmarker_num].data_ready = false; /* not ready */\r
- (*jwmarker_num)++;\r
- }\r
-\r
- /* increment epb index */\r
- (*idx)++;\r
-\r
- /* decrease postlen */\r
- post_len -= dL4;\r
-\r
- /* increase the total length of EPBs */\r
- epbs_len += epb_mark->Lepb + 2;\r
-\r
- } else {\r
- /* ooops, problems */\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB for UEP in tile %d\n", tileno); \r
- };\r
- }\r
-\r
- return epbs_len;\r
-}\r
-\r
-\r
-jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, bool latest, bool packed, int tileno, int idx, int hprot,\r
- unsigned long int pre_len, unsigned long int post_len) {\r
-\r
- jpwl_epb_ms_t *epb = NULL;\r
- unsigned short int data_len = 0;\r
- unsigned short int L2, L3;\r
- unsigned long int L1, L4;\r
- unsigned char *predata_in = NULL;\r
-\r
- bool insideMH = (tileno == -1);\r
-\r
- /* Alloc space */\r
- if (!(epb = (jpwl_epb_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epb_ms_t)))) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for one EPB MS\n");\r
- return NULL;\r
- };\r
-\r
- /* We set RS(n,k) for EPB parms and pre-data, if any */\r
- if (insideMH && (idx == 0)) {\r
- /* First EPB in MH */ \r
- epb->k_pre = 64;\r
- epb->n_pre = 160;\r
- } else if (!insideMH && (idx == 0)) {\r
- /* First EPB in TH */\r
- epb->k_pre = 25;\r
- epb->n_pre = 80;\r
- } else {\r
- /* Following EPBs in MH or TH */\r
- epb->k_pre = 13;\r
- epb->n_pre = 40;\r
- };\r
-\r
- /* Find lengths, Figs. B3 and B4 */\r
- /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */\r
- L1 = pre_len + 13;\r
- epb->pre_len = pre_len;\r
-\r
- /* size of pre-data redundancy */\r
- /* (redundancy per codeword) * (number of codewords, rounded up) */\r
- L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);\r
-\r
- /* length of post-data */\r
- L4 = post_len;\r
- epb->post_len = post_len;\r
-\r
- /* Find protection type for post data and its associated redundancy field length*/\r
- if ((hprot == 16) || (hprot == 32)) {\r
- /* there is a CRC for post-data */\r
- epb->Pepb = 0x10000000 | ((unsigned long int) hprot >> 5); /* 0=CRC-16, 1=CRC-32 */\r
- epb->k_post = post_len;\r
- epb->n_post = post_len + (hprot >> 3);\r
- /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */\r
-\r
- } else if ((hprot >= 37) && (hprot <= 128)) {\r
- /* there is a RS for post-data */\r
- epb->Pepb = 0x20000020 | (((unsigned long int) hprot & 0x000000FF) << 8);\r
- epb->k_post = 32;\r
- epb->n_post = hprot;\r
-\r
- } else if (hprot == 1) {\r
- /* Use predefined codes */\r
- epb->Pepb = (unsigned long int) 0x00000000;\r
- epb->n_post = epb->n_pre;\r
- epb->k_post = epb->k_pre;\r
- \r
- } else if (hprot == 0) {\r
- /* Placeholder EPB: only protects its parameters, no protection method */\r
- epb->Pepb = (unsigned long int) 0xFFFFFFFF;\r
- epb->n_post = 1;\r
- epb->k_post = 1;\r
- \r
- } else {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Invalid protection value for EPB h = %d\n", hprot); \r
- return NULL;\r
- }\r
-\r
- epb->hprot = hprot;\r
-\r
- /* (redundancy per codeword) * (number of codewords, rounded up) */\r
- L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);\r
-\r
- /* private fields */\r
- epb->tileno = tileno;\r
-\r
- /* Fill some fields of the EPB */\r
-\r
- /* total length of the EPB MS (less the EPB marker itself): */\r
- /* Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) + pre_redundancy + post-redundancy */\r
- epb->Lepb = 11 + L2 + L3;\r
-\r
- /* EPB style */\r
- epb->Depb = ((packed & 0x0001) << 7) | ((latest & 0x0001) << 6) | (idx & 0x003F);\r
-\r
- /* length of data protected by EPB: */\r
- epb->LDPepb = L1 + L4;\r
-\r
- return epb;\r
-}\r
-\r
-void jpwl_epb_write(jpwl_epb_ms_t *epb, unsigned char *buf) {\r
-\r
- /* Marker */\r
- *(buf++) = (unsigned char) (J2K_MS_EPB >> 8); \r
- *(buf++) = (unsigned char) (J2K_MS_EPB >> 0); \r
-\r
- /* Lepb */\r
- *(buf++) = (unsigned char) (epb->Lepb >> 8); \r
- *(buf++) = (unsigned char) (epb->Lepb >> 0); \r
-\r
- /* Depb */\r
- *(buf++) = (unsigned char) (epb->Depb >> 0); \r
-\r
- /* LDPepb */\r
- *(buf++) = (unsigned char) (epb->LDPepb >> 24); \r
- *(buf++) = (unsigned char) (epb->LDPepb >> 16); \r
- *(buf++) = (unsigned char) (epb->LDPepb >> 8); \r
- *(buf++) = (unsigned char) (epb->LDPepb >> 0); \r
-\r
- /* Pepb */\r
- *(buf++) = (unsigned char) (epb->Pepb >> 24); \r
- *(buf++) = (unsigned char) (epb->Pepb >> 16); \r
- *(buf++) = (unsigned char) (epb->Pepb >> 8); \r
- *(buf++) = (unsigned char) (epb->Pepb >> 0); \r
-\r
- /* Data */\r
- /*memcpy(buf, epb->data, (size_t) epb->Lepb - 11);*/\r
- memset(buf, 0, (size_t) epb->Lepb - 11);\r
-};\r
-\r
-\r
-jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, bool esd_on, bool red_on, bool epb_on, bool info_on) {\r
-\r
- jpwl_epc_ms_t *epc = NULL;\r
-\r
- /* Alloc space */\r
- if (!(epc = (jpwl_epc_ms_t *) malloc((size_t) 1 * sizeof (jpwl_epc_ms_t)))) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for EPC MS\n");\r
- return NULL;\r
- };\r
-\r
- /* Set the EPC parameters */\r
- epc->esd_on = esd_on;\r
- epc->epb_on = epb_on;\r
- epc->red_on = red_on;\r
- epc->info_on = info_on;\r
-\r
- /* Fill the EPC fields with default values */\r
- epc->Lepc = 9;\r
- epc->Pcrc = 0x0000;\r
- epc->DL = 0x00000000;\r
- epc->Pepc = ((j2k->cp->esd_on & 0x0001) << 4) | ((j2k->cp->red_on & 0x0001) << 5) |\r
- ((j2k->cp->epb_on & 0x0001) << 6) | ((j2k->cp->info_on & 0x0001) << 7);\r
-\r
- return (epc);\r
-}\r
-\r
-bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf, unsigned char *post_buf) {\r
-\r
- unsigned long int L1, L2, L3, L4;\r
- int remaining;\r
- unsigned long int P, NN_P;\r
-\r
- /* Operating buffer */\r
- static unsigned char codeword[NN], *parityword;\r
-\r
- unsigned char *L1_buf, *L2_buf;\r
- /* these ones are static, since we need to keep memory of\r
- the exact place from one call to the other */\r
- static unsigned char *L3_buf, *L4_buf;\r
-\r
- /* some consistency check */\r
- if (!buf) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs\n");\r
- return false;\r
- }\r
-\r
- if (!post_buf && !L4_buf) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs data\n");\r
- return false;\r
- }\r
-\r
- /*\r
- * Compute parity bytes on pre-data, ALWAYS present (at least only for EPB parms)\r
- */\r
-\r
- /* Initialize RS structures */\r
- P = epb->n_pre - epb->k_pre;\r
- NN_P = NN - P;\r
- memset(codeword, 0, NN);\r
- parityword = codeword + NN_P;\r
- init_rs(NN_P);\r
-\r
- /* pre-data begins pre_len bytes before of EPB buf */\r
- L1_buf = buf - epb->pre_len;\r
- L1 = epb->pre_len + 13;\r
-\r
- /* redundancy for pre-data begins immediately after EPB parms */\r
- L2_buf = buf + 13;\r
- L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);\r
-\r
- /* post-data\r
- the position of L4 buffer can be:\r
- 1) passed as a parameter: in that case use it\r
- 2) null: in that case use the previous (static) one\r
- */\r
- if (post_buf)\r
- L4_buf = post_buf;\r
- L4 = epb->post_len;\r
-\r
- /* post-data redundancy begins immediately after pre-data redundancy */\r
- L3_buf = L2_buf + L2;\r
- L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);\r
-\r
- /* let's check whether EPB length is sufficient to contain all these data */\r
- if (epb->Lepb < (11 + L2 + L3))\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no room in EPB data field for writing redundancy data\n");\r
- /*printf("Env. %d, nec. %d (%d + %d)\n", epb->Lepb - 11, L2 + L3, L2, L3);*/\r
-\r
- /* Compute redundancy of pre-data message words */\r
- remaining = L1;\r
- while (remaining) {\r
-\r
- /* copy message data into codeword buffer */\r
- if (remaining < epb->k_pre) {\r
- /* the last message word is zero-padded */\r
- memset(codeword, 0, NN);\r
- memcpy(codeword, L1_buf, remaining);\r
- L1_buf += remaining;\r
- remaining = 0;\r
-\r
- } else {\r
- memcpy(codeword, L1_buf, epb->k_pre);\r
- L1_buf += epb->k_pre;\r
- remaining -= epb->k_pre;\r
-\r
- }\r
-\r
- /* Encode the buffer and obtain parity bytes */\r
- if (encode_rs(codeword, parityword))\r
- opj_event_msg(j2k->cinfo, EVT_WARNING,\r
- "Possible encoding error in codeword @ position #%d\n", (L1_buf - buf) / epb->k_pre);\r
-\r
- /* copy parity bytes only in redundancy buffer */\r
- memcpy(L2_buf, parityword, P); \r
-\r
- /* advance parity buffer */\r
- L2_buf += P;\r
- }\r
-\r
- /*\r
- * Compute parity bytes on post-data, may be absent if there are no data\r
- */\r
- /*printf("Hprot is %d (tileno=%d, k_pre=%d, n_pre=%d, k_post=%d, n_post=%d, pre_len=%d, post_len=%d)\n",\r
- epb->hprot, epb->tileno, epb->k_pre, epb->n_pre, epb->k_post, epb->n_post, epb->pre_len,\r
- epb->post_len);*/\r
- if (epb->hprot < 0) {\r
-\r
- /* there should be no EPB */\r
- \r
- } else if (epb->hprot == 0) {\r
-\r
- /* no protection for the data */\r
- /* advance anyway */\r
- L4_buf += epb->post_len;\r
-\r
- } else if (epb->hprot == 16) {\r
-\r
- /* CRC-16 */\r
- unsigned short int mycrc = 0x0000;\r
-\r
- /* compute the CRC field (excluding itself) */\r
- remaining = L4;\r
- while (remaining--)\r
- jpwl_updateCRC16(&mycrc, *(L4_buf++));\r
-\r
- /* write the CRC field */\r
- *(L3_buf++) = (unsigned char) (mycrc >> 8);\r
- *(L3_buf++) = (unsigned char) (mycrc >> 0);\r
-\r
- } else if (epb->hprot == 32) {\r
-\r
- /* CRC-32 */\r
- unsigned long int mycrc = 0x00000000;\r
-\r
- /* compute the CRC field (excluding itself) */\r
- remaining = L4;\r
- while (remaining--)\r
- jpwl_updateCRC32(&mycrc, *(L4_buf++));\r
-\r
- /* write the CRC field */\r
- *(L3_buf++) = (unsigned char) (mycrc >> 24);\r
- *(L3_buf++) = (unsigned char) (mycrc >> 16);\r
- *(L3_buf++) = (unsigned char) (mycrc >> 8);\r
- *(L3_buf++) = (unsigned char) (mycrc >> 0);\r
-\r
- } else {\r
-\r
- /* RS */\r
-\r
- /* Initialize RS structures */\r
- P = epb->n_post - epb->k_post;\r
- NN_P = NN - P;\r
- memset(codeword, 0, NN);\r
- parityword = codeword + NN_P;\r
- init_rs(NN_P);\r
-\r
- /* Compute redundancy of post-data message words */\r
- remaining = L4;\r
- while (remaining) {\r
-\r
- /* copy message data into codeword buffer */\r
- if (remaining < epb->k_post) {\r
- /* the last message word is zero-padded */\r
- memset(codeword, 0, NN);\r
- memcpy(codeword, L4_buf, remaining);\r
- L4_buf += remaining;\r
- remaining = 0;\r
-\r
- } else {\r
- memcpy(codeword, L4_buf, epb->k_post);\r
- L4_buf += epb->k_post;\r
- remaining -= epb->k_post;\r
-\r
- }\r
-\r
- /* Encode the buffer and obtain parity bytes */\r
- if (encode_rs(codeword, parityword))\r
- opj_event_msg(j2k->cinfo, EVT_WARNING,\r
- "Possible encoding error in codeword @ position #%d\n", (L4_buf - buf) / epb->k_post);\r
-\r
- /* copy parity bytes only in redundancy buffer */\r
- memcpy(L3_buf, parityword, P); \r
-\r
- /* advance parity buffer */\r
- L3_buf += P;\r
- }\r
-\r
- }\r
-\r
- return true;\r
-}\r
-\r
-\r
-bool jpwl_correct(opj_j2k_t *j2k) {\r
-\r
- opj_cio_t *cio = j2k->cio;\r
- bool status;\r
- static bool mh_done = false;\r
- int mark_pos, id, len, skips, sot_pos;\r
- unsigned long int Psot = 0;\r
-\r
- /* go back to marker position */\r
- mark_pos = cio_tell(cio) - 2;\r
- cio_seek(cio, mark_pos);\r
-\r
- if ((j2k->state == J2K_STATE_MHSOC) && !mh_done) {\r
-\r
- int mark_val = 0, skipnum = 0;\r
-\r
- /*\r
- COLOR IMAGE\r
- first thing to do, if we are here, is to look whether\r
- 51 (skipnum) positions ahead there is an EPB, in case of MH\r
- */\r
- /*\r
- B/W IMAGE\r
- first thing to do, if we are here, is to look whether\r
- 45 (skipnum) positions ahead there is an EPB, in case of MH\r
- */\r
- /* SIZ SIZ_FIELDS SIZ_COMPS FOLLOWING_MARKER */\r
- skipnum = 2 + 38 + 3 * j2k->cp->exp_comps + 2;\r
- if ((cio->bp + skipnum) < cio->end) {\r
-\r
- cio_skip(cio, skipnum);\r
-\r
- /* check that you are not going beyond the end of codestream */\r
-\r
- /* call EPB corrector */\r
- status = jpwl_epb_correct(j2k, /* J2K decompressor handle */\r
- cio->bp, /* pointer to EPB in codestream buffer */\r
- 0, /* EPB type: MH */\r
- skipnum, /* length of pre-data */\r
- -1, /* length of post-data: -1 means auto */\r
- NULL,\r
- NULL\r
- );\r
-\r
- /* read the marker value */\r
- mark_val = (*(cio->bp) << 8) | *(cio->bp + 1);\r
-\r
- if (status && (mark_val == J2K_MS_EPB)) {\r
- /* we found it! */\r
- mh_done = true;\r
- return true;\r
- }\r
-\r
- }\r
-\r
- }\r
-\r
- if (true /*(j2k->state == J2K_STATE_TPHSOT) || (j2k->state == J2K_STATE_TPH)*/) {\r
- /* else, look if 12 positions ahead there is an EPB, in case of TPH */\r
- cio_seek(cio, mark_pos);\r
- if ((cio->bp + 12) < cio->end) {\r
-\r
- cio_skip(cio, 12);\r
-\r
- /* call EPB corrector */\r
- status = jpwl_epb_correct(j2k, /* J2K decompressor handle */\r
- cio->bp, /* pointer to EPB in codestream buffer */\r
- 1, /* EPB type: TPH */\r
- 12, /* length of pre-data */\r
- -1, /* length of post-data: -1 means auto */\r
- NULL,\r
- NULL\r
- );\r
- if (status)\r
- /* we found it! */\r
- return true;\r
- }\r
- }\r
-\r
- return false;\r
-\r
- /* for now, don't use this code */\r
-\r
- /* else, look if here is an EPB, in case of other */\r
- if (mark_pos > 64) {\r
- /* it cannot stay before the first MH EPB */\r
- cio_seek(cio, mark_pos);\r
- cio_skip(cio, 0);\r
-\r
- /* call EPB corrector */\r
- status = jpwl_epb_correct(j2k, /* J2K decompressor handle */\r
- cio->bp, /* pointer to EPB in codestream buffer */\r
- 2, /* EPB type: TPH */\r
- 0, /* length of pre-data */\r
- -1, /* length of post-data: -1 means auto */\r
- NULL,\r
- NULL\r
- );\r
- if (status)\r
- /* we found it! */\r
- return true;\r
- }\r
-\r
- /* nope, no EPBs probably, or they are so damaged that we can give up */\r
- return false;\r
- \r
- return true;\r
-\r
- /* AN ATTEMPT OF PARSER */\r
- /* NOT USED ACTUALLY */\r
-\r
- /* go to the beginning of the file */\r
- cio_seek(cio, 0);\r
-\r
- /* let's begin */\r
- j2k->state = J2K_STATE_MHSOC;\r
-\r
- /* cycle all over the markers */\r
- while (cio_tell(cio) < cio->length) {\r
-\r
- /* read the marker */\r
- mark_pos = cio_tell(cio);\r
- id = cio_read(cio, 2);\r
-\r
- /* details */\r
- printf("Marker@%d: %X\n", cio_tell(cio) - 2, id);\r
-\r
- /* do an action in response to the read marker */\r
- switch (id) {\r
-\r
- /* short markers */\r
-\r
- /* SOC */\r
- case J2K_MS_SOC:\r
- j2k->state = J2K_STATE_MHSIZ;\r
- len = 0;\r
- skips = 0;\r
- break;\r
-\r
- /* EOC */\r
- case J2K_MS_EOC:\r
- j2k->state = J2K_STATE_MT;\r
- len = 0;\r
- skips = 0;\r
- break;\r
-\r
- /* particular case of SOD */\r
- case J2K_MS_SOD:\r
- len = Psot - (mark_pos - sot_pos) - 2;\r
- skips = len;\r
- break;\r
-\r
- /* long markers */\r
-\r
- /* SOT */\r
- case J2K_MS_SOT:\r
- j2k->state = J2K_STATE_TPH;\r
- sot_pos = mark_pos; /* position of SOT */\r
- len = cio_read(cio, 2); /* read the length field */\r
- cio_skip(cio, 2); /* this field is unnecessary */\r
- Psot = cio_read(cio, 4); /* tile length */\r
- skips = len - 8;\r
- break;\r
-\r
- /* remaining */\r
- case J2K_MS_SIZ:\r
- j2k->state = J2K_STATE_MH;\r
- /* read the length field */\r
- len = cio_read(cio, 2);\r
- skips = len - 2;\r
- break;\r
-\r
- /* remaining */\r
- default:\r
- /* read the length field */\r
- len = cio_read(cio, 2);\r
- skips = len - 2;\r
- break;\r
-\r
- }\r
-\r
- /* skip to marker's end */\r
- cio_skip(cio, skips); \r
-\r
- }\r
-\r
-\r
-}\r
-\r
-bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,\r
- unsigned char **L4_bufp) {\r
-\r
- /* Operating buffer */\r
- unsigned char codeword[NN], *parityword;\r
-\r
- unsigned long int P, NN_P;\r
- unsigned long int L1, L4;\r
- int remaining, n_pre, k_pre, n_post, k_post;\r
-\r
- int status, tt;\r
-\r
- int orig_pos = cio_tell(j2k->cio);\r
-\r
- unsigned char *L1_buf, *L2_buf;\r
- unsigned char *L3_buf, *L4_buf;\r
-\r
- unsigned long int LDPepb, Pepb;\r
- unsigned short int Lepb;\r
- unsigned char Depb;\r
- char str1[25] = "";\r
- int myconn, errnum = 0;\r
- bool errflag = false;\r
- \r
- opj_cio_t *cio = j2k->cio;\r
-\r
- /* check for common errors */\r
- if (!buffer) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "The EPB pointer is a NULL buffer\n");\r
- return false;\r
- }\r
- \r
- /* set bignesses */\r
- L1 = pre_len + 13;\r
-\r
- /* pre-data correction */\r
- switch (type) {\r
-\r
- case 0:\r
- /* MH EPB */\r
- k_pre = 64;\r
- n_pre = 160;\r
- break;\r
-\r
- case 1:\r
- /* TPH EPB */\r
- k_pre = 25;\r
- n_pre = 80;\r
- break;\r
-\r
- case 2:\r
- /* other EPBs */\r
- k_pre = 13;\r
- n_pre = 40;\r
- break;\r
-\r
- case 3:\r
- /* automatic setup */\r
- break;\r
-\r
- default:\r
- /* unknown type */\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Unknown expected EPB type\n");\r
- return false;\r
- break;\r
-\r
- }\r
-\r
- /* Initialize RS structures */\r
- P = n_pre - k_pre;\r
- NN_P = NN - P;\r
- tt = (int) floor((float) P / 2.0F);\r
- memset(codeword, 0, NN);\r
- parityword = codeword + NN_P;\r
- init_rs(NN_P);\r
-\r
- /* Correct pre-data message words */\r
- L1_buf = buffer - pre_len;\r
- L2_buf = buffer + 13;\r
- remaining = L1;\r
- while (remaining) {\r
- \r
- /* always zero-pad codewords */\r
- /* (this is required, since after decoding the zeros in the long codeword\r
- could change, and keep unchanged in subsequent calls) */\r
- memset(codeword, 0, NN);\r
-\r
- /* copy codeword buffer into message bytes */\r
- if (remaining < k_pre)\r
- memcpy(codeword, L1_buf, remaining);\r
- else\r
- memcpy(codeword, L1_buf, k_pre);\r
-\r
- /* copy redundancy buffer in parity bytes */\r
- memcpy(parityword, L2_buf, P); \r
-\r
- /* Decode the buffer and possibly obtain corrected bytes */\r
- status = eras_dec_rs(codeword, NULL, 0);\r
- if (status == -1) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING,\r
- "Possible decoding error in codeword @ position #%d\n", (L1_buf - buffer) / k_pre);*/\r
- errflag = true;\r
- /* we can try to safely get out from the function:\r
- if we are here, either this is not an EPB or the first codeword\r
- is too damaged to be helpful */\r
- /*return false;*/\r
-\r
- } else if (status == 0) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/\r
-\r
- } else if (status < tt) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/\r
- errnum += status;\r
-\r
- } else {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");\r
- return false;*/\r
- errflag = true;\r
- }\r
-\r
-\r
- /* advance parity buffer */\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected parity only if all is OK */\r
- memcpy(L2_buf, parityword, P);\r
- L2_buf += P;\r
-\r
- /* advance message buffer */\r
- if (remaining < k_pre) {\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected data only if all is OK */\r
- memcpy(L1_buf, codeword, remaining);\r
- L1_buf += remaining;\r
- remaining = 0;\r
-\r
- } else {\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected data only if all is OK */\r
- memcpy(L1_buf, codeword, k_pre);\r
- L1_buf += k_pre;\r
- remaining -= k_pre;\r
-\r
- }\r
- }\r
-\r
- /* print summary */\r
- if (!conn) {\r
-\r
- /*if (errnum)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "+ %d symbol errors corrected (Ps=%.1e)\n", errnum,\r
- (float) errnum / ((float) n_pre * (float) L1 / (float) k_pre));*/\r
- if (errflag) {\r
- /*opj_event_msg(j2k->cinfo, EVT_INFO, "+ there were unrecoverable errors\n");*/\r
- return false;\r
- }\r
-\r
- }\r
-\r
- /* presumably, now, EPB parameters are correct */\r
- /* let's get them */\r
-\r
- /* Simply read the EPB parameters */\r
- if (conn)\r
- cio->bp = buffer;\r
- cio_skip(cio, 2); /* the marker */\r
- Lepb = cio_read(cio, 2);\r
- Depb = cio_read(cio, 1);\r
- LDPepb = cio_read(cio, 4);\r
- Pepb = cio_read(cio, 4);\r
-\r
- /* What does Pepb tells us about the protection method? */\r
- if (((Pepb & 0xF0000000) >> 28) == 0)\r
- sprintf(str1, "pred"); /* predefined */\r
- else if (((Pepb & 0xF0000000) >> 28) == 1)\r
- sprintf(str1, "crc-%d", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */\r
- else if (((Pepb & 0xF0000000) >> 28) == 2)\r
- sprintf(str1, "rs(%d,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */\r
- else if (Pepb == 0xFFFFFFFF)\r
- sprintf(str1, "nometh"); /* RS mode */\r
- else\r
- sprintf(str1, "unknown"); /* unknown */\r
-\r
- /* Now we write them to screen */\r
- if (!conn && post_len)\r
- opj_event_msg(j2k->cinfo, EVT_INFO,\r
- "EPB(%d): (%sl, %sp, %u), %lu, %s\n",\r
- cio_tell(cio) - 13,\r
- (Depb & 0x40) ? "" : "n", /* latest EPB or not? */\r
- (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */\r
- (Depb & 0x3F), /* EPB index value */\r
- LDPepb, /*length of the data protected by the EPB */\r
- str1); /* protection method */\r
-\r
-\r
- /* well, we need to investigate how long is the connected length of packed EPBs */\r
- myconn = Lepb + 2;\r
- if ((Depb & 0x40) == 0) /* not latest in header */\r
- jpwl_epb_correct(j2k, /* J2K decompressor handle */\r
- buffer + Lepb + 2, /* pointer to next EPB in codestream buffer */\r
- 2, /* EPB type: should be of other type */\r
- 0, /* only EPB fields */\r
- 0, /* do not look after */\r
- &myconn,\r
- NULL\r
- );\r
- if (conn)\r
- *conn += myconn;\r
-\r
- /*if (!conn)\r
- printf("connected = %d\n", myconn);*/\r
-\r
- /*cio_seek(j2k->cio, orig_pos);\r
- return true;*/\r
-\r
- /* post-data\r
- the position of L4 buffer is at the end of currently connected EPBs\r
- */\r
- if (!(L4_bufp))\r
- L4_buf = buffer + myconn;\r
- else if (!(*L4_bufp))\r
- L4_buf = buffer + myconn;\r
- else\r
- L4_buf = *L4_bufp;\r
- if (post_len == -1) \r
- L4 = LDPepb - pre_len - 13;\r
- else if (post_len == 0)\r
- L4 = 0;\r
- else\r
- L4 = post_len;\r
-\r
- L3_buf = L2_buf;\r
-\r
- /* Do a further check here on the read parameters */\r
- if (L4 > (unsigned long) cio_numbytesleft(j2k->cio))\r
- /* overflow */\r
- return false;\r
-\r
- /* we are ready for decoding the remaining data */\r
- if (((Pepb & 0xF0000000) >> 28) == 1) {\r
- /* CRC here */\r
- if ((16 * ((Pepb & 0x00000001) + 1)) == 16) {\r
-\r
- /* CRC-16 */\r
- unsigned short int mycrc = 0x0000, filecrc = 0x0000;\r
-\r
- /* compute the CRC field */\r
- remaining = L4;\r
- while (remaining--)\r
- jpwl_updateCRC16(&mycrc, *(L4_buf++));\r
-\r
- /* read the CRC field */\r
- filecrc = *(L3_buf++) << 8;\r
- filecrc |= *(L3_buf++);\r
-\r
- /* check the CRC field */\r
- if (mycrc == filecrc) {\r
- if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");\r
- } else {\r
- if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);\r
- errflag = true;\r
- } \r
- }\r
-\r
- if ((16 * ((Pepb & 0x00000001) + 1)) == 32) {\r
-\r
- /* CRC-32 */\r
- unsigned long int mycrc = 0x00000000, filecrc = 0x00000000;\r
-\r
- /* compute the CRC field */\r
- remaining = L4;\r
- while (remaining--)\r
- jpwl_updateCRC32(&mycrc, *(L4_buf++));\r
-\r
- /* read the CRC field */\r
- filecrc = *(L3_buf++) << 24;\r
- filecrc |= *(L3_buf++) << 16;\r
- filecrc |= *(L3_buf++) << 8;\r
- filecrc |= *(L3_buf++);\r
-\r
- /* check the CRC field */\r
- if (mycrc == filecrc) {\r
- if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");\r
- } else {\r
- if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);\r
- errflag = true;\r
- }\r
- }\r
-\r
- } else if ((((Pepb & 0xF0000000) >> 28) == 2) || (((Pepb & 0xF0000000) >> 28) == 0)) {\r
- /* RS coding here */\r
-\r
- if (((Pepb & 0xF0000000) >> 28) == 0) {\r
-\r
- k_post = k_pre;\r
- n_post = n_pre;\r
-\r
- } else {\r
-\r
- k_post = 32;\r
- n_post = (Pepb & 0x0000FF00) >> 8;\r
- }\r
-\r
- /* Initialize RS structures */\r
- P = n_post - k_post;\r
- NN_P = NN - P;\r
- tt = (int) floor((float) P / 2.0F);\r
- memset(codeword, 0, NN);\r
- parityword = codeword + NN_P;\r
- init_rs(NN_P);\r
-\r
- /* Correct post-data message words */\r
- /*L4_buf = buffer + Lepb + 2;*/\r
- L3_buf = L2_buf;\r
- remaining = L4;\r
- while (remaining) {\r
- \r
- /* always zero-pad codewords */\r
- /* (this is required, since after decoding the zeros in the long codeword\r
- could change, and keep unchanged in subsequent calls) */\r
- memset(codeword, 0, NN);\r
-\r
- /* copy codeword buffer into message bytes */\r
- if (remaining < k_post)\r
- memcpy(codeword, L4_buf, remaining);\r
- else\r
- memcpy(codeword, L4_buf, k_post);\r
-\r
- /* copy redundancy buffer in parity bytes */\r
- memcpy(parityword, L3_buf, P); \r
-\r
- /* Decode the buffer and possibly obtain corrected bytes */\r
- status = eras_dec_rs(codeword, NULL, 0);\r
- if (status == -1) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING,\r
- "Possible decoding error in codeword @ position #%d\n", (L4_buf - (buffer + Lepb + 2)) / k_post);*/\r
- errflag = true;\r
-\r
- } else if (status == 0) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/\r
-\r
- } else if (status < tt) {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/\r
- errnum += status;\r
-\r
- } else {\r
- /*if (conn == NULL)\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");\r
- return false;*/\r
- errflag = true;\r
- }\r
-\r
-\r
- /* advance parity buffer */\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected data only if all is OK */\r
- memcpy(L3_buf, parityword, P);\r
- L3_buf += P;\r
-\r
- /* advance message buffer */\r
- if (remaining < k_post) {\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected data only if all is OK */\r
- memcpy(L4_buf, codeword, remaining);\r
- L4_buf += remaining;\r
- remaining = 0;\r
-\r
- } else {\r
- if ((status >= 0) && (status < tt))\r
- /* copy back corrected data only if all is OK */\r
- memcpy(L4_buf, codeword, k_post);\r
- L4_buf += k_post;\r
- remaining -= k_post;\r
-\r
- }\r
- }\r
- }\r
-\r
- /* give back the L4_buf address */\r
- if (L4_bufp)\r
- *L4_bufp = L4_buf;\r
-\r
- /* print summary */\r
- if (!conn) {\r
-\r
- if (errnum)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "- %d symbol errors corrected (Ps=%.1e)\n", errnum,\r
- (float) errnum / (float) LDPepb);\r
- if (errflag)\r
- opj_event_msg(j2k->cinfo, EVT_INFO, "- there were unrecoverable errors\n");\r
-\r
- }\r
-\r
- cio_seek(j2k->cio, orig_pos);\r
-\r
- return true;\r
-}\r
-\r
-void jpwl_epc_write(jpwl_epc_ms_t *epc, unsigned char *buf) {\r
-\r
- /* Marker */\r
- *(buf++) = (unsigned char) (J2K_MS_EPC >> 8); \r
- *(buf++) = (unsigned char) (J2K_MS_EPC >> 0); \r
-\r
- /* Lepc */\r
- *(buf++) = (unsigned char) (epc->Lepc >> 8); \r
- *(buf++) = (unsigned char) (epc->Lepc >> 0); \r
-\r
- /* Pcrc */\r
- *(buf++) = (unsigned char) (epc->Pcrc >> 8); \r
- *(buf++) = (unsigned char) (epc->Pcrc >> 0);\r
-\r
- /* DL */\r
- *(buf++) = (unsigned char) (epc->DL >> 24); \r
- *(buf++) = (unsigned char) (epc->DL >> 16); \r
- *(buf++) = (unsigned char) (epc->DL >> 8); \r
- *(buf++) = (unsigned char) (epc->DL >> 0); \r
-\r
- /* Pepc */\r
- *(buf++) = (unsigned char) (epc->Pepc >> 0); \r
-\r
- /* Data */\r
- /*memcpy(buf, epc->data, (size_t) epc->Lepc - 9);*/\r
- memset(buf, 0, (size_t) epc->Lepc - 9);\r
-};\r
-\r
-int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,\r
- int comps, unsigned char addrm, unsigned char ad_size,\r
- unsigned char senst, unsigned char se_size,\r
- double place_pos, int tileno) {\r
-\r
- return 0;\r
-}\r
-\r
-jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comp, unsigned char addrm, unsigned char ad_size,\r
- unsigned char senst, unsigned char se_size, int tileno,\r
- unsigned long int svalnum, void *sensval) {\r
-\r
- jpwl_esd_ms_t *esd = NULL;\r
-\r
- /* Alloc space */\r
- if (!(esd = (jpwl_esd_ms_t *) malloc((size_t) 1 * sizeof (jpwl_esd_ms_t)))) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for ESD MS\n");\r
- return NULL;\r
- };\r
-\r
- /* if relative sensitivity, activate byte range mode */\r
- if (senst == 0)\r
- addrm = 1;\r
-\r
- /* size of sensval's ... */\r
- if ((ad_size != 0) && (ad_size != 2) && (ad_size != 4)) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Address size %d for ESD MS is forbidden\n", ad_size);\r
- return NULL;\r
- }\r
- if ((se_size != 1) && (se_size != 2)) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Sensitivity size %d for ESD MS is forbidden\n", se_size);\r
- return NULL;\r
- }\r
- \r
- /* ... depends on the addressing mode */\r
- switch (addrm) {\r
-\r
- /* packet mode */\r
- case (0):\r
- ad_size = 0; /* as per the standard */\r
- esd->sensval_size = se_size; \r
- break;\r
-\r
- /* byte range */\r
- case (1):\r
- /* auto sense address size */\r
- if (ad_size == 0)\r
- /* if there are more than 66% of (2^16 - 1) bytes, switch to 4 bytes\r
- (we keep space for possible EPBs being inserted) */\r
- ad_size = (j2k->image_info->codestream_size > (1 * 65535 / 3)) ? 4 : 2;\r
- esd->sensval_size = ad_size + ad_size + se_size; \r
- break;\r
-\r
- /* packet range */\r
- case (2):\r
- /* auto sense address size */\r
- if (ad_size == 0)\r
- /* if there are more than 2^16 - 1 packets, switch to 4 bytes */\r
- ad_size = (j2k->image_info->num > 65535) ? 4 : 2;\r
- esd->sensval_size = ad_size + ad_size + se_size; \r
- break;\r
-\r
- case (3):\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is unimplemented\n", addrm);\r
- return NULL;\r
-\r
- default:\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is forbidden\n", addrm);\r
- return NULL;\r
- }\r
-\r
- /* set or unset sensitivity values */\r
- if (svalnum <= 0) {\r
-\r
- switch (senst) {\r
-\r
- /* just based on the portions of a codestream */\r
- case (0):\r
- /* MH + no. of THs + no. of packets */\r
- svalnum = 1 + (j2k->image_info->tw * j2k->image_info->th) * (1 + j2k->image_info->num);\r
- break;\r
-\r
- /* all the ones that are based on the packets */\r
- default:\r
- if (tileno < 0)\r
- /* MH: all the packets and all the tiles info is written */\r
- svalnum = j2k->image_info->tw * j2k->image_info->th * j2k->image_info->num;\r
- else\r
- /* TPH: only that tile info is written */\r
- svalnum = j2k->image_info->num;\r
- break;\r
-\r
- }\r
- } \r
-\r
- /* fill private fields */\r
- esd->senst = senst;\r
- esd->ad_size = ad_size;\r
- esd->se_size = se_size;\r
- esd->addrm = addrm;\r
- esd->svalnum = svalnum;\r
- esd->numcomps = j2k->image->numcomps;\r
- esd->tileno = tileno;\r
- \r
- /* Set the ESD parameters */\r
- /* length, excluding data field */\r
- if (esd->numcomps < 257)\r
- esd->Lesd = 4 + (unsigned short int) (esd->svalnum * esd->sensval_size);\r
- else\r
- esd->Lesd = 5 + (unsigned short int) (esd->svalnum * esd->sensval_size);\r
-\r
- /* component data field */\r
- if (comp >= 0)\r
- esd->Cesd = comp;\r
- else\r
- /* we are averaging */\r
- esd->Cesd = 0;\r
-\r
- /* Pesd field */\r
- esd->Pesd = 0x00;\r
- esd->Pesd |= (esd->addrm & 0x03) << 6; /* addressing mode */\r
- esd->Pesd |= (esd->senst & 0x07) << 3; /* sensitivity type */\r
- esd->Pesd |= ((esd->se_size >> 1) & 0x01) << 2; /* sensitivity size */\r
- esd->Pesd |= ((esd->ad_size >> 2) & 0x01) << 1; /* addressing size */\r
- esd->Pesd |= (comp < 0) ? 0x01 : 0x00; /* averaging components */\r
-\r
- /* if pointer to sensval is NULL, we can fill data field by ourselves */\r
- if (!sensval) {\r
-\r
- /* old code moved to jpwl_esd_fill() */\r
- esd->data = NULL;\r
-\r
- } else {\r
- /* we set the data field as the sensitivity values poinnter passed to the function */\r
- esd->data = (unsigned char *) sensval;\r
- }\r
-\r
- return (esd);\r
-}\r
-\r
-bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {\r
-\r
- int i;\r
- unsigned long int vv;\r
- unsigned long int addr1, addr2;\r
- double dvalue, Omax2, tmp, TSE, MSE, oldMSE, PSNR, oldPSNR;\r
- unsigned short int pfpvalue;\r
- unsigned long int addrmask = 0x00000000;\r
- bool doneMH = false, doneTPH = false;\r
-\r
- /* sensitivity values in image info are as follows:\r
- - for each tile, distotile is the starting distortion for that tile, sum of all components\r
- - for each packet in a tile, disto is the distortion reduction caused by that packet to that tile\r
- - the TSE for a single tile should be given by distotile - sum(disto) , for all components\r
- - the MSE for a single tile is given by TSE / nbpix , for all components\r
- - the PSNR for a single tile is given by 10*log10( Omax^2 / MSE) , for all components\r
- (Omax is given by 2^bpp - 1 for unsigned images and by 2^(bpp - 1) - 1 for signed images\r
- */\r
-\r
- /* browse all components and find Omax */\r
- Omax2 = 0.0;\r
- for (i = 0; i < j2k->image->numcomps; i++) {\r
- tmp = pow(2.0, (double) (j2k->image->comps[i].sgnd ?\r
- (j2k->image->comps[i].bpp - 1) : (j2k->image->comps[i].bpp))) - 1;\r
- if (tmp > Omax2)\r
- Omax2 = tmp;\r
- }\r
- Omax2 = Omax2 * Omax2;\r
-\r
- /* if pointer of esd->data is not null, simply write down all the values byte by byte */\r
- if (esd->data) {\r
- for (i = 0; i < (int) esd->svalnum; i++)\r
- *(buf++) = esd->data[i]; \r
- return true;\r
- }\r
-\r
- /* addressing mask */\r
- if (esd->ad_size == 2)\r
- addrmask = 0x0000FFFF; /* two bytes */\r
- else\r
- addrmask = 0xFFFFFFFF; /* four bytes */\r
-\r
- /* set on precise point where sensitivity starts */\r
- if (esd->numcomps < 257)\r
- buf += 6;\r
- else\r
- buf += 7;\r
-\r
- /* let's fill the data fields */\r
- for (vv = (esd->tileno < 0) ? 0 : (j2k->image_info->num * esd->tileno); vv < esd->svalnum; vv++) {\r
-\r
- int thistile = vv / j2k->image_info->num, thispacket = vv % j2k->image_info->num;\r
-\r
- /* skip for the hack some lines below */\r
- if (thistile == j2k->image_info->tw * j2k->image_info->th)\r
- break;\r
-\r
- /* starting tile distortion */\r
- if (thispacket == 0) {\r
- TSE = j2k->image_info->tile[thistile].distotile;\r
- oldMSE = TSE / j2k->image_info->tile[thistile].nbpix;\r
- oldPSNR = 10.0 * log10(Omax2 / oldMSE);\r
- }\r
-\r
- /* TSE */\r
- TSE -= j2k->image_info->tile[thistile].packet[thispacket].disto;\r
-\r
- /* MSE */\r
- MSE = TSE / j2k->image_info->tile[thistile].nbpix;\r
-\r
- /* PSNR */\r
- PSNR = 10.0 * log10(Omax2 / MSE);\r
-\r
- /* fill the address range */\r
- switch (esd->addrm) {\r
-\r
- /* packet mode */\r
- case (0):\r
- /* nothing, there is none */\r
- break;\r
-\r
- /* byte range */\r
- case (1):\r
- /* start address of packet */\r
- addr1 = (j2k->image_info->tile[thistile].packet[thispacket].start_pos) & addrmask;\r
- /* end address of packet */\r
- addr2 = (j2k->image_info->tile[thistile].packet[thispacket].end_pos) & addrmask;\r
- break;\r
-\r
- /* packet range */\r
- case (2):\r
- /* not implemented here */\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "Addressing mode packet_range is not implemented\n");\r
- break;\r
-\r
- /* unknown addressing method */\r
- default:\r
- /* not implemented here */\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown addressing mode\n");\r
- break;\r
-\r
- }\r
-\r
- /* hack for writing relative sensitivity of MH and TPHs */\r
- if ((esd->senst == 0) && (thispacket == 0)) {\r
-\r
- /* possible MH */\r
- if ((thistile == 0) && !doneMH) {\r
- /* we have to manage MH addresses */\r
- addr1 = 0; /* start of MH */\r
- addr2 = j2k->image_info->main_head_end; /* end of MH */\r
- /* set special dvalue for this MH */\r
- dvalue = -10.0;\r
- doneMH = true; /* don't come here anymore */\r
- vv--; /* wrap back loop counter */\r
-\r
- } else if (!doneTPH) {\r
- /* we have to manage TPH addresses */\r
- addr1 = j2k->image_info->tile[thistile].start_pos;\r
- addr2 = j2k->image_info->tile[thistile].end_header;\r
- /* set special dvalue for this TPH */\r
- dvalue = -1.0;\r
- doneTPH = true; /* don't come here till the next tile */\r
- vv--; /* wrap back loop counter */\r
- }\r
-\r
- } else\r
- doneTPH = false; /* reset TPH counter */\r
-\r
- /* write the addresses to the buffer */\r
- switch (esd->ad_size) {\r
-\r
- case (0):\r
- /* do nothing */\r
- break;\r
-\r
- case (2):\r
- /* two bytes */\r
- *(buf++) = (unsigned char) (addr1 >> 8); \r
- *(buf++) = (unsigned char) (addr1 >> 0); \r
- *(buf++) = (unsigned char) (addr2 >> 8); \r
- *(buf++) = (unsigned char) (addr2 >> 0); \r
- break;\r
-\r
- case (4):\r
- /* four bytes */\r
- *(buf++) = (unsigned char) (addr1 >> 24); \r
- *(buf++) = (unsigned char) (addr1 >> 16); \r
- *(buf++) = (unsigned char) (addr1 >> 8); \r
- *(buf++) = (unsigned char) (addr1 >> 0); \r
- *(buf++) = (unsigned char) (addr2 >> 24); \r
- *(buf++) = (unsigned char) (addr2 >> 16); \r
- *(buf++) = (unsigned char) (addr2 >> 8); \r
- *(buf++) = (unsigned char) (addr2 >> 0); \r
- break;\r
-\r
- default:\r
- /* do nothing */\r
- break;\r
- }\r
-\r
-\r
- /* let's fill the value field */\r
- switch (esd->senst) {\r
-\r
- /* relative sensitivity */\r
- case (0):\r
- /* we just write down the packet ordering */\r
- if (dvalue == -10)\r
- /* MH */\r
- dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */\r
- else if (dvalue == -1)\r
- /* TPH */\r
- dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */\r
- else\r
- /* packet: first is most important, and then in decreasing order\r
- down to the last, which counts for 1 */\r
- dvalue = jpwl_pfp_to_double(j2k->image_info->num - thispacket, esd->se_size);\r
- break;\r
-\r
- /* MSE */\r
- case (1):\r
- /* !!! WRONG: let's put here disto field of packets !!! */\r
- dvalue = MSE;\r
- break;\r
-\r
- /* MSE reduction */\r
- case (2):\r
- dvalue = oldMSE - MSE;\r
- oldMSE = MSE;\r
- break;\r
-\r
- /* PSNR */\r
- case (3):\r
- dvalue = PSNR;\r
- break;\r
-\r
- /* PSNR increase */\r
- case (4):\r
- dvalue = PSNR - oldPSNR;\r
- oldPSNR = PSNR;\r
- break;\r
-\r
- /* MAXERR */\r
- case (5):\r
- dvalue = 0.0;\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "MAXERR sensitivity mode is not implemented\n");\r
- break;\r
-\r
- /* TSE */\r
- case (6):\r
- dvalue = TSE;\r
- break;\r
-\r
- /* reserved */\r
- case (7):\r
- dvalue = 0.0;\r
- opj_event_msg(j2k->cinfo, EVT_WARNING, "Reserved sensitivity mode is not implemented\n");\r
- break;\r
-\r
- default:\r
- dvalue = 0.0;\r
- break;\r
- }\r
-\r
- /* compute the pseudo-floating point value */\r
- pfpvalue = jpwl_double_to_pfp(dvalue, esd->se_size);\r
-\r
- /* write the pfp value to the buffer */\r
- switch (esd->se_size) {\r
-\r
- case (1):\r
- /* one byte */\r
- *(buf++) = (unsigned char) (pfpvalue >> 0); \r
- break;\r
-\r
- case (2):\r
- /* two bytes */\r
- *(buf++) = (unsigned char) (pfpvalue >> 8); \r
- *(buf++) = (unsigned char) (pfpvalue >> 0); \r
- break;\r
- }\r
-\r
- }\r
-\r
- return true;\r
-}\r
-\r
-void jpwl_esd_write(jpwl_esd_ms_t *esd, unsigned char *buf) {\r
-\r
- /* Marker */\r
- *(buf++) = (unsigned char) (J2K_MS_ESD >> 8); \r
- *(buf++) = (unsigned char) (J2K_MS_ESD >> 0); \r
-\r
- /* Lesd */\r
- *(buf++) = (unsigned char) (esd->Lesd >> 8); \r
- *(buf++) = (unsigned char) (esd->Lesd >> 0); \r
-\r
- /* Cesd */\r
- if (esd->numcomps >= 257)\r
- *(buf++) = (unsigned char) (esd->Cesd >> 8); \r
- *(buf++) = (unsigned char) (esd->Cesd >> 0); \r
-\r
- /* Pesd */\r
- *(buf++) = (unsigned char) (esd->Pesd >> 0); \r
-\r
- /* Data */\r
- if (esd->numcomps < 257)\r
- memset(buf, 0xAA, (size_t) esd->Lesd - 4);\r
- /*memcpy(buf, esd->data, (size_t) esd->Lesd - 4);*/\r
- else\r
- memset(buf, 0xAA, (size_t) esd->Lesd - 5);\r
- /*memcpy(buf, esd->data, (size_t) esd->Lesd - 5);*/\r
-}\r
-\r
-unsigned short int jpwl_double_to_pfp(double V, int bytes) {\r
-\r
- unsigned short int em, e, m;\r
-\r
- switch (bytes) {\r
-\r
- case (1):\r
-\r
- if (V < MIN_V1) {\r
- e = 0x0000;\r
- m = 0x0000;\r
- } else if (V > MAX_V1) {\r
- e = 0x000F;\r
- m = 0x000F;\r
- } else {\r
- e = (unsigned short int) (floor(log(V) * 1.44269504088896) / 4.0);\r
- m = (unsigned short int) (0.5 + (V / (pow(2.0, (double) (4 * e)))));\r
- }\r
- em = ((e & 0x000F) << 4) + (m & 0x000F); \r
- break;\r
-\r
- case (2):\r
-\r
- if (V < MIN_V2) {\r
- e = 0x0000;\r
- m = 0x0000;\r
- } else if (V > MAX_V2) {\r
- e = 0x001F;\r
- m = 0x07FF;\r
- } else {\r
- e = (unsigned short int) floor(log(V) * 1.44269504088896) + 15;\r
- m = (unsigned short int) (0.5 + 2048.0 * ((V / (pow(2.0, (double) e - 15.0))) - 1.0));\r
- }\r
- em = ((e & 0x001F) << 11) + (m & 0x07FF);\r
- break;\r
-\r
- default:\r
-\r
- em = 0x0000;\r
- break;\r
- };\r
-\r
- return em;\r
-}\r
-\r
-double jpwl_pfp_to_double(unsigned short int em, int bytes) {\r
-\r
- double V;\r
-\r
- switch (bytes) {\r
-\r
- case 1:\r
- V = (double) (em & 0x0F) * pow(2.0, (double) (em & 0xF0));\r
- break;\r
-\r
- case 2:\r
-\r
- V = pow(2.0, (double) ((em & 0xF800) >> 11) - 15.0) * (1.0 + (double) (em & 0x07FF) / 2048.0);\r
- break;\r
-\r
- default:\r
- V = 0.0;\r
- break;\r
-\r
- }\r
-\r
- return V;\r
-\r
-}\r
-\r
-bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num) {\r
-\r
- int mm;\r
- unsigned long int addlen;\r
-\r
- opj_image_info_t *info = j2k->image_info;\r
- int tileno, packno, numtiles = info->th * info->tw, numpacks = info->num;\r
-\r
- if (!j2k || !jwmarker ) {\r
- opj_event_msg(j2k->cinfo, EVT_ERROR, "J2K handle or JPWL markers list badly allocated\n");\r
- return false;\r
- }\r
-\r
- /* main_head_end: how many markers are there before? */\r
- addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->main_head_end)\r
- addlen += jwmarker[mm].len + 2;\r
- info->main_head_end += addlen;\r
-\r
- /* codestream_size: always increment with all markers */\r
- addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- addlen += jwmarker[mm].len + 2;\r
- info->codestream_size += addlen;\r
-\r
- /* navigate through all the tiles */\r
- for (tileno = 0; tileno < numtiles; tileno++) {\r
-\r
- /* start_pos: increment with markers before SOT */\r
- addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].start_pos)\r
- addlen += jwmarker[mm].len + 2;\r
- info->tile[tileno].start_pos += addlen;\r
-\r
- /* end_header: increment with markers before of it */\r
- addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_header)\r
- addlen += jwmarker[mm].len + 2;\r
- info->tile[tileno].end_header += addlen;\r
-\r
- /* end_pos: increment with markers before the end of this tile */\r
- /* code is disabled, since according to JPWL no markers can be beyond TPH */\r
- /*addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_pos)\r
- addlen += jwmarker[mm].len + 2;*/\r
- info->tile[tileno].end_pos += addlen;\r
-\r
- /* navigate through all the packets in this tile */\r
- for (packno = 0; packno < numpacks; packno++) {\r
- \r
- /* start_pos: increment with markers before the packet */\r
- /* disabled for the same reason as before */\r
- /*addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].start_pos)\r
- addlen += jwmarker[mm].len + 2;*/\r
- info->tile[tileno].packet[packno].start_pos += addlen;\r
-\r
- /* end_pos: increment if marker is before the end of packet */\r
- /* disabled for the same reason as before */\r
- /*addlen = 0;\r
- for (mm = 0; mm < jwmarker_num; mm++)\r
- if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_pos)\r
- addlen += jwmarker[mm].len + 2;*/\r
- info->tile[tileno].packet[packno].end_pos += addlen;\r
-\r
- }\r
- }\r
-\r
- return true;\r
-}\r
-\r
-#endif /* USE_JPWL */
\ No newline at end of file
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herv� Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef USE_JPWL
+
+#include "../libopenjpeg/opj_includes.h"
+
+/** Minimum and maximum values for the double->pfp conversion */
+#define MIN_V1 0.0
+#define MAX_V1 17293822569102704640.0
+#define MIN_V2 0.000030517578125
+#define MAX_V2 131040.0
+
+/** conversion between a double precision floating point
+number and the corresponding pseudo-floating point used
+to represent sensitivity values
+@param V the double precision value
+@param bytes the number of bytes of the representation
+@return the pseudo-floating point value (cast accordingly)
+*/
+unsigned short int jpwl_double_to_pfp(double V, int bytes);
+
+/** conversion between a pseudo-floating point used
+to represent sensitivity values and the corresponding
+double precision floating point number
+@param em the pseudo-floating point value (cast accordingly)
+@param bytes the number of bytes of the representation
+@return the double precision value
+*/
+double jpwl_pfp_to_double(unsigned short int em, int bytes);
+
+ /*-------------------------------------------------------------*/
+
+int jpwl_markcomp(const void *arg1, const void *arg2)
+{
+ /* Compare the two markers' positions */
+ double diff = (((jpwl_marker_t *) arg1)->dpos - ((jpwl_marker_t *) arg2)->dpos);
+
+ if (diff == 0.0)
+ return (0);
+ else if (diff < 0)
+ return (-1);
+ else
+ return (+1);
+}
+
+int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ bool latest, bool packed, bool insideMH, int *idx, int hprot,
+ double place_pos, int tileno,
+ unsigned long int pre_len, unsigned long int post_len) {
+
+ jpwl_epb_ms_t *epb_mark = NULL;
+
+ int k_pre, k_post, n_pre, n_post;
+
+ unsigned long int L1, L2, dL4, max_postlen, epbs_len = 0;
+
+ /* We find RS(n,k) for EPB parms and pre-data, if any */
+ if (insideMH && (*idx == 0)) {
+ /* First EPB in MH */
+ k_pre = 64;
+ n_pre = 160;
+ } else if (!insideMH && (*idx == 0)) {
+ /* First EPB in TH */
+ k_pre = 25;
+ n_pre = 80;
+ } else {
+ /* Following EPBs in MH or TH */
+ k_pre = 13;
+ n_pre = 40;
+ };
+
+ /* Find lengths, Figs. B3 and B4 */
+ /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+ L1 = pre_len + 13;
+
+ /* size of pre-data redundancy */
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L2 = (n_pre - k_pre) * (unsigned long int) ceil((double) L1 / (double) k_pre);
+
+ /* Find protection type for post data and its associated redundancy field length*/
+ if ((hprot == 16) || (hprot == 32)) {
+ /* there is a CRC for post-data */
+ k_post = post_len;
+ n_post = post_len + (hprot >> 3);
+ /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+ } else if ((hprot >= 37) && (hprot <= 128)) {
+ /* there is a RS for post-data */
+ k_post = 32;
+ n_post = hprot;
+
+ } else {
+ /* Use predefined codes */
+ n_post = n_pre;
+ k_post = k_pre;
+ };
+
+ /* Create the EPB(s) */
+ while (post_len > 0) {
+
+ /* maximum postlen in order to respect EPB size
+ (we use JPWL_MAXIMUM_EPB_ROOM instead of 65535 for keeping room for EPB parms)*/
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) JPWL_MAXIMUM_EPB_ROOM / (double) (n_post - k_post));
+
+ /* maximum postlen in order to respect EPB size */
+ if (*idx == 0)
+ /* (we use (JPWL_MAXIMUM_EPB_ROOM - L2) instead of 65535 for keeping room for EPB parms + pre-data) */
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) (JPWL_MAXIMUM_EPB_ROOM - L2) / (double) (n_post - k_post));
+
+ else
+ /* (we use JPWL_MAXIMUM_EPB_ROOM instead of 65535 for keeping room for EPB parms) */
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) JPWL_MAXIMUM_EPB_ROOM / (double) (n_post - k_post));
+
+ /* length to use */
+ dL4 = min(max_postlen, post_len);
+
+ if (epb_mark = jpwl_epb_create(
+ j2k, /* this encoder handle */
+ latest ? (dL4 < max_postlen) : false, /* is it the latest? */
+ packed, /* is it packed? */
+ tileno, /* we are in TPH */
+ *idx, /* its index */
+ hprot, /* protection type parameters of following data */
+ 0, /* pre-data: nothing for now */
+ dL4 /* post-data: the stub computed previously */
+ )) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (*jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[*jwmarker_num].id = J2K_MS_EPB; /* its type */
+ jwmarker[*jwmarker_num].epbmark = epb_mark; /* the EPB */
+ jwmarker[*jwmarker_num].pos = (int) place_pos; /* after SOT */
+ jwmarker[*jwmarker_num].dpos = place_pos + 0.0000001 * (double)(*idx); /* not very first! */
+ jwmarker[*jwmarker_num].len = epb_mark->Lepb; /* its length */
+ jwmarker[*jwmarker_num].len_ready = true; /* ready */
+ jwmarker[*jwmarker_num].pos_ready = true; /* ready */
+ jwmarker[*jwmarker_num].parms_ready = true; /* ready */
+ jwmarker[*jwmarker_num].data_ready = false; /* not ready */
+ (*jwmarker_num)++;
+ }
+
+ /* increment epb index */
+ (*idx)++;
+
+ /* decrease postlen */
+ post_len -= dL4;
+
+ /* increase the total length of EPBs */
+ epbs_len += epb_mark->Lepb + 2;
+
+ } else {
+ /* ooops, problems */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB for UEP in tile %d\n", tileno);
+ };
+ }
+
+ return epbs_len;
+}
+
+
+jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, bool latest, bool packed, int tileno, int idx, int hprot,
+ unsigned long int pre_len, unsigned long int post_len) {
+
+ jpwl_epb_ms_t *epb = NULL;
+ unsigned short int data_len = 0;
+ unsigned short int L2, L3;
+ unsigned long int L1, L4;
+ unsigned char *predata_in = NULL;
+
+ bool insideMH = (tileno == -1);
+
+ /* Alloc space */
+ if (!(epb = (jpwl_epb_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epb_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for one EPB MS\n");
+ return NULL;
+ };
+
+ /* We set RS(n,k) for EPB parms and pre-data, if any */
+ if (insideMH && (idx == 0)) {
+ /* First EPB in MH */
+ epb->k_pre = 64;
+ epb->n_pre = 160;
+ } else if (!insideMH && (idx == 0)) {
+ /* First EPB in TH */
+ epb->k_pre = 25;
+ epb->n_pre = 80;
+ } else {
+ /* Following EPBs in MH or TH */
+ epb->k_pre = 13;
+ epb->n_pre = 40;
+ };
+
+ /* Find lengths, Figs. B3 and B4 */
+ /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+ L1 = pre_len + 13;
+ epb->pre_len = pre_len;
+
+ /* size of pre-data redundancy */
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+ /* length of post-data */
+ L4 = post_len;
+ epb->post_len = post_len;
+
+ /* Find protection type for post data and its associated redundancy field length*/
+ if ((hprot == 16) || (hprot == 32)) {
+ /* there is a CRC for post-data */
+ epb->Pepb = 0x10000000 | ((unsigned long int) hprot >> 5); /* 0=CRC-16, 1=CRC-32 */
+ epb->k_post = post_len;
+ epb->n_post = post_len + (hprot >> 3);
+ /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+ } else if ((hprot >= 37) && (hprot <= 128)) {
+ /* there is a RS for post-data */
+ epb->Pepb = 0x20000020 | (((unsigned long int) hprot & 0x000000FF) << 8);
+ epb->k_post = 32;
+ epb->n_post = hprot;
+
+ } else if (hprot == 1) {
+ /* Use predefined codes */
+ epb->Pepb = (unsigned long int) 0x00000000;
+ epb->n_post = epb->n_pre;
+ epb->k_post = epb->k_pre;
+
+ } else if (hprot == 0) {
+ /* Placeholder EPB: only protects its parameters, no protection method */
+ epb->Pepb = (unsigned long int) 0xFFFFFFFF;
+ epb->n_post = 1;
+ epb->k_post = 1;
+
+ } else {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Invalid protection value for EPB h = %d\n", hprot);
+ return NULL;
+ }
+
+ epb->hprot = hprot;
+
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+ /* private fields */
+ epb->tileno = tileno;
+
+ /* Fill some fields of the EPB */
+
+ /* total length of the EPB MS (less the EPB marker itself): */
+ /* Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) + pre_redundancy + post-redundancy */
+ epb->Lepb = 11 + L2 + L3;
+
+ /* EPB style */
+ epb->Depb = ((packed & 0x0001) << 7) | ((latest & 0x0001) << 6) | (idx & 0x003F);
+
+ /* length of data protected by EPB: */
+ epb->LDPepb = L1 + L4;
+
+ return epb;
+}
+
+void jpwl_epb_write(jpwl_epb_ms_t *epb, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_EPB >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_EPB >> 0);
+
+ /* Lepb */
+ *(buf++) = (unsigned char) (epb->Lepb >> 8);
+ *(buf++) = (unsigned char) (epb->Lepb >> 0);
+
+ /* Depb */
+ *(buf++) = (unsigned char) (epb->Depb >> 0);
+
+ /* LDPepb */
+ *(buf++) = (unsigned char) (epb->LDPepb >> 24);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 16);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 8);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 0);
+
+ /* Pepb */
+ *(buf++) = (unsigned char) (epb->Pepb >> 24);
+ *(buf++) = (unsigned char) (epb->Pepb >> 16);
+ *(buf++) = (unsigned char) (epb->Pepb >> 8);
+ *(buf++) = (unsigned char) (epb->Pepb >> 0);
+
+ /* Data */
+ /*memcpy(buf, epb->data, (size_t) epb->Lepb - 11);*/
+ memset(buf, 0, (size_t) epb->Lepb - 11);
+};
+
+
+jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, bool esd_on, bool red_on, bool epb_on, bool info_on) {
+
+ jpwl_epc_ms_t *epc = NULL;
+
+ /* Alloc space */
+ if (!(epc = (jpwl_epc_ms_t *) malloc((size_t) 1 * sizeof (jpwl_epc_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for EPC MS\n");
+ return NULL;
+ };
+
+ /* Set the EPC parameters */
+ epc->esd_on = esd_on;
+ epc->epb_on = epb_on;
+ epc->red_on = red_on;
+ epc->info_on = info_on;
+
+ /* Fill the EPC fields with default values */
+ epc->Lepc = 9;
+ epc->Pcrc = 0x0000;
+ epc->DL = 0x00000000;
+ epc->Pepc = ((j2k->cp->esd_on & 0x0001) << 4) | ((j2k->cp->red_on & 0x0001) << 5) |
+ ((j2k->cp->epb_on & 0x0001) << 6) | ((j2k->cp->info_on & 0x0001) << 7);
+
+ return (epc);
+}
+
+bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf, unsigned char *post_buf) {
+
+ unsigned long int L1, L2, L3, L4;
+ int remaining;
+ unsigned long int P, NN_P;
+
+ /* Operating buffer */
+ static unsigned char codeword[NN], *parityword;
+
+ unsigned char *L1_buf, *L2_buf;
+ /* these ones are static, since we need to keep memory of
+ the exact place from one call to the other */
+ static unsigned char *L3_buf, *L4_buf;
+
+ /* some consistency check */
+ if (!buf) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs\n");
+ return false;
+ }
+
+ if (!post_buf && !L4_buf) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs data\n");
+ return false;
+ }
+
+ /*
+ * Compute parity bytes on pre-data, ALWAYS present (at least only for EPB parms)
+ */
+
+ /* Initialize RS structures */
+ P = epb->n_pre - epb->k_pre;
+ NN_P = NN - P;
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* pre-data begins pre_len bytes before of EPB buf */
+ L1_buf = buf - epb->pre_len;
+ L1 = epb->pre_len + 13;
+
+ /* redundancy for pre-data begins immediately after EPB parms */
+ L2_buf = buf + 13;
+ L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+ /* post-data
+ the position of L4 buffer can be:
+ 1) passed as a parameter: in that case use it
+ 2) null: in that case use the previous (static) one
+ */
+ if (post_buf)
+ L4_buf = post_buf;
+ L4 = epb->post_len;
+
+ /* post-data redundancy begins immediately after pre-data redundancy */
+ L3_buf = L2_buf + L2;
+ L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+ /* let's check whether EPB length is sufficient to contain all these data */
+ if (epb->Lepb < (11 + L2 + L3))
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no room in EPB data field for writing redundancy data\n");
+ /*printf("Env. %d, nec. %d (%d + %d)\n", epb->Lepb - 11, L2 + L3, L2, L3);*/
+
+ /* Compute redundancy of pre-data message words */
+ remaining = L1;
+ while (remaining) {
+
+ /* copy message data into codeword buffer */
+ if (remaining < epb->k_pre) {
+ /* the last message word is zero-padded */
+ memset(codeword, 0, NN);
+ memcpy(codeword, L1_buf, remaining);
+ L1_buf += remaining;
+ remaining = 0;
+
+ } else {
+ memcpy(codeword, L1_buf, epb->k_pre);
+ L1_buf += epb->k_pre;
+ remaining -= epb->k_pre;
+
+ }
+
+ /* Encode the buffer and obtain parity bytes */
+ if (encode_rs(codeword, parityword))
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible encoding error in codeword @ position #%d\n", (L1_buf - buf) / epb->k_pre);
+
+ /* copy parity bytes only in redundancy buffer */
+ memcpy(L2_buf, parityword, P);
+
+ /* advance parity buffer */
+ L2_buf += P;
+ }
+
+ /*
+ * Compute parity bytes on post-data, may be absent if there are no data
+ */
+ /*printf("Hprot is %d (tileno=%d, k_pre=%d, n_pre=%d, k_post=%d, n_post=%d, pre_len=%d, post_len=%d)\n",
+ epb->hprot, epb->tileno, epb->k_pre, epb->n_pre, epb->k_post, epb->n_post, epb->pre_len,
+ epb->post_len);*/
+ if (epb->hprot < 0) {
+
+ /* there should be no EPB */
+
+ } else if (epb->hprot == 0) {
+
+ /* no protection for the data */
+ /* advance anyway */
+ L4_buf += epb->post_len;
+
+ } else if (epb->hprot == 16) {
+
+ /* CRC-16 */
+ unsigned short int mycrc = 0x0000;
+
+ /* compute the CRC field (excluding itself) */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+ /* write the CRC field */
+ *(L3_buf++) = (unsigned char) (mycrc >> 8);
+ *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+ } else if (epb->hprot == 32) {
+
+ /* CRC-32 */
+ unsigned long int mycrc = 0x00000000;
+
+ /* compute the CRC field (excluding itself) */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+ /* write the CRC field */
+ *(L3_buf++) = (unsigned char) (mycrc >> 24);
+ *(L3_buf++) = (unsigned char) (mycrc >> 16);
+ *(L3_buf++) = (unsigned char) (mycrc >> 8);
+ *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+ } else {
+
+ /* RS */
+
+ /* Initialize RS structures */
+ P = epb->n_post - epb->k_post;
+ NN_P = NN - P;
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Compute redundancy of post-data message words */
+ remaining = L4;
+ while (remaining) {
+
+ /* copy message data into codeword buffer */
+ if (remaining < epb->k_post) {
+ /* the last message word is zero-padded */
+ memset(codeword, 0, NN);
+ memcpy(codeword, L4_buf, remaining);
+ L4_buf += remaining;
+ remaining = 0;
+
+ } else {
+ memcpy(codeword, L4_buf, epb->k_post);
+ L4_buf += epb->k_post;
+ remaining -= epb->k_post;
+
+ }
+
+ /* Encode the buffer and obtain parity bytes */
+ if (encode_rs(codeword, parityword))
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible encoding error in codeword @ position #%d\n", (L4_buf - buf) / epb->k_post);
+
+ /* copy parity bytes only in redundancy buffer */
+ memcpy(L3_buf, parityword, P);
+
+ /* advance parity buffer */
+ L3_buf += P;
+ }
+
+ }
+
+ return true;
+}
+
+
+bool jpwl_correct(opj_j2k_t *j2k) {
+
+ opj_cio_t *cio = j2k->cio;
+ bool status;
+ static bool mh_done = false;
+ int mark_pos, id, len, skips, sot_pos;
+ unsigned long int Psot = 0;
+
+ /* go back to marker position */
+ mark_pos = cio_tell(cio) - 2;
+ cio_seek(cio, mark_pos);
+
+ if ((j2k->state == J2K_STATE_MHSOC) && !mh_done) {
+
+ int mark_val = 0, skipnum = 0;
+
+ /*
+ COLOR IMAGE
+ first thing to do, if we are here, is to look whether
+ 51 (skipnum) positions ahead there is an EPB, in case of MH
+ */
+ /*
+ B/W IMAGE
+ first thing to do, if we are here, is to look whether
+ 45 (skipnum) positions ahead there is an EPB, in case of MH
+ */
+ /* SIZ SIZ_FIELDS SIZ_COMPS FOLLOWING_MARKER */
+ skipnum = 2 + 38 + 3 * j2k->cp->exp_comps + 2;
+ if ((cio->bp + skipnum) < cio->end) {
+
+ cio_skip(cio, skipnum);
+
+ /* check that you are not going beyond the end of codestream */
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 0, /* EPB type: MH */
+ skipnum, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+
+ /* read the marker value */
+ mark_val = (*(cio->bp) << 8) | *(cio->bp + 1);
+
+ if (status && (mark_val == J2K_MS_EPB)) {
+ /* we found it! */
+ mh_done = true;
+ return true;
+ }
+
+ }
+
+ }
+
+ if (true /*(j2k->state == J2K_STATE_TPHSOT) || (j2k->state == J2K_STATE_TPH)*/) {
+ /* else, look if 12 positions ahead there is an EPB, in case of TPH */
+ cio_seek(cio, mark_pos);
+ if ((cio->bp + 12) < cio->end) {
+
+ cio_skip(cio, 12);
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 1, /* EPB type: TPH */
+ 12, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+ if (status)
+ /* we found it! */
+ return true;
+ }
+ }
+
+ return false;
+
+ /* for now, don't use this code */
+
+ /* else, look if here is an EPB, in case of other */
+ if (mark_pos > 64) {
+ /* it cannot stay before the first MH EPB */
+ cio_seek(cio, mark_pos);
+ cio_skip(cio, 0);
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 2, /* EPB type: TPH */
+ 0, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+ if (status)
+ /* we found it! */
+ return true;
+ }
+
+ /* nope, no EPBs probably, or they are so damaged that we can give up */
+ return false;
+
+ return true;
+
+ /* AN ATTEMPT OF PARSER */
+ /* NOT USED ACTUALLY */
+
+ /* go to the beginning of the file */
+ cio_seek(cio, 0);
+
+ /* let's begin */
+ j2k->state = J2K_STATE_MHSOC;
+
+ /* cycle all over the markers */
+ while (cio_tell(cio) < cio->length) {
+
+ /* read the marker */
+ mark_pos = cio_tell(cio);
+ id = cio_read(cio, 2);
+
+ /* details */
+ printf("Marker@%d: %X\n", cio_tell(cio) - 2, id);
+
+ /* do an action in response to the read marker */
+ switch (id) {
+
+ /* short markers */
+
+ /* SOC */
+ case J2K_MS_SOC:
+ j2k->state = J2K_STATE_MHSIZ;
+ len = 0;
+ skips = 0;
+ break;
+
+ /* EOC */
+ case J2K_MS_EOC:
+ j2k->state = J2K_STATE_MT;
+ len = 0;
+ skips = 0;
+ break;
+
+ /* particular case of SOD */
+ case J2K_MS_SOD:
+ len = Psot - (mark_pos - sot_pos) - 2;
+ skips = len;
+ break;
+
+ /* long markers */
+
+ /* SOT */
+ case J2K_MS_SOT:
+ j2k->state = J2K_STATE_TPH;
+ sot_pos = mark_pos; /* position of SOT */
+ len = cio_read(cio, 2); /* read the length field */
+ cio_skip(cio, 2); /* this field is unnecessary */
+ Psot = cio_read(cio, 4); /* tile length */
+ skips = len - 8;
+ break;
+
+ /* remaining */
+ case J2K_MS_SIZ:
+ j2k->state = J2K_STATE_MH;
+ /* read the length field */
+ len = cio_read(cio, 2);
+ skips = len - 2;
+ break;
+
+ /* remaining */
+ default:
+ /* read the length field */
+ len = cio_read(cio, 2);
+ skips = len - 2;
+ break;
+
+ }
+
+ /* skip to marker's end */
+ cio_skip(cio, skips);
+
+ }
+
+
+}
+
+bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,
+ unsigned char **L4_bufp) {
+
+ /* Operating buffer */
+ unsigned char codeword[NN], *parityword;
+
+ unsigned long int P, NN_P;
+ unsigned long int L1, L4;
+ int remaining, n_pre, k_pre, n_post, k_post;
+
+ int status, tt;
+
+ int orig_pos = cio_tell(j2k->cio);
+
+ unsigned char *L1_buf, *L2_buf;
+ unsigned char *L3_buf, *L4_buf;
+
+ unsigned long int LDPepb, Pepb;
+ unsigned short int Lepb;
+ unsigned char Depb;
+ char str1[25] = "";
+ int myconn, errnum = 0;
+ bool errflag = false;
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* check for common errors */
+ if (!buffer) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "The EPB pointer is a NULL buffer\n");
+ return false;
+ }
+
+ /* set bignesses */
+ L1 = pre_len + 13;
+
+ /* pre-data correction */
+ switch (type) {
+
+ case 0:
+ /* MH EPB */
+ k_pre = 64;
+ n_pre = 160;
+ break;
+
+ case 1:
+ /* TPH EPB */
+ k_pre = 25;
+ n_pre = 80;
+ break;
+
+ case 2:
+ /* other EPBs */
+ k_pre = 13;
+ n_pre = 40;
+ break;
+
+ case 3:
+ /* automatic setup */
+ break;
+
+ default:
+ /* unknown type */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Unknown expected EPB type\n");
+ return false;
+ break;
+
+ }
+
+ /* Initialize RS structures */
+ P = n_pre - k_pre;
+ NN_P = NN - P;
+ tt = (int) floor((float) P / 2.0F); /* correction capability of the code */
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Correct pre-data message words */
+ L1_buf = buffer - pre_len;
+ L2_buf = buffer + 13;
+ remaining = L1;
+ while (remaining) {
+
+ /* always zero-pad codewords */
+ /* (this is required, since after decoding the zeros in the long codeword
+ could change, and keep unchanged in subsequent calls) */
+ memset(codeword, 0, NN);
+
+ /* copy codeword buffer into message bytes */
+ if (remaining < k_pre)
+ memcpy(codeword, L1_buf, remaining);
+ else
+ memcpy(codeword, L1_buf, k_pre);
+
+ /* copy redundancy buffer in parity bytes */
+ memcpy(parityword, L2_buf, P);
+
+ /* Decode the buffer and possibly obtain corrected bytes */
+ status = eras_dec_rs(codeword, NULL, 0);
+ if (status == -1) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible decoding error in codeword @ position #%d\n", (L1_buf - buffer) / k_pre);*/
+ errflag = true;
+ /* we can try to safely get out from the function:
+ if we are here, either this is not an EPB or the first codeword
+ is too damaged to be helpful */
+ /*return false;*/
+
+ } else if (status == 0) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+ } else if (status <= tt) {
+ /* it has corrected 0 <= errs <= tt */
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+ errnum += status;
+
+ } else {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+ return false;*/
+ errflag = true;
+ }
+
+
+ /* advance parity buffer */
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected parity only if all is OK */
+ memcpy(L2_buf, parityword, P);
+ L2_buf += P;
+
+ /* advance message buffer */
+ if (remaining < k_pre) {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L1_buf, codeword, remaining);
+ L1_buf += remaining;
+ remaining = 0;
+
+ } else {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L1_buf, codeword, k_pre);
+ L1_buf += k_pre;
+ remaining -= k_pre;
+
+ }
+ }
+
+ /* print summary */
+ if (!conn) {
+
+ /*if (errnum)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "+ %d symbol errors corrected (Ps=%.1e)\n", errnum,
+ (float) errnum / ((float) n_pre * (float) L1 / (float) k_pre));*/
+ if (errflag) {
+ /*opj_event_msg(j2k->cinfo, EVT_INFO, "+ there were unrecoverable errors\n");*/
+ return false;
+ }
+
+ }
+
+ /* presumably, now, EPB parameters are correct */
+ /* let's get them */
+
+ /* Simply read the EPB parameters */
+ if (conn)
+ cio->bp = buffer;
+ cio_skip(cio, 2); /* the marker */
+ Lepb = cio_read(cio, 2);
+ Depb = cio_read(cio, 1);
+ LDPepb = cio_read(cio, 4);
+ Pepb = cio_read(cio, 4);
+
+ /* What does Pepb tells us about the protection method? */
+ if (((Pepb & 0xF0000000) >> 28) == 0)
+ sprintf(str1, "pred"); /* predefined */
+ else if (((Pepb & 0xF0000000) >> 28) == 1)
+ sprintf(str1, "crc-%d", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
+ else if (((Pepb & 0xF0000000) >> 28) == 2)
+ sprintf(str1, "rs(%d,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
+ else if (Pepb == 0xFFFFFFFF)
+ sprintf(str1, "nometh"); /* RS mode */
+ else
+ sprintf(str1, "unknown"); /* unknown */
+
+ /* Now we write them to screen */
+ if (!conn && post_len)
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
+ cio_tell(cio) - 13,
+ (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
+ (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
+ (Depb & 0x3F), /* EPB index value */
+ LDPepb, /*length of the data protected by the EPB */
+ str1); /* protection method */
+
+
+ /* well, we need to investigate how long is the connected length of packed EPBs */
+ myconn = Lepb + 2;
+ if ((Depb & 0x40) == 0) /* not latest in header */
+ jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ buffer + Lepb + 2, /* pointer to next EPB in codestream buffer */
+ 2, /* EPB type: should be of other type */
+ 0, /* only EPB fields */
+ 0, /* do not look after */
+ &myconn,
+ NULL
+ );
+ if (conn)
+ *conn += myconn;
+
+ /*if (!conn)
+ printf("connected = %d\n", myconn);*/
+
+ /*cio_seek(j2k->cio, orig_pos);
+ return true;*/
+
+ /* post-data
+ the position of L4 buffer is at the end of currently connected EPBs
+ */
+ if (!(L4_bufp))
+ L4_buf = buffer + myconn;
+ else if (!(*L4_bufp))
+ L4_buf = buffer + myconn;
+ else
+ L4_buf = *L4_bufp;
+ if (post_len == -1)
+ L4 = LDPepb - pre_len - 13;
+ else if (post_len == 0)
+ L4 = 0;
+ else
+ L4 = post_len;
+
+ L3_buf = L2_buf;
+
+ /* Do a further check here on the read parameters */
+ if (L4 > (unsigned long) cio_numbytesleft(j2k->cio))
+ /* overflow */
+ return false;
+
+ /* we are ready for decoding the remaining data */
+ if (((Pepb & 0xF0000000) >> 28) == 1) {
+ /* CRC here */
+ if ((16 * ((Pepb & 0x00000001) + 1)) == 16) {
+
+ /* CRC-16 */
+ unsigned short int mycrc = 0x0000, filecrc = 0x0000;
+
+ /* compute the CRC field */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+ /* read the CRC field */
+ filecrc = *(L3_buf++) << 8;
+ filecrc |= *(L3_buf++);
+
+ /* check the CRC field */
+ if (mycrc == filecrc) {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+ } else {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+ errflag = true;
+ }
+ }
+
+ if ((16 * ((Pepb & 0x00000001) + 1)) == 32) {
+
+ /* CRC-32 */
+ unsigned long int mycrc = 0x00000000, filecrc = 0x00000000;
+
+ /* compute the CRC field */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+ /* read the CRC field */
+ filecrc = *(L3_buf++) << 24;
+ filecrc |= *(L3_buf++) << 16;
+ filecrc |= *(L3_buf++) << 8;
+ filecrc |= *(L3_buf++);
+
+ /* check the CRC field */
+ if (mycrc == filecrc) {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+ } else {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+ errflag = true;
+ }
+ }
+
+ } else if (Pepb == 0xFFFFFFFF) {
+ /* no method */
+
+ /* advance without doing anything */
+ remaining = L4;
+ while (remaining--)
+ L4_buf++;
+
+ } else if ((((Pepb & 0xF0000000) >> 28) == 2) || (((Pepb & 0xF0000000) >> 28) == 0)) {
+ /* RS coding here */
+
+ if (((Pepb & 0xF0000000) >> 28) == 0) {
+
+ k_post = k_pre;
+ n_post = n_pre;
+
+ } else {
+
+ k_post = 32;
+ n_post = (Pepb & 0x0000FF00) >> 8;
+ }
+
+ /* Initialize RS structures */
+ P = n_post - k_post;
+ NN_P = NN - P;
+ tt = (int) floor((float) P / 2.0F); /* again, correction capability */
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Correct post-data message words */
+ /*L4_buf = buffer + Lepb + 2;*/
+ L3_buf = L2_buf;
+ remaining = L4;
+ while (remaining) {
+
+ /* always zero-pad codewords */
+ /* (this is required, since after decoding the zeros in the long codeword
+ could change, and keep unchanged in subsequent calls) */
+ memset(codeword, 0, NN);
+
+ /* copy codeword buffer into message bytes */
+ if (remaining < k_post)
+ memcpy(codeword, L4_buf, remaining);
+ else
+ memcpy(codeword, L4_buf, k_post);
+
+ /* copy redundancy buffer in parity bytes */
+ memcpy(parityword, L3_buf, P);
+
+ /* Decode the buffer and possibly obtain corrected bytes */
+ status = eras_dec_rs(codeword, NULL, 0);
+ if (status == -1) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible decoding error in codeword @ position #%d\n", (L4_buf - (buffer + Lepb + 2)) / k_post);*/
+ errflag = true;
+
+ } else if (status == 0) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+ } else if (status <= tt) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+ errnum += status;
+
+ } else {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+ return false;*/
+ errflag = true;
+ }
+
+
+ /* advance parity buffer */
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L3_buf, parityword, P);
+ L3_buf += P;
+
+ /* advance message buffer */
+ if (remaining < k_post) {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L4_buf, codeword, remaining);
+ L4_buf += remaining;
+ remaining = 0;
+
+ } else {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L4_buf, codeword, k_post);
+ L4_buf += k_post;
+ remaining -= k_post;
+
+ }
+ }
+ }
+
+ /* give back the L4_buf address */
+ if (L4_bufp)
+ *L4_bufp = L4_buf;
+
+ /* print summary */
+ if (!conn) {
+
+ if (errnum)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- %d symbol errors corrected (Ps=%.1e)\n", errnum,
+ (float) errnum / (float) LDPepb);
+ if (errflag)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- there were unrecoverable errors\n");
+
+ }
+
+ cio_seek(j2k->cio, orig_pos);
+
+ return true;
+}
+
+void jpwl_epc_write(jpwl_epc_ms_t *epc, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_EPC >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_EPC >> 0);
+
+ /* Lepc */
+ *(buf++) = (unsigned char) (epc->Lepc >> 8);
+ *(buf++) = (unsigned char) (epc->Lepc >> 0);
+
+ /* Pcrc */
+ *(buf++) = (unsigned char) (epc->Pcrc >> 8);
+ *(buf++) = (unsigned char) (epc->Pcrc >> 0);
+
+ /* DL */
+ *(buf++) = (unsigned char) (epc->DL >> 24);
+ *(buf++) = (unsigned char) (epc->DL >> 16);
+ *(buf++) = (unsigned char) (epc->DL >> 8);
+ *(buf++) = (unsigned char) (epc->DL >> 0);
+
+ /* Pepc */
+ *(buf++) = (unsigned char) (epc->Pepc >> 0);
+
+ /* Data */
+ /*memcpy(buf, epc->data, (size_t) epc->Lepc - 9);*/
+ memset(buf, 0, (size_t) epc->Lepc - 9);
+};
+
+int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ int comps, unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, unsigned char se_size,
+ double place_pos, int tileno) {
+
+ return 0;
+}
+
+jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comp, unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, unsigned char se_size, int tileno,
+ unsigned long int svalnum, void *sensval) {
+
+ jpwl_esd_ms_t *esd = NULL;
+
+ /* Alloc space */
+ if (!(esd = (jpwl_esd_ms_t *) malloc((size_t) 1 * sizeof (jpwl_esd_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for ESD MS\n");
+ return NULL;
+ };
+
+ /* if relative sensitivity, activate byte range mode */
+ if (senst == 0)
+ addrm = 1;
+
+ /* size of sensval's ... */
+ if ((ad_size != 0) && (ad_size != 2) && (ad_size != 4)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address size %d for ESD MS is forbidden\n", ad_size);
+ return NULL;
+ }
+ if ((se_size != 1) && (se_size != 2)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Sensitivity size %d for ESD MS is forbidden\n", se_size);
+ return NULL;
+ }
+
+ /* ... depends on the addressing mode */
+ switch (addrm) {
+
+ /* packet mode */
+ case (0):
+ ad_size = 0; /* as per the standard */
+ esd->sensval_size = se_size;
+ break;
+
+ /* byte range */
+ case (1):
+ /* auto sense address size */
+ if (ad_size == 0)
+ /* if there are more than 66% of (2^16 - 1) bytes, switch to 4 bytes
+ (we keep space for possible EPBs being inserted) */
+ ad_size = (j2k->image_info->codestream_size > (1 * 65535 / 3)) ? 4 : 2;
+ esd->sensval_size = ad_size + ad_size + se_size;
+ break;
+
+ /* packet range */
+ case (2):
+ /* auto sense address size */
+ if (ad_size == 0)
+ /* if there are more than 2^16 - 1 packets, switch to 4 bytes */
+ ad_size = (j2k->image_info->num > 65535) ? 4 : 2;
+ esd->sensval_size = ad_size + ad_size + se_size;
+ break;
+
+ case (3):
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is unimplemented\n", addrm);
+ return NULL;
+
+ default:
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is forbidden\n", addrm);
+ return NULL;
+ }
+
+ /* set or unset sensitivity values */
+ if (svalnum <= 0) {
+
+ switch (senst) {
+
+ /* just based on the portions of a codestream */
+ case (0):
+ /* MH + no. of THs + no. of packets */
+ svalnum = 1 + (j2k->image_info->tw * j2k->image_info->th) * (1 + j2k->image_info->num);
+ break;
+
+ /* all the ones that are based on the packets */
+ default:
+ if (tileno < 0)
+ /* MH: all the packets and all the tiles info is written */
+ svalnum = j2k->image_info->tw * j2k->image_info->th * j2k->image_info->num;
+ else
+ /* TPH: only that tile info is written */
+ svalnum = j2k->image_info->num;
+ break;
+
+ }
+ }
+
+ /* fill private fields */
+ esd->senst = senst;
+ esd->ad_size = ad_size;
+ esd->se_size = se_size;
+ esd->addrm = addrm;
+ esd->svalnum = svalnum;
+ esd->numcomps = j2k->image->numcomps;
+ esd->tileno = tileno;
+
+ /* Set the ESD parameters */
+ /* length, excluding data field */
+ if (esd->numcomps < 257)
+ esd->Lesd = 4 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+ else
+ esd->Lesd = 5 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+
+ /* component data field */
+ if (comp >= 0)
+ esd->Cesd = comp;
+ else
+ /* we are averaging */
+ esd->Cesd = 0;
+
+ /* Pesd field */
+ esd->Pesd = 0x00;
+ esd->Pesd |= (esd->addrm & 0x03) << 6; /* addressing mode */
+ esd->Pesd |= (esd->senst & 0x07) << 3; /* sensitivity type */
+ esd->Pesd |= ((esd->se_size >> 1) & 0x01) << 2; /* sensitivity size */
+ esd->Pesd |= ((esd->ad_size >> 2) & 0x01) << 1; /* addressing size */
+ esd->Pesd |= (comp < 0) ? 0x01 : 0x00; /* averaging components */
+
+ /* if pointer to sensval is NULL, we can fill data field by ourselves */
+ if (!sensval) {
+
+ /* old code moved to jpwl_esd_fill() */
+ esd->data = NULL;
+
+ } else {
+ /* we set the data field as the sensitivity values poinnter passed to the function */
+ esd->data = (unsigned char *) sensval;
+ }
+
+ return (esd);
+}
+
+bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+ int i;
+ unsigned long int vv;
+ unsigned long int addr1, addr2;
+ double dvalue, Omax2, tmp, TSE, MSE, oldMSE, PSNR, oldPSNR;
+ unsigned short int pfpvalue;
+ unsigned long int addrmask = 0x00000000;
+ bool doneMH = false, doneTPH = false;
+
+ /* sensitivity values in image info are as follows:
+ - for each tile, distotile is the starting distortion for that tile, sum of all components
+ - for each packet in a tile, disto is the distortion reduction caused by that packet to that tile
+ - the TSE for a single tile should be given by distotile - sum(disto) , for all components
+ - the MSE for a single tile is given by TSE / nbpix , for all components
+ - the PSNR for a single tile is given by 10*log10( Omax^2 / MSE) , for all components
+ (Omax is given by 2^bpp - 1 for unsigned images and by 2^(bpp - 1) - 1 for signed images
+ */
+
+ /* browse all components and find Omax */
+ Omax2 = 0.0;
+ for (i = 0; i < j2k->image->numcomps; i++) {
+ tmp = pow(2.0, (double) (j2k->image->comps[i].sgnd ?
+ (j2k->image->comps[i].bpp - 1) : (j2k->image->comps[i].bpp))) - 1;
+ if (tmp > Omax2)
+ Omax2 = tmp;
+ }
+ Omax2 = Omax2 * Omax2;
+
+ /* if pointer of esd->data is not null, simply write down all the values byte by byte */
+ if (esd->data) {
+ for (i = 0; i < (int) esd->svalnum; i++)
+ *(buf++) = esd->data[i];
+ return true;
+ }
+
+ /* addressing mask */
+ if (esd->ad_size == 2)
+ addrmask = 0x0000FFFF; /* two bytes */
+ else
+ addrmask = 0xFFFFFFFF; /* four bytes */
+
+ /* set on precise point where sensitivity starts */
+ if (esd->numcomps < 257)
+ buf += 6;
+ else
+ buf += 7;
+
+ /* let's fill the data fields */
+ for (vv = (esd->tileno < 0) ? 0 : (j2k->image_info->num * esd->tileno); vv < esd->svalnum; vv++) {
+
+ int thistile = vv / j2k->image_info->num, thispacket = vv % j2k->image_info->num;
+
+ /* skip for the hack some lines below */
+ if (thistile == j2k->image_info->tw * j2k->image_info->th)
+ break;
+
+ /* starting tile distortion */
+ if (thispacket == 0) {
+ TSE = j2k->image_info->tile[thistile].distotile;
+ oldMSE = TSE / j2k->image_info->tile[thistile].nbpix;
+ oldPSNR = 10.0 * log10(Omax2 / oldMSE);
+ }
+
+ /* TSE */
+ TSE -= j2k->image_info->tile[thistile].packet[thispacket].disto;
+
+ /* MSE */
+ MSE = TSE / j2k->image_info->tile[thistile].nbpix;
+
+ /* PSNR */
+ PSNR = 10.0 * log10(Omax2 / MSE);
+
+ /* fill the address range */
+ switch (esd->addrm) {
+
+ /* packet mode */
+ case (0):
+ /* nothing, there is none */
+ break;
+
+ /* byte range */
+ case (1):
+ /* start address of packet */
+ addr1 = (j2k->image_info->tile[thistile].packet[thispacket].start_pos) & addrmask;
+ /* end address of packet */
+ addr2 = (j2k->image_info->tile[thistile].packet[thispacket].end_pos) & addrmask;
+ break;
+
+ /* packet range */
+ case (2):
+ /* not implemented here */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Addressing mode packet_range is not implemented\n");
+ break;
+
+ /* unknown addressing method */
+ default:
+ /* not implemented here */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown addressing mode\n");
+ break;
+
+ }
+
+ /* hack for writing relative sensitivity of MH and TPHs */
+ if ((esd->senst == 0) && (thispacket == 0)) {
+
+ /* possible MH */
+ if ((thistile == 0) && !doneMH) {
+ /* we have to manage MH addresses */
+ addr1 = 0; /* start of MH */
+ addr2 = j2k->image_info->main_head_end; /* end of MH */
+ /* set special dvalue for this MH */
+ dvalue = -10.0;
+ doneMH = true; /* don't come here anymore */
+ vv--; /* wrap back loop counter */
+
+ } else if (!doneTPH) {
+ /* we have to manage TPH addresses */
+ addr1 = j2k->image_info->tile[thistile].start_pos;
+ addr2 = j2k->image_info->tile[thistile].end_header;
+ /* set special dvalue for this TPH */
+ dvalue = -1.0;
+ doneTPH = true; /* don't come here till the next tile */
+ vv--; /* wrap back loop counter */
+ }
+
+ } else
+ doneTPH = false; /* reset TPH counter */
+
+ /* write the addresses to the buffer */
+ switch (esd->ad_size) {
+
+ case (0):
+ /* do nothing */
+ break;
+
+ case (2):
+ /* two bytes */
+ *(buf++) = (unsigned char) (addr1 >> 8);
+ *(buf++) = (unsigned char) (addr1 >> 0);
+ *(buf++) = (unsigned char) (addr2 >> 8);
+ *(buf++) = (unsigned char) (addr2 >> 0);
+ break;
+
+ case (4):
+ /* four bytes */
+ *(buf++) = (unsigned char) (addr1 >> 24);
+ *(buf++) = (unsigned char) (addr1 >> 16);
+ *(buf++) = (unsigned char) (addr1 >> 8);
+ *(buf++) = (unsigned char) (addr1 >> 0);
+ *(buf++) = (unsigned char) (addr2 >> 24);
+ *(buf++) = (unsigned char) (addr2 >> 16);
+ *(buf++) = (unsigned char) (addr2 >> 8);
+ *(buf++) = (unsigned char) (addr2 >> 0);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+
+ /* let's fill the value field */
+ switch (esd->senst) {
+
+ /* relative sensitivity */
+ case (0):
+ /* we just write down the packet ordering */
+ if (dvalue == -10)
+ /* MH */
+ dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+ else if (dvalue == -1)
+ /* TPH */
+ dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+ else
+ /* packet: first is most important, and then in decreasing order
+ down to the last, which counts for 1 */
+ dvalue = jpwl_pfp_to_double((unsigned short) (j2k->image_info->num - thispacket), esd->se_size);
+ break;
+
+ /* MSE */
+ case (1):
+ /* !!! WRONG: let's put here disto field of packets !!! */
+ dvalue = MSE;
+ break;
+
+ /* MSE reduction */
+ case (2):
+ dvalue = oldMSE - MSE;
+ oldMSE = MSE;
+ break;
+
+ /* PSNR */
+ case (3):
+ dvalue = PSNR;
+ break;
+
+ /* PSNR increase */
+ case (4):
+ dvalue = PSNR - oldPSNR;
+ oldPSNR = PSNR;
+ break;
+
+ /* MAXERR */
+ case (5):
+ dvalue = 0.0;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "MAXERR sensitivity mode is not implemented\n");
+ break;
+
+ /* TSE */
+ case (6):
+ dvalue = TSE;
+ break;
+
+ /* reserved */
+ case (7):
+ dvalue = 0.0;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Reserved sensitivity mode is not implemented\n");
+ break;
+
+ default:
+ dvalue = 0.0;
+ break;
+ }
+
+ /* compute the pseudo-floating point value */
+ pfpvalue = jpwl_double_to_pfp(dvalue, esd->se_size);
+
+ /* write the pfp value to the buffer */
+ switch (esd->se_size) {
+
+ case (1):
+ /* one byte */
+ *(buf++) = (unsigned char) (pfpvalue >> 0);
+ break;
+
+ case (2):
+ /* two bytes */
+ *(buf++) = (unsigned char) (pfpvalue >> 8);
+ *(buf++) = (unsigned char) (pfpvalue >> 0);
+ break;
+ }
+
+ }
+
+ return true;
+}
+
+void jpwl_esd_write(jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_ESD >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_ESD >> 0);
+
+ /* Lesd */
+ *(buf++) = (unsigned char) (esd->Lesd >> 8);
+ *(buf++) = (unsigned char) (esd->Lesd >> 0);
+
+ /* Cesd */
+ if (esd->numcomps >= 257)
+ *(buf++) = (unsigned char) (esd->Cesd >> 8);
+ *(buf++) = (unsigned char) (esd->Cesd >> 0);
+
+ /* Pesd */
+ *(buf++) = (unsigned char) (esd->Pesd >> 0);
+
+ /* Data */
+ if (esd->numcomps < 257)
+ memset(buf, 0xAA, (size_t) esd->Lesd - 4);
+ /*memcpy(buf, esd->data, (size_t) esd->Lesd - 4);*/
+ else
+ memset(buf, 0xAA, (size_t) esd->Lesd - 5);
+ /*memcpy(buf, esd->data, (size_t) esd->Lesd - 5);*/
+}
+
+unsigned short int jpwl_double_to_pfp(double V, int bytes) {
+
+ unsigned short int em, e, m;
+
+ switch (bytes) {
+
+ case (1):
+
+ if (V < MIN_V1) {
+ e = 0x0000;
+ m = 0x0000;
+ } else if (V > MAX_V1) {
+ e = 0x000F;
+ m = 0x000F;
+ } else {
+ e = (unsigned short int) (floor(log(V) * 1.44269504088896) / 4.0);
+ m = (unsigned short int) (0.5 + (V / (pow(2.0, (double) (4 * e)))));
+ }
+ em = ((e & 0x000F) << 4) + (m & 0x000F);
+ break;
+
+ case (2):
+
+ if (V < MIN_V2) {
+ e = 0x0000;
+ m = 0x0000;
+ } else if (V > MAX_V2) {
+ e = 0x001F;
+ m = 0x07FF;
+ } else {
+ e = (unsigned short int) floor(log(V) * 1.44269504088896) + 15;
+ m = (unsigned short int) (0.5 + 2048.0 * ((V / (pow(2.0, (double) e - 15.0))) - 1.0));
+ }
+ em = ((e & 0x001F) << 11) + (m & 0x07FF);
+ break;
+
+ default:
+
+ em = 0x0000;
+ break;
+ };
+
+ return em;
+}
+
+double jpwl_pfp_to_double(unsigned short int em, int bytes) {
+
+ double V;
+
+ switch (bytes) {
+
+ case 1:
+ V = (double) (em & 0x0F) * pow(2.0, (double) (em & 0xF0));
+ break;
+
+ case 2:
+
+ V = pow(2.0, (double) ((em & 0xF800) >> 11) - 15.0) * (1.0 + (double) (em & 0x07FF) / 2048.0);
+ break;
+
+ default:
+ V = 0.0;
+ break;
+
+ }
+
+ return V;
+
+}
+
+bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num) {
+
+ int mm;
+ unsigned long int addlen;
+
+ opj_image_info_t *info = j2k->image_info;
+ int tileno, packno, numtiles = info->th * info->tw, numpacks = info->num;
+
+ if (!j2k || !jwmarker ) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "J2K handle or JPWL markers list badly allocated\n");
+ return false;
+ }
+
+ /* main_head_end: how many markers are there before? */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->main_head_end)
+ addlen += jwmarker[mm].len + 2;
+ info->main_head_end += addlen;
+
+ /* codestream_size: always increment with all markers */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ addlen += jwmarker[mm].len + 2;
+ info->codestream_size += addlen;
+
+ /* navigate through all the tiles */
+ for (tileno = 0; tileno < numtiles; tileno++) {
+
+ /* start_pos: increment with markers before SOT */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].start_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].start_pos += addlen;
+
+ /* end_header: increment with markers before of it */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_header)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].end_header += addlen;
+
+ /* end_pos: increment with markers before the end of this tile */
+ /* code is disabled, since according to JPWL no markers can be beyond TPH */
+ /*addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_pos)
+ addlen += jwmarker[mm].len + 2;*/
+ info->tile[tileno].end_pos += addlen;
+
+ /* navigate through all the packets in this tile */
+ for (packno = 0; packno < numpacks; packno++) {
+
+ /* start_pos: increment with markers before the packet */
+ /* disabled for the same reason as before */
+ /*addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].start_pos)
+ addlen += jwmarker[mm].len + 2;*/
+ info->tile[tileno].packet[packno].start_pos += addlen;
+
+ /* end_pos: increment if marker is before the end of packet */
+ /* disabled for the same reason as before */
+ /*addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_pos)
+ addlen += jwmarker[mm].len + 2;*/
+ info->tile[tileno].packet[packno].end_pos += addlen;
+
+ }
+ }
+
+ return true;
+}
+
+#endif /* USE_JPWL */