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