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