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