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