* Better fix of the TPH EPBs bug in JPWL module
[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 #ifdef USE_JPWL\r
33 \r
34 #include "../libopenjpeg/opj_includes.h"\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 /** position of markers to insert */\r
43 static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS]; \r
44 /** number of prepared markers */\r
45 static int jwmarker_num;\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_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
111 \r
112         unsigned short int socsiz_len = 0;\r
113         int ciopos = cio_tell(cio);\r
114         unsigned char *socp = NULL;\r
115 \r
116         int tileno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;\r
117 \r
118         jpwl_epb_ms_t *epb_mark;\r
119         jpwl_epc_ms_t *epc_mark;\r
120         jpwl_esd_ms_t *esd_mark;\r
121 \r
122         /* find SOC + SIZ length */\r
123         /* I assume SIZ is always the first marker after SOC */\r
124         cio_seek(cio, 4);\r
125         socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */\r
126         cio_seek(cio, 0);\r
127         socp = cio_getbp(cio); /* pointer to SOC */\r
128 \r
129         /* \r
130          EPC MS for Main Header: if we are here it's required\r
131         */\r
132         /* create the EPC */\r
133         if (epc_mark = jpwl_epc_create(\r
134                         j2k,\r
135                         j2k->cp->esd_on, /* is ESD present? */\r
136                         j2k->cp->red_on, /* is RED present? */\r
137                         j2k->cp->epb_on, /* is EPB present? */\r
138                         false /* are informative techniques present? */\r
139                 )) {\r
140 \r
141                 /* Add this marker to the 'insertanda' list */\r
142                 if (epc_mark) {\r
143                         jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */\r
144                         jwmarker[jwmarker_num].epcmark = epc_mark; /* the EPC */\r
145                         jwmarker[jwmarker_num].pos = socsiz_len; /* after SIZ */\r
146                         jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */\r
147                         jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */\r
148                         jwmarker[jwmarker_num].len_ready = true; /* ready */\r
149                         jwmarker[jwmarker_num].pos_ready = true; /* ready */\r
150                         jwmarker[jwmarker_num].parms_ready = false; /* not ready */\r
151                         jwmarker[jwmarker_num].data_ready = true; /* ready */\r
152                         jwmarker_num++;\r
153                 };\r
154 \r
155                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
156                         "MH  EPC : setting %s%s%s\n",\r
157                         j2k->cp->esd_on ? "ESD, " : "",\r
158                         j2k->cp->red_on ? "RED, " : "",\r
159                         j2k->cp->epb_on ? "EPB, " : ""\r
160                         );\r
161 \r
162         } else {\r
163                 /* ooops, problems */\r
164                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");                              \r
165         };\r
166 \r
167         /* \r
168          ESD MS for Main Header\r
169         */\r
170         /* first of all, must MH have an ESD MS? */\r
171         if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {\r
172 \r
173                 /* Create the ESD */\r
174                 if (esd_mark = jpwl_esd_create(\r
175                         j2k, /* this encoder handle */\r
176                         -1, /* we are averaging over all components */\r
177                         (unsigned char) j2k->cp->sens_range, /* range method */\r
178                         (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */\r
179                         (unsigned char) j2k->cp->sens_MH, /* sensitivity method */\r
180                         j2k->cp->sens_size, /* sensitivity size */\r
181                         -1, /* this ESD is in main header */\r
182                         0 /*j2k->image_info->num*/, /* number of packets in codestream */\r
183                         NULL /*sensval*/ /* pointer to sensitivity data of packets */\r
184                         )) {\r
185                         \r
186                         /* Add this marker to the 'insertanda' list */\r
187                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
188                                 jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */\r
189                                 jwmarker[jwmarker_num].esdmark = esd_mark; /* the EPB */\r
190                                 jwmarker[jwmarker_num].pos = socsiz_len; /* we choose to place it after SIZ */\r
191                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
192                                 jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
193                                 jwmarker[jwmarker_num].len_ready = true; /* not ready, yet */\r
194                                 jwmarker[jwmarker_num].pos_ready = true; /* ready */\r
195                                 jwmarker[jwmarker_num].parms_ready = true; /* not ready */\r
196                                 jwmarker[jwmarker_num].data_ready = false; /* not ready */\r
197                                 jwmarker_num++;\r
198                         }\r
199 \r
200                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
201                                 "MH  ESDs: method %d\n",\r
202                                 j2k->cp->sens_MH\r
203                                 );\r
204 \r
205                 } else {\r
206                         /* ooops, problems */\r
207                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");                              \r
208                 };\r
209 \r
210         }\r
211 \r
212         /* \r
213          ESD MSs for Tile Part Headers \r
214         */\r
215         /* cycle through TPHs */\r
216         sens = -1; /* default spec: no ESD */\r
217         tilespec = 0; /* first tile spec */\r
218         for (tileno = 0; tileno < j2k->image_info->tw * j2k->image_info->th; tileno++) {\r
219 \r
220                 int sot_len, Psot, Psotp, mm;\r
221                 unsigned long sot_pos, post_sod_pos;\r
222 \r
223                 unsigned long int left_THmarks_len;\r
224 \r
225                 sot_pos = j2k->image_info->tile[tileno].start_pos;\r
226                 cio_seek(cio, sot_pos + 2); \r
227                 sot_len = cio_read(cio, 2); /* SOT Len */\r
228                 cio_skip(cio, 2);\r
229                 Psotp = cio_tell(cio);\r
230                 Psot = cio_read(cio, 4); /* tile length */\r
231 \r
232                 post_sod_pos = j2k->image_info->tile[tileno].end_header + 1;\r
233                 left_THmarks_len = post_sod_pos - sot_pos;\r
234 \r
235                 /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */\r
236                 for (mm = 0; mm < jwmarker_num; mm++) {\r
237                         if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
238                                 if (jwmarker[mm].len_ready)\r
239                                         left_THmarks_len += jwmarker[mm].len + 2;\r
240                                 else {\r
241                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
242                                                 jwmarker[mm].id, jwmarker[mm].dpos);                            \r
243                                         exit(1);\r
244                                 }\r
245                         }\r
246                 }\r
247 \r
248                 if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno))\r
249                         /* we got a specification from this tile onwards */\r
250                         sens = j2k->cp->sens_TPH[tilespec++];\r
251         \r
252                 /* must this TPH have an ESD MS? */\r
253                 if (j2k->cp->esd_on && (sens >= 0)) {\r
254 \r
255                         /* Create the ESD */\r
256                         if (esd_mark = jpwl_esd_create(\r
257                                 j2k, /* this encoder handle */\r
258                                 -1, /* we are averaging over all components */\r
259                                 (unsigned char) j2k->cp->sens_range, /* range method */\r
260                                 (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */\r
261                                 (unsigned char) sens, /* sensitivity method */\r
262                                 j2k->cp->sens_size, /* sensitivity value size */\r
263                                 tileno, /* this ESD is in a tile */\r
264                                 0, /* number of packets in codestream */\r
265                                 NULL /* pointer to sensitivity data of packets */\r
266                                 )) {\r
267                                 \r
268                                 /* Add this marker to the 'insertanda' list */\r
269                                 if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
270                                         jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */\r
271                                         jwmarker[jwmarker_num].esdmark = esd_mark; /* the EPB */\r
272                                         jwmarker[jwmarker_num].pos = j2k->image_info->tile[tileno].start_pos + sot_len + 2; /* after SOT */\r
273                                         jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
274                                         jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
275                                         jwmarker[jwmarker_num].len_ready = true; /* ready, yet */\r
276                                         jwmarker[jwmarker_num].pos_ready = true; /* ready */\r
277                                         jwmarker[jwmarker_num].parms_ready = true; /* not ready */\r
278                                         jwmarker[jwmarker_num].data_ready = false; /* ready */\r
279                                         jwmarker_num++;\r
280                                 }\r
281 \r
282                                 /* update Psot of the tile  */\r
283                                 cio_seek(cio, Psotp);\r
284                                 cio_write(cio, Psot + esd_mark->Lesd + 2, 4);\r
285 \r
286                                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
287                                         "TPH ESDs: tile %02d, method %d\n",\r
288                                         tileno,\r
289                                         sens\r
290                                         );\r
291 \r
292                         } else {\r
293                                 /* ooops, problems */\r
294                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno);                         \r
295                         };\r
296 \r
297                 }                               \r
298         \r
299         };\r
300 \r
301         /* \r
302          EPB MS for Main Header\r
303         */\r
304         /* first of all, must MH have an EPB MS? */\r
305         if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {\r
306 \r
307                 int mm;\r
308 \r
309                 /* position of SOT */\r
310                 unsigned int sot_pos = j2k->image_info->main_head_end + 1;\r
311 \r
312                 /* how much space is there between end of SIZ and beginning of SOT? */\r
313                 int left_MHmarks_len = sot_pos - socsiz_len;\r
314 \r
315                 /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */\r
316                 for (mm = 0; mm < jwmarker_num; mm++) {\r
317                         if ((jwmarker[mm].pos >=0) && (jwmarker[mm].pos < sot_pos)) {\r
318                                 if (jwmarker[mm].len_ready)\r
319                                         left_MHmarks_len += jwmarker[mm].len + 2;\r
320                                 else {\r
321                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",\r
322                                                 jwmarker[mm].id, jwmarker[mm].dpos);                            \r
323                                         exit(1);\r
324                                 }\r
325                         }\r
326                 }\r
327 \r
328                 /* Create the EPB */\r
329                 if (epb_mark = jpwl_epb_create(\r
330                         j2k, /* this encoder handle */\r
331                         true, /* is it the latest? */\r
332                         true, /* is it packed? not for now */\r
333                         -1, /* we are in main header */\r
334                         0, /* its index is 0 (first) */\r
335                         j2k->cp->hprot_MH, /* protection type parameters of data */\r
336                         socsiz_len, /* pre-data: only SOC+SIZ */\r
337                         left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */\r
338                         )) {\r
339                         \r
340                         /* Add this marker to the 'insertanda' list */\r
341                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
342                                 jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */\r
343                                 jwmarker[jwmarker_num].epbmark = epb_mark; /* the EPB */\r
344                                 jwmarker[jwmarker_num].pos = socsiz_len; /* after SIZ */\r
345                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
346                                 jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
347                                 jwmarker[jwmarker_num].len_ready = true; /* ready */\r
348                                 jwmarker[jwmarker_num].pos_ready = true; /* ready */\r
349                                 jwmarker[jwmarker_num].parms_ready = true; /* ready */\r
350                                 jwmarker[jwmarker_num].data_ready = false; /* not ready */\r
351                                 jwmarker_num++;\r
352                         }\r
353 \r
354                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
355                                 "MH  EPB : prot. %d\n",\r
356                                 j2k->cp->hprot_MH\r
357                                 );\r
358 \r
359                 } else {\r
360                         /* ooops, problems */\r
361                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");                              \r
362                 };\r
363         }\r
364 \r
365         /* \r
366          EPB MSs for Tile Parts\r
367         */\r
368         /* cycle through TPHs */\r
369         hprot = j2k->cp->hprot_MH; /* default spec */\r
370         tilespec = 0; /* first tile spec */\r
371         lastileno = 0;\r
372         packspec = 0;\r
373         pprot = -1;\r
374         for (tileno = 0; tileno < j2k->image_info->tw * j2k->image_info->th; tileno++) {\r
375 \r
376                 int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;\r
377                 unsigned long sot_pos, post_sod_pos;\r
378                 unsigned long int left_THmarks_len, epbs_len = 0;\r
379                 int startpack = 0, stoppack = j2k->image_info->num;\r
380                 jpwl_epb_ms_t *tph_epb = NULL;\r
381 \r
382                 sot_pos = j2k->image_info->tile[tileno].start_pos;\r
383                 cio_seek(cio, sot_pos + 2); \r
384                 sot_len = cio_read(cio, 2); /* SOT Len */\r
385                 cio_skip(cio, 2);\r
386                 Psotp = cio_tell(cio);\r
387                 Psot = cio_read(cio, 4); /* tile length */\r
388 \r
389                 /* a-priori length of the data dwelling between SOT and SOD */\r
390                 post_sod_pos = j2k->image_info->tile[tileno].end_header + 1;\r
391                 left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);\r
392 \r
393                 /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */\r
394                 for (mm = 0; mm < jwmarker_num; mm++) {\r
395                         if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
396                                 if (jwmarker[mm].len_ready)\r
397                                         left_THmarks_len += jwmarker[mm].len + 2;\r
398                                 else {\r
399                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
400                                                 jwmarker[mm].id, jwmarker[mm].dpos);                            \r
401                                         exit(1);\r
402                                 }\r
403                         }\r
404                 }\r
405 \r
406                 if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno))\r
407                         /* we got a specification from this tile onwards */\r
408                         hprot = j2k->cp->hprot_TPH[tilespec++];\r
409         \r
410                 /* must this TPH have an EPB MS? */\r
411                 if (j2k->cp->epb_on && (hprot > 0)) {\r
412 \r
413                         /* Create the EPB */\r
414                         if (epb_mark = jpwl_epb_create(\r
415                                 j2k, /* this encoder handle */\r
416                                 false, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */\r
417                                 true, /* is it packed? yes for now */\r
418                                 tileno, /* we are in TPH */\r
419                                 epb_index++, /* its index is 0 (first) */\r
420                                 hprot, /* protection type parameters of following data */\r
421                                 sot_len + 2, /* pre-data length: only SOT */\r
422                                 left_THmarks_len /* post-data length: from SOT end to SOD inclusive */\r
423                                 )) {\r
424                                 \r
425                                 /* Add this marker to the 'insertanda' list */\r
426                                 if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
427                                         jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */\r
428                                         jwmarker[jwmarker_num].epbmark = epb_mark; /* the EPB */\r
429                                         jwmarker[jwmarker_num].pos = j2k->image_info->tile[tileno].start_pos + sot_len + 2; /* after SOT */\r
430                                         jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
431                                         jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
432                                         jwmarker[jwmarker_num].len_ready = true; /* ready */\r
433                                         jwmarker[jwmarker_num].pos_ready = true; /* ready */\r
434                                         jwmarker[jwmarker_num].parms_ready = true; /* ready */\r
435                                         jwmarker[jwmarker_num].data_ready = false; /* not ready */\r
436                                         jwmarker_num++;\r
437                                 }\r
438 \r
439                                 /* update Psot of the tile  */\r
440                                 Psot += epb_mark->Lepb + 2;\r
441 \r
442                                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
443                                         "TPH EPB : tile %02d, prot. %d\n",\r
444                                         tileno,\r
445                                         hprot\r
446                                         );\r
447 \r
448                                 /* save this TPH EPB address */\r
449                                 tph_epb = epb_mark;\r
450 \r
451                         } else {\r
452                                 /* ooops, problems */\r
453                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno);                         \r
454                         };\r
455 \r
456                 }                               \r
457         \r
458                 startpack = 0;\r
459                 /* EPB MSs for UEP packet data protection in Tile Parts */\r
460                 for (packno = 0; packno < j2k->image_info->num; packno++) {\r
461 \r
462                         if ((packspec < JPWL_MAX_NO_PACKSPECS) &&\r
463                                 (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) {\r
464 \r
465                                 /* we got a specification from this tile and packet onwards */\r
466                                 /* print the previous spec */\r
467                                 if (packno > 0) {\r
468                                         stoppack = packno - 1;                          \r
469                                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
470                                                 "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
471                                                 tileno,\r
472                                                 startpack,\r
473                                                 stoppack,\r
474                                                 j2k->image_info->tile[tileno].packet[startpack].start_pos,\r
475                                                 j2k->image_info->tile[tileno].packet[stoppack].end_pos,\r
476                                                 pprot);\r
477 \r
478                                         prot_len = j2k->image_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
479                                                 j2k->image_info->tile[tileno].packet[startpack].start_pos;\r
480 \r
481                                         /*\r
482                                           particular case: if this is the last header and the last packet,\r
483                                           then it is better to protect even the EOC marker\r
484                                         */\r
485                                         if ((tileno == ((j2k->image_info->tw * j2k->image_info->th) - 1)) &&\r
486                                                 (stoppack == (j2k->image_info->num - 1)))\r
487                                                 /* add the EOC len */\r
488                                                 prot_len += 2;\r
489 \r
490                                         /* let's add the EPBs */\r
491                                         Psot += jpwl_epbs_add(\r
492                                                 j2k, /* J2K handle */\r
493                                                 jwmarker, /* pointer to JPWL markers list */\r
494                                                 &jwmarker_num, /* pointer to the number of current markers */\r
495                                                 false, /* latest */\r
496                                                 true, /* packed */\r
497                                                 false, /* inside MH */\r
498                                                 &epb_index, /* pointer to EPB index */\r
499                                                 pprot, /* protection type */\r
500                                                 (double) (j2k->image_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, /* position */\r
501                                                 tileno, /* number of tile */\r
502                                                 0, /* length of pre-data */\r
503                                                 prot_len /*4000*/ /* length of post-data */\r
504                                                 );\r
505                                 }\r
506 \r
507                                 startpack = packno;\r
508                                 pprot = j2k->cp->pprot[packspec++];\r
509                         }\r
510 \r
511                         //printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);\r
512         \r
513                 }\r
514 \r
515                 /* we are at the end: print the remaining spec */\r
516                 stoppack = packno - 1;\r
517                 if (pprot >= 0) {\r
518 \r
519                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
520                                 "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
521                                 tileno,\r
522                                 startpack,\r
523                                 stoppack,\r
524                                 j2k->image_info->tile[tileno].packet[startpack].start_pos,\r
525                                 j2k->image_info->tile[tileno].packet[stoppack].end_pos,\r
526                                 pprot);\r
527 \r
528                         prot_len = j2k->image_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
529                                 j2k->image_info->tile[tileno].packet[startpack].start_pos;\r
530 \r
531                         /*\r
532                           particular case: if this is the last header and the last packet,\r
533                           then it is better to protect even the EOC marker\r
534                         */\r
535                         if ((tileno == ((j2k->image_info->tw * j2k->image_info->th) - 1)) &&\r
536                                 (stoppack == (j2k->image_info->num - 1)))\r
537                                 /* add the EOC len */\r
538                                 prot_len += 2;\r
539 \r
540                         /* let's add the EPBs */\r
541                         Psot += jpwl_epbs_add(\r
542                                                 j2k, /* J2K handle */\r
543                                                 jwmarker, /* pointer to JPWL markers list */\r
544                                                 &jwmarker_num, /* pointer to the number of current markers */\r
545                                                 true, /* latest */\r
546                                                 true, /* packed */\r
547                                                 false, /* inside MH */\r
548                                                 &epb_index, /* pointer to EPB index */\r
549                                                 pprot, /* protection type */\r
550                                                 (double) (j2k->image_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, /* position */\r
551                                                 tileno, /* number of tile */\r
552                                                 0, /* length of pre-data */\r
553                                                 prot_len /*4000*/ /* length of post-data */\r
554                                                 );\r
555                 }\r
556 \r
557                 /* we can now check if the TPH EPB was really the last one */\r
558                 if (tph_epb && (epb_index == 1)) {\r
559                         /* set the TPH EPB to be the last one in current header */\r
560                         tph_epb->Depb |= (unsigned char) ((true & 0x0001) << 6);\r
561                         tph_epb = NULL;\r
562                 }\r
563 \r
564                 /* write back Psot */\r
565                 cio_seek(cio, Psotp);\r
566                 cio_write(cio, Psot, 4);\r
567 \r
568         };\r
569 \r
570         /* reset the position */\r
571         cio_seek(cio, ciopos);\r
572 \r
573 }\r
574 \r
575 void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
576 \r
577         int mm;\r
578         unsigned long int old_size = j2k->image_info->codestream_size;\r
579         unsigned long int new_size = old_size;\r
580         int ciopos = cio_tell(cio);\r
581         unsigned char *jpwl_buf, *orig_buf;\r
582         unsigned long int orig_pos;\r
583         double epbcoding_time = 0.0, esdcoding_time = 0.0;\r
584 \r
585         /* Order JPWL markers according to their wishlist position */\r
586         qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);\r
587 \r
588         /* compute markers total size */\r
589         for (mm = 0; mm < jwmarker_num; mm++) {\r
590                 /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,\r
591                         jwmarker[mm].dpos, jwmarker[mm].len);*/\r
592                 new_size += jwmarker[mm].len + 2;\r
593         }\r
594 \r
595         /* allocate a temporary buffer of proper size */\r
596         if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) new_size * sizeof (unsigned char)))) {\r
597                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL temp codestream buffer\n");\r
598                 exit(1);\r
599         };\r
600         orig_buf = jpwl_buf;\r
601 \r
602         /* cycle through markers */\r
603         orig_pos = 0; /* start from the beginning */\r
604         cio_seek(cio, 0); /* rewind the original */\r
605         for (mm = 0; mm < jwmarker_num; mm++) {\r
606 \r
607                 /*\r
608                 need to copy a piece of the original codestream\r
609                 if there is such\r
610                 */\r
611                 memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);\r
612                 jpwl_buf += jwmarker[mm].pos - orig_pos;\r
613                 orig_pos = jwmarker[mm].pos;\r
614                 cio_seek(cio, orig_pos);\r
615 \r
616                 /*\r
617                 then write down the marker\r
618                 */\r
619                 switch (jwmarker[mm].id) {\r
620 \r
621                 case J2K_MS_EPB:\r
622                         jpwl_epb_write(jwmarker[mm].epbmark, jpwl_buf);\r
623                         break;\r
624 \r
625                 case J2K_MS_EPC:\r
626                         jpwl_epc_write(jwmarker[mm].epcmark, jpwl_buf);\r
627                         break;\r
628 \r
629                 case J2K_MS_ESD:\r
630                         jpwl_esd_write(jwmarker[mm].esdmark, jpwl_buf);\r
631                         break;\r
632 \r
633                 case J2K_MS_RED:\r
634                         memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */\r
635                         break;\r
636 \r
637                 default:\r
638                         break;\r
639                 };\r
640 \r
641                 /* we set the marker dpos to the new position in the JPWL codestream */\r
642                 jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);\r
643 \r
644                 /* advance JPWL buffer position */\r
645                 jpwl_buf += jwmarker[mm].len + 2;\r
646 \r
647         }\r
648 \r
649         /* finish remaining original codestream */\r
650         memcpy(jpwl_buf, cio_getbp(cio), old_size - orig_pos);\r
651         jpwl_buf += old_size - orig_pos;\r
652         cio_seek(cio, old_size);\r
653         \r
654         /*\r
655         update info file based on added markers\r
656         */\r
657         if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))\r
658                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ image_info structure\n");\r
659 \r
660         /* now we need to repass some markers and fill their data fields */\r
661         \r
662         /* first of all, DL and Pcrc in EPCs */ \r
663         for (mm = 0; mm < jwmarker_num; mm++) {\r
664 \r
665                 /* find the EPCs */\r
666                 if (jwmarker[mm].id == J2K_MS_EPC) {\r
667 \r
668                         int epc_pos = (int) jwmarker[mm].dpos, pp;\r
669                         unsigned short int mycrc = 0x0000;\r
670 \r
671                         /* fix and fill the DL field */\r
672                         jwmarker[mm].epcmark->DL = new_size;\r
673                         orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].epcmark->DL >> 24);\r
674                         orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].epcmark->DL >> 16);\r
675                         orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].epcmark->DL >> 8);\r
676                         orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].epcmark->DL >> 0);\r
677 \r
678                         /* compute the CRC field (excluding itself) */\r
679                         for (pp = 0; pp < 4; pp++)\r
680                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
681                         for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)\r
682                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
683 \r
684                         /* fix and fill the CRC */\r
685                         jwmarker[mm].epcmark->Pcrc = mycrc;\r
686                         orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].epcmark->Pcrc >> 8);\r
687                         orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].epcmark->Pcrc >> 0);\r
688 \r
689                 }\r
690         }\r
691 \r
692         /* then, sensitivity data in ESDs */ \r
693         esdcoding_time = opj_clock();\r
694         for (mm = 0; mm < jwmarker_num; mm++) {\r
695 \r
696                 /* find the ESDs */\r
697                 if (jwmarker[mm].id == J2K_MS_ESD) {\r
698 \r
699                         /* remember that they are now in a new position (dpos) */\r
700                         int esd_pos = (int) jwmarker[mm].dpos;\r
701 \r
702                         jpwl_esd_fill(j2k, jwmarker[mm].esdmark, &orig_buf[esd_pos]);\r
703                 \r
704                 }\r
705 \r
706         }\r
707         esdcoding_time = opj_clock() - esdcoding_time;\r
708         if (j2k->cp->esd_on)\r
709                 opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);\r
710 \r
711         /* finally, RS or CRC parity in EPBs */ \r
712         epbcoding_time = opj_clock();\r
713         for (mm = 0; mm < jwmarker_num; mm++) {\r
714 \r
715                 /* find the EPBs */\r
716                 if (jwmarker[mm].id == J2K_MS_EPB) {\r
717 \r
718                         /* remember that they are now in a new position (dpos) */\r
719                         int nn, accum_len;\r
720 \r
721                         /* let's see how many EPBs are following this one, included itself */\r
722                         /* for this to work, we suppose that the markers are correctly ordered */\r
723                         /* and, overall, that they are in packed mode inside headers */\r
724                         accum_len = 0;\r
725                         for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
726                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
727                                 accum_len += jwmarker[nn].epbmark->Lepb + 2;\r
728 \r
729                         /* fill the current (first) EPB with post-data starting from the computed position */\r
730                         jpwl_epb_fill(j2k, jwmarker[mm].epbmark, &orig_buf[(int) jwmarker[mm].dpos],\r
731                                 &orig_buf[(int) jwmarker[mm].dpos + accum_len]);\r
732                 \r
733                         /* fill the remaining EPBs in the header with post-data starting from the last position */\r
734                         for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
735                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
736                                 jpwl_epb_fill(j2k, jwmarker[nn].epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);\r
737 \r
738                         /* skip all the processed EPBs */\r
739                         mm = nn - 1;\r
740                 }\r
741 \r
742         }\r
743         epbcoding_time = opj_clock() - epbcoding_time;\r
744         if (j2k->cp->epb_on)\r
745                 opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);\r
746 \r
747         /* free original cio buffer and set it to the JPWL one */\r
748         opj_free(cio->buffer);\r
749         /*cio->cinfo;*/ /* no change */\r
750         /*cio->openmode;*/ /* no change */\r
751         cio->buffer = jpwl_buf - new_size;\r
752         cio->length = new_size;\r
753         cio->start = jpwl_buf - new_size;\r
754         cio->end = jpwl_buf - 1;\r
755         cio->bp = jpwl_buf - new_size;\r
756         cio_seek(cio, new_size);\r
757 \r
758 }\r
759 \r
760 \r
761 void j2k_read_epc(opj_j2k_t *j2k) {\r
762         unsigned long int DL, Lepcp, Pcrcp, l;\r
763         unsigned short int Lepc, Pcrc = 0x0000;\r
764         unsigned char Pepc;     \r
765         opj_cio_t *cio = j2k->cio;\r
766         char *ans1;\r
767 \r
768         /* Simply read the EPC parameters */\r
769         Lepcp = cio_tell(cio);\r
770         Lepc = cio_read(cio, 2);\r
771         Pcrcp = cio_tell(cio);\r
772         cio_skip(cio, 2); /* Pcrc */\r
773         DL = cio_read(cio, 4);\r
774         Pepc = cio_read(cio, 1);\r
775 \r
776         /* compute Pcrc */\r
777         cio_seek(cio, Lepcp - 2);\r
778 \r
779                 /* Marker */\r
780                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
781                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
782 \r
783                 /* Length */\r
784                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
785                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
786 \r
787                 /* skip Pcrc */\r
788                 cio_skip(cio, 2);\r
789 \r
790                 /* read all remaining */\r
791                 for (l = 4; l < Lepc; l++)\r
792                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
793 \r
794                 /* check Pcrc with the result */\r
795                 cio_seek(cio, Pcrcp);\r
796                 ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";\r
797 \r
798         /* now we write them to screen */\r
799         opj_event_msg(j2k->cinfo, EVT_INFO, \r
800                 "EPC(%u,%d): %s, DL=%d%s %s %s\n",\r
801                 Lepcp - 2,\r
802                 Lepc,\r
803                 ans1,\r
804                 DL, /* data length this EPC is referring to */\r
805                 (Pepc & 0x10) ? ", esd" : "", /* ESD is present */\r
806                 (Pepc & 0x20) ? ", red" : "", /* RED is present */\r
807                 (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */\r
808 \r
809         cio_seek(cio, Lepcp + Lepc);  \r
810 }\r
811 \r
812 void j2k_write_epc(opj_j2k_t *j2k) {\r
813 \r
814         unsigned long int DL, Lepcp, Pcrcp, l;\r
815         unsigned short int Lepc, Pcrc;\r
816         unsigned char Pepc;     \r
817 \r
818         opj_cio_t *cio = j2k->cio;\r
819 \r
820         cio_write(cio, J2K_MS_EPC, 2);  /* EPC */\r
821         Lepcp = cio_tell(cio);\r
822         cio_skip(cio, 2);\r
823 \r
824         /* CRC-16 word of the EPC */\r
825         Pcrc = 0x0000; /* initialize */\r
826         Pcrcp = cio_tell(cio);\r
827         cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/\r
828 \r
829         /* data length of the EPC protection domain */\r
830         DL = 0x00000000; /* we leave this set to 0, as if the information is not available */\r
831         cio_write(cio, DL, 4);   /* DL */\r
832 \r
833         /* jpwl capabilities */\r
834         Pepc = 0x00;\r
835         cio_write(cio, Pepc, 1); /* Pepc */\r
836 \r
837         /* ID section */\r
838         /* no ID's, as of now */\r
839 \r
840         Lepc = (unsigned short) (cio_tell(cio) - Lepcp);\r
841         cio_seek(cio, Lepcp);\r
842         cio_write(cio, Lepc, 2); /* Lepc */\r
843 \r
844         /* compute Pcrc */\r
845         cio_seek(cio, Lepcp - 2);\r
846 \r
847                 /* Marker */\r
848                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
849                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
850 \r
851                 /* Length */\r
852                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
853                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
854 \r
855                 /* skip Pcrc */\r
856                 cio_skip(cio, 2);\r
857 \r
858                 /* read all remaining */\r
859                 for (l = 4; l < Lepc; l++)\r
860                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
861 \r
862                 /* fill Pcrc with the result */\r
863                 cio_seek(cio, Pcrcp);\r
864                 cio_write(cio, Pcrc, 2);\r
865 \r
866         cio_seek(cio, Lepcp + Lepc);\r
867 }\r
868 \r
869 void j2k_read_epb(opj_j2k_t *j2k) {\r
870         unsigned long int LDPepb, Pepb;\r
871         unsigned short int Lepb;\r
872         unsigned char Depb;\r
873         char str1[25] = "";\r
874         bool status;\r
875         static bool first_in_tph = true;\r
876         int type, pre_len, post_len;\r
877         static unsigned char *redund = NULL;\r
878         \r
879         opj_cio_t *cio = j2k->cio;\r
880 \r
881         /* B/W = 45, RGB = 51 */\r
882         /*           SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */\r
883         int skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;\r
884 \r
885         if (j2k->cp->correct) {\r
886 \r
887                 /* go back to EPB marker value */\r
888                 cio_seek(cio, cio_tell(cio) - 2);\r
889 \r
890                 /* we need to understand where we are */\r
891                 if (j2k->state == J2K_STATE_MH) {\r
892                         /* we are in MH */\r
893                         type = 0; /* MH */\r
894                         pre_len = skipnum; /* SOC+SIZ */\r
895                         post_len = -1; /* auto */\r
896 \r
897                 } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {\r
898                         /* we are in TPH */\r
899                         type = 1; /* TPH */\r
900                         pre_len = 12; /* SOC+SIZ */\r
901                         first_in_tph = false;\r
902                         post_len = -1; /* auto */\r
903 \r
904                 } else {\r
905                         /* we are elsewhere */\r
906                         type = 2; /* other */\r
907                         pre_len = 0; /* nada */\r
908                         post_len = -1; /* auto */\r
909 \r
910                 }\r
911 \r
912                 /* call EPB corrector */\r
913                 /*printf("before %x, ", redund);*/\r
914                 status = jpwl_epb_correct(j2k,      /* J2K decompressor handle */\r
915                                                                   cio->bp,  /* pointer to EPB in codestream buffer */\r
916                                                                   type,     /* EPB type: MH */\r
917                                                                   pre_len,  /* length of pre-data */\r
918                                                                   post_len, /* length of post-data: -1 means auto */\r
919                                                                   NULL,     /* do everything auto */\r
920                                                                   &redund\r
921                                                                  );\r
922                 /*printf("after %x\n", redund);*/\r
923 \r
924                 /* Read the (possibly corrected) EPB parameters */\r
925                 cio_skip(cio, 2);\r
926                 Lepb = cio_read(cio, 2);\r
927                 Depb = cio_read(cio, 1);\r
928                 LDPepb = cio_read(cio, 4);\r
929                 Pepb = cio_read(cio, 4);\r
930 \r
931                 if (!status) {\r
932 \r
933                         opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");\r
934 \r
935                         /* advance to EPB endpoint */\r
936                         cio_skip(cio, Lepb + 2);  \r
937 \r
938                         return;\r
939                 }\r
940 \r
941                 /* last in current header? */\r
942                 if (Depb & 0x40) {\r
943                         redund = NULL; /* reset the pointer to L4 buffer */\r
944                         first_in_tph = true;\r
945                 }\r
946 \r
947                 /* advance to EPB endpoint */\r
948                 cio_skip(cio, Lepb - 11);  \r
949 \r
950         } else {\r
951 \r
952                 /* Simply read the EPB parameters */\r
953                 Lepb = cio_read(cio, 2);\r
954                 Depb = cio_read(cio, 1);\r
955                 LDPepb = cio_read(cio, 4);\r
956                 Pepb = cio_read(cio, 4);\r
957 \r
958                 /* What does Pepb tells us about the protection method? */\r
959                 if (((Pepb & 0xF0000000) >> 28) == 0)\r
960                         sprintf(str1, "pred"); /* predefined */\r
961                 else if (((Pepb & 0xF0000000) >> 28) == 1)\r
962                         sprintf(str1, "crc-%d", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */\r
963                 else if (((Pepb & 0xF0000000) >> 28) == 2)\r
964                         sprintf(str1, "rs(%d,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */\r
965                 else if (Pepb == 0xFFFFFFFF)\r
966                         sprintf(str1, "nometh"); /* RS mode */\r
967                 else\r
968                         sprintf(str1, "unknown"); /* unknown */\r
969 \r
970                 /* Now we write them to screen */\r
971                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
972                         "EPB(%d): (%sl, %sp, %u), %lu, %s\n",\r
973                         cio_tell(cio) - 13,\r
974                         (Depb & 0x40) ? "" : "n", /* latest EPB or not? */\r
975                         (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */\r
976                         (Depb & 0x3F), /* EPB index value */\r
977                         LDPepb, /*length of the data protected by the EPB */\r
978                         str1); /* protection method */\r
979 \r
980                 cio_skip(cio, Lepb - 11);  \r
981         }\r
982 }\r
983 \r
984 void j2k_write_epb(opj_j2k_t *j2k) {\r
985         unsigned long int LDPepb, Pepb, Lepbp;\r
986         unsigned short int Lepb;\r
987         unsigned char Depb;\r
988 \r
989         opj_cio_t *cio = j2k->cio;\r
990 \r
991         cio_write(cio, J2K_MS_EPB, 2);  /* EPB */\r
992         Lepbp = cio_tell(cio);\r
993         cio_skip(cio, 2);\r
994 \r
995         /* EPB style */\r
996         Depb = 0x00; /* test */\r
997         cio_write(cio, Depb, 1);   /* Depb */\r
998 \r
999         /* length of the data to be protected by this EPB */\r
1000         LDPepb = 0x00000000; /* test */\r
1001         cio_write(cio, LDPepb, 4);   /* LDPepb */\r
1002 \r
1003         /* next error correction tool */\r
1004         Pepb = 0x00000000; /* test */\r
1005         cio_write(cio, Pepb, 4);   /* Pepb */\r
1006 \r
1007         /* EPB data */\r
1008         /* no data, as of now */\r
1009 \r
1010         Lepb = (unsigned short) (cio_tell(cio) - Lepbp);\r
1011         cio_seek(cio, Lepbp);\r
1012         cio_write(cio, Lepb, 2);                /* Lepb */\r
1013 \r
1014         cio_seek(cio, Lepbp + Lepb);\r
1015 }\r
1016 \r
1017 void j2k_read_esd(opj_j2k_t *j2k) {\r
1018         unsigned short int Lesd, Cesd;\r
1019         unsigned char Pesd;\r
1020 \r
1021         int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;\r
1022 \r
1023         char str1[4][4] = {"p", "br", "pr", "res"};\r
1024         char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};\r
1025         \r
1026         opj_cio_t *cio = j2k->cio;\r
1027 \r
1028         /* Simply read the ESD parameters */\r
1029         Lesd = cio_read(cio, 2);\r
1030         Cesd = cio_read(cio, cesdsize);\r
1031         Pesd = cio_read(cio, 1);\r
1032 \r
1033         /* Now we write them to screen */\r
1034         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1035                 "ESD(%d): c%d, %s, %s, %s, %s, %s\n",\r
1036                 cio_tell(cio) - (5 + cesdsize),\r
1037                 Cesd, /* component number for this ESD */\r
1038                 str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
1039                 str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */\r
1040                 ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",\r
1041                 ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",\r
1042                 (Pesd & (unsigned char) 0x01) ? "avgc" : "");\r
1043 \r
1044         cio_skip(cio, Lesd - (3 + cesdsize));  \r
1045 }\r
1046 \r
1047 void j2k_read_red(opj_j2k_t *j2k) {\r
1048         unsigned short int Lred;\r
1049         unsigned char Pred;\r
1050         char str1[4][4] = {"p", "br", "pr", "res"};\r
1051         \r
1052         opj_cio_t *cio = j2k->cio;\r
1053 \r
1054         /* Simply read the RED parameters */\r
1055         Lred = cio_read(cio, 2);\r
1056         Pred = cio_read(cio, 1);\r
1057 \r
1058         /* Now we write them to screen */\r
1059         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1060                 "RED(%d): %s, %dc, %s, %s\n",\r
1061                 cio_tell(cio) - 5,\r
1062                 str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
1063                 (Pred & (unsigned char) 0x38) >> 3, /* corruption level */\r
1064                 ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */\r
1065                 (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */\r
1066 \r
1067         cio_skip(cio, Lred - 3);  \r
1068 }\r
1069 \r
1070 bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {\r
1071 \r
1072         /*\r
1073            we navigate through the tile and find possible invalid parameters:\r
1074        this saves a lot of crashes!!!!!\r
1075          */\r
1076         int compno, resno, precno, /*layno,*/ bandno, blockno;\r
1077         int numprecincts, numblocks;\r
1078 \r
1079         /* this is the selected tile */\r
1080         opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);\r
1081 \r
1082         /* will keep the component */\r
1083         opj_tcd_tilecomp_t *comp = NULL;\r
1084 \r
1085         /* will keep the resolution */\r
1086         opj_tcd_resolution_t *res;\r
1087 \r
1088         /* will keep the subband */\r
1089         opj_tcd_band_t *band; \r
1090 \r
1091         /* will keep the precinct */\r
1092         opj_tcd_precinct_t *prec; \r
1093 \r
1094         /* will keep the codeblock */\r
1095         opj_tcd_cblk_t *block;\r
1096 \r
1097         /* check all tile components */\r
1098         for (compno = 0; compno < tile->numcomps; compno++) {\r
1099                 comp = &(tile->comps[compno]);\r
1100 \r
1101                 /* check all component resolutions */\r
1102                 for (resno = 0; resno < comp->numresolutions; resno++) {\r
1103                         res = &(comp->resolutions[resno]);\r
1104                         numprecincts = res->pw * res->ph;\r
1105 \r
1106                         /* check all the subbands */\r
1107                         for (bandno = 0; bandno < res->numbands; bandno++) {\r
1108                                 band = &(res->bands[bandno]);\r
1109 \r
1110                                 /* check all the precincts */\r
1111                                 for (precno = 0; precno < numprecincts; precno++) {\r
1112                                         prec = &(band->precincts[precno]);\r
1113                                         numblocks = prec->ch * prec->cw;\r
1114 \r
1115                                         /* check all the codeblocks */\r
1116                                         for (blockno = 0; blockno < numblocks; blockno++) {\r
1117                                                 block = &(prec->cblks[blockno]);\r
1118 \r
1119                                                 /* x-origin is invalid */\r
1120                                                 if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {\r
1121                                                         opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,\r
1122                                                                 "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",\r
1123                                                                 block->x0, prec->x0, prec->x1);\r
1124                                                         if (!JPWL_ASSUME || JPWL_ASSUME)\r
1125                                                                 return false;\r
1126                                                 };\r
1127                                         }\r
1128                                 }                               \r
1129                         }\r
1130                 }\r
1131         }\r
1132 \r
1133         return true;\r
1134 }\r
1135 \r
1136 /*@}*/\r
1137 \r
1138 #endif /* USE_JPWL */