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