[trunk] merge r1479 from branch 1.5 over to trunk
[openjpeg.git] / libopenjpeg / jpwl / jpwl.c
1 /*
2  * Copyright (c) 2001-2003, David Janssens
3  * Copyright (c) 2002-2003, Yannick Verschueren
4  * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
5  * Copyright (c) 2005, Herve Drolon, FreeImage Team
6  * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
7  * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "opj_includes.h"
33
34 #ifdef USE_JPWL
35
36 /** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */
37 /*@{*/
38
39 /** @name Local static variables */
40 /*@{*/
41
42 /** number of JPWL prepared markers */
43 static int jwmarker_num;
44 /** properties of JPWL markers to insert */
45 static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS]; 
46
47 /*@}*/
48
49 /*@}*/
50
51 /** @name Local static functions */
52 /*@{*/
53
54 /** create an EPC marker segment
55 @param j2k J2K compressor handle
56 @param esd_on true if ESD is activated
57 @param red_on true if RED is activated
58 @param epb_on true if EPB is activated
59 @param info_on true if informative techniques are activated
60 @return returns the freshly created EPC
61 */
62 jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on);
63
64 /*@}*/
65
66 /** create an EPC marker segment
67 @param j2k J2K compressor handle
68 @param comps considered component (-1=average, 0/1/2/...=component no.)
69 @param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)
70 @param ad_size size of addresses (2/4 bytes)
71 @param senst sensitivity type
72 @param se_size sensitivity values size (1/2 bytes)
73 @param tileno tile where this ESD lies (-1 means MH)
74 @param svalnum number of sensitivity values (if 0, they will be automatically filled)
75 @param sensval pointer to an array of sensitivity values (if NULL, they will be automatically filled)
76 @return returns the freshly created ESD
77 */
78 jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comps, 
79         unsigned char addrm, unsigned char ad_size,
80         unsigned char senst, int se_size, int tileno,
81         unsigned long int svalnum, void *sensval);
82                         
83 /** this function is used to compare two JPWL markers based on
84 their relevant wishlist position
85 @param arg1 pointer to first marker
86 @param arg2 pointer to second marker
87 @return 1 if arg1>arg2, 0 if arg1=arg2, -1 if arg1<arg2
88 */
89 int jpwl_markcomp(const void *arg1, const void *arg2);
90
91 /** write an EPB MS to a buffer
92 @param j2k J2K compressor handle
93 @param epbmark pointer to the EPB MS
94 @param buf pointer to the memory buffer
95 */
96 void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf);
97
98 /** write an EPC MS to a buffer
99 @param j2k J2K compressor handle
100 @param epcmark pointer to the EPC MS
101 @param buf pointer to the memory buffer
102 */
103 void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epcmark, unsigned char *buf);
104
105 /** write an ESD MS to a buffer
106 @param j2k J2K compressor handle
107 @param esdmark pointer to the ESD MS
108 @param buf pointer to the memory buffer
109 */
110 void jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);
111
112 /*-----------------------------------------------------------------*/
113
114 void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
115
116         int mm;
117
118         /* let's reset some settings */
119
120         /* clear the existing markers */
121         for (mm = 0; mm < jwmarker_num; mm++) {
122
123                 switch (jwmarker[mm].id) {
124
125                 case J2K_MS_EPB:
126                         opj_free(jwmarker[mm].m.epbmark);
127                         break;
128
129                 case J2K_MS_EPC:
130                         opj_free(jwmarker[mm].m.epcmark);
131                         break;
132
133                 case J2K_MS_ESD:
134                         opj_free(jwmarker[mm].m.esdmark);
135                         break;
136
137                 case J2K_MS_RED:
138                         opj_free(jwmarker[mm].m.redmark);
139                         break;
140
141                 default:
142                         break;
143                 }
144         }
145
146         /* clear the marker structure array */
147         memset(jwmarker, 0, sizeof(jpwl_marker_t) * JPWL_MAX_NO_MARKERS);
148
149         /* no more markers in the list */
150         jwmarker_num = 0;
151
152         /* let's begin creating a marker list, according to user wishes */
153         jpwl_prepare_marks(j2k, cio, image);
154
155         /* now we dump the JPWL markers on the codestream */
156         jpwl_dump_marks(j2k, cio, image);
157
158         /* do not know exactly what is this for,
159         but it gets called during index creation */
160         j2k->pos_correction = 0;
161
162 }
163
164 void j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
165
166         if (!cstr_info)
167                 return;
168
169         /* expand the list? */
170         if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {
171                 cstr_info->maxmarknum += 100;
172                 cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum * sizeof(opj_marker_info_t));
173         }
174
175         /* add the marker */
176         cstr_info->marker[cstr_info->marknum].type = type;
177         cstr_info->marker[cstr_info->marknum].pos = pos;
178         cstr_info->marker[cstr_info->marknum].len = len;
179         cstr_info->marknum++;
180
181 }
182
183 void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
184
185         unsigned short int socsiz_len = 0;
186         int ciopos = cio_tell(cio), soc_pos = j2k->cstr_info->main_head_start;
187         unsigned char *socp = NULL;
188
189         int tileno, acc_tpno, tpno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;
190
191         jpwl_epb_ms_t *epb_mark;
192         jpwl_epc_ms_t *epc_mark;
193         jpwl_esd_ms_t *esd_mark;
194   (void)image;
195
196         /* find (SOC + SIZ) length */
197         /* I assume SIZ is always the first marker after SOC */
198         cio_seek(cio, soc_pos + 4);
199         socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */
200         cio_seek(cio, soc_pos + 0);
201         socp = cio_getbp(cio); /* pointer to SOC */
202
203         /* 
204          EPC MS for Main Header: if we are here it's required
205         */
206         /* create the EPC */
207         if ((epc_mark = jpwl_epc_create(
208                         j2k,
209                         j2k->cp->esd_on, /* is ESD present? */
210                         j2k->cp->red_on, /* is RED present? */
211                         j2k->cp->epb_on, /* is EPB present? */
212                         OPJ_FALSE /* are informative techniques present? */
213                 ))) {
214
215                 /* Add this marker to the 'insertanda' list */
216                 if (epc_mark) {
217                         jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */
218                         jwmarker[jwmarker_num].m.epcmark = epc_mark; /* the EPC */
219                         jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
220                         jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */
221                         jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */
222                         jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
223                         jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
224                         jwmarker[jwmarker_num].parms_ready = OPJ_FALSE; /* not ready */
225                         jwmarker[jwmarker_num].data_ready = OPJ_TRUE; /* ready */
226                         jwmarker_num++;
227                 };
228
229                 opj_event_msg(j2k->cinfo, EVT_INFO,
230                         "MH  EPC : setting %s%s%s\n",
231                         j2k->cp->esd_on ? "ESD, " : "",
232                         j2k->cp->red_on ? "RED, " : "",
233                         j2k->cp->epb_on ? "EPB, " : ""
234                         );
235
236         } else {
237                 /* ooops, problems */
238                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");                              
239         };
240
241         /* 
242          ESD MS for Main Header
243         */
244         /* first of all, must MH have an ESD MS? */
245         if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {
246
247                 /* Create the ESD */
248                 if ((esd_mark = jpwl_esd_create(
249                         j2k, /* this encoder handle */
250                         -1, /* we are averaging over all components */
251                         (unsigned char) j2k->cp->sens_range, /* range method */
252                         (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */
253                         (unsigned char) j2k->cp->sens_MH, /* sensitivity method */
254                         j2k->cp->sens_size, /* sensitivity size */
255                         -1, /* this ESD is in main header */
256                         0 /*j2k->cstr_info->num*/, /* number of packets in codestream */
257                         NULL /*sensval*/ /* pointer to sensitivity data of packets */
258                         ))) {
259                         
260                         /* Add this marker to the 'insertanda' list */
261                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
262                                 jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
263                                 jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
264                                 jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* we choose to place it after SIZ */
265                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
266                                 jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
267                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* not ready, yet */
268                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
269                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
270                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
271                                 jwmarker_num++;
272                         }
273
274                         opj_event_msg(j2k->cinfo, EVT_INFO,
275                                 "MH  ESDs: method %d\n",
276                                 j2k->cp->sens_MH
277                                 );
278
279                 } else {
280                         /* ooops, problems */
281                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");                              
282                 };
283
284         }
285
286         /* 
287          ESD MSs for Tile Part Headers 
288         */
289         /* cycle through tiles */
290         sens = -1; /* default spec: no ESD */
291         tilespec = 0; /* first tile spec */
292         acc_tpno = 0;
293         for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
294
295                 opj_event_msg(j2k->cinfo, EVT_INFO,
296                         "Tile %d has %d tile part(s)\n",
297                         tileno, j2k->cstr_info->tile[tileno].num_tps
298                         );
299
300                 /* for every tile part in the tile */
301                 for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {
302         
303                         int sot_len, Psot, Psotp, mm;
304                         unsigned long sot_pos, post_sod_pos;
305
306                         unsigned long int left_THmarks_len;
307
308                         /******* sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
309                         sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
310                         cio_seek(cio, sot_pos + 2); 
311                         sot_len = cio_read(cio, 2); /* SOT Len */
312                         cio_skip(cio, 2);
313                         Psotp = cio_tell(cio);
314                         Psot = cio_read(cio, 4); /* tile length */
315
316                         /******* post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
317                         post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
318                         left_THmarks_len = post_sod_pos - sot_pos;
319
320                         /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */
321                         for (mm = 0; mm < jwmarker_num; mm++) {
322                                 if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
323                                         if (jwmarker[mm].len_ready)
324                                                 left_THmarks_len += jwmarker[mm].len + 2;
325                                         else {
326                                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
327                                                         jwmarker[mm].id, jwmarker[mm].dpos);                            
328                                                 exit(1);
329                                         }
330                                 }
331                         }
332
333                         /******* if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno)) */
334                         if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == acc_tpno))
335                                 /* we got a specification from this tile onwards */
336                                 sens = j2k->cp->sens_TPH[tilespec++];
337                 
338                         /* must this TPH have an ESD MS? */
339                         if (j2k->cp->esd_on && (sens >= 0)) {
340
341                                 /* Create the ESD */
342                                 if ((esd_mark = jpwl_esd_create(
343                                         j2k, /* this encoder handle */
344                                         -1, /* we are averaging over all components */
345                                         (unsigned char) j2k->cp->sens_range, /* range method */
346                                         (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */
347                                         (unsigned char) sens, /* sensitivity method */
348                                         j2k->cp->sens_size, /* sensitivity value size */
349                                         tileno, /* this ESD is in a tile */
350                                         0, /* number of packets in codestream */
351                                         NULL /* pointer to sensitivity data of packets */
352                                         ))) {
353                                         
354                                         /* Add this marker to the 'insertanda' list */
355                                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
356                                                 jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
357                                                 jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
358                                                 /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
359                                                 jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
360                                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
361                                                 jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
362                                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready, yet */
363                                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
364                                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
365                                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* ready */
366                                                 jwmarker_num++;
367                                         }
368
369                                         /* update Psot of the tile  */
370                                         cio_seek(cio, Psotp);
371                                         cio_write(cio, Psot + esd_mark->Lesd + 2, 4);
372
373                                         opj_event_msg(j2k->cinfo, EVT_INFO,
374                                                 /******* "TPH ESDs: tile %02d, method %d\n", */
375                                                 "TPH ESDs: tile %02d, part %02d, method %d\n",
376                                                 /******* tileno, */
377                                                 tileno, tpno,
378                                                 sens
379                                                 );
380
381                                 } else {
382                                         /* ooops, problems */
383                                         /***** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno); */
384                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d,%d\n", tileno, tpno);
385                                 };
386
387                         }
388                         
389                 }
390         
391         };
392
393         /* 
394          EPB MS for Main Header
395         */
396         /* first of all, must MH have an EPB MS? */
397         if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {
398
399                 int mm;
400
401                 /* position of SOT */
402                 unsigned int sot_pos = j2k->cstr_info->main_head_end + 1;
403
404                 /* how much space is there between end of SIZ and beginning of SOT? */
405                 int left_MHmarks_len = sot_pos - socsiz_len;
406
407                 /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */
408                 for (mm = 0; mm < jwmarker_num; mm++) {
409                         if ( jwmarker[mm].pos < sot_pos) { /* jwmarker[mm].pos >=0 since ulong */
410                                 if (jwmarker[mm].len_ready)
411                                         left_MHmarks_len += jwmarker[mm].len + 2;
412                                 else {
413                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",
414                                                 jwmarker[mm].id, jwmarker[mm].dpos);                            
415                                         exit(1);
416                                 }
417                         }
418                 }
419
420                 /* Create the EPB */
421                 if ((epb_mark = jpwl_epb_create(
422                         j2k, /* this encoder handle */
423                         OPJ_TRUE, /* is it the latest? */
424                         OPJ_TRUE, /* is it packed? not for now */
425                         -1, /* we are in main header */
426                         0, /* its index is 0 (first) */
427                         j2k->cp->hprot_MH, /* protection type parameters of data */
428                         socsiz_len, /* pre-data: only SOC+SIZ */
429                         left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */
430                         ))) {
431                         
432                         /* Add this marker to the 'insertanda' list */
433                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
434                                 jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */
435                                 jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */
436                                 jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
437                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
438                                 jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
439                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
440                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
441                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
442                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
443                                 jwmarker_num++;
444                         }
445
446                         opj_event_msg(j2k->cinfo, EVT_INFO,
447                                 "MH  EPB : prot. %d\n",
448                                 j2k->cp->hprot_MH
449                                 );
450
451                 } else {
452                         /* ooops, problems */
453                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");                              
454                 };
455         }
456
457         /* 
458          EPB MSs for Tile Parts
459         */
460         /* cycle through TPHs */
461         hprot = j2k->cp->hprot_MH; /* default spec */
462         tilespec = 0; /* first tile spec */
463         lastileno = 0;
464         packspec = 0;
465         pprot = -1;
466         acc_tpno = 0;
467         for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
468
469                 opj_event_msg(j2k->cinfo, EVT_INFO,
470                         "Tile %d has %d tile part(s)\n",
471                         tileno, j2k->cstr_info->tile[tileno].num_tps
472                         );
473
474                 /* for every tile part in the tile */
475                 for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) { 
476                 
477                         int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;
478                         unsigned long sot_pos, post_sod_pos;
479                         unsigned long int left_THmarks_len/*, epbs_len = 0*/;
480                         int startpack = 0, stoppack = j2k->cstr_info->packno;
481                         int first_tp_pack, last_tp_pack;
482                         jpwl_epb_ms_t *tph_epb = NULL;
483
484                         /****** sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
485                         sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
486                         cio_seek(cio, sot_pos + 2); 
487                         sot_len = cio_read(cio, 2); /* SOT Len */
488                         cio_skip(cio, 2);
489                         Psotp = cio_tell(cio);
490                         Psot = cio_read(cio, 4); /* tile length */
491
492                         /* a-priori length of the data dwelling between SOT and SOD */
493                         /****** post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
494                         post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
495                         left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);
496
497                         /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */
498                         for (mm = 0; mm < jwmarker_num; mm++) {
499                                 if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
500                                         if (jwmarker[mm].len_ready)
501                                                 left_THmarks_len += jwmarker[mm].len + 2;
502                                         else {
503                                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
504                                                         jwmarker[mm].id, jwmarker[mm].dpos);                            
505                                                 exit(1);
506                                         }
507                                 }
508                         }
509
510                         /****** if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno)) */
511                         if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == acc_tpno))
512                                 /* we got a specification from this tile part onwards */
513                                 hprot = j2k->cp->hprot_TPH[tilespec++];
514                 
515                         /* must this TPH have an EPB MS? */
516                         if (j2k->cp->epb_on && (hprot > 0)) {
517
518                                 /* Create the EPB */
519                                 if ((epb_mark = jpwl_epb_create(
520                                         j2k, /* this encoder handle */
521                                         OPJ_FALSE, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */
522                                         OPJ_TRUE, /* is it packed? yes for now */
523                                         tileno, /* we are in TPH */
524                                         epb_index++, /* its index is 0 (first) */
525                                         hprot, /* protection type parameters of following data */
526                                         sot_len + 2, /* pre-data length: only SOT */
527                                         left_THmarks_len /* post-data length: from SOT end to SOD inclusive */
528                                         ))) {
529                                         
530                                         /* Add this marker to the 'insertanda' list */
531                                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
532                                                 jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */
533                                                 jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */
534                                                 /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
535                                                 jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
536                                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
537                                                 jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
538                                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
539                                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
540                                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
541                                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
542                                                 jwmarker_num++;
543                                         }
544
545                                         /* update Psot of the tile  */
546                                         Psot += epb_mark->Lepb + 2;
547
548                                         opj_event_msg(j2k->cinfo, EVT_INFO,
549                                                 /***** "TPH EPB : tile %02d, prot. %d\n", */
550                                                 "TPH EPB : tile %02d, part %02d, prot. %d\n",
551                                                 /***** tileno, */
552                                                 tileno, tpno,
553                                                 hprot
554                                                 );
555
556                                         /* save this TPH EPB address */
557                                         tph_epb = epb_mark;
558
559                                 } else {
560                                         /* ooops, problems */
561                                         /****** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno); */
562                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB in #%d,d\n", tileno, tpno);
563                                 };
564
565                         }                               
566                 
567                         startpack = 0;
568                         /* EPB MSs for UEP packet data protection in Tile Parts */
569                         /****** for (packno = 0; packno < j2k->cstr_info->num; packno++) { */
570                         /*first_tp_pack = (tpno > 0) ? (first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno - 1].tp_numpacks) : 0;*/
571                         first_tp_pack = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pack;
572                         last_tp_pack = first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks - 1;
573                         for (packno = 0; packno < j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks; packno++) {
574
575                                 /******** if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
576                                         (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) { */
577                                 if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
578                                         (j2k->cp->pprot_tileno[packspec] == acc_tpno) && (j2k->cp->pprot_packno[packspec] == packno)) {
579
580                                         /* we got a specification from this tile and packet onwards */
581                                         /* print the previous spec */
582                                         if (packno > 0) {
583                                                 stoppack = packno - 1;                          
584                                                 opj_event_msg(j2k->cinfo, EVT_INFO,
585                                                         /***** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
586                                                         "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
587                                                         /***** tileno, */
588                                                         tileno, tpno,
589                                                         startpack,
590                                                         stoppack,
591                                                         /***** j2k->cstr_info->tile[tileno].packet[startpack].start_pos, */
592                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
593                                                         /***** j2k->cstr_info->tile[tileno].packet[stoppack].end_pos, */
594                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
595                                                         pprot);
596
597                                                 /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
598                                                         j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
599                                                 prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
600                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
601
602                                                 /*
603                                                   particular case: if this is the last header and the last packet,
604                                                   then it is better to protect even the EOC marker
605                                                 */
606                                                 /****** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
607                                                         (stoppack == (j2k->cstr_info->num - 1))) */
608                                                 if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
609                                                         (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
610                                                         (stoppack == last_tp_pack))
611                                                         /* add the EOC len */
612                                                         prot_len += 2;
613
614                                                 /* let's add the EPBs */
615                                                 Psot += jpwl_epbs_add(
616                                                         j2k, /* J2K handle */
617                                                         jwmarker, /* pointer to JPWL markers list */
618                                                         &jwmarker_num, /* pointer to the number of current markers */
619                                                         OPJ_FALSE, /* latest */
620                                                         OPJ_TRUE, /* packed */
621                                                         OPJ_FALSE, /* inside MH */
622                                                         &epb_index, /* pointer to EPB index */
623                                                         pprot, /* protection type */
624                                                         /****** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, */ /* position */
625                                                         (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
626                                                         tileno, /* number of tile */
627                                                         0, /* length of pre-data */
628                                                         prot_len /*4000*/ /* length of post-data */
629                                                         );
630                                         }
631
632                                         startpack = packno;
633                                         pprot = j2k->cp->pprot[packspec++];
634                                 }
635
636                                 /*printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);*/
637                 
638                         }
639
640                         /* we are at the end: print the remaining spec */
641                         stoppack = packno - 1;
642                         if (pprot >= 0) {
643
644                                 opj_event_msg(j2k->cinfo, EVT_INFO,
645                                         /**** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
646                                         "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
647                                         /**** tileno, */
648                                         tileno, tpno,
649                                         startpack,
650                                         stoppack,
651                                         /***** j2k->image_info->tile[tileno].packet[startpack].start_pos,
652                                         j2k->image_info->tile[tileno].packet[stoppack].end_pos, */
653                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
654                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
655                                         pprot);
656
657                                 /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
658                                         j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
659                                 prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
660                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
661
662                                 /*
663                                   particular case: if this is the last header and the last packet,
664                                   then it is better to protect even the EOC marker
665                                 */
666                                 /***** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
667                                         (stoppack == (j2k->cstr_info->num - 1))) */
668                                 if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
669                                         (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
670                                         (stoppack == last_tp_pack))
671                                         /* add the EOC len */
672                                         prot_len += 2;
673
674                                 /* let's add the EPBs */
675                                 Psot += jpwl_epbs_add(
676                                                         j2k, /* J2K handle */
677                                                         jwmarker, /* pointer to JPWL markers list */
678                                                         &jwmarker_num, /* pointer to the number of current markers */
679                                                         OPJ_TRUE, /* latest */
680                                                         OPJ_TRUE, /* packed */
681                                                         OPJ_FALSE, /* inside MH */
682                                                         &epb_index, /* pointer to EPB index */
683                                                         pprot, /* protection type */
684                                                         /***** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001,*/ /* position */
685                                                         (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
686                                                         tileno, /* number of tile */
687                                                         0, /* length of pre-data */
688                                                         prot_len /*4000*/ /* length of post-data */
689                                                         );
690                         }
691
692                         /* we can now check if the TPH EPB was really the last one */
693                         if (tph_epb && (epb_index == 1)) {
694                                 /* set the TPH EPB to be the last one in current header */
695                                 tph_epb->Depb |= (unsigned char) ((OPJ_TRUE & 0x0001) << 6);
696                                 tph_epb = NULL;
697                         }
698
699                         /* write back Psot */
700                         cio_seek(cio, Psotp);
701                         cio_write(cio, Psot, 4);
702                 
703                 }
704
705         };
706
707         /* reset the position */
708         cio_seek(cio, ciopos);
709
710 }
711
712 void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
713
714         int mm;
715         unsigned long int old_size = j2k->cstr_info->codestream_size;
716         unsigned long int new_size = old_size;
717         int /*ciopos = cio_tell(cio),*/ soc_pos = j2k->cstr_info->main_head_start;
718         unsigned char *jpwl_buf, *orig_buf;
719         unsigned long int orig_pos;
720         double epbcoding_time = 0.0, esdcoding_time = 0.0;
721   (void)image;
722
723         /* Order JPWL markers according to their wishlist position */
724         qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);
725
726         /* compute markers total size */ 
727         for (mm = 0; mm < jwmarker_num; mm++) {
728                 /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,
729                         jwmarker[mm].dpos, jwmarker[mm].len);*/
730                 new_size += jwmarker[mm].len + 2;
731         }
732
733         /* allocate a new buffer of proper size */
734         if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) (new_size + soc_pos) * sizeof(unsigned char)))) {
735                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL codestream buffer\n");
736                 exit(1);
737         };
738
739         /* copy the jp2 part, if any */
740         orig_buf = jpwl_buf;
741         memcpy(jpwl_buf, cio->buffer, soc_pos);
742         jpwl_buf += soc_pos;
743
744         /* cycle through markers */
745         orig_pos = soc_pos + 0; /* start from the beginning */
746         cio_seek(cio, soc_pos + 0); /* rewind the original */
747         for (mm = 0; mm < jwmarker_num; mm++) {
748
749                 /*
750                 need to copy a piece of the original codestream
751                 if there is such
752                 */
753                 memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);
754                 jpwl_buf += jwmarker[mm].pos - orig_pos;
755                 orig_pos = jwmarker[mm].pos;
756                 cio_seek(cio, orig_pos);
757
758                 /*
759                 then write down the marker
760                 */
761                 switch (jwmarker[mm].id) {
762
763                 case J2K_MS_EPB:
764                         jpwl_epb_write(j2k, jwmarker[mm].m.epbmark, jpwl_buf);
765                         break;
766
767                 case J2K_MS_EPC:
768                         jpwl_epc_write(j2k, jwmarker[mm].m.epcmark, jpwl_buf);
769                         break;
770
771                 case J2K_MS_ESD:
772                         jpwl_esd_write(j2k, jwmarker[mm].m.esdmark, jpwl_buf);
773                         break;
774
775                 case J2K_MS_RED:
776                         memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */
777                         break;
778
779                 default:
780                         break;
781                 };
782
783                 /* we update the markers struct */
784                 if (j2k->cstr_info)
785                         j2k->cstr_info->marker[j2k->cstr_info->marknum - 1].pos = (jpwl_buf - orig_buf);
786                 
787                 /* we set the marker dpos to the new position in the JPWL codestream */
788                 jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);
789
790                 /* advance JPWL buffer position */
791                 jpwl_buf += jwmarker[mm].len + 2;
792
793         }
794
795         /* finish remaining original codestream */
796         memcpy(jpwl_buf, cio_getbp(cio), old_size - (orig_pos - soc_pos));
797         jpwl_buf += old_size - (orig_pos - soc_pos);
798         cio_seek(cio, soc_pos + old_size);
799         
800         /*
801         update info file based on added markers
802         */
803         if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))
804                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ cstr_info structure\n");
805
806         /* now we need to repass some markers and fill their data fields */
807         
808         /* first of all, DL and Pcrc in EPCs */ 
809         for (mm = 0; mm < jwmarker_num; mm++) {
810
811                 /* find the EPCs */
812                 if (jwmarker[mm].id == J2K_MS_EPC) {
813
814                         int epc_pos = (int) jwmarker[mm].dpos, pp;
815                         unsigned short int mycrc = 0x0000;
816
817                         /* fix and fill the DL field */
818                         jwmarker[mm].m.epcmark->DL = new_size;
819                         orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 24);
820                         orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 16);
821                         orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 8);
822                         orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 0);
823
824                         /* compute the CRC field (excluding itself) */
825                         for (pp = 0; pp < 4; pp++)
826                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
827                         for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)
828                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
829
830                         /* fix and fill the CRC */
831                         jwmarker[mm].m.epcmark->Pcrc = mycrc;
832                         orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 8);
833                         orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 0);
834
835                 }
836         }
837
838         /* then, sensitivity data in ESDs */ 
839         esdcoding_time = opj_clock();
840         for (mm = 0; mm < jwmarker_num; mm++) {
841
842                 /* find the ESDs */
843                 if (jwmarker[mm].id == J2K_MS_ESD) {
844
845                         /* remember that they are now in a new position (dpos) */
846                         int esd_pos = (int) jwmarker[mm].dpos;
847
848                         jpwl_esd_fill(j2k, jwmarker[mm].m.esdmark, &orig_buf[esd_pos]);
849                 
850                 }
851
852         }
853         esdcoding_time = opj_clock() - esdcoding_time;
854         if (j2k->cp->esd_on)
855                 opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);
856
857         /* finally, RS or CRC parity in EPBs */ 
858         epbcoding_time = opj_clock();
859         for (mm = 0; mm < jwmarker_num; mm++) {
860
861                 /* find the EPBs */
862                 if (jwmarker[mm].id == J2K_MS_EPB) {
863
864                         /* remember that they are now in a new position (dpos) */
865                         int nn, accum_len;
866
867                         /* let's see how many EPBs are following this one, included itself */
868                         /* for this to work, we suppose that the markers are correctly ordered */
869                         /* and, overall, that they are in packed mode inside headers */
870                         accum_len = 0;
871                         for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
872                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
873                                 accum_len += jwmarker[nn].m.epbmark->Lepb + 2;
874
875                         /* fill the current (first) EPB with post-data starting from the computed position */
876                         jpwl_epb_fill(j2k, jwmarker[mm].m.epbmark, &orig_buf[(int) jwmarker[mm].dpos],
877                                 &orig_buf[(int) jwmarker[mm].dpos + accum_len]);
878                 
879                         /* fill the remaining EPBs in the header with post-data starting from the last position */
880                         for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
881                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
882                                 jpwl_epb_fill(j2k, jwmarker[nn].m.epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);
883
884                         /* skip all the processed EPBs */
885                         mm = nn - 1;
886                 }
887
888         }
889         epbcoding_time = opj_clock() - epbcoding_time;
890         if (j2k->cp->epb_on)
891                 opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);
892
893         /* free original cio buffer and set it to the JPWL one */
894         opj_free(cio->buffer);
895         cio->cinfo = cio->cinfo; /* no change */
896         cio->openmode = cio->openmode; /* no change */
897         cio->buffer = orig_buf;
898         cio->length = new_size + soc_pos;
899         cio->start = cio->buffer;
900         cio->end = cio->buffer + cio->length;
901         cio->bp = cio->buffer;
902         cio_seek(cio, soc_pos + new_size);
903
904 }
905
906
907 void j2k_read_epc(opj_j2k_t *j2k) {
908         unsigned long int DL, Lepcp, Pcrcp, l;
909         unsigned short int Lepc, Pcrc = 0x0000;
910         unsigned char Pepc;     
911         opj_cio_t *cio = j2k->cio;
912         const char *ans1;
913
914         /* Simply read the EPC parameters */
915         Lepcp = cio_tell(cio);
916         Lepc = cio_read(cio, 2);
917         Pcrcp = cio_tell(cio);
918         cio_skip(cio, 2); /* Pcrc */
919         DL = cio_read(cio, 4);
920         Pepc = cio_read(cio, 1);
921
922         /* compute Pcrc */
923         cio_seek(cio, Lepcp - 2);
924
925                 /* Marker */
926                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
927                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
928
929                 /* Length */
930                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
931                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
932
933                 /* skip Pcrc */
934                 cio_skip(cio, 2);
935
936                 /* read all remaining */
937                 for (l = 4; l < Lepc; l++)
938                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
939
940                 /* check Pcrc with the result */
941                 cio_seek(cio, Pcrcp);
942                 ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";
943
944         /* now we write them to screen */
945         opj_event_msg(j2k->cinfo, EVT_INFO, 
946                 "EPC(%u,%d): %s, DL=%d%s %s %s\n",
947                 Lepcp - 2,
948                 Lepc,
949                 ans1,
950                 DL, /* data length this EPC is referring to */
951                 (Pepc & 0x10) ? ", esd" : "", /* ESD is present */
952                 (Pepc & 0x20) ? ", red" : "", /* RED is present */
953                 (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */
954
955         cio_seek(cio, Lepcp + Lepc);  
956 }
957
958 void j2k_write_epc(opj_j2k_t *j2k) {
959
960         unsigned long int DL, Lepcp, Pcrcp, l;
961         unsigned short int Lepc, Pcrc;
962         unsigned char Pepc;     
963
964         opj_cio_t *cio = j2k->cio;
965
966         cio_write(cio, J2K_MS_EPC, 2);  /* EPC */
967         Lepcp = cio_tell(cio);
968         cio_skip(cio, 2);
969
970         /* CRC-16 word of the EPC */
971         Pcrc = 0x0000; /* initialize */
972         Pcrcp = cio_tell(cio);
973         cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/
974
975         /* data length of the EPC protection domain */
976         DL = 0x00000000; /* we leave this set to 0, as if the information is not available */
977         cio_write(cio, DL, 4);   /* DL */
978
979         /* jpwl capabilities */
980         Pepc = 0x00;
981         cio_write(cio, Pepc, 1); /* Pepc */
982
983         /* ID section */
984         /* no ID's, as of now */
985
986         Lepc = (unsigned short) (cio_tell(cio) - Lepcp);
987         cio_seek(cio, Lepcp);
988         cio_write(cio, Lepc, 2); /* Lepc */
989
990         /* compute Pcrc */
991         cio_seek(cio, Lepcp - 2);
992
993                 /* Marker */
994                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
995                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
996
997                 /* Length */
998                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
999                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
1000
1001                 /* skip Pcrc */
1002                 cio_skip(cio, 2);
1003
1004                 /* read all remaining */
1005                 for (l = 4; l < Lepc; l++)
1006                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); 
1007
1008                 /* fill Pcrc with the result */
1009                 cio_seek(cio, Pcrcp);
1010                 cio_write(cio, Pcrc, 2);
1011
1012         cio_seek(cio, Lepcp + Lepc);
1013
1014         /* marker struct update */
1015         j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, Lepcp - 2, Lepc + 2);
1016
1017 }
1018
1019 void j2k_read_epb(opj_j2k_t *j2k) {
1020         unsigned long int LDPepb, Pepb;
1021         unsigned short int Lepb;
1022         unsigned char Depb;
1023         char str1[25] = "";
1024         opj_bool status;
1025         static opj_bool first_in_tph = OPJ_TRUE;
1026         int type, pre_len, post_len;
1027         static unsigned char *redund = NULL;
1028         
1029         opj_cio_t *cio = j2k->cio;
1030
1031         /* B/W = 45, RGB = 51 */
1032         /*           SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */
1033         int skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;
1034
1035         if (j2k->cp->correct) {
1036
1037                 /* go back to EPB marker value */
1038                 cio_seek(cio, cio_tell(cio) - 2);
1039
1040                 /* we need to understand where we are */
1041                 if (j2k->state == J2K_STATE_MH) {
1042                         /* we are in MH */
1043                         type = 0; /* MH */
1044                         pre_len = skipnum; /* SOC+SIZ */
1045                         post_len = -1; /* auto */
1046
1047                 } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {
1048                         /* we are in TPH */
1049                         type = 1; /* TPH */
1050                         pre_len = 12; /* SOC+SIZ */
1051                         first_in_tph = OPJ_FALSE;
1052                         post_len = -1; /* auto */
1053
1054                 } else {
1055                         /* we are elsewhere */
1056                         type = 2; /* other */
1057                         pre_len = 0; /* nada */
1058                         post_len = -1; /* auto */
1059
1060                 }
1061
1062                 /* call EPB corrector */
1063                 /*printf("before %x, ", redund);*/
1064                 status = jpwl_epb_correct(j2k,      /* J2K decompressor handle */
1065                                                                   cio->bp,  /* pointer to EPB in codestream buffer */
1066                                                                   type,     /* EPB type: MH */
1067                                                                   pre_len,  /* length of pre-data */
1068                                                                   post_len, /* length of post-data: -1 means auto */
1069                                                                   NULL,     /* do everything auto */
1070                                                                   &redund
1071                                                                  );
1072                 /*printf("after %x\n", redund);*/
1073
1074                 /* Read the (possibly corrected) EPB parameters */
1075                 cio_skip(cio, 2);
1076                 Lepb = cio_read(cio, 2);
1077                 Depb = cio_read(cio, 1);
1078                 LDPepb = cio_read(cio, 4);
1079                 Pepb = cio_read(cio, 4);
1080
1081                 if (!status) {
1082
1083                         opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");
1084
1085                         /* advance to EPB endpoint */
1086                         cio_skip(cio, Lepb + 2);  
1087
1088                         return;
1089                 }
1090
1091                 /* last in current header? */
1092                 if (Depb & 0x40) {
1093                         redund = NULL; /* reset the pointer to L4 buffer */
1094                         first_in_tph = OPJ_TRUE;
1095                 }
1096
1097                 /* advance to EPB endpoint */
1098                 cio_skip(cio, Lepb - 11);  
1099
1100         } else {
1101
1102                 /* Simply read the EPB parameters */
1103                 Lepb = cio_read(cio, 2);
1104                 Depb = cio_read(cio, 1);
1105                 LDPepb = cio_read(cio, 4);
1106                 Pepb = cio_read(cio, 4);
1107
1108                 /* What does Pepb tells us about the protection method? */
1109                 if (((Pepb & 0xF0000000) >> 28) == 0)
1110                         sprintf(str1, "pred"); /* predefined */
1111                 else if (((Pepb & 0xF0000000) >> 28) == 1)
1112                         sprintf(str1, "crc-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
1113                 else if (((Pepb & 0xF0000000) >> 28) == 2)
1114                         sprintf(str1, "rs(%lu,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
1115                 else if (Pepb == 0xFFFFFFFF)
1116                         sprintf(str1, "nometh"); /* RS mode */
1117                 else
1118                         sprintf(str1, "unknown"); /* unknown */
1119
1120                 /* Now we write them to screen */
1121                 opj_event_msg(j2k->cinfo, EVT_INFO,
1122                         "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
1123                         cio_tell(cio) - 13,
1124                         (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
1125                         (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
1126                         (Depb & 0x3F), /* EPB index value */
1127                         LDPepb, /*length of the data protected by the EPB */
1128                         str1); /* protection method */
1129
1130                 cio_skip(cio, Lepb - 11);  
1131         }
1132 }
1133
1134 void j2k_write_epb(opj_j2k_t *j2k) {
1135         unsigned long int LDPepb, Pepb, Lepbp;
1136         unsigned short int Lepb;
1137         unsigned char Depb;
1138
1139         opj_cio_t *cio = j2k->cio;
1140
1141         cio_write(cio, J2K_MS_EPB, 2);  /* EPB */
1142         Lepbp = cio_tell(cio);
1143         cio_skip(cio, 2);
1144
1145         /* EPB style */
1146         Depb = 0x00; /* test */
1147         cio_write(cio, Depb, 1);   /* Depb */
1148
1149         /* length of the data to be protected by this EPB */
1150         LDPepb = 0x00000000; /* test */
1151         cio_write(cio, LDPepb, 4);   /* LDPepb */
1152
1153         /* next error correction tool */
1154         Pepb = 0x00000000; /* test */
1155         cio_write(cio, Pepb, 4);   /* Pepb */
1156
1157         /* EPB data */
1158         /* no data, as of now */
1159
1160         Lepb = (unsigned short) (cio_tell(cio) - Lepbp);
1161         cio_seek(cio, Lepbp);
1162         cio_write(cio, Lepb, 2);                /* Lepb */
1163
1164         cio_seek(cio, Lepbp + Lepb);
1165
1166         /* marker struct update */
1167         j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, Lepbp - 2, Lepb + 2);
1168 }
1169
1170 void j2k_read_esd(opj_j2k_t *j2k) {
1171         unsigned short int Lesd, Cesd;
1172         unsigned char Pesd;
1173
1174         int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;
1175
1176         char str1[4][4] = {"p", "br", "pr", "res"};
1177         char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};
1178         
1179         opj_cio_t *cio = j2k->cio;
1180
1181         /* Simply read the ESD parameters */
1182         Lesd = cio_read(cio, 2);
1183         Cesd = cio_read(cio, cesdsize);
1184         Pesd = cio_read(cio, 1);
1185
1186         /* Now we write them to screen */
1187         opj_event_msg(j2k->cinfo, EVT_INFO,
1188                 "ESD(%d): c%d, %s, %s, %s, %s, %s\n",
1189                 cio_tell(cio) - (5 + cesdsize),
1190                 Cesd, /* component number for this ESD */
1191                 str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */
1192                 str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */
1193                 ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",
1194                 ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",
1195                 (Pesd & (unsigned char) 0x01) ? "avgc" : "");
1196
1197         cio_skip(cio, Lesd - (3 + cesdsize));  
1198 }
1199
1200 void j2k_read_red(opj_j2k_t *j2k) {
1201         unsigned short int Lred;
1202         unsigned char Pred;
1203         char str1[4][4] = {"p", "br", "pr", "res"};
1204         
1205         opj_cio_t *cio = j2k->cio;
1206
1207         /* Simply read the RED parameters */
1208         Lred = cio_read(cio, 2);
1209         Pred = cio_read(cio, 1);
1210
1211         /* Now we write them to screen */
1212         opj_event_msg(j2k->cinfo, EVT_INFO,
1213                 "RED(%d): %s, %dc, %s, %s\n",
1214                 cio_tell(cio) - 5,
1215                 str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */
1216                 (Pred & (unsigned char) 0x38) >> 3, /* corruption level */
1217                 ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */
1218                 (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */
1219
1220         cio_skip(cio, Lred - 3);  
1221 }
1222
1223 opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {
1224
1225 #ifdef oerhgierhgvhreit4u
1226         /*
1227            we navigate through the tile and find possible invalid parameters:
1228        this saves a lot of crashes!!!!!
1229          */
1230         int compno, resno, precno, /*layno,*/ bandno, blockno;
1231         int numprecincts, numblocks;
1232
1233         /* this is the selected tile */
1234         opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);
1235
1236         /* will keep the component */
1237         opj_tcd_tilecomp_t *comp = NULL;
1238
1239         /* will keep the resolution */
1240         opj_tcd_resolution_t *res;
1241
1242         /* will keep the subband */
1243         opj_tcd_band_t *band; 
1244
1245         /* will keep the precinct */
1246         opj_tcd_precinct_t *prec; 
1247
1248         /* will keep the codeblock */
1249         opj_tcd_cblk_t *block;
1250
1251         /* check all tile components */
1252         for (compno = 0; compno < tile->numcomps; compno++) {
1253                 comp = &(tile->comps[compno]);
1254
1255                 /* check all component resolutions */
1256                 for (resno = 0; resno < comp->numresolutions; resno++) {
1257                         res = &(comp->resolutions[resno]);
1258                         numprecincts = res->pw * res->ph;
1259
1260                         /* check all the subbands */
1261                         for (bandno = 0; bandno < res->numbands; bandno++) {
1262                                 band = &(res->bands[bandno]);
1263
1264                                 /* check all the precincts */
1265                                 for (precno = 0; precno < numprecincts; precno++) {
1266                                         prec = &(band->precincts[precno]);
1267                                         numblocks = prec->ch * prec->cw;
1268
1269                                         /* check all the codeblocks */
1270                                         for (blockno = 0; blockno < numblocks; blockno++) {
1271                                                 block = &(prec->cblks[blockno]);
1272
1273                                                 /* x-origin is invalid */
1274                                                 if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {
1275                                                         opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
1276                                                                 "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",
1277                                                                 block->x0, prec->x0, prec->x1);
1278                                                         if (!JPWL_ASSUME || JPWL_ASSUME)
1279                                                                 return OPJ_FALSE;
1280                                                 };
1281                                         }
1282                                 }                               
1283                         }
1284                 }
1285         }
1286
1287 #else
1288   (void)j2k;
1289   (void)tcd;
1290   (void)tileno;
1291 #endif
1292
1293         return OPJ_TRUE;
1294 }
1295
1296 /*@}*/
1297
1298 #endif /* USE_JPWL */
1299
1300
1301 #ifdef USE_JPSEC
1302
1303 /** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */
1304 /*@{*/
1305
1306
1307 /** @name Local static functions */
1308 /*@{*/
1309
1310 void j2k_read_sec(opj_j2k_t *j2k) {
1311         unsigned short int Lsec;
1312         
1313         opj_cio_t *cio = j2k->cio;
1314
1315         /* Simply read the SEC length */
1316         Lsec = cio_read(cio, 2);
1317
1318         /* Now we write them to screen */
1319         opj_event_msg(j2k->cinfo, EVT_INFO,
1320                 "SEC(%d)\n",
1321                 cio_tell(cio) - 2
1322                 );
1323
1324         cio_skip(cio, Lsec - 2);  
1325 }
1326
1327 void j2k_write_sec(opj_j2k_t *j2k) {
1328         unsigned short int Lsec = 24;
1329         int i;
1330
1331         opj_cio_t *cio = j2k->cio;
1332
1333         cio_write(cio, J2K_MS_SEC, 2);  /* SEC */
1334         cio_write(cio, Lsec, 2);
1335
1336         /* write dummy data */
1337         for (i = 0; i < Lsec - 2; i++)
1338                 cio_write(cio, 0, 1);
1339 }
1340
1341 void j2k_read_insec(opj_j2k_t *j2k) {
1342         unsigned short int Linsec;
1343         
1344         opj_cio_t *cio = j2k->cio;
1345
1346         /* Simply read the INSEC length */
1347         Linsec = cio_read(cio, 2);
1348
1349         /* Now we write them to screen */
1350         opj_event_msg(j2k->cinfo, EVT_INFO,
1351                 "INSEC(%d)\n",
1352                 cio_tell(cio) - 2
1353                 );
1354
1355         cio_skip(cio, Linsec - 2);  
1356 }
1357
1358
1359 /*@}*/
1360
1361 /*@}*/
1362
1363 #endif /* USE_JPSEC */
1364