OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
ojph_params.cpp
Go to the documentation of this file.
1//***************************************************************************/
2// This software is released under the 2-Clause BSD license, included
3// below.
4//
5// Copyright (c) 2019, Aous Naman
6// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
7// Copyright (c) 2019, The University of New South Wales, Australia
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13// 1. Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//
16// 2. Redistributions in binary form must reproduce the above copyright
17// notice, this list of conditions and the following disclaimer in the
18// documentation and/or other materials provided with the distribution.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31//***************************************************************************/
32// This file is part of the OpenJPH software implementation.
33// File: ojph_params.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38#define _USE_MATH_DEFINES
39#include <cmath>
40
41#include "ojph_base.h"
42#include "ojph_file.h"
43#include "ojph_params.h"
44
45#include "ojph_params_local.h"
46#include "ojph_message.h"
47
48namespace ojph {
49
51 //
52 //
53 //
54 //
55 //
57
60 {
61 state->Xsiz = dims.x;
62 state->Ysiz = dims.y;
63 }
64
67 {
68 state->XTsiz = s.w;
69 state->YTsiz = s.h;
70 }
71
74 { // WARNING need to check if these are valid
75 state->XOsiz = offset.x;
76 state->YOsiz = offset.y;
77 }
78
81 { // WARNING need to check if these are valid
82 state->XTOsiz = offset.x;
83 state->YTOsiz = offset.y;
84 }
85
88 {
89 state->set_num_components(num_comps);
90 }
91
93 void param_siz::set_component(ui32 comp_num, const point& downsampling,
94 ui32 bit_depth, bool is_signed)
95 {
96 state->set_comp_info(comp_num, downsampling, bit_depth, is_signed);
97 }
98
101 {
102 return point(state->Xsiz, state->Ysiz);
103 }
104
107 {
108 return point(state->XOsiz, state->YOsiz);
109 }
110
113 {
114 return size(state->XTsiz, state->YTsiz);
115 }
116
119 {
120 return point(state->XTOsiz, state->YTOsiz);
121 }
122
125 {
126 return state->Csiz;
127 }
128
131 {
132 return state->get_bit_depth(comp_num);
133 }
134
136 bool param_siz::is_signed(ui32 comp_num) const
137 {
138 return state->is_signed(comp_num);
139 }
140
143 {
144 return state->get_downsampling(comp_num);
145 }
146
149 {
150 return state->get_recon_width(comp_num);
151 }
152
155 {
156 return state->get_recon_height(comp_num);
157 }
158
160 //
161 //
162 //
163 //
164 //
166
168 void param_cod::set_num_decomposition(ui32 num_decompositions)
169 {
170 if (num_decompositions > 32)
171 OJPH_ERROR(0x00050001,
172 "maximum number of decompositions cannot exceed 32");
173 state->SPcod.num_decomp = (ui8)num_decompositions;
174 }
175
178 {
179 ui32 log_width = 31 - count_leading_zeros(width);
180 ui32 log_height = 31 - count_leading_zeros(height);
181 if (width == 0 || width != (1u << log_width)
182 || height == 0 || height != (1u << log_height)
183 || log_width < 2 || log_height < 2
184 || log_width + log_height > 12)
185 OJPH_ERROR(0x00050011, "incorrect code block dimensions");
186 state->SPcod.block_width = (ui8)(log_width - 2);
187 state->SPcod.block_height = (ui8)(log_height - 2);
188 }
189
191 void param_cod::set_precinct_size(int num_levels, size* precinct_size)
192 {
193 if (num_levels == 0 || precinct_size == NULL)
194 state->Scod &= 0xFE;
195 else
196 {
197 state->Scod |= 1;
198 for (int i = 0; i <= state->SPcod.num_decomp; ++i)
199 {
200 size t = precinct_size[i < num_levels ? i : num_levels - 1];
201
202 ui32 PPx = 31 - count_leading_zeros(t.w);
203 ui32 PPy = 31 - count_leading_zeros(t.h);
204 if (t.w == 0 || t.h == 0)
205 OJPH_ERROR(0x00050021, "precinct width or height cannot be 0");
206 if (t.w != (1u<<PPx) || t.h != (1u<<PPy))
207 OJPH_ERROR(0x00050022,
208 "precinct width and height should be a power of 2");
209 if (PPx > 15 || PPy > 15)
210 OJPH_ERROR(0x00050023, "precinct size is too large");
211 if (i > 0 && (PPx == 0 || PPy == 0))
212 OJPH_ERROR(0x00050024, "precinct size is too small");
213 state->SPcod.precinct_size[i] = (ui8)(PPx | (PPy << 4));
214 }
215 }
216 }
217
219 void param_cod::set_progression_order(const char *name)
220 {
221 int prog_order = 0;
222 size_t len = strlen(name);
223 if (len == 4)
224 {
225 if (strncmp(name, OJPH_PO_STRING_LRCP, 4) == 0)
226 prog_order = OJPH_PO_LRCP;
227 else if (strncmp(name, OJPH_PO_STRING_RLCP, 4) == 0)
228 prog_order = OJPH_PO_RLCP;
229 else if (strncmp(name, OJPH_PO_STRING_RPCL, 4) == 0)
230 prog_order = OJPH_PO_RPCL;
231 else if (strncmp(name, OJPH_PO_STRING_PCRL, 4) == 0)
232 prog_order = OJPH_PO_PCRL;
233 else if (strncmp(name, OJPH_PO_STRING_CPRL, 4) == 0)
234 prog_order = OJPH_PO_CPRL;
235 else
236 OJPH_ERROR(0x00050031, "unknown progression order");
237 }
238 else
239 OJPH_ERROR(0x00050032, "improper progression order");
240
241
242 state->SGCod.prog_order = (ui8)prog_order;
243 }
244
246 void param_cod::set_color_transform(bool color_transform)
247 {
248 state->employ_color_transform(color_transform ? 1 : 0);
249 }
250
252 void param_cod::set_reversible(bool reversible)
253 {
254 state->set_reversible(reversible);
255 }
256
259 {
260 local::param_cod *p = state->get_coc(component_idx);
261 if (p == state) // no COC segment marker for this component
262 p = state->add_coc_object(component_idx);
263 return param_coc(p);
264 }
265
268 {
269 return state->get_num_decompositions();
270 }
271
274 {
275 return state->get_block_dims();
276 }
277
280 {
281 return state->get_log_block_dims();
282 }
283
286 {
287 return state->is_reversible();
288 }
289
292 {
293 return state->get_precinct_size(level_num);
294 }
295
298 {
299 return state->get_log_precinct_size(level_num);
300 }
301
304 {
305 return state->SGCod.prog_order;
306 }
307
310 {
311 if (state->SGCod.prog_order == OJPH_PO_LRCP)
312 return OJPH_PO_STRING_LRCP;
313 else if (state->SGCod.prog_order == OJPH_PO_RLCP)
314 return OJPH_PO_STRING_RLCP;
315 else if (state->SGCod.prog_order == OJPH_PO_RPCL)
316 return OJPH_PO_STRING_RPCL;
317 else if (state->SGCod.prog_order == OJPH_PO_PCRL)
318 return OJPH_PO_STRING_PCRL;
319 else if (state->SGCod.prog_order == OJPH_PO_CPRL)
320 return OJPH_PO_STRING_CPRL;
321 else
322 assert(0);
323 return "";
324 }
325
328 {
329 return state->SGCod.num_layers;
330 }
331
334 {
335 return state->is_employing_color_transform();
336 }
337
340 {
341 return state->packets_may_use_sop();
342 }
343
346 {
347 return state->packets_use_eph();
348 }
349
352 {
353 return state->get_block_vertical_causality();
354 }
355
357 //
358 //
359 //
360 //
361 //
363
365 void param_coc::set_num_decomposition(ui32 num_decompositions)
366 { ojph::param_cod(state).set_num_decomposition(num_decompositions); }
367
370 { ojph::param_cod(state).set_block_dims(width, height); }
371
373 void param_coc::set_precinct_size(int num_levels, size* precinct_size)
374 { ojph::param_cod(state).set_precinct_size(num_levels, precinct_size); }
375
377 void param_coc::set_reversible(bool reversible)
378 { ojph::param_cod(state).set_reversible(reversible); }
379
383
387
391
395
398 { return ojph::param_cod(state).get_precinct_size(level_num); }
399
403
407
408
410 //
411 //
412 //
413 //
414 //
416
419 {
420 state->set_delta(delta);
421 }
422
424 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta)
425 {
426 state->set_delta(comp_idx, delta);
427 }
428
430 //
431 //
432 //
433 //
434 //
436
439 {
440 state->set_nonlinear_transform(comp_num, nl_type);
441 }
442
444 bool param_nlt::get_nonlinear_transform(ui32 comp_num, ui8& bit_depth,
445 bool& is_signed, ui8& nl_type) const
446 {
447 return state->get_nonlinear_transform(comp_num, bit_depth, is_signed,
448 nl_type);
449 }
450
452 //
453 //
454 //
455 //
456 //
458
460 void comment_exchange::set_string(const char* str)
461 {
462 size_t t = strlen(str);
463 if (len > 65531)
464 OJPH_ERROR(0x000500C1,
465 "COM marker string length cannot be larger than 65531");
466 this->data = str;
467 this->len = (ui16)t;
468 this->Rcom = 1;
469 }
470
473 {
474 if (len > 65531)
475 OJPH_ERROR(0x000500C2,
476 "COM marker string length cannot be larger than 65531");
477 this->data = data;
478 this->len = len;
479 this->Rcom = 0;
480 }
481
483 //
484 //
485 // LOCAL
486 //
487 //
489
490 namespace local {
491
493 static inline
495 {
496 return (ui16)((t << 8) | (t >> 8));
497 }
498
500 static inline
502 {
503 ui32 u = swap_byte((ui16)(t & 0xFFFFu));
504 u <<= 16;
505 u |= swap_byte((ui16)(t >> 16));
506 return u;
507 }
508
510 static inline
512 {
513 ui64 u = swap_byte((ui32)(t & 0xFFFFFFFFu));
514 u <<= 32;
515 u |= swap_byte((ui32)(t >> 32));
516 return u;
517 }
518
520 //
521 //
522 //
523 //
524 //
526
528 //static
530 {
531 public:
532 static float get_gain_l(ui32 num_decomp, bool reversible)
533 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
534 static float get_gain_h(ui32 num_decomp, bool reversible)
535 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
536
537 private:
538 static const float gain_9x7_l[34];
539 static const float gain_9x7_h[34];
540 static const float gain_5x3_l[34];
541 static const float gain_5x3_h[34];
542 };
543
545 const float sqrt_energy_gains::gain_9x7_l[34] = { 1.0000e+00f,
546 1.4021e+00f, 2.0304e+00f, 2.9012e+00f, 4.1153e+00f, 5.8245e+00f,
547 8.2388e+00f, 1.1652e+01f, 1.6479e+01f, 2.3304e+01f, 3.2957e+01f,
548 4.6609e+01f, 6.5915e+01f, 9.3217e+01f, 1.3183e+02f, 1.8643e+02f,
549 2.6366e+02f, 3.7287e+02f, 5.2732e+02f, 7.4574e+02f, 1.0546e+03f,
550 1.4915e+03f, 2.1093e+03f, 2.9830e+03f, 4.2185e+03f, 5.9659e+03f,
551 8.4371e+03f, 1.1932e+04f, 1.6874e+04f, 2.3864e+04f, 3.3748e+04f,
552 4.7727e+04f, 6.7496e+04f, 9.5454e+04f };
553 const float sqrt_energy_gains::gain_9x7_h[34] = { 1.4425e+00f,
554 1.9669e+00f, 2.8839e+00f, 4.1475e+00f, 5.8946e+00f, 8.3472e+00f,
555 1.1809e+01f, 1.6701e+01f, 2.3620e+01f, 3.3403e+01f, 4.7240e+01f,
556 6.6807e+01f, 9.4479e+01f, 1.3361e+02f, 1.8896e+02f, 2.6723e+02f,
557 3.7792e+02f, 5.3446e+02f, 7.5583e+02f, 1.0689e+03f, 1.5117e+03f,
558 2.1378e+03f, 3.0233e+03f, 4.2756e+03f, 6.0467e+03f, 8.5513e+03f,
559 1.2093e+04f, 1.7103e+04f, 2.4187e+04f, 3.4205e+04f, 4.8373e+04f,
560 6.8410e+04f, 9.6747e+04f, 1.3682e+05f };
561 const float sqrt_energy_gains::gain_5x3_l[34] = { 1.0000e+00f,
562 1.2247e+00f, 1.3229e+00f, 1.5411e+00f, 1.7139e+00f, 1.9605e+00f,
563 2.2044e+00f, 2.5047e+00f, 2.8277e+00f, 3.2049e+00f, 3.6238e+00f,
564 4.1033e+00f, 4.6423e+00f, 5.2548e+00f, 5.9462e+00f, 6.7299e+00f,
565 7.6159e+00f, 8.6193e+00f, 9.7544e+00f, 1.1039e+01f, 1.2493e+01f,
566 1.4139e+01f, 1.6001e+01f, 1.8108e+01f, 2.0493e+01f, 2.3192e+01f,
567 2.6246e+01f, 2.9702e+01f, 3.3614e+01f, 3.8041e+01f, 4.3051e+01f,
568 4.8721e+01f, 5.5138e+01f, 6.2399e+01f };
569 const float sqrt_energy_gains::gain_5x3_h[34] = { 1.0458e+00f,
570 1.3975e+00f, 1.4389e+00f, 1.7287e+00f, 1.8880e+00f, 2.1841e+00f,
571 2.4392e+00f, 2.7830e+00f, 3.1341e+00f, 3.5576e+00f, 4.0188e+00f,
572 4.5532e+00f, 5.1494e+00f, 5.8301e+00f, 6.5963e+00f, 7.4663e+00f,
573 8.4489e+00f, 9.5623e+00f, 1.0821e+01f, 1.2247e+01f, 1.3860e+01f,
574 1.5685e+01f, 1.7751e+01f, 2.0089e+01f, 2.2735e+01f, 2.5729e+01f,
575 2.9117e+01f, 3.2952e+01f, 3.7292e+01f, 4.2203e+01f, 4.7761e+01f,
576 5.4051e+01f, 6.1170e+01f, 6.9226e+01f };
577
579 //static
581 {
582 public:
583 static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
584 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
585 static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
586 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
587
588 private:
589 static const float gain_9x7_l[34];
590 static const float gain_9x7_h[34];
591 static const float gain_5x3_l[34];
592 static const float gain_5x3_h[34];
593 };
594
596 const float bibo_gains::gain_9x7_l[34] = { 1.0000e+00f, 1.3803e+00f,
597 1.3328e+00f, 1.3067e+00f, 1.3028e+00f, 1.3001e+00f, 1.2993e+00f,
598 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
599 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
600 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
601 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
602 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
603 1.2992e+00f, 1.2992e+00f };
604 const float bibo_gains::gain_9x7_h[34] = { 1.2976e+00f, 1.3126e+00f,
605 1.2757e+00f, 1.2352e+00f, 1.2312e+00f, 1.2285e+00f, 1.2280e+00f,
606 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
607 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
608 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
609 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
610 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
611 1.2278e+00f, 1.2278e+00f };
612 const float bibo_gains::gain_5x3_l[34] = { 1.0000e+00f, 1.5000e+00f,
613 1.6250e+00f, 1.6875e+00f, 1.6963e+00f, 1.7067e+00f, 1.7116e+00f,
614 1.7129e+00f, 1.7141e+00f, 1.7145e+00f, 1.7151e+00f, 1.7152e+00f,
615 1.7155e+00f, 1.7155e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
616 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
617 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
618 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
619 1.7156e+00f, 1.7156e+00f };
620 const float bibo_gains::gain_5x3_h[34] = { 2.0000e+00f, 2.5000e+00f,
621 2.7500e+00f, 2.8047e+00f, 2.8198e+00f, 2.8410e+00f, 2.8558e+00f,
622 2.8601e+00f, 2.8628e+00f, 2.8656e+00f, 2.8662e+00f, 2.8667e+00f,
623 2.8669e+00f, 2.8670e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
624 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
625 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
626 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
627 2.8671e+00f, 2.8671e+00f };
628
629
631 //
632 //
633 //
634 //
635 //
637
640 {
641 //marker size excluding header
642 Lsiz = (ui16)(38 + 3 * Csiz);
643
644 ui8 buf[4];
645 bool result = true;
646
647 *(ui16*)buf = JP2K_MARKER::SIZ;
648 *(ui16*)buf = swap_byte(*(ui16*)buf);
649 result &= file->write(&buf, 2) == 2;
650 *(ui16*)buf = swap_byte(Lsiz);
651 result &= file->write(&buf, 2) == 2;
652 *(ui16*)buf = swap_byte(Rsiz);
653 result &= file->write(&buf, 2) == 2;
654 *(ui32*)buf = swap_byte(Xsiz);
655 result &= file->write(&buf, 4) == 4;
656 *(ui32*)buf = swap_byte(Ysiz);
657 result &= file->write(&buf, 4) == 4;
658 *(ui32*)buf = swap_byte(XOsiz);
659 result &= file->write(&buf, 4) == 4;
660 *(ui32*)buf = swap_byte(YOsiz);
661 result &= file->write(&buf, 4) == 4;
662 *(ui32*)buf = swap_byte(XTsiz);
663 result &= file->write(&buf, 4) == 4;
664 *(ui32*)buf = swap_byte(YTsiz);
665 result &= file->write(&buf, 4) == 4;
666 *(ui32*)buf = swap_byte(XTOsiz);
667 result &= file->write(&buf, 4) == 4;
668 *(ui32*)buf = swap_byte(YTOsiz);
669 result &= file->write(&buf, 4) == 4;
670 *(ui16*)buf = swap_byte(Csiz);
671 result &= file->write(&buf, 2) == 2;
672 for (int c = 0; c < Csiz; ++c)
673 {
674 buf[0] = cptr[c].SSiz;
675 buf[1] = cptr[c].XRsiz;
676 buf[2] = cptr[c].YRsiz;
677 result &= file->write(&buf, 3) == 3;
678 }
679
680 return result;
681 }
682
685 {
686 if (file->read(&Lsiz, 2) != 2)
687 OJPH_ERROR(0x00050041, "error reading SIZ marker");
689 int num_comps = (Lsiz - 38) / 3;
690 if (Lsiz != 38 + 3 * num_comps)
691 OJPH_ERROR(0x00050042, "error in SIZ marker length");
692 if (file->read(&Rsiz, 2) != 2)
693 OJPH_ERROR(0x00050043, "error reading SIZ marker");
695 if ((Rsiz & 0x4000) == 0)
696 OJPH_ERROR(0x00050044,
697 "Rsiz bit 14 is not set (this is not a JPH file)");
698 if ((Rsiz & 0x8000) != 0 && (Rsiz & 0xD5F) != 0)
699 OJPH_WARN(0x00050001, "Rsiz in SIZ has unimplemented fields");
700 if (file->read(&Xsiz, 4) != 4)
701 OJPH_ERROR(0x00050045, "error reading SIZ marker");
703 if (file->read(&Ysiz, 4) != 4)
704 OJPH_ERROR(0x00050046, "error reading SIZ marker");
706 if (file->read(&XOsiz, 4) != 4)
707 OJPH_ERROR(0x00050047, "error reading SIZ marker");
709 if (file->read(&YOsiz, 4) != 4)
710 OJPH_ERROR(0x00050048, "error reading SIZ marker");
712 if (file->read(&XTsiz, 4) != 4)
713 OJPH_ERROR(0x00050049, "error reading SIZ marker");
715 if (file->read(&YTsiz, 4) != 4)
716 OJPH_ERROR(0x0005004A, "error reading SIZ marker");
718 if (file->read(&XTOsiz, 4) != 4)
719 OJPH_ERROR(0x0005004B, "error reading SIZ marker");
721 if (file->read(&YTOsiz, 4) != 4)
722 OJPH_ERROR(0x0005004C, "error reading SIZ marker");
724 if (file->read(&Csiz, 2) != 2)
725 OJPH_ERROR(0x0005004D, "error reading SIZ marker");
727 if (Csiz != num_comps)
728 OJPH_ERROR(0x0005004E, "Csiz does not match the SIZ marker size");
730 for (int c = 0; c < Csiz; ++c)
731 {
732 if (file->read(&cptr[c].SSiz, 1) != 1)
733 OJPH_ERROR(0x00050051, "error reading SIZ marker");
734 if (file->read(&cptr[c].XRsiz, 1) != 1)
735 OJPH_ERROR(0x00050052, "error reading SIZ marker");
736 if (file->read(&cptr[c].YRsiz, 1) != 1)
737 OJPH_ERROR(0x00050053, "error reading SIZ marker");
738 }
739
740 ws_kern_support_needed = (Rsiz & 0x20) != 0;
741 dfs_support_needed = (Rsiz & 0x80) != 0;
742 }
743
746 {
747 assert(comp_num < get_num_components());
748
749 point factor(1u << skipped_resolutions, 1u << skipped_resolutions);
750 const param_cod* cdp = cod->get_coc(comp_num);
751 if (dfs && cdp && cdp->is_dfs_defined()) {
752 const param_dfs* d = dfs->get_dfs(cdp->get_dfs_index());
754 }
755 factor.x *= (ui32)cptr[comp_num].XRsiz;
756 factor.y *= (ui32)cptr[comp_num].YRsiz;
757 return factor;
758 }
759
762 {
763 assert(comp_num < get_num_components());
764
765 point factor = get_recon_downsampling(comp_num);
766 point r;
767 r.x = ojph_div_ceil(Xsiz, factor.x) - ojph_div_ceil(XOsiz, factor.x);
768 r.y = ojph_div_ceil(Ysiz, factor.y) - ojph_div_ceil(YOsiz, factor.y);
769 return r;
770 }
771
772
774 //
775 //
776 //
777 //
778 //
780
783 {
784 //marker size excluding header
785 Lcap = 8;
786
787 char buf[4];
788 bool result = true;
789
790 *(ui16*)buf = JP2K_MARKER::CAP;
791 *(ui16*)buf = swap_byte(*(ui16*)buf);
792 result &= file->write(&buf, 2) == 2;
793 *(ui16*)buf = swap_byte(Lcap);
794 result &= file->write(&buf, 2) == 2;
795 *(ui32*)buf = swap_byte(Pcap);
796 result &= file->write(&buf, 4) == 4;
797
798 *(ui16*)buf = swap_byte(Ccap[0]);
799 result &= file->write(&buf, 2) == 2;
800
801 return result;
802 }
803
806 {
807 if (file->read(&Lcap, 2) != 2)
808 OJPH_ERROR(0x00050061, "error reading CAP marker");
810 if (file->read(&Pcap, 4) != 4)
811 OJPH_ERROR(0x00050062, "error reading CAP marker");
813 ui32 count = population_count(Pcap);
814 if (Pcap & 0xFFFDFFFF)
815 OJPH_ERROR(0x00050063,
816 "error Pcap in CAP has options that are not supported");
817 if ((Pcap & 0x00020000) == 0)
818 OJPH_ERROR(0x00050064,
819 "error Pcap should have its 15th MSB set, Pcap^15. "
820 " This is not a JPH file");
821 for (ui32 i = 0; i < count; ++i)
822 if (file->read(Ccap+i, 2) != 2)
823 OJPH_ERROR(0x00050065, "error reading CAP marker");
824 if (Lcap != 6 + 2 * count)
825 OJPH_ERROR(0x00050066, "error in CAP marker length");
826 }
827
829 //
830 //
831 //
832 //
833 //
835
838 {
839 if (SPcod.wavelet_trans <= 1)
841 else {
842 assert(atk != NULL);
843 return atk->is_reversible();
844 }
845 }
846
849 {
850 assert(type == COD_MAIN);
851
852 //marker size excluding header
853 Lcod = 12;
854 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
855
856 ui8 buf[4];
857 bool result = true;
858
859 *(ui16*)buf = JP2K_MARKER::COD;
860 *(ui16*)buf = swap_byte(*(ui16*)buf);
861 result &= file->write(&buf, 2) == 2;
862 *(ui16*)buf = swap_byte(Lcod);
863 result &= file->write(&buf, 2) == 2;
864 *(ui8*)buf = Scod;
865 result &= file->write(&buf, 1) == 1;
866 *(ui8*)buf = SGCod.prog_order;
867 result &= file->write(&buf, 1) == 1;
868 *(ui16*)buf = swap_byte(SGCod.num_layers);
869 result &= file->write(&buf, 2) == 2;
870 *(ui8*)buf = SGCod.mc_trans;
871 result &= file->write(&buf, 1) == 1;
872 buf[0] = SPcod.num_decomp;
873 buf[1] = SPcod.block_width;
874 buf[2] = SPcod.block_height;
875 buf[3] = SPcod.block_style;
876 result &= file->write(&buf, 4) == 4;
877 *(ui8*)buf = SPcod.wavelet_trans;
878 result &= file->write(&buf, 1) == 1;
879 if (Scod & 1)
880 for (int i = 0; i <= SPcod.num_decomp; ++i)
881 {
882 *(ui8*)buf = SPcod.precinct_size[i];
883 result &= file->write(&buf, 1) == 1;
884 }
885
886 return result;
887 }
888
891 {
892 assert(type == COD_MAIN);
893 bool result = true;
894 param_cod *p = this->next;
895 while (p)
896 {
897 if (p->comp_idx < num_comps)
898 result &= p->internal_write_coc(file, num_comps);
899 p = p->next;
900 }
901 return result;
902 }
903
906 {
907 assert(type == COC_MAIN);
908
909 //marker size excluding header
910 Lcod = num_comps < 257 ? 9 : 10;
911 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
912
913 ui8 buf[4];
914 bool result = true;
915
916 *(ui16*)buf = JP2K_MARKER::COC;
917 *(ui16*)buf = swap_byte(*(ui16*)buf);
918 result &= file->write(&buf, 2) == 2;
919 *(ui16*)buf = swap_byte(Lcod);
920 result &= file->write(&buf, 2) == 2;
921 if (num_comps < 257)
922 {
923 *(ui8*)buf = (ui8)comp_idx;
924 result &= file->write(&buf, 1) == 1;
925 }
926 else
927 {
928 *(ui16*)buf = swap_byte(comp_idx);
929 result &= file->write(&buf, 2) == 2;
930 }
931 *(ui8*)buf = Scod;
932 result &= file->write(&buf, 1) == 1;
933 buf[0] = SPcod.num_decomp;
934 buf[1] = SPcod.block_width;
935 buf[2] = SPcod.block_height;
936 buf[3] = SPcod.block_style;
937 result &= file->write(&buf, 4) == 4;
938 *(ui8*)buf = SPcod.wavelet_trans;
939 result &= file->write(&buf, 1) == 1;
940 if (Scod & 1)
941 for (int i = 0; i <= SPcod.num_decomp; ++i)
942 {
943 *(ui8*)buf = SPcod.precinct_size[i];
944 result &= file->write(&buf, 1) == 1;
945 }
946
947 return result;
948 }
949
952 {
953 assert(type == COD_MAIN);
954
955 if (file->read(&Lcod, 2) != 2)
956 OJPH_ERROR(0x00050071, "error reading COD segment");
958 if (file->read(&Scod, 1) != 1)
959 OJPH_ERROR(0x00050072, "error reading COD segment");
960 if (file->read(&SGCod.prog_order, 1) != 1)
961 OJPH_ERROR(0x00050073, "error reading COD segment");
962 if (file->read(&SGCod.num_layers, 2) != 2)
963 { OJPH_ERROR(0x00050074, "error reading COD segment"); }
964 else
965 SGCod.num_layers = swap_byte(SGCod.num_layers);
966 if (file->read(&SGCod.mc_trans, 1) != 1)
967 OJPH_ERROR(0x00050075, "error reading COD segment");
968 if (file->read(&SPcod.num_decomp, 1) != 1)
969 OJPH_ERROR(0x00050076, "error reading COD segment");
970 if (file->read(&SPcod.block_width, 1) != 1)
971 OJPH_ERROR(0x00050077, "error reading COD segment");
972 if (file->read(&SPcod.block_height, 1) != 1)
973 OJPH_ERROR(0x00050078, "error reading COD segment");
974 if (file->read(&SPcod.block_style, 1) != 1)
975 OJPH_ERROR(0x00050079, "error reading COD segment");
976 if (file->read(&SPcod.wavelet_trans, 1) != 1)
977 OJPH_ERROR(0x0005007A, "error reading COD segment");
978
979 if (((SPcod.num_decomp & 0x80) == 0 && SPcod.num_decomp > 32)
980 || SPcod.block_width > 8
981 || SPcod.block_height > 8
982 || SPcod.block_width + SPcod.block_height > 8
983 || (SPcod.block_style & 0x40) != 0x40
984 || (SPcod.block_style & 0xB7) != 0x00)
985 OJPH_ERROR(0x0005007D, "wrong settings in a COD-SPcod parameter");
986 if ((SPcod.block_style & 0x40) != 0x40
987 || (SPcod.block_style & 0xB7) != 0x00)
988 OJPH_ERROR(0x0005007E, "unsupported settings in a COD-SPcod parameter");
989
990 if (Scod & 1)
991 for (int i = 0; i <= SPcod.num_decomp; ++i)
992 if (file->read(&SPcod.precinct_size[i], 1) != 1)
993 OJPH_ERROR(0x0005007B, "error reading COD segment");
994 if (Lcod != 12 + ((Scod & 1) ? 1 + SPcod.num_decomp : 0))
995 OJPH_ERROR(0x0005007C, "error in COD segment length");
996 }
997
999 void param_cod::read_coc(infile_base* file, ui32 num_comps,
1001 {
1002 assert(type == COC_MAIN);
1003 assert(top_cod != NULL);
1004
1005 this->SGCod = top_cod->SGCod;
1006 this->top_cod = top_cod;
1007 if (file->read(&Lcod, 2) != 2)
1008 OJPH_ERROR(0x00050121, "error reading COC segment");
1009 Lcod = swap_byte(Lcod);
1010 if (num_comps < 257) {
1011 ui8 t;
1012 if (file->read(&t, 1) != 1)
1013 OJPH_ERROR(0x00050122, "error reading COC segment");
1014 comp_idx = t;
1015 }
1016 else {
1017 if (file->read(&comp_idx, 2) != 2)
1018 OJPH_ERROR(0x00050123, "error reading COC segment");
1020 }
1021 if (file->read(&Scod, 1) != 1)
1022 OJPH_ERROR(0x00050124, "error reading COC segment");
1023 if (Scod & 0xF8)
1024 OJPH_WARN(0x00050011,
1025 "Unsupported options in Scoc field of the COC segment");
1026 if (file->read(&SPcod.num_decomp, 1) != 1)
1027 OJPH_ERROR(0x00050125, "error reading COC segment");
1028 if (file->read(&SPcod.block_width, 1) != 1)
1029 OJPH_ERROR(0x00050126, "error reading COC segment");
1030 if (file->read(&SPcod.block_height, 1) != 1)
1031 OJPH_ERROR(0x00050127, "error reading COC segment");
1032 if (file->read(&SPcod.block_style, 1) != 1)
1033 OJPH_ERROR(0x00050128, "error reading COC segment");
1034 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1035 OJPH_ERROR(0x00050129, "error reading COC segment");
1036
1037 if (((SPcod.num_decomp & 0x80) == 0 && SPcod.num_decomp > 32)
1038 || SPcod.block_width > 8
1039 || SPcod.block_height > 8
1040 || SPcod.block_width + SPcod.block_height > 8
1041 || (SPcod.block_style & 0x40) != 0x40
1042 || (SPcod.block_style & 0xB7) != 0x00)
1043 OJPH_ERROR(0x0005012C, "wrong settings in a COC-SPcoc parameter");
1044 if ((SPcod.block_style & 0x40) != 0x40
1045 || (SPcod.block_style & 0xB7) != 0x00)
1046 OJPH_ERROR(0x0005012D, "unsupported settings in a COC-SPcoc parameter");
1047
1048 if (Scod & 1)
1049 for (int i = 0; i <= get_num_decompositions(); ++i)
1050 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1051 OJPH_ERROR(0x0005012A, "error reading COC segment");
1052 ui32 t = 9;
1053 t += num_comps < 257 ? 0 : 1;
1054 t += (Scod & 1) ? 1 + get_num_decompositions() : 0;
1055 if (Lcod != t)
1056 OJPH_ERROR(0x0005012B, "error in COC segment length");
1057 }
1058
1061 {
1062 assert(type == COD_MAIN);
1063 this->atk = atk->get_atk(SPcod.wavelet_trans);
1064 if (this->atk == NULL)
1065 OJPH_ERROR(0x00050131, "A COD segment employs the DWT kernel "
1066 "atk = %d, but a corresponding ATK segment cannot be found.",
1067 SPcod.wavelet_trans);
1068 param_cod *p = next;
1069 while (p)
1070 {
1071 p->atk = atk->get_atk(p->SPcod.wavelet_trans);
1072 if (p->atk == NULL)
1073 OJPH_ERROR(0x00050132, "A COC segment employs the DWT kernel "
1074 "atk = %d, but a corresponding ATK segment cannot be found",
1075 SPcod.wavelet_trans);
1076 p = p->next;
1077 }
1078 }
1079
1082 {
1083 assert(this->type == COD_MAIN || this->top_cod->type == COD_MAIN);
1084 const param_cod *p, *q;
1085 if (this->type == COD_MAIN)
1086 q = p = this;
1087 else
1088 q = p = this->top_cod;
1089 while (p && p->comp_idx != comp_idx)
1090 p = p->next;
1091 return p ? p : q;
1092 }
1093
1096 {
1097 // cast object to constant
1098 const param_cod* const_p = const_cast<const param_cod*>(this);
1099 // call using the constant object, then cast to non-const
1100 return const_cast<param_cod*>(const_p->get_coc(comp_idx));
1101 }
1102
1105 {
1106 assert(type == COD_MAIN);
1107 param_cod *p = this;
1108 while (p->next != NULL)
1109 p = p->next;
1110 if (avail)
1111 {
1112 p->next = avail;
1113 avail = avail->next;
1114 p->next->init(this, (ui16)comp_idx);
1115 }
1116 else
1117 p->next = new param_cod(this, (ui16)comp_idx);
1118 return p->next;
1119 }
1120
1122 //
1123 //
1124 //
1125 //
1126 //
1128
1130 void param_qcd::check_validity(const param_siz& siz, const param_cod& cod)
1131 {
1132 ui32 num_comps = siz.get_num_components();
1134
1135 // first check that all the component captured by QCD have the same
1136 // bit_depth and signedness
1137 bool all_same = true;
1138 bool other_comps_exist = false;
1139 ui32 first_comp = 0xFFFF; // an impossible component
1140 {
1141 ui32 num_decompositions = 0;
1142 ui32 bit_depth = 0;
1143 bool is_signed = false;
1144 ui32 wavelet_kern = param_cod::DWT_IRV97;
1145
1146 for (ui32 c = 0; c < num_comps; ++c)
1147 {
1148 if (get_qcc(c) == this) // no qcc defined for component c
1149 {
1150 const param_cod *p = cod.get_coc(c);
1151 if (bit_depth == 0) // first component captured by QCD
1152 {
1153 num_decompositions = p->get_num_decompositions();
1154 bit_depth = siz.get_bit_depth(c);
1155 is_signed = siz.is_signed(c);
1156 wavelet_kern = p->get_wavelet_kern();
1157 first_comp = c;
1158 }
1159 else
1160 {
1161 all_same = all_same
1162 && (num_decompositions == p->get_num_decompositions())
1163 && (bit_depth == siz.get_bit_depth(c))
1164 && (is_signed == siz.is_signed(c))
1165 && (wavelet_kern == p->get_wavelet_kern());
1166 }
1167 }
1168 else
1169 other_comps_exist = true;
1170 }
1171 }
1172
1173 // configure QCD according COD
1174 ui32 qcd_num_decompositions;
1175 ui32 qcd_bit_depth;
1176 bool qcd_is_signed;
1177 ui32 qcd_wavelet_kern;
1178 {
1179 ui32 qcd_component = first_comp != 0xFFFF ? first_comp : 0;
1180 bool employing_color_transform = cod.is_employing_color_transform();
1181 qcd_num_decompositions = cod.get_num_decompositions();
1182 qcd_bit_depth = siz.get_bit_depth(qcd_component);
1183 qcd_is_signed = siz.is_signed(qcd_component);
1184 qcd_wavelet_kern = cod.get_wavelet_kern();
1185 this->num_subbands = 1 + 3 * qcd_num_decompositions;
1186 if (qcd_wavelet_kern == param_cod::DWT_REV53)
1187 set_rev_quant(qcd_num_decompositions, qcd_bit_depth,
1188 qcd_component < 3 ? employing_color_transform : false);
1189 else if (qcd_wavelet_kern == param_cod::DWT_IRV97)
1190 {
1191 if (this->base_delta == -1.0f)
1192 this->base_delta = 1.0f / (float)(1 << qcd_bit_depth);
1193 set_irrev_quant(qcd_num_decompositions);
1194 }
1195 else
1196 assert(0);
1197 }
1198
1199 // if not all the same and captured by QCD, then create QCC for them
1200 if (!all_same)
1201 {
1202 bool employing_color_transform = cod.is_employing_color_transform();
1203 for (ui32 c = 0; c < num_comps; ++c)
1204 {
1205 const param_cod *cp = cod.get_coc(c);
1206 if (qcd_num_decompositions == cp->get_num_decompositions()
1207 && qcd_bit_depth == siz.get_bit_depth(c)
1208 && qcd_is_signed == siz.is_signed(c)
1209 && qcd_wavelet_kern == cp->get_wavelet_kern())
1210 continue; // captured by QCD
1211
1212 // Does not match QCD, must have QCC
1213 param_qcd *qp = get_qcc(c);
1214 if (qp == this) // no QCC was defined, create QCC
1215 qp = this->add_qcc_object(c);
1216
1217 ui32 num_decompositions = cp->get_num_decompositions();
1218 qp->num_subbands = 1 + 3 * num_decompositions;
1219 ui32 bit_depth = siz.get_bit_depth(c);
1221 qp->set_rev_quant(num_decompositions, bit_depth,
1222 c < 3 ? employing_color_transform : false);
1223 else if (cp->get_wavelet_kern() == param_cod::DWT_IRV97)
1224 {
1225 if (qp->base_delta == -1.0f)
1226 qp->base_delta = 1.0f / (float)(1 << bit_depth);
1227 qp->set_irrev_quant(num_decompositions);
1228 }
1229 else
1230 assert(0);
1231 }
1232 }
1233 else if (other_comps_exist) // Some are captured by QCD
1234 {
1235 bool employing_color_transform = cod.is_employing_color_transform();
1236 for (ui32 c = 0; c < num_comps; ++c)
1237 {
1238 param_qcd *qp = get_qcc(c);
1239 if (qp == this) // if captured by QCD continue
1240 continue;
1241 const param_cod *cp = cod.get_coc(c);
1242 ui32 num_decompositions = cp->get_num_decompositions();
1243 qp->num_subbands = 1 + 3 * num_decompositions;
1244 ui32 bit_depth = siz.get_bit_depth(c);
1246 qp->set_rev_quant(num_decompositions, bit_depth,
1247 c < 3 ? employing_color_transform : false);
1248 else if (cp->get_wavelet_kern() == param_cod::DWT_IRV97)
1249 {
1250 if (qp->base_delta == -1.0f)
1251 qp->base_delta = 1.0f / (float)(1 << bit_depth);
1252 qp->set_irrev_quant(num_decompositions);
1253 }
1254 else
1255 assert(0);
1256 }
1257 }
1258 }
1259
1262 {
1263 assert(type == QCD_MAIN);
1265 if (p == NULL)
1267 p->set_delta(delta);
1268 }
1269
1271 void param_qcd::set_rev_quant(ui32 num_decomps, ui32 bit_depth,
1272 bool is_employing_color_transform)
1273 {
1274 ui32 B = bit_depth;
1275 B += is_employing_color_transform ? 1 : 0; //1 bit for RCT
1276 int s = 0;
1277 double bibo_l = bibo_gains::get_bibo_gain_l(num_decomps, true);
1278 ui32 X = (ui32) ceil(log(bibo_l * bibo_l) / M_LN2);
1279 SPqcd.u8[s++] = (ui8)(B + X);
1280 ui32 max_B_plus_X = (ui32)(B + X);
1281 for (ui32 d = num_decomps; d > 0; --d)
1282 {
1283 double bibo_l = bibo_gains::get_bibo_gain_l(d, true);
1284 double bibo_h = bibo_gains::get_bibo_gain_h(d - 1, true);
1285 X = (ui32) ceil(log(bibo_h * bibo_l) / M_LN2);
1286 SPqcd.u8[s++] = (ui8)(B + X);
1287 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1288 SPqcd.u8[s++] = (ui8)(B + X);
1289 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1290 X = (ui32) ceil(log(bibo_h * bibo_h) / M_LN2);
1291 SPqcd.u8[s++] = (ui8)(B + X);
1292 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1293 }
1294
1295 if (max_B_plus_X > 38)
1296 OJPH_ERROR(0x00050151, "The specified combination of bit_depth, "
1297 "colour transform, and type of wavelet transform requires more than "
1298 "38 bits; it requires %d bits. This is beyond what is allowed in "
1299 "the JPEG2000 image coding format.", max_B_plus_X);
1300
1301 int guard_bits = ojph_max(1, (si32)max_B_plus_X - 31);
1302 Sqcd = (ui8)(guard_bits << 5);
1303 s = 0;
1304 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1305 s++;
1306 for (ui32 d = num_decomps; d > 0; --d)
1307 {
1308 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1309 s++;
1310 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1311 s++;
1312 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1313 s++;
1314 }
1315 }
1316
1319 {
1320 int guard_bits = 1;
1321 Sqcd = (ui8)((guard_bits<<5)|0x2);//one guard bit, scalar quantization
1322 int s = 0;
1323 float gain_l = sqrt_energy_gains::get_gain_l(num_decomps, false);
1324 float delta_b = base_delta / (gain_l * gain_l);
1325 int exp = 0, mantissa;
1326 while (delta_b < 1.0f)
1327 { exp++; delta_b *= 2.0f; }
1328 //with rounding, there is a risk of becoming equal to 1<<12
1329 // but that should not happen in reality
1330 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1331 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1332 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1333 for (ui32 d = num_decomps; d > 0; --d)
1334 {
1335 float gain_l = sqrt_energy_gains::get_gain_l(d, false);
1336 float gain_h = sqrt_energy_gains::get_gain_h(d - 1, false);
1337
1338 delta_b = base_delta / (gain_l * gain_h);
1339
1340 int exp = 0, mantissa;
1341 while (delta_b < 1.0f)
1342 { exp++; delta_b *= 2.0f; }
1343 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1344 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1345 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1346 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1347
1348 delta_b = base_delta / (gain_h * gain_h);
1349
1350 exp = 0;
1351 while (delta_b < 1)
1352 { exp++; delta_b *= 2.0f; }
1353 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1354 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1355 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1356 }
1357 }
1358
1361 {
1362 ui32 B = 0;
1363
1364 const param_qcd *p = this;
1365 while (p)
1366 {
1367 //this can be written better, but it is only executed once
1368 // this assumes a bi-directional wavelet (conventional DWT)
1369 ui32 num_decomps = (p->num_subbands - 1) / 3;
1370
1371 int irrev = p->Sqcd & 0x1F;
1372 if (irrev == 0) //reversible
1373 for (ui32 i = 0; i < p->num_subbands; ++i) {
1374 ui32 t = p->decode_SPqcd(p->SPqcd.u8[i]);
1375 t += p->get_num_guard_bits() - 1u;
1376 B = ojph_max(B, t);
1377 }
1378 else if (irrev == 2) //scalar expounded
1379 for (ui32 i = 0; i < p->num_subbands; ++i)
1380 {
1381 ui32 nb = num_decomps - (i ? (i - 1) / 3 : 0); //decompsition level
1382 ui32 t = (p->SPqcd.u16[i] >> 11) + p->get_num_guard_bits() - nb;
1383 B = ojph_max(B, t);
1384 }
1385 else
1386 assert(0);
1387
1388 p = p->next;
1389 }
1390
1391 return B;
1392 }
1393
1396 ui32 num_decompositions,
1397 ui32 resolution, ui32 subband) const
1398 {
1399 float arr[] = { 1.0f, 2.0f, 2.0f, 4.0f };
1400 assert((Sqcd & 0x1F) == 2);
1401
1402 ui32 idx;
1403 if (dfs != NULL && dfs->exists())
1404 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1405 else
1406 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1407 if (idx >= num_subbands) {
1408 OJPH_INFO(0x00050101, "Trying to access quantization step size for "
1409 "subband %d when the QCD/QCC marker segment specifies "
1410 "quantization step sizes for %d subbands only. To continue "
1411 "decoding, we are using the step size for subband %d, which can "
1412 "produce incorrect results",
1413 idx + 1, num_subbands, num_subbands - 1);
1414 idx = num_subbands - 1;
1415 }
1416 int eps = SPqcd.u16[idx] >> 11;
1417 float mantissa;
1418 mantissa = (float)((SPqcd.u16[idx] & 0x7FF) | 0x800) * arr[subband];
1419 mantissa /= (float)(1 << 11);
1420 mantissa /= (float)(1u << eps);
1421 return mantissa;
1422 }
1423
1426 {
1427 ui32 comp_idx = cod->get_comp_idx();
1428 ui32 precision = 0;
1429 const param_cod *main =
1431 if (main->is_employing_color_transform() && comp_idx < 3)
1432 {
1433 for (ui32 i = 0; i < 3; ++i) {
1434 const param_qcd* p = this->get_qcc(i);
1435 precision = ojph_max(precision, p->get_largest_Kmax());
1436 }
1437 }
1438 else {
1439 precision = get_largest_Kmax();
1440 }
1441 // ``precision'' now holds the largest K_max, which excludes the sign
1442 // bit.
1443 // + 1 for the sign bit
1444 // + 1 because my block decoder/encoder does not supports up to 30
1445 // bits (not 31), so we bump it by one more bit.
1446 return precision + 1 + 1;
1447 }
1448
1451 {
1452 return (Sqcd >> 5);
1453 }
1454
1456 ui32 param_qcd::get_Kmax(const param_dfs* dfs, ui32 num_decompositions,
1457 ui32 resolution, ui32 subband) const
1458 {
1459 ui32 idx;
1460 if (dfs != NULL && dfs->exists())
1461 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1462 else
1463 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1464 if (idx >= num_subbands) {
1465 OJPH_INFO(0x00050111, "Trying to access quantization step size for "
1466 "subband %d when the QCD/QCC marker segment specifies "
1467 "quantization step sizes for %d subbands only. To continue "
1468 "decoding, we are using the step size for subband %d, which can "
1469 "produce incorrect results",
1470 idx + 1, num_subbands, num_subbands - 1);
1471 idx = num_subbands - 1;
1472 }
1473
1474 int irrev = Sqcd & 0x1F;
1475 ui32 num_bits = 0;
1476 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1477 {
1478 num_bits = decode_SPqcd(SPqcd.u8[idx]);
1479 num_bits = num_bits == 0 ? 0 : num_bits - 1;
1480 }
1481 else if (irrev == 1)
1482 assert(0);
1483 else if (irrev == 2) //scalar expounded
1484 num_bits = (SPqcd.u16[idx] >> 11) - 1;
1485 else
1486 assert(0);
1487
1488 return num_bits + get_num_guard_bits();
1489 }
1490
1493 {
1494 int irrev = Sqcd & 0x1F;
1495 ui32 num_bits = 0;
1496 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1497 {
1498 for (ui32 i = 0; i < num_subbands; ++i) {
1499 ui32 t = decode_SPqcd(SPqcd.u8[i]);
1500 num_bits = ojph_max(num_bits, t == 0 ? 0 : t - 1);
1501 }
1502 }
1503 else if (irrev == 1)
1504 assert(0);
1505 else if (irrev == 2) //scalar expounded
1506 {
1507 for (ui32 i = 0; i < num_subbands; ++i) {
1508 ui32 t = (SPqcd.u16[i] >> 11) - 1;
1509 num_bits = ojph_max(num_bits, t);
1510 }
1511 }
1512 else
1513 assert(0);
1514
1515 return num_bits + get_num_guard_bits();
1516 }
1517
1520 {
1521 int irrev = Sqcd & 0x1F;
1522
1523 //marker size excluding header
1524 Lqcd = 3;
1525 if (irrev == 0)
1526 Lqcd = (ui16)(Lqcd + num_subbands);
1527 else if (irrev == 2)
1528 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1529 else
1530 assert(0);
1531
1532 char buf[4];
1533 bool result = true;
1534
1535 *(ui16*)buf = JP2K_MARKER::QCD;
1536 *(ui16*)buf = swap_byte(*(ui16*)buf);
1537 result &= file->write(&buf, 2) == 2;
1538 *(ui16*)buf = swap_byte(Lqcd);
1539 result &= file->write(&buf, 2) == 2;
1540 *(ui8*)buf = Sqcd;
1541 result &= file->write(&buf, 1) == 1;
1542
1543 if (irrev == 0)
1544 for (ui32 i = 0; i < num_subbands; ++i)
1545 {
1546 *(ui8*)buf = SPqcd.u8[i];
1547 result &= file->write(&buf, 1) == 1;
1548 }
1549 else if (irrev == 2)
1550 for (ui32 i = 0; i < num_subbands; ++i)
1551 {
1552 *(ui16*)buf = swap_byte(SPqcd.u16[i]);
1553 result &= file->write(&buf, 2) == 2;
1554 }
1555 else
1556 assert(0);
1557
1558 return result;
1559 }
1560
1563 {
1564 assert(type == QCD_MAIN);
1565 bool result = true;
1566 param_qcd *p = this->next;
1567 while (p)
1568 {
1569 if (p->enabled)
1570 result &= p->internal_write_qcc(file, num_comps);
1571 p = p->next;
1572 }
1573 return result;
1574 }
1575
1578 {
1579 int irrev = Sqcd & 0x1F;
1580
1581 //marker size excluding header
1582 Lqcd = (ui16)(4 + (num_comps < 257 ? 0 : 1));
1583 if (irrev == 0)
1584 Lqcd = (ui16)(Lqcd + num_subbands);
1585 else if (irrev == 2)
1586 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1587 else
1588 assert(0);
1589
1590 char buf[4];
1591 bool result = true;
1592
1593 *(ui16*)buf = JP2K_MARKER::QCC;
1594 *(ui16*)buf = swap_byte(*(ui16*)buf);
1595 result &= file->write(&buf, 2) == 2;
1596 *(ui16*)buf = swap_byte(Lqcd);
1597 result &= file->write(&buf, 2) == 2;
1598 if (num_comps < 257)
1599 {
1600 *(ui8*)buf = (ui8)comp_idx;
1601 result &= file->write(&buf, 1) == 1;
1602 }
1603 else
1604 {
1605 *(ui16*)buf = swap_byte(comp_idx);
1606 result &= file->write(&buf, 2) == 2;
1607 }
1608 *(ui8*)buf = Sqcd;
1609 result &= file->write(&buf, 1) == 1;
1610 if (irrev == 0)
1611 for (ui32 i = 0; i < num_subbands; ++i)
1612 {
1613 *(ui8*)buf = SPqcd.u8[i];
1614 result &= file->write(&buf, 1) == 1;
1615 }
1616 else if (irrev == 2)
1617 for (ui32 i = 0; i < num_subbands; ++i)
1618 {
1619 *(ui16*)buf = swap_byte(SPqcd.u16[i]);
1620 result &= file->write(&buf, 2) == 2;
1621 }
1622 else
1623 assert(0);
1624
1625 return result;
1626 }
1627
1630 {
1631 assert(type == QCD_MAIN && comp_idx == OJPH_QCD_DEFAULT);
1632 param_qcd *p = this->next;
1633 while (p)
1634 {
1635 assert(p->type == QCC_MAIN);
1636 p->enabled = p->comp_idx < num_comps;
1637 p = p->next;
1638 }
1639 }
1640
1643 {
1644 if (file->read(&Lqcd, 2) != 2)
1645 OJPH_ERROR(0x00050081, "error reading QCD marker");
1646 Lqcd = swap_byte(Lqcd);
1647 if (file->read(&Sqcd, 1) != 1)
1648 OJPH_ERROR(0x00050082, "error reading QCD marker");
1649 if ((Sqcd & 0x1F) == 0)
1650 {
1651 num_subbands = (Lqcd - 3);
1652 if (num_subbands > 97 || Lqcd != 3 + num_subbands)
1653 OJPH_ERROR(0x00050083, "wrong Lqcd value of %d in QCD marker", Lqcd);
1654 for (ui32 i = 0; i < num_subbands; ++i)
1655 if (file->read(&SPqcd.u8[i], 1) != 1)
1656 OJPH_ERROR(0x00050084, "error reading QCD marker");
1657 }
1658 else if ((Sqcd & 0x1F) == 1)
1659 {
1660 num_subbands = 0;
1661 OJPH_ERROR(0x00050089,
1662 "Scalar derived quantization is not supported yet in QCD marker");
1663 if (Lqcd != 5)
1664 OJPH_ERROR(0x00050085, "wrong Lqcd value in QCD marker");
1665 }
1666 else if ((Sqcd & 0x1F) == 2)
1667 {
1668 num_subbands = (Lqcd - 3) / 2;
1669 if (num_subbands > 97 || Lqcd != 3 + 2 * num_subbands)
1670 OJPH_ERROR(0x00050086, "wrong Lqcd value of %d in QCD marker", Lqcd);
1671 for (ui32 i = 0; i < num_subbands; ++i)
1672 {
1673 if (file->read(&SPqcd.u16[i], 2) != 2)
1674 OJPH_ERROR(0x00050087, "error reading QCD marker");
1675 SPqcd.u16[i] = swap_byte(SPqcd.u16[i]);
1676 }
1677 }
1678 else
1679 OJPH_ERROR(0x00050088, "wrong Sqcd value in QCD marker");
1680 }
1681
1683 void param_qcd::read_qcc(infile_base *file, ui32 num_comps)
1684 {
1685 if (file->read(&Lqcd, 2) != 2)
1686 OJPH_ERROR(0x000500A1, "error reading QCC marker");
1687 Lqcd = swap_byte(Lqcd);
1688 if (num_comps < 257)
1689 {
1690 ui8 v;
1691 if (file->read(&v, 1) != 1)
1692 OJPH_ERROR(0x000500A2, "error reading QCC marker");
1693 comp_idx = v;
1694 }
1695 else
1696 {
1697 if (file->read(&comp_idx, 2) != 2)
1698 OJPH_ERROR(0x000500A3, "error reading QCC marker");
1700 }
1701 if (file->read(&Sqcd, 1) != 1)
1702 OJPH_ERROR(0x000500A4, "error reading QCC marker");
1703 ui32 offset = num_comps < 257 ? 4 : 5;
1704 if ((Sqcd & 0x1F) == 0)
1705 {
1706 num_subbands = (Lqcd - offset);
1707 if (num_subbands > 97 || Lqcd != offset + num_subbands)
1708 OJPH_ERROR(0x000500A5, "wrong Lqcd value of %d in QCC marker", Lqcd);
1709 for (ui32 i = 0; i < num_subbands; ++i)
1710 if (file->read(&SPqcd.u8[i], 1) != 1)
1711 OJPH_ERROR(0x000500A6, "error reading QCC marker");
1712 }
1713 else if ((Sqcd & 0x1F) == 1)
1714 {
1715 num_subbands = 0;
1716 OJPH_ERROR(0x000500AB,
1717 "Scalar derived quantization is not supported yet in QCC marker");
1718 if (Lqcd != offset)
1719 OJPH_ERROR(0x000500A7, "wrong Lqcc value in QCC marker");
1720 }
1721 else if ((Sqcd & 0x1F) == 2)
1722 {
1723 num_subbands = (Lqcd - offset) / 2;
1724 if (num_subbands > 97 || Lqcd != offset + 2 * num_subbands)
1725 OJPH_ERROR(0x000500A8, "wrong Lqcc value of %d in QCC marker", Lqcd);
1726 for (ui32 i = 0; i < num_subbands; ++i)
1727 {
1728 if (file->read(&SPqcd.u16[i], 2) != 2)
1729 OJPH_ERROR(0x000500A9, "error reading QCC marker");
1730 SPqcd.u16[i] = swap_byte(SPqcd.u16[i]);
1731 }
1732 }
1733 else
1734 OJPH_ERROR(0x000500AA, "wrong Sqcc value in QCC marker");
1735 }
1736
1739 {
1740 // cast object to constant
1741 const param_qcd* const_p = const_cast<const param_qcd*>(this);
1742 // call using the constant object, then cast to non-const
1743 return const_cast<param_qcd*>(const_p->get_qcc(comp_idx));
1744 }
1745
1748 {
1749 assert(this->type == QCD_MAIN || this->top_qcd->type == QCD_MAIN);
1750 const param_qcd *p, *q;
1751 if (this->type == QCD_MAIN)
1752 q = p = this;
1753 else
1754 q = p = this->top_qcd;
1755 while (p && p->comp_idx != comp_idx)
1756 p = p->next;
1757 return p ? p : q;
1758 }
1759
1762 {
1763 assert(type == QCD_MAIN);
1764 param_qcd *p = this;
1765 while (p->next != NULL)
1766 p = p->next;
1767 if (avail)
1768 {
1769 p->next = avail;
1770 avail = avail->next;
1771 p->next->init(this, (ui16)comp_idx);
1772 }
1773 else
1774 p->next = new param_qcd(this, (ui16)comp_idx);
1775 return p->next;
1776 }
1777
1779 //
1780 //
1781 //
1782 //
1783 //
1785
1788 {
1789 if (is_any_enabled() == false)
1790 return;
1791
1792 if (this->enabled && this->Tnlt == nonlinearity::OJPH_NLT_NO_NLT)
1793 this->enabled = false;
1794
1795 if (this->enabled &&
1796 this->Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
1797 {
1798 bool all_same = true;
1799 ui32 num_comps = siz.get_num_components();
1800
1801 // first stage; find out if all components captured by the default
1802 // entry (ALL_COMPS) has the same bit_depth/signedness,
1803 // while doing this, set the BDnlt for components not captured by the
1804 // default entry (ALL_COMPS)
1805 ui32 bit_depth = 0; // unknown yet
1806 bool is_signed = false; // unknown yet
1807 for (ui32 c = 0; c < num_comps; ++c)
1808 { // captured by ALL_COMPS
1809 param_nlt* p = get_nlt_object(c);
1810 if (p == NULL || !p->enabled)
1811 {
1812 if (bit_depth != 0)
1813 {
1814 // we have seen an undefined component previously
1815 all_same = all_same && (bit_depth == siz.get_bit_depth(c));
1816 all_same = all_same && (is_signed == siz.is_signed(c));
1817 }
1818 else
1819 {
1820 // this is the first component which has not type 3 nlt definition
1821 bit_depth = siz.get_bit_depth(c);
1822 is_signed = siz.is_signed(c);
1823 }
1824 }
1825 else
1826 { // can be type 0 or type 3
1827 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1828 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1829 }
1830 }
1831
1832 if (all_same && bit_depth != 0)
1833 { // all the same, and some components are captured by ALL_COMPS
1834 this->BDnlt = (ui8)(bit_depth - 1);
1835 this->BDnlt = (ui8)(this->BDnlt | (is_signed ? 0x80 : 0));
1836 }
1837 else if (!all_same)
1838 { // have different settings or no component is captured by ALL_COMPS
1839 this->enabled = false;
1840 for (ui32 c = 0; c < num_comps; ++c)
1841 {
1842 param_nlt* p = get_nlt_object(c);
1843 if (p == NULL || !p->enabled)
1844 { // captured by ALL_COMPS
1845 if (p == NULL)
1846 p = add_object(c);
1847 p->enabled = true;
1848 p->Tnlt = nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
1849 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1850 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1851 }
1852 }
1853 }
1854 }
1855 else {
1856 // fill NLT segment markers with correct information
1857 ui32 num_comps = siz.get_num_components();
1858 for (ui32 c = 0; c < num_comps; ++c)
1859 { // captured by ALL_COMPS
1860 param_nlt* p = get_nlt_object(c);
1861 if (p != NULL && p->enabled)
1862 { // can be type 0 or type 3
1863 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1864 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1865 }
1866 }
1867 }
1868
1870
1871 if (is_any_enabled() == true)
1873 }
1874
1877 {
1878 if (nl_type != ojph::param_nlt::OJPH_NLT_NO_NLT &&
1880 OJPH_ERROR(0x00050171, "Nonliearities other than type 0 "
1881 "(No Nonlinearity) or type 3 (Binary Binary Complement to Sign "
1882 "Magnitude Conversion) are not supported yet");
1883 param_nlt* p = get_nlt_object(comp_num);
1884 if (p == NULL)
1885 p = add_object(comp_num);
1886 p->Tnlt = nl_type;
1887 p->enabled = true;
1888 }
1889
1891 bool
1893 bool& is_signed, ui8& nl_type) const
1894 {
1895 assert(Cnlt == special_comp_num::ALL_COMPS);
1896 const param_nlt* p = get_nlt_object(comp_num);
1897 p = (p && p->enabled) ? p : this;
1898 if (p->enabled)
1899 {
1900 bit_depth = (ui8)((p->BDnlt & 0x7F) + 1);
1901 bit_depth = bit_depth <= 38 ? bit_depth : 38;
1902 is_signed = (p->BDnlt & 0x80) == 0x80;
1903 nl_type = (nonlinearity)p->Tnlt;
1904 return true;
1905 }
1906 return false;
1907 }
1908
1911 {
1912 if (is_any_enabled() == false)
1913 return true;
1914
1915 char buf[2];
1916 bool result = true;
1917 const param_nlt* p = this;
1918 while (p)
1919 {
1920 if (p->enabled)
1921 {
1922 *(ui16*)buf = JP2K_MARKER::NLT;
1923 *(ui16*)buf = swap_byte(*(ui16*)buf);
1924 result &= file->write(&buf, 2) == 2;
1925 *(ui16*)buf = swap_byte(p->Lnlt);
1926 result &= file->write(&buf, 2) == 2;
1927 *(ui16*)buf = swap_byte(p->Cnlt);
1928 result &= file->write(&buf, 2) == 2;
1929 result &= file->write(&p->BDnlt, 1) == 1;
1930 result &= file->write(&p->Tnlt, 1) == 1;
1931 }
1932 p = p->next;
1933 }
1934 return result;
1935 }
1936
1939 {
1940 ui8 buf[6];
1941
1942 if (file->read(buf, 6) != 6)
1943 OJPH_ERROR(0x00050141, "error reading NLT marker segment");
1944
1945 ui16 length = swap_byte(*(ui16*)buf);
1946 if (length != 6 || (buf[5] != 3 && buf[5] != 0)) // wrong length or type
1947 OJPH_ERROR(0x00050142, "Unsupported NLT type %d\n", buf[5]);
1948
1949 ui16 comp = swap_byte(*(ui16*)(buf + 2));
1950 param_nlt* p = get_nlt_object(comp);
1951 if (p == NULL)
1952 p = add_object(comp);
1953 p->enabled = true;
1954 p->Cnlt = comp;
1955 p->BDnlt = buf[4];
1956 p->Tnlt = buf[5];
1957 }
1958
1961 {
1962 // cast object to constant
1963 const param_nlt* const_p = const_cast<const param_nlt*>(this);
1964 // call using the constant object, then cast to non-const
1965 return const_cast<param_nlt*>(const_p->get_nlt_object(comp_num));
1966 }
1967
1970 {
1971 const param_nlt* p = this;
1972 while (p && p->Cnlt != comp_num)
1973 p = p->next;
1974 return p;
1975 }
1976
1979 {
1980 assert(comp_num != special_comp_num::ALL_COMPS);
1981 assert(Cnlt == special_comp_num::ALL_COMPS);
1982 param_nlt* p = this;
1983 while (p->next != NULL) {
1984 assert(p->Cnlt != comp_num);
1985 p = p->next;
1986 }
1987 if (avail)
1988 {
1989 p->next = avail;
1990 avail = avail->next;
1991 p->next->init();
1992 }
1993 else
1994 p->next = new param_nlt;
1995 p = p->next;
1996 p->Cnlt = (ui16)comp_num;
1997 return p;
1998 }
1999
2002 {
2003 // check if any field is enabled
2004 const param_nlt* p = this;
2005 while (p && p->enabled == false)
2006 p = p->next;
2007 return (p != NULL);
2008 }
2009
2012 {
2013 param_nlt* p = this->next;
2014 while (p) {
2015 if (p->enabled == true && p->Cnlt >= num_comps) {
2016 p->enabled = false;
2017 OJPH_INFO(0x00050161, "The NLT marker segment for the "
2018 "non-existing component %d has been removed.", p->Cnlt);
2019 }
2020 p = p->next;
2021 }
2022 }
2023
2024
2026 //
2027 //
2028 //
2029 //
2030 //
2032
2034 bool param_sot::write(outfile_base *file, ui32 payload_len)
2035 {
2036 char buf[4];
2037 bool result = true;
2038
2039 this->Psot = payload_len + 14; //inc. SOT marker, field & SOD
2040
2041 *(ui16*)buf = JP2K_MARKER::SOT;
2042 *(ui16*)buf = swap_byte(*(ui16*)buf);
2043 result &= file->write(&buf, 2) == 2;
2044 *(ui16*)buf = swap_byte(Lsot);
2045 result &= file->write(&buf, 2) == 2;
2046 *(ui16*)buf = swap_byte(Isot);
2047 result &= file->write(&buf, 2) == 2;
2048 *(ui32*)buf = swap_byte(Psot);
2049 result &= file->write(&buf, 4) == 4;
2050 result &= file->write(&TPsot, 1) == 1;
2051 result &= file->write(&TNsot, 1) == 1;
2052
2053 return result;
2054 }
2055
2057 bool param_sot::write(outfile_base *file, ui32 payload_len,
2058 ui8 TPsot, ui8 TNsot)
2059 {
2060 char buf[4];
2061 bool result = true;
2062
2063 *(ui16*)buf = JP2K_MARKER::SOT;
2064 *(ui16*)buf = swap_byte(*(ui16*)buf);
2065 result &= file->write(&buf, 2) == 2;
2066 *(ui16*)buf = swap_byte(Lsot);
2067 result &= file->write(&buf, 2) == 2;
2068 *(ui16*)buf = swap_byte(Isot);
2069 result &= file->write(&buf, 2) == 2;
2070 *(ui32*)buf = swap_byte(payload_len + 14);
2071 result &= file->write(&buf, 4) == 4;
2072 result &= file->write(&TPsot, 1) == 1;
2073 result &= file->write(&TNsot, 1) == 1;
2074
2075 return result;
2076 }
2077
2079 bool param_sot::read(infile_base *file, bool resilient)
2080 {
2081 if (resilient)
2082 {
2083 if (file->read(&Lsot, 2) != 2)
2084 {
2085 OJPH_INFO(0x00050091, "error reading SOT marker");
2086 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2087 return false;
2088 }
2089 Lsot = swap_byte(Lsot);
2090 if (Lsot != 10)
2091 {
2092 OJPH_INFO(0x00050092, "error in SOT length");
2093 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2094 return false;
2095 }
2096 if (file->read(&Isot, 2) != 2)
2097 {
2098 OJPH_INFO(0x00050093, "error reading tile index");
2099 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2100 return false;
2101 }
2102 Isot = swap_byte(Isot);
2103 if (Isot == 0xFFFF)
2104 {
2105 OJPH_INFO(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2106 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2107 return false;
2108 }
2109 if (file->read(&Psot, 4) != 4)
2110 {
2111 OJPH_INFO(0x00050095, "error reading SOT marker");
2112 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2113 return false;
2114 }
2115 Psot = swap_byte(Psot);
2116 if (file->read(&TPsot, 1) != 1)
2117 {
2118 OJPH_INFO(0x00050096, "error reading SOT marker");
2119 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2120 return false;
2121 }
2122 if (file->read(&TNsot, 1) != 1)
2123 {
2124 OJPH_INFO(0x00050097, "error reading SOT marker");
2125 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2126 return false;
2127 }
2128 }
2129 else
2130 {
2131 if (file->read(&Lsot, 2) != 2)
2132 OJPH_ERROR(0x00050091, "error reading SOT marker");
2133 Lsot = swap_byte(Lsot);
2134 if (Lsot != 10)
2135 OJPH_ERROR(0x00050092, "error in SOT length");
2136 if (file->read(&Isot, 2) != 2)
2137 OJPH_ERROR(0x00050093, "error reading SOT tile index");
2138 Isot = swap_byte(Isot);
2139 if (Isot == 0xFFFF)
2140 OJPH_ERROR(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2141 if (file->read(&Psot, 4) != 4)
2142 OJPH_ERROR(0x00050095, "error reading SOT marker");
2143 Psot = swap_byte(Psot);
2144 if (file->read(&TPsot, 1) != 1)
2145 OJPH_ERROR(0x00050096, "error reading SOT marker");
2146 if (file->read(&TNsot, 1) != 1)
2147 OJPH_ERROR(0x00050097, "error reading SOT marker");
2148 }
2149 return true;
2150 }
2151
2153 //
2154 //
2155 //
2156 //
2157 //
2159
2162 {
2163 if (4 + 6 * num_pairs > 65535)
2164 OJPH_ERROR(0x000500B1, "Trying to allocate more than 65535 bytes for "
2165 "a TLM marker; this can be resolved by having more than "
2166 "one TLM marker, but the code does not support this. "
2167 "In any case, this limit means that we have 10922 "
2168 "tileparts or more, which is a huge number.");
2169 this->num_pairs = num_pairs;
2170 pairs = store;
2171 Ltlm = (ui16)(4 + 6 * num_pairs);
2172 Ztlm = 0;
2173 Stlm = 0x60;
2174 }
2175
2178 {
2179 assert(next_pair_index < num_pairs);
2180 pairs[next_pair_index].Ttlm = Ttlm;
2181 pairs[next_pair_index].Ptlm = Ptlm + 14;
2183 }
2184
2187 {
2188 assert(next_pair_index == num_pairs);
2189 char buf[4];
2190 bool result = true;
2191
2192 *(ui16*)buf = JP2K_MARKER::TLM;
2193 *(ui16*)buf = swap_byte(*(ui16*)buf);
2194 result &= file->write(&buf, 2) == 2;
2195 *(ui16*)buf = swap_byte(Ltlm);
2196 result &= file->write(&buf, 2) == 2;
2197 result &= file->write(&Ztlm, 1) == 1;
2198 result &= file->write(&Stlm, 1) == 1;
2199 for (ui32 i = 0; i < num_pairs; ++i)
2200 {
2201 *(ui16*)buf = swap_byte(pairs[i].Ttlm);
2202 result &= file->write(&buf, 2) == 2;
2203 *(ui32*)buf = swap_byte(pairs[i].Ptlm);
2204 result &= file->write(&buf, 4) == 4;
2205 }
2206 return result;
2207 }
2208
2210 //
2211 //
2212 //
2213 //
2214 //
2216
2218 const param_dfs* param_dfs::get_dfs(int index) const
2219 {
2220 const param_dfs* p = this;
2221 while (p && p->Sdfs != index)
2222 p = p->next;
2223 return p;
2224 }
2225
2228 {
2229 decomp_level = ojph_min(decomp_level, Ids);
2230 ui32 d = decomp_level - 1; // decomp_level starts from 1
2231 ui32 idx = d >> 2; // complete bytes
2232 ui32 bits = d & 0x3; // bit within the bytes
2233 ui32 val = (Ddfs[idx] >> (6 - 2 * bits)) & 0x3;
2234 return (dfs_dwt_type)val;
2235 }
2236
2239 ui32 subband) const
2240 {
2241 assert((resolution == 0 && subband == 0) ||
2242 (resolution > 0 && subband > 0 && subband < 4));
2243
2244 ui32 ns[4] = { 0, 3, 1, 1 };
2245
2246 ui32 idx = 0;
2247 if (resolution > 0)
2248 {
2249 idx = 0;
2250 ui32 i = 1;
2251 for (; i < resolution; ++i)
2252 idx += ns[get_dwt_type(num_decompositions - i + 1)];
2253 dfs_dwt_type t = get_dwt_type(num_decompositions - i + 1);
2254 idx += subband;
2255 if (t == VERT_DWT && subband == 2)
2256 --idx;
2257 }
2258
2259 return idx;
2260 }
2261
2263 point param_dfs::get_res_downsamp(ui32 skipped_resolutions) const
2264 {
2265 point factor(1, 1);
2266 ui32 decomp_level = 1;
2267 while (skipped_resolutions > 0)
2268 {
2269 param_dfs::dfs_dwt_type type = get_dwt_type(decomp_level);
2270 if (type == BIDIR_DWT)
2271 { factor.x *= 2; factor.y *= 2; }
2272 else if (type == HORZ_DWT)
2273 factor.x *= 2;
2274 else if (type == VERT_DWT)
2275 factor.y *= 2;
2276
2277 ++decomp_level;
2278 --skipped_resolutions;
2279 }
2280 return factor;
2281 }
2282
2285 {
2286 if (Ldfs != 0) { // this param_dfs is used
2287 param_dfs* p = this;
2288 while (p->next != NULL)
2289 p = p->next;
2290 if (avail)
2291 {
2292 p->next = avail;
2293 avail = avail->next;
2294 p->next->init();
2295 }
2296 else
2297 p->next = new param_dfs;
2298 p = p->next;
2299 return p->read(file);
2300 }
2301
2302 if (file->read(&Ldfs, 2) != 2)
2303 OJPH_ERROR(0x000500D1, "error reading DFS-Ldfs parameter");
2304 Ldfs = swap_byte(Ldfs);
2305 if (file->read(&Sdfs, 2) != 2)
2306 OJPH_ERROR(0x000500D2, "error reading DFS-Sdfs parameter");
2307 Sdfs = swap_byte(Sdfs);
2308 if (Sdfs > 15)
2309 OJPH_ERROR(0x000500D3, "The DFS-Sdfs parameter is %d, which is "
2310 "larger than the permissible 15", Sdfs);
2311 ui8 t, l_Ids = 0;
2312 if (file->read(&l_Ids, 1) != 1)
2313 OJPH_ERROR(0x000500D4, "error reading DFS-Ids parameter");
2314 constexpr int max_Ddfs = sizeof(Ddfs) * 4;
2315 if (l_Ids > max_Ddfs)
2316 OJPH_INFO(0x000500D5, "The DFS-Ids parameter is %d; while this is "
2317 "valid, the number is unnessarily large -- you do not need more "
2318 "than %d. Please contact me regarding this issue.",
2319 l_Ids, max_Ddfs);
2320 Ids = l_Ids < max_Ddfs ? l_Ids : max_Ddfs;
2321 for (int i = 0; i < Ids; i += 4)
2322 if (file->read(&Ddfs[i / 4], 1) != 1)
2323 OJPH_ERROR(0x000500D6, "error reading DFS-Ddfs parameters");
2324 for (int i = Ids; i < l_Ids; i += 4)
2325 if (file->read(&t, 1) != 1)
2326 OJPH_ERROR(0x000500D7, "error reading DFS-Ddfs parameters");
2327 return true;
2328 }
2329
2331 //
2332 //
2333 //
2334 //
2335 //
2337
2340 {
2341 assert(top_atk == NULL);
2342
2343 if (Latk == 0)
2344 {
2345 // This atk object is not used, initialize it to either 0 (irv97)
2346 // or 1 (rev53), and use it. If index is not 0 nor 1, then index
2347 // must have been read from file previously, otherwise it is an
2348 // error.
2349 if (index == 0) { this->init_irv97(); return this; }
2350 else if (index == 1) { this->init_rev53(); return this; }
2351 }
2352
2353 param_atk* p = this;
2354 while (p && p->get_index() != index)
2355 p = p->next;
2356
2357 if (p == NULL && (index == 0 || index == 1))
2358 {
2359 // The index was not found, add an atk object only if the index is
2360 // either 0 or 1
2361 p = add_object();
2362 if (index == 0)
2363 p->init_irv97();
2364 else if (index == 1)
2365 p->init_rev53();
2366 }
2367
2368 return p;
2369 }
2370
2372 bool param_atk::read_coefficient(infile_base *file, float &K, si32& bytes)
2373 {
2374 int coeff_type = get_coeff_type();
2375 if (coeff_type == 0) { // 8bit
2376 ui8 v;
2377 if (file->read(&v, 1) != 1) return false;
2378 bytes -= 1;
2379 K = v;
2380 }
2381 else if (coeff_type == 1) { // 16bit
2382 ui16 v;
2383 if (file->read(&v, 2) != 2) return false;
2384 bytes -= 2;
2385 K = swap_byte(v);
2386 }
2387 else if (coeff_type == 2) { // float
2388 union {
2389 float f;
2390 ui32 i;
2391 } v;
2392 if (file->read(&v.i, 4) != 4) return false;
2393 bytes -= 4;
2394 v.i = swap_byte(v.i);
2395 K = v.f;
2396 }
2397 else if (coeff_type == 3) { // double
2398 union {
2399 double d;
2400 ui64 i;
2401 } v;
2402 if (file->read(&v.i, 8) != 8) return false;
2403 bytes -= 8;
2404 v.i = swap_byte(v.i);
2405 K = (float)v.d;
2406 }
2407 else if (coeff_type == 4) { // 128 bit float
2408 ui64 v, v1;
2409 if (file->read(&v, 8) != 8) return false;
2410 bytes -= 8;
2411 if (file->read(&v1, 8) != 8) return false; // v1 not needed
2412 bytes -= 8;
2413 v = swap_byte(v);
2414
2415 union {
2416 float f;
2417 ui32 i;
2418 } s;
2419 // convert the MSB of 128b float to 32b float
2420 // 32b float has 1 sign bit, 8 exponent (offset 127), 23 mantissa
2421 // 128b float has 1 sign bit, 15 exponent (offset 16383), 112 mantissa
2422 si32 e = (si32)((v >> 48) & 0x7FFF); // exponent
2423 e -= 16383;
2424 e += 127;
2425 e = e & 0xFF; // removes MSBs if negative
2426 e <<= 23; // move bits to their location
2427 s.i = 0;
2428 s.i |= ((ui32)(v >> 32) & 0x80000000); // copy sign bit
2429 s.i |= (ui32)e; // copy exponent
2430 s.i |= (ui32)((v >> 25) & 0x007FFFFF); // copy 23 mantissa
2431 K = s.f;
2432 }
2433 return true;
2434 }
2435
2436
2439 {
2440 int coeff_type = get_coeff_type();
2441 if (coeff_type == 0) {
2442 si8 v;
2443 if (file->read(&v, 1) != 1) return false;
2444 bytes -= 1;
2445 K = v;
2446 }
2447 else if (coeff_type == 1) {
2448 si16 v;
2449 if (file->read(&v, 2) != 2) return false;
2450 bytes -= 2;
2451 K = (si16)swap_byte((ui16)v);
2452 }
2453 else
2454 return false;
2455 return true;
2456 }
2457
2460 {
2461 if (Latk != 0) // this param_atk is used
2462 return add_object()->read(file);
2463
2464 if (file->read(&Latk, 2) != 2)
2465 OJPH_ERROR(0x000500E1, "error reading ATK-Latk parameter");
2466 Latk = swap_byte(Latk);
2467 si32 bytes = Latk - 2;
2468 ojph::ui16 temp_Satk;
2469 if (file->read(&temp_Satk, 2) != 2)
2470 OJPH_ERROR(0x000500E2, "error reading ATK-Satk parameter");
2471 bytes -= 2;
2472 temp_Satk = swap_byte(temp_Satk);
2473 int tmp_idx = temp_Satk & 0xFF;
2474 if ((top_atk && top_atk->get_atk(tmp_idx) != NULL)
2475 || tmp_idx == 0 || tmp_idx == 1)
2476 OJPH_ERROR(0x000500F3, "ATK-Satk parameter sets ATK marker index to "
2477 "the illegal value of %d. ATK-Satk should be in (2-255) and, I "
2478 "believe, must not be repeated; otherwise, it would be unclear "
2479 "what marker segment must be employed when an index is repeated.",
2480 tmp_idx);
2481 Satk = temp_Satk;
2482 if (is_m_init0() == false) // only even-indexed is supported
2483 OJPH_ERROR(0x000500E3, "ATK-Satk parameter sets m_init to 1, "
2484 "requiring odd-indexed subsequence in first reconstruction step, "
2485 "which is not supported yet.");
2486 if (is_whole_sample() == false) // ARB filter not supported
2487 OJPH_ERROR(0x000500E4, "ATK-Satk parameter specified ARB filter, "
2488 "which is not supported yet.");
2489 if (is_reversible() && get_coeff_type() >= 2) // reversible & float
2490 OJPH_ERROR(0x000500E5, "ATK-Satk parameter does not make sense. "
2491 "It employs floats with reversible filtering.");
2492 if (is_using_ws_extension() == false) // only sym. ext is supported
2493 OJPH_ERROR(0x000500E6, "ATK-Satk parameter requires constant "
2494 "boundary extension, which is not supported yet.");
2495 if (is_reversible() == false)
2496 if (read_coefficient(file, Katk, bytes) == false)
2497 OJPH_ERROR(0x000500E7, "error reading ATK-Katk parameter");
2498 if (file->read(&Natk, 1) != 1)
2499 OJPH_ERROR(0x000500E8, "error reading ATK-Natk parameter");
2500 bytes -= 1;
2501 if (Natk > max_steps) {
2502 if (d != d_store) // was this allocated -- very unlikely
2503 delete[] d;
2504 d = new lifting_step[Natk];
2505 max_steps = Natk;
2506 }
2507
2508 if (is_reversible())
2509 {
2510 for (int s = 0; s < Natk; ++s)
2511 {
2512 if (file->read(&d[s].rev.Eatk, 1) != 1)
2513 OJPH_ERROR(0x000500E9, "error reading ATK-Eatk parameter");
2514 bytes -= 1;
2515 if (file->read(&d[s].rev.Batk, 2) != 2)
2516 OJPH_ERROR(0x000500EA, "error reading ATK-Batk parameter");
2517 bytes -= 2;
2518 d[s].rev.Batk = (si16)swap_byte((ui16)d[s].rev.Batk);
2519 ui8 LCatk;
2520 if (file->read(&LCatk, 1) != 1)
2521 OJPH_ERROR(0x000500EB, "error reading ATK-LCatk parameter");
2522 bytes -= 1;
2523 if (LCatk == 0)
2524 OJPH_ERROR(0x000500EC, "Encountered a ATK-LCatk value of zero; "
2525 "something is wrong.");
2526 if (LCatk > 1)
2527 OJPH_ERROR(0x000500ED, "ATK-LCatk value greater than 1; "
2528 "that is, a multitap filter is not supported");
2529 if (read_coefficient(file, d[s].rev.Aatk, bytes) == false)
2530 OJPH_ERROR(0x000500EE, "Error reding ATK-Aatk parameter");
2531 }
2532 }
2533 else
2534 {
2535 for (int s = 0; s < Natk; ++s)
2536 {
2537 ui8 LCatk;
2538 if (file->read(&LCatk, 1) != 1)
2539 OJPH_ERROR(0x000500EF, "error reading ATK-LCatk parameter");
2540 bytes -= 1;
2541 if (LCatk == 0)
2542 OJPH_ERROR(0x000500F0, "Encountered a ATK-LCatk value of zero; "
2543 "something is wrong.");
2544 if (LCatk > 1)
2545 OJPH_ERROR(0x000500F1, "ATK-LCatk value greater than 1; "
2546 "that is, a multitap filter is not supported.");
2547 if (read_coefficient(file, d[s].irv.Aatk, bytes) == false)
2548 OJPH_ERROR(0x000500F2, "Error reding ATK-Aatk parameter");
2549 }
2550 }
2551 if (bytes != 0)
2552 OJPH_ERROR(0x000500F3, "The length of an ATK marker segment "
2553 "(ATK-Latk) is not correct");
2554
2555 return true;
2556 }
2557
2560 {
2561 Satk = 0x4a00; // illegal because ATK = 0
2562 Katk = (float)1.230174104914001;
2563 Natk = 4;
2564 // next is (A-4) in T.801 second line
2565 Latk = (ui16)(5 + Natk + sizeof(float) * (1 + Natk));
2566 d[0].irv.Aatk = (float)0.443506852043971;
2567 d[1].irv.Aatk = (float)0.882911075530934;
2568 d[2].irv.Aatk = (float)-0.052980118572961;
2569 d[3].irv.Aatk = (float)-1.586134342059924;
2570 }
2571
2574 {
2575 Satk = 0x5801; // illegal because ATK = 1
2576 Natk = 2;
2577 // next is (A-4) in T.801 fourth line
2578 Latk = (ui16)(5 + 2 * Natk + sizeof(ui8) * (Natk + Natk));
2579 d[0].rev.Aatk = 1;
2580 d[0].rev.Batk = 2;
2581 d[0].rev.Eatk = 2;
2582 d[1].rev.Aatk = -1;
2583 d[1].rev.Batk = 1;
2584 d[1].rev.Eatk = 1;
2585 }
2586
2589 {
2590 assert(top_atk = NULL);
2591 param_atk *p = this;
2592 while (p->next != NULL)
2593 p = p->next;
2594 if (avail)
2595 {
2596 p->next = avail;
2597 avail = avail->next;
2598 }
2599 else
2600 p->next = new param_atk;
2601 p = p->next;
2602 p->init(this);
2603 return p;
2604 }
2605
2606 } // !local namespace
2607} // !ojph namespace
void set_string(const char *str)
void set_data(const char *data, ui16 len)
virtual size_t read(void *ptr, size_t size)=0
static const float gain_5x3_l[34]
static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
static const float gain_5x3_h[34]
static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
static const float gain_9x7_h[34]
static const float gain_9x7_l[34]
static const float gain_5x3_l[34]
static const float gain_5x3_h[34]
static float get_gain_l(ui32 num_decomp, bool reversible)
static const float gain_9x7_l[34]
static float get_gain_h(ui32 num_decomp, bool reversible)
static const float gain_9x7_h[34]
virtual size_t write(const void *ptr, size_t size)=0
bool is_reversible() const
void set_precinct_size(int num_levels, size *precinct_size)
size get_block_dims() const
void set_reversible(bool reversible)
size get_precinct_size(ui32 level_num) const
ui32 get_num_decompositions() const
local::param_cod * state
size get_log_block_dims() const
size get_log_precinct_size(ui32 level_num) const
void set_num_decomposition(ui32 num_decompositions)
bool get_block_vertical_causality() const
void set_block_dims(ui32 width, ui32 height)
size get_block_dims() const
int get_progression_order() const
bool is_using_color_transform() const
param_coc get_coc(ui32 component_idx)
void set_num_decomposition(ui32 num_decompositions)
ui32 get_num_decompositions() const
size get_log_block_dims() const
bool packets_may_use_sop() const
size get_precinct_size(ui32 level_num) const
const char * get_progression_order_as_string() const
void set_precinct_size(int num_levels, size *precinct_size)
bool packets_use_eph() const
local::param_cod * state
bool is_reversible() const
void set_progression_order(const char *name)
bool get_block_vertical_causality() const
void set_block_dims(ui32 width, ui32 height)
size get_log_precinct_size(ui32 level_num) const
int get_num_layers() const
void set_color_transform(bool color_transform)
void set_reversible(bool reversible)
@ OJPH_NLT_BINARY_COMPLEMENT_NLT
bool get_nonlinear_transform(ui32 comp_num, ui8 &bit_depth, bool &is_signed, ui8 &nl_type) const
get the nonlinearity type associated with comp_num, which should be one from enum nonlinearity
local::param_nlt * state
void set_nonlinear_transform(ui32 comp_num, ui8 nl_type)
enables or disables type 3 nonlinearity for a component or the default setting
void set_irrev_quant(float delta)
Set the irreversible quantization base delta.
local::param_qcd * state
void set_tile_size(size s)
point get_image_extent() const
void set_component(ui32 comp_num, const point &downsampling, ui32 bit_depth, bool is_signed)
void set_num_components(ui32 num_comps)
ui32 get_bit_depth(ui32 comp_num) const
void set_tile_offset(point offset)
point get_image_offset() const
local::param_siz * state
Definition ojph_params.h:99
void set_image_offset(point offset)
size get_tile_size() const
ui32 get_recon_height(ui32 comp_num) const
point get_downsampling(ui32 comp_num) const
void set_image_extent(point extent)
point get_tile_offset() const
ui32 get_recon_width(ui32 comp_num) const
bool is_signed(ui32 comp_num) const
ui32 get_num_components() const
static ui16 swap_byte(ui16 t)
const char OJPH_PO_STRING_PCRL[]
int8_t si8
Definition ojph_defs.h:51
uint64_t ui64
Definition ojph_defs.h:56
uint16_t ui16
Definition ojph_defs.h:52
static ui32 population_count(ui32 val)
Definition ojph_arch.h:152
const char OJPH_PO_STRING_RLCP[]
const char OJPH_PO_STRING_RPCL[]
const char OJPH_PO_STRING_CPRL[]
static ui32 count_leading_zeros(ui32 val)
Definition ojph_arch.h:173
int32_t si32
Definition ojph_defs.h:55
int16_t si16
Definition ojph_defs.h:53
uint32_t ui32
Definition ojph_defs.h:54
uint8_t ui8
Definition ojph_defs.h:50
const char OJPH_PO_STRING_LRCP[]
int main(int argc, char *argv[])
#define ojph_max(a, b)
Definition ojph_defs.h:73
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
#define ojph_min(a, b)
Definition ojph_defs.h:76
#define OJPH_INFO(t,...)
MACROs to insert file and line number for info, warning, and error.
#define OJPH_ERROR(t,...)
#define OJPH_WARN(t,...)
bool read_coefficient(infile_base *file, float &K, si32 &bytes)
void init(param_atk *top_atk)
bool read(infile_base *file)
param_atk * get_atk(int index)
void read(infile_base *file)
bool write(outfile_base *file)
bool write(outfile_base *file)
const param_cod * get_coc(ui32 comp_idx) const
bool internal_write_coc(outfile_base *file, ui32 num_comps)
bool write_coc(outfile_base *file, ui32 num_comps)
bool is_employing_color_transform() const
void read(infile_base *file)
void init(param_cod *top_cod, ui16 comp_idx)
void read_coc(infile_base *file, ui32 num_comps, param_cod *top_cod)
void update_atk(param_atk *atk)
param_cod(param_cod *top_cod=NULL, ui16 comp_idx=OJPH_COD_DEFAULT)
param_cod * add_coc_object(ui32 comp_idx)
bool read(infile_base *file)
dfs_dwt_type get_dwt_type(ui32 decomp_level) const
point get_res_downsamp(ui32 skipped_resolutions) const
ui32 get_subband_idx(ui32 num_decompositions, ui32 resolution, ui32 subband) const
const param_dfs * get_dfs(int index) const
bool write(outfile_base *file) const
param_nlt * add_object(ui32 comp_num)
void trim_non_existing_components(ui32 num_comps)
void read(infile_base *file)
ojph::param_nlt::nonlinearity nonlinearity
bool get_nonlinear_transform(ui32 comp_num, ui8 &bit_depth, bool &is_signed, ui8 &nl_type) const
const param_nlt * get_nlt_object(ui32 comp_num) const
void check_validity(param_siz &siz)
void set_nonlinear_transform(ui32 comp_num, ui8 nl_type)
ui8 encode_SPqcd(ui8 v) const
union ojph::local::param_qcd::@236113141123035351244222037050256251044053245335 SPqcd
bool write_qcc(outfile_base *file, ui32 num_comps)
void set_rev_quant(ui32 num_decomps, ui32 bit_depth, bool is_employing_color_transform)
void set_irrev_quant(ui32 num_decomps)
ui32 get_largest_Kmax() const
ui32 get_num_guard_bits() const
float get_irrev_delta(const param_dfs *dfs, ui32 num_decompositions, ui32 resolution, ui32 subband) const
void set_delta(float delta)
void read_qcc(infile_base *file, ui32 num_comps)
void check_validity(const param_siz &siz, const param_cod &cod)
bool write(outfile_base *file)
ui32 propose_precision(const param_cod *cod) const
void read(infile_base *file)
void init(param_qcd *top_qcd, ui16 comp_idx)
param_qcd * add_qcc_object(ui32 comp_idx)
ui32 get_Kmax(const param_dfs *dfs, ui32 num_decompositions, ui32 resolution, ui32 subband) const
ui8 decode_SPqcd(ui8 v) const
param_qcd * get_qcc(ui32 comp_idx)
param_qcd(param_qcd *top_qcd=NULL, ui16 comp_idx=OJPH_QCD_DEFAULT)
void trim_non_existing_components(ui32 num_comps)
bool internal_write_qcc(outfile_base *file, ui32 num_comps)
ui32 get_bit_depth(ui32 comp_num) const
bool is_signed(ui32 comp_num) const
bool write(outfile_base *file)
point get_recon_downsampling(ui32 comp_num) const
void set_Rsiz_flag(ui16 flag)
point get_recon_size(ui32 comp_num) const
void read(infile_base *file)
void set_num_components(ui32 num_comps)
bool read(infile_base *file, bool resilient)
bool write(outfile_base *file, ui32 payload_len)
void set_next_pair(ui16 Ttlm, ui32 Ptlm)
bool write(outfile_base *file)
void init(ui32 num_pairs, Ttlm_Ptlm_pair *store)