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