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->set_image_extent(dims);
62 }
63
66 {
67 state->set_tile_size(s);
68 }
69
72 {
73 state->set_image_offset(offset);
74 }
75
78 {
79 state->set_tile_offset(offset);
80 }
81
84 {
85 state->set_num_components(num_comps);
86 }
87
89 void param_siz::set_component(ui32 comp_num, const point& downsampling,
90 ui32 bit_depth, bool is_signed)
91 {
92 state->set_comp_info(comp_num, downsampling, bit_depth, is_signed);
93 }
94
97 {
98 return point(state->Xsiz, state->Ysiz);
99 }
100
103 {
104 return point(state->XOsiz, state->YOsiz);
105 }
106
109 {
110 return size(state->XTsiz, state->YTsiz);
111 }
112
115 {
116 return point(state->XTOsiz, state->YTOsiz);
117 }
118
121 {
122 return state->Csiz;
123 }
124
127 {
128 return state->get_bit_depth(comp_num);
129 }
130
132 bool param_siz::is_signed(ui32 comp_num) const
133 {
134 return state->is_signed(comp_num);
135 }
136
139 {
140 return state->get_downsampling(comp_num);
141 }
142
145 {
146 return state->get_recon_width(comp_num);
147 }
148
151 {
152 return state->get_recon_height(comp_num);
153 }
154
156 //
157 //
158 //
159 //
160 //
162
164 void param_cod::set_num_decomposition(ui32 num_decompositions)
165 {
166 if (num_decompositions > 32)
167 OJPH_ERROR(0x00050001,
168 "maximum number of decompositions cannot exceed 32");
169 state->SPcod.num_decomp = (ui8)num_decompositions;
170 }
171
174 {
175 ui32 log_width = 31 - count_leading_zeros(width);
176 ui32 log_height = 31 - count_leading_zeros(height);
177 if (width == 0 || width != (1u << log_width)
178 || height == 0 || height != (1u << log_height)
179 || log_width < 2 || log_height < 2
180 || log_width + log_height > 12)
181 OJPH_ERROR(0x00050011, "incorrect code block dimensions");
182 state->SPcod.block_width = (ui8)(log_width - 2);
183 state->SPcod.block_height = (ui8)(log_height - 2);
184 }
185
187 void param_cod::set_precinct_size(int num_levels, size* precinct_size)
188 {
189 if (num_levels == 0 || precinct_size == NULL)
190 state->Scod &= 0xFE;
191 else
192 {
193 state->Scod |= 1;
194 for (int i = 0; i <= state->SPcod.num_decomp; ++i)
195 {
196 size t = precinct_size[i < num_levels ? i : num_levels - 1];
197
198 ui32 PPx = 31 - count_leading_zeros(t.w);
199 ui32 PPy = 31 - count_leading_zeros(t.h);
200 if (t.w == 0 || t.h == 0)
201 OJPH_ERROR(0x00050021, "precinct width or height cannot be 0");
202 if (t.w != (1u<<PPx) || t.h != (1u<<PPy))
203 OJPH_ERROR(0x00050022,
204 "precinct width and height should be a power of 2");
205 if (PPx > 15 || PPy > 15)
206 OJPH_ERROR(0x00050023, "precinct size is too large");
207 if (i > 0 && (PPx == 0 || PPy == 0))
208 OJPH_ERROR(0x00050024, "precinct size is too small");
209 state->SPcod.precinct_size[i] = (ui8)(PPx | (PPy << 4));
210 }
211 }
212 }
213
215 void param_cod::set_progression_order(const char *name)
216 {
217 int prog_order = 0;
218 size_t len = strlen(name);
219 if (len == 4)
220 {
221 if (strncmp(name, OJPH_PO_STRING_LRCP, 4) == 0)
222 prog_order = OJPH_PO_LRCP;
223 else if (strncmp(name, OJPH_PO_STRING_RLCP, 4) == 0)
224 prog_order = OJPH_PO_RLCP;
225 else if (strncmp(name, OJPH_PO_STRING_RPCL, 4) == 0)
226 prog_order = OJPH_PO_RPCL;
227 else if (strncmp(name, OJPH_PO_STRING_PCRL, 4) == 0)
228 prog_order = OJPH_PO_PCRL;
229 else if (strncmp(name, OJPH_PO_STRING_CPRL, 4) == 0)
230 prog_order = OJPH_PO_CPRL;
231 else
232 OJPH_ERROR(0x00050031, "unknown progression order");
233 }
234 else
235 OJPH_ERROR(0x00050032, "improper progression order");
236
237
238 state->SGCod.prog_order = (ui8)prog_order;
239 }
240
242 void param_cod::set_color_transform(bool color_transform)
243 {
244 state->employ_color_transform(color_transform ? 1 : 0);
245 }
246
248 void param_cod::set_reversible(bool reversible)
249 {
250 state->set_reversible(reversible);
251 }
252
255 {
256 local::param_cod *p = state->get_coc(component_idx);
257 if (p == state) // no COC segment marker for this component
258 p = state->add_coc_object(component_idx);
259 return param_coc(p);
260 }
261
264 {
265 return state->get_num_decompositions();
266 }
267
270 {
271 return state->get_block_dims();
272 }
273
276 {
277 return state->get_log_block_dims();
278 }
279
282 {
283 return state->is_reversible();
284 }
285
288 {
289 return state->get_precinct_size(level_num);
290 }
291
294 {
295 return state->get_log_precinct_size(level_num);
296 }
297
300 {
301 return state->SGCod.prog_order;
302 }
303
306 {
307 if (state->SGCod.prog_order == OJPH_PO_LRCP)
308 return OJPH_PO_STRING_LRCP;
309 else if (state->SGCod.prog_order == OJPH_PO_RLCP)
310 return OJPH_PO_STRING_RLCP;
311 else if (state->SGCod.prog_order == OJPH_PO_RPCL)
312 return OJPH_PO_STRING_RPCL;
313 else if (state->SGCod.prog_order == OJPH_PO_PCRL)
314 return OJPH_PO_STRING_PCRL;
315 else if (state->SGCod.prog_order == OJPH_PO_CPRL)
316 return OJPH_PO_STRING_CPRL;
317 else
318 assert(0);
319 return "";
320 }
321
324 {
325 return state->SGCod.num_layers;
326 }
327
330 {
331 return state->is_employing_color_transform();
332 }
333
336 {
337 return state->packets_may_use_sop();
338 }
339
342 {
343 return state->packets_use_eph();
344 }
345
348 {
349 return state->get_block_vertical_causality();
350 }
351
353 //
354 //
355 //
356 //
357 //
359
361 void param_coc::set_num_decomposition(ui32 num_decompositions)
362 { ojph::param_cod(state).set_num_decomposition(num_decompositions); }
363
366 { ojph::param_cod(state).set_block_dims(width, height); }
367
369 void param_coc::set_precinct_size(int num_levels, size* precinct_size)
370 { ojph::param_cod(state).set_precinct_size(num_levels, precinct_size); }
371
373 void param_coc::set_reversible(bool reversible)
374 { ojph::param_cod(state).set_reversible(reversible); }
375
379
383
387
391
394 { return ojph::param_cod(state).get_precinct_size(level_num); }
395
399
403
404
406 //
407 //
408 //
409 //
410 //
412
415 {
416 state->set_delta(delta);
417 }
418
420 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta)
421 {
422 state->set_delta(comp_idx, delta);
423 }
424
426 //
427 //
428 //
429 //
430 //
432
435 {
436 state->set_nonlinear_transform(comp_num, nl_type);
437 }
438
440 bool param_nlt::get_nonlinear_transform(ui32 comp_num, ui8& bit_depth,
441 bool& is_signed, ui8& nl_type) const
442 {
443 return state->get_nonlinear_transform(comp_num, bit_depth, is_signed,
444 nl_type);
445 }
446
448 //
449 //
450 //
451 //
452 //
454
456 void comment_exchange::set_string(const char* str)
457 {
458 size_t t = strlen(str);
459 if (len > 65531)
460 OJPH_ERROR(0x000500C1,
461 "COM marker string length cannot be larger than 65531");
462 this->data = str;
463 this->len = (ui16)t;
464 this->Rcom = 1;
465 }
466
469 {
470 if (len > 65531)
471 OJPH_ERROR(0x000500C2,
472 "COM marker string length cannot be larger than 65531");
473 this->data = data;
474 this->len = len;
475 this->Rcom = 0;
476 }
477
479 //
480 //
481 // LOCAL
482 //
483 //
485
486 namespace local {
487
489 static inline
491 {
492 return (ui16)((t << 8) | (t >> 8));
493 }
494
496 static inline
498 {
499 ui32 u = swap_byte((ui16)(t & 0xFFFFu));
500 u <<= 16;
501 u |= swap_byte((ui16)(t >> 16));
502 return u;
503 }
504
506 static inline
508 {
509 ui64 u = swap_byte((ui32)(t & 0xFFFFFFFFu));
510 u <<= 32;
511 u |= swap_byte((ui32)(t >> 32));
512 return u;
513 }
514
516 //
517 //
518 //
519 //
520 //
522
524 //static
526 {
527 public:
528 static float get_gain_l(ui32 num_decomp, bool reversible)
529 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
530 static float get_gain_h(ui32 num_decomp, bool reversible)
531 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
532
533 private:
534 static const float gain_9x7_l[34];
535 static const float gain_9x7_h[34];
536 static const float gain_5x3_l[34];
537 static const float gain_5x3_h[34];
538 };
539
541 const float sqrt_energy_gains::gain_9x7_l[34] = { 1.0000e+00f,
542 1.4021e+00f, 2.0304e+00f, 2.9012e+00f, 4.1153e+00f, 5.8245e+00f,
543 8.2388e+00f, 1.1652e+01f, 1.6479e+01f, 2.3304e+01f, 3.2957e+01f,
544 4.6609e+01f, 6.5915e+01f, 9.3217e+01f, 1.3183e+02f, 1.8643e+02f,
545 2.6366e+02f, 3.7287e+02f, 5.2732e+02f, 7.4574e+02f, 1.0546e+03f,
546 1.4915e+03f, 2.1093e+03f, 2.9830e+03f, 4.2185e+03f, 5.9659e+03f,
547 8.4371e+03f, 1.1932e+04f, 1.6874e+04f, 2.3864e+04f, 3.3748e+04f,
548 4.7727e+04f, 6.7496e+04f, 9.5454e+04f };
549 const float sqrt_energy_gains::gain_9x7_h[34] = { 1.4425e+00f,
550 1.9669e+00f, 2.8839e+00f, 4.1475e+00f, 5.8946e+00f, 8.3472e+00f,
551 1.1809e+01f, 1.6701e+01f, 2.3620e+01f, 3.3403e+01f, 4.7240e+01f,
552 6.6807e+01f, 9.4479e+01f, 1.3361e+02f, 1.8896e+02f, 2.6723e+02f,
553 3.7792e+02f, 5.3446e+02f, 7.5583e+02f, 1.0689e+03f, 1.5117e+03f,
554 2.1378e+03f, 3.0233e+03f, 4.2756e+03f, 6.0467e+03f, 8.5513e+03f,
555 1.2093e+04f, 1.7103e+04f, 2.4187e+04f, 3.4205e+04f, 4.8373e+04f,
556 6.8410e+04f, 9.6747e+04f, 1.3682e+05f };
557 const float sqrt_energy_gains::gain_5x3_l[34] = { 1.0000e+00f,
558 1.2247e+00f, 1.3229e+00f, 1.5411e+00f, 1.7139e+00f, 1.9605e+00f,
559 2.2044e+00f, 2.5047e+00f, 2.8277e+00f, 3.2049e+00f, 3.6238e+00f,
560 4.1033e+00f, 4.6423e+00f, 5.2548e+00f, 5.9462e+00f, 6.7299e+00f,
561 7.6159e+00f, 8.6193e+00f, 9.7544e+00f, 1.1039e+01f, 1.2493e+01f,
562 1.4139e+01f, 1.6001e+01f, 1.8108e+01f, 2.0493e+01f, 2.3192e+01f,
563 2.6246e+01f, 2.9702e+01f, 3.3614e+01f, 3.8041e+01f, 4.3051e+01f,
564 4.8721e+01f, 5.5138e+01f, 6.2399e+01f };
565 const float sqrt_energy_gains::gain_5x3_h[34] = { 1.0458e+00f,
566 1.3975e+00f, 1.4389e+00f, 1.7287e+00f, 1.8880e+00f, 2.1841e+00f,
567 2.4392e+00f, 2.7830e+00f, 3.1341e+00f, 3.5576e+00f, 4.0188e+00f,
568 4.5532e+00f, 5.1494e+00f, 5.8301e+00f, 6.5963e+00f, 7.4663e+00f,
569 8.4489e+00f, 9.5623e+00f, 1.0821e+01f, 1.2247e+01f, 1.3860e+01f,
570 1.5685e+01f, 1.7751e+01f, 2.0089e+01f, 2.2735e+01f, 2.5729e+01f,
571 2.9117e+01f, 3.2952e+01f, 3.7292e+01f, 4.2203e+01f, 4.7761e+01f,
572 5.4051e+01f, 6.1170e+01f, 6.9226e+01f };
573
575 //static
577 {
578 public:
579 static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
580 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
581 static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
582 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
583
584 private:
585 static const float gain_9x7_l[34];
586 static const float gain_9x7_h[34];
587 static const float gain_5x3_l[34];
588 static const float gain_5x3_h[34];
589 };
590
592 const float bibo_gains::gain_9x7_l[34] = { 1.0000e+00f, 1.3803e+00f,
593 1.3328e+00f, 1.3067e+00f, 1.3028e+00f, 1.3001e+00f, 1.2993e+00f,
594 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
595 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
596 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
597 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
598 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
599 1.2992e+00f, 1.2992e+00f };
600 const float bibo_gains::gain_9x7_h[34] = { 1.2976e+00f, 1.3126e+00f,
601 1.2757e+00f, 1.2352e+00f, 1.2312e+00f, 1.2285e+00f, 1.2280e+00f,
602 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
603 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
604 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
605 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
606 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
607 1.2278e+00f, 1.2278e+00f };
608 const float bibo_gains::gain_5x3_l[34] = { 1.0000e+00f, 1.5000e+00f,
609 1.6250e+00f, 1.6875e+00f, 1.6963e+00f, 1.7067e+00f, 1.7116e+00f,
610 1.7129e+00f, 1.7141e+00f, 1.7145e+00f, 1.7151e+00f, 1.7152e+00f,
611 1.7155e+00f, 1.7155e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
612 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
613 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
614 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
615 1.7156e+00f, 1.7156e+00f };
616 const float bibo_gains::gain_5x3_h[34] = { 2.0000e+00f, 2.5000e+00f,
617 2.7500e+00f, 2.8047e+00f, 2.8198e+00f, 2.8410e+00f, 2.8558e+00f,
618 2.8601e+00f, 2.8628e+00f, 2.8656e+00f, 2.8662e+00f, 2.8667e+00f,
619 2.8669e+00f, 2.8670e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
620 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
621 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
622 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
623 2.8671e+00f, 2.8671e+00f };
624
625
627 //
628 //
629 //
630 //
631 //
633
636 {
637 //marker size excluding header
638 Lsiz = (ui16)(38 + 3 * Csiz);
639
640 ui8 buf[4];
641 bool result = true;
642
643 *(ui16*)buf = JP2K_MARKER::SIZ;
644 *(ui16*)buf = swap_byte(*(ui16*)buf);
645 result &= file->write(&buf, 2) == 2;
646 *(ui16*)buf = swap_byte(Lsiz);
647 result &= file->write(&buf, 2) == 2;
648 *(ui16*)buf = swap_byte(Rsiz);
649 result &= file->write(&buf, 2) == 2;
650 *(ui32*)buf = swap_byte(Xsiz);
651 result &= file->write(&buf, 4) == 4;
652 *(ui32*)buf = swap_byte(Ysiz);
653 result &= file->write(&buf, 4) == 4;
654 *(ui32*)buf = swap_byte(XOsiz);
655 result &= file->write(&buf, 4) == 4;
656 *(ui32*)buf = swap_byte(YOsiz);
657 result &= file->write(&buf, 4) == 4;
658 *(ui32*)buf = swap_byte(XTsiz);
659 result &= file->write(&buf, 4) == 4;
660 *(ui32*)buf = swap_byte(YTsiz);
661 result &= file->write(&buf, 4) == 4;
662 *(ui32*)buf = swap_byte(XTOsiz);
663 result &= file->write(&buf, 4) == 4;
664 *(ui32*)buf = swap_byte(YTOsiz);
665 result &= file->write(&buf, 4) == 4;
666 *(ui16*)buf = swap_byte(Csiz);
667 result &= file->write(&buf, 2) == 2;
668 for (int c = 0; c < Csiz; ++c)
669 {
670 buf[0] = cptr[c].SSiz;
671 buf[1] = cptr[c].XRsiz;
672 buf[2] = cptr[c].YRsiz;
673 result &= file->write(&buf, 3) == 3;
674 }
675
676 return result;
677 }
678
681 {
682 if (file->read(&Lsiz, 2) != 2)
683 OJPH_ERROR(0x00050041, "error reading SIZ marker");
685 int num_comps = (Lsiz - 38) / 3;
686 if (Lsiz != 38 + 3 * num_comps)
687 OJPH_ERROR(0x00050042, "error in SIZ marker length");
688 if (file->read(&Rsiz, 2) != 2)
689 OJPH_ERROR(0x00050043, "error reading SIZ marker");
691 if ((Rsiz & 0x4000) == 0)
692 OJPH_ERROR(0x00050044,
693 "Rsiz bit 14 is not set (this is not a JPH file)");
694 if ((Rsiz & 0x8000) != 0 && (Rsiz & 0xD5F) != 0)
695 OJPH_WARN(0x00050001, "Rsiz in SIZ has unimplemented fields");
696 if (file->read(&Xsiz, 4) != 4)
697 OJPH_ERROR(0x00050045, "error reading SIZ marker");
699 if (file->read(&Ysiz, 4) != 4)
700 OJPH_ERROR(0x00050046, "error reading SIZ marker");
702 ui32 t_XOsiz, t_YOsiz;
703 if (file->read(&t_XOsiz, 4) != 4)
704 OJPH_ERROR(0x00050047, "error reading SIZ marker");
705 if (file->read(&t_YOsiz, 4) != 4)
706 OJPH_ERROR(0x00050048, "error reading SIZ marker");
707 set_image_offset(point(swap_byte(t_XOsiz), swap_byte(t_YOsiz)));
708 ui32 t_XTsiz, t_YTsiz;
709 if (file->read(&t_XTsiz, 4) != 4)
710 OJPH_ERROR(0x00050049, "error reading SIZ marker");
711 if (file->read(&t_YTsiz, 4) != 4)
712 OJPH_ERROR(0x0005004A, "error reading SIZ marker");
713 set_tile_size(size(swap_byte(t_XTsiz), swap_byte(t_YTsiz)));
714 ui32 t_XTOsiz, t_YTOsiz;
715 if (file->read(&t_XTOsiz, 4) != 4)
716 OJPH_ERROR(0x0005004B, "error reading SIZ marker");
717 if (file->read(&t_YTOsiz, 4) != 4)
718 OJPH_ERROR(0x0005004C, "error reading SIZ marker");
719 set_tile_offset(point(swap_byte(t_XTOsiz), swap_byte(t_YTOsiz)));
720 if (file->read(&Csiz, 2) != 2)
721 OJPH_ERROR(0x0005004D, "error reading SIZ marker");
723 if (Csiz != num_comps)
724 OJPH_ERROR(0x0005004E, "Csiz does not match the SIZ marker size");
726 for (int c = 0; c < Csiz; ++c)
727 {
728 if (file->read(&cptr[c].SSiz, 1) != 1)
729 OJPH_ERROR(0x00050051, "error reading SIZ marker");
730 if (file->read(&cptr[c].XRsiz, 1) != 1)
731 OJPH_ERROR(0x00050052, "error reading SIZ marker");
732 if (file->read(&cptr[c].YRsiz, 1) != 1)
733 OJPH_ERROR(0x00050053, "error reading SIZ marker");
734 if ((cptr[c].SSiz & 0x7F) > 37)
735 OJPH_ERROR(0x00050054, "Wrong SIZ-SSiz value of %d", cptr[c].SSiz);
736 if (cptr[c].XRsiz == 0)
737 OJPH_ERROR(0x00050055, "Wrong SIZ-XRsiz value of %d", cptr[c].XRsiz);
738 if (cptr[c].YRsiz == 0)
739 OJPH_ERROR(0x00050056, "Wrong SIZ-YRsiz value of %d", cptr[c].YRsiz);
740 }
741
742 ws_kern_support_needed = (Rsiz & 0x20) != 0;
743 dfs_support_needed = (Rsiz & 0x80) != 0;
744
746 }
747
750 {
751 assert(comp_num < get_num_components());
752
753 point factor(1u << skipped_resolutions, 1u << skipped_resolutions);
754 const param_cod* cdp = cod->get_coc(comp_num);
755 if (dfs && cdp && cdp->is_dfs_defined()) {
756 const param_dfs* d = dfs->get_dfs(cdp->get_dfs_index());
758 }
759 factor.x *= (ui32)cptr[comp_num].XRsiz;
760 factor.y *= (ui32)cptr[comp_num].YRsiz;
761 return factor;
762 }
763
766 {
767 assert(comp_num < get_num_components());
768
769 point factor = get_recon_downsampling(comp_num);
770 point r;
771 r.x = ojph_div_ceil(Xsiz, factor.x) - ojph_div_ceil(XOsiz, factor.x);
772 r.y = ojph_div_ceil(Ysiz, factor.y) - ojph_div_ceil(YOsiz, factor.y);
773 return r;
774 }
775
776
778 //
779 //
780 //
781 //
782 //
784
787 {
788 //marker size excluding header
789 Lcap = 8;
790
791 char buf[4];
792 bool result = true;
793
794 *(ui16*)buf = JP2K_MARKER::CAP;
795 *(ui16*)buf = swap_byte(*(ui16*)buf);
796 result &= file->write(&buf, 2) == 2;
797 *(ui16*)buf = swap_byte(Lcap);
798 result &= file->write(&buf, 2) == 2;
799 *(ui32*)buf = swap_byte(Pcap);
800 result &= file->write(&buf, 4) == 4;
801
802 *(ui16*)buf = swap_byte(Ccap[0]);
803 result &= file->write(&buf, 2) == 2;
804
805 return result;
806 }
807
810 {
811 if (file->read(&Lcap, 2) != 2)
812 OJPH_ERROR(0x00050061, "error reading CAP marker");
814 if (file->read(&Pcap, 4) != 4)
815 OJPH_ERROR(0x00050062, "error reading CAP marker");
817 ui32 count = population_count(Pcap);
818 if (Pcap & 0xFFFDFFFF)
819 OJPH_ERROR(0x00050063,
820 "error Pcap in CAP has options that are not supported");
821 if ((Pcap & 0x00020000) == 0)
822 OJPH_ERROR(0x00050064,
823 "error Pcap should have its 15th MSB set, Pcap^15. "
824 " This is not a JPH file");
825 for (ui32 i = 0; i < count; ++i)
826 if (file->read(Ccap+i, 2) != 2)
827 OJPH_ERROR(0x00050065, "error reading CAP marker");
828 if (Lcap != 6 + 2 * count)
829 OJPH_ERROR(0x00050066, "error in CAP marker length");
830 }
831
833 //
834 //
835 //
836 //
837 //
839
842 {
843 if (SPcod.wavelet_trans <= 1)
845 else {
846 assert(atk != NULL);
847 return atk->is_reversible();
848 }
849 }
850
853 {
854 assert(type == COD_MAIN);
855
856 //marker size excluding header
857 Lcod = 12;
858 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
859
860 ui8 buf[4];
861 bool result = true;
862
863 *(ui16*)buf = JP2K_MARKER::COD;
864 *(ui16*)buf = swap_byte(*(ui16*)buf);
865 result &= file->write(&buf, 2) == 2;
866 *(ui16*)buf = swap_byte(Lcod);
867 result &= file->write(&buf, 2) == 2;
868 *(ui8*)buf = Scod;
869 result &= file->write(&buf, 1) == 1;
870 *(ui8*)buf = SGCod.prog_order;
871 result &= file->write(&buf, 1) == 1;
872 *(ui16*)buf = swap_byte(SGCod.num_layers);
873 result &= file->write(&buf, 2) == 2;
874 *(ui8*)buf = SGCod.mc_trans;
875 result &= file->write(&buf, 1) == 1;
876 buf[0] = SPcod.num_decomp;
877 buf[1] = SPcod.block_width;
878 buf[2] = SPcod.block_height;
879 buf[3] = SPcod.block_style;
880 result &= file->write(&buf, 4) == 4;
881 *(ui8*)buf = SPcod.wavelet_trans;
882 result &= file->write(&buf, 1) == 1;
883 if (Scod & 1)
884 for (int i = 0; i <= SPcod.num_decomp; ++i)
885 {
886 *(ui8*)buf = SPcod.precinct_size[i];
887 result &= file->write(&buf, 1) == 1;
888 }
889
890 return result;
891 }
892
895 {
896 assert(type == COD_MAIN);
897 bool result = true;
898 param_cod *p = this->next;
899 while (p)
900 {
901 if (p->comp_idx < num_comps)
902 result &= p->internal_write_coc(file, num_comps);
903 p = p->next;
904 }
905 return result;
906 }
907
910 {
911 assert(type == COC_MAIN);
912
913 //marker size excluding header
914 Lcod = num_comps < 257 ? 9 : 10;
915 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
916
917 ui8 buf[4];
918 bool result = true;
919
920 *(ui16*)buf = JP2K_MARKER::COC;
921 *(ui16*)buf = swap_byte(*(ui16*)buf);
922 result &= file->write(&buf, 2) == 2;
923 *(ui16*)buf = swap_byte(Lcod);
924 result &= file->write(&buf, 2) == 2;
925 if (num_comps < 257)
926 {
927 *(ui8*)buf = (ui8)comp_idx;
928 result &= file->write(&buf, 1) == 1;
929 }
930 else
931 {
932 *(ui16*)buf = swap_byte(comp_idx);
933 result &= file->write(&buf, 2) == 2;
934 }
935 *(ui8*)buf = Scod;
936 result &= file->write(&buf, 1) == 1;
937 buf[0] = SPcod.num_decomp;
938 buf[1] = SPcod.block_width;
939 buf[2] = SPcod.block_height;
940 buf[3] = SPcod.block_style;
941 result &= file->write(&buf, 4) == 4;
942 *(ui8*)buf = SPcod.wavelet_trans;
943 result &= file->write(&buf, 1) == 1;
944 if (Scod & 1)
945 for (int i = 0; i <= SPcod.num_decomp; ++i)
946 {
947 *(ui8*)buf = SPcod.precinct_size[i];
948 result &= file->write(&buf, 1) == 1;
949 }
950
951 return result;
952 }
953
956 {
957 assert(type == COD_MAIN);
958
959 if (file->read(&Lcod, 2) != 2)
960 OJPH_ERROR(0x00050071, "error reading COD segment");
962 if (file->read(&Scod, 1) != 1)
963 OJPH_ERROR(0x00050072, "error reading COD segment");
964 if (file->read(&SGCod.prog_order, 1) != 1)
965 OJPH_ERROR(0x00050073, "error reading COD segment");
966 if (file->read(&SGCod.num_layers, 2) != 2)
967 { OJPH_ERROR(0x00050074, "error reading COD segment"); }
968 else
969 SGCod.num_layers = swap_byte(SGCod.num_layers);
970 if (file->read(&SGCod.mc_trans, 1) != 1)
971 OJPH_ERROR(0x00050075, "error reading COD segment");
972 if (file->read(&SPcod.num_decomp, 1) != 1)
973 OJPH_ERROR(0x00050076, "error reading COD segment");
974 if (file->read(&SPcod.block_width, 1) != 1)
975 OJPH_ERROR(0x00050077, "error reading COD segment");
976 if (file->read(&SPcod.block_height, 1) != 1)
977 OJPH_ERROR(0x00050078, "error reading COD segment");
978 if (file->read(&SPcod.block_style, 1) != 1)
979 OJPH_ERROR(0x00050079, "error reading COD segment");
980 if (file->read(&SPcod.wavelet_trans, 1) != 1)
981 OJPH_ERROR(0x0005007A, "error reading COD segment");
982
983 if (get_num_decompositions() > 32
984 || SPcod.block_width > 8
985 || SPcod.block_height > 8
986 || SPcod.block_width + SPcod.block_height > 8
987 || (SPcod.block_style & 0x40) != 0x40
988 || (SPcod.block_style & 0xB7) != 0x00)
989 OJPH_ERROR(0x0005007D, "wrong settings in a COD-SPcod parameter");
990 if ((SPcod.block_style & 0x40) != 0x40
991 || (SPcod.block_style & 0xB7) != 0x00)
992 OJPH_ERROR(0x0005007E, "unsupported settings in a COD-SPcod parameter");
993
994 ui8 num_decompositions = get_num_decompositions();
995 if (Scod & 1) {
996 for (int i = 0; i <= num_decompositions; ++i) {
997 if (file->read(&SPcod.precinct_size[i], 1) != 1)
998 OJPH_ERROR(0x0005007B, "error reading COD segment");
999 if (i)
1000 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1001 (SPcod.precinct_size[i] >> 4) == 0)
1002 OJPH_ERROR(0x0005007F,
1003 "Precinct width or height for resolutions other than the"
1004 " coarsest must be larger than 1; here, they are %d and %d,"
1005 " respectively.",
1006 1 << (SPcod.precinct_size[i] & 0x0F),
1007 1 << (SPcod.precinct_size[i] >> 4));
1008 }
1009 }
1010 if (Lcod != 12 + ((Scod & 1) ? 1 + SPcod.num_decomp : 0))
1011 OJPH_ERROR(0x0005007C, "error in COD segment length");
1012 }
1013
1015 void param_cod::read_coc(infile_base* file, ui32 num_comps,
1017 {
1018 assert(type == COC_MAIN);
1019 assert(top_cod != NULL);
1020
1021 this->SGCod = top_cod->SGCod;
1022 this->top_cod = top_cod;
1023 if (file->read(&Lcod, 2) != 2)
1024 OJPH_ERROR(0x00050121, "error reading COC segment");
1025 Lcod = swap_byte(Lcod);
1026 if (num_comps < 257) {
1027 ui8 t;
1028 if (file->read(&t, 1) != 1)
1029 OJPH_ERROR(0x00050122, "error reading COC segment");
1030 comp_idx = t;
1031 }
1032 else {
1033 if (file->read(&comp_idx, 2) != 2)
1034 OJPH_ERROR(0x00050123, "error reading COC segment");
1036 }
1037 if (file->read(&Scod, 1) != 1)
1038 OJPH_ERROR(0x00050124, "error reading COC segment");
1039 if (Scod & 0xF8)
1040 OJPH_WARN(0x00050011,
1041 "Unsupported options in Scoc field of the COC segment");
1042 if (file->read(&SPcod.num_decomp, 1) != 1)
1043 OJPH_ERROR(0x00050125, "error reading COC segment");
1044 if (file->read(&SPcod.block_width, 1) != 1)
1045 OJPH_ERROR(0x00050126, "error reading COC segment");
1046 if (file->read(&SPcod.block_height, 1) != 1)
1047 OJPH_ERROR(0x00050127, "error reading COC segment");
1048 if (file->read(&SPcod.block_style, 1) != 1)
1049 OJPH_ERROR(0x00050128, "error reading COC segment");
1050 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1051 OJPH_ERROR(0x00050129, "error reading COC segment");
1052
1053 if (get_num_decompositions() > 32
1054 || SPcod.block_width > 8
1055 || SPcod.block_height > 8
1056 || SPcod.block_width + SPcod.block_height > 8
1057 || (SPcod.block_style & 0x40) != 0x40
1058 || (SPcod.block_style & 0xB7) != 0x00)
1059 OJPH_ERROR(0x0005012C, "wrong settings in a COC-SPcoc parameter");
1060 if ((SPcod.block_style & 0x40) != 0x40
1061 || (SPcod.block_style & 0xB7) != 0x00)
1062 OJPH_ERROR(0x0005012D, "unsupported settings in a COC-SPcoc parameter");
1063
1064 ui8 num_decompositions = get_num_decompositions();
1065 if (Scod & 1) {
1066 for (int i = 0; i <= num_decompositions; ++i) {
1067 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1068 OJPH_ERROR(0x0005012A, "error reading COC segment");
1069 if (i)
1070 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1071 (SPcod.precinct_size[i] >> 4) == 0)
1072 OJPH_ERROR(0x0005012E,
1073 "Precinct width or height for resolutions other than the"
1074 " coarsest must be larger than 1; here, they are %d and %d,"
1075 " respectively.",
1076 1 << (SPcod.precinct_size[i] & 0x0F),
1077 1 << (SPcod.precinct_size[i] >> 4));
1078 }
1079 }
1080 ui32 t = 9;
1081 t += num_comps < 257 ? 0 : 1;
1082 t += (Scod & 1) ? 1 + num_decompositions : 0;
1083 if (Lcod != t)
1084 OJPH_ERROR(0x0005012B, "error in COC segment length");
1085 }
1086
1089 {
1090 assert(type == COD_MAIN);
1091 this->atk = atk->get_atk(SPcod.wavelet_trans);
1092 if (this->atk == NULL)
1093 OJPH_ERROR(0x00050131, "A COD segment employs the DWT kernel "
1094 "atk = %d, but a corresponding ATK segment cannot be found.",
1095 SPcod.wavelet_trans);
1096 param_cod *p = next;
1097 while (p)
1098 {
1099 p->atk = atk->get_atk(p->SPcod.wavelet_trans);
1100 if (p->atk == NULL)
1101 OJPH_ERROR(0x00050132, "A COC segment employs the DWT kernel "
1102 "atk = %d, but a corresponding ATK segment cannot be found",
1103 SPcod.wavelet_trans);
1104 p = p->next;
1105 }
1106 }
1107
1110 {
1111 assert(this->type == COD_MAIN || this->top_cod->type == COD_MAIN);
1112 const param_cod *p, *q;
1113 if (this->type == COD_MAIN)
1114 q = p = this;
1115 else
1116 q = p = this->top_cod;
1117 while (p && p->comp_idx != comp_idx)
1118 p = p->next;
1119 return p ? p : q;
1120 }
1121
1124 {
1125 // cast object to constant
1126 const param_cod* const_p = const_cast<const param_cod*>(this);
1127 // call using the constant object, then cast to non-const
1128 return const_cast<param_cod*>(const_p->get_coc(comp_idx));
1129 }
1130
1133 {
1134 assert(type == COD_MAIN);
1135 param_cod *p = this;
1136 while (p->next != NULL)
1137 p = p->next;
1138 if (avail)
1139 {
1140 p->next = avail;
1141 avail = avail->next;
1142 p->next->init(this, (ui16)comp_idx);
1143 }
1144 else
1145 p->next = new param_cod(this, (ui16)comp_idx);
1146 return p->next;
1147 }
1148
1150 //
1151 //
1152 //
1153 //
1154 //
1156
1158 void param_qcd::check_validity(const param_siz& siz, const param_cod& cod)
1159 {
1160 ui32 num_comps = siz.get_num_components();
1162
1163 // first check that all the component captured by QCD have the same
1164 // bit_depth and signedness
1165 bool all_same = true;
1166 bool other_comps_exist = false;
1167 ui32 first_comp = 0xFFFF; // an impossible component
1168 {
1169 ui32 num_decompositions = 0;
1170 ui32 bit_depth = 0;
1171 bool is_signed = false;
1172 ui32 wavelet_kern = param_cod::DWT_IRV97;
1173
1174 for (ui32 c = 0; c < num_comps; ++c)
1175 {
1176 if (get_qcc(c) == this) // no qcc defined for component c
1177 {
1178 const param_cod *p = cod.get_coc(c);
1179 if (bit_depth == 0) // first component captured by QCD
1180 {
1181 num_decompositions = p->get_num_decompositions();
1182 bit_depth = siz.get_bit_depth(c);
1183 is_signed = siz.is_signed(c);
1184 wavelet_kern = p->get_wavelet_kern();
1185 first_comp = c;
1186 }
1187 else
1188 {
1189 all_same = all_same
1190 && (num_decompositions == p->get_num_decompositions())
1191 && (bit_depth == siz.get_bit_depth(c))
1192 && (is_signed == siz.is_signed(c))
1193 && (wavelet_kern == p->get_wavelet_kern());
1194 }
1195 }
1196 else
1197 other_comps_exist = true;
1198 }
1199 }
1200
1201 // configure QCD according COD
1202 ui32 qcd_num_decompositions;
1203 ui32 qcd_bit_depth;
1204 bool qcd_is_signed;
1205 ui32 qcd_wavelet_kern;
1206 {
1207 ui32 qcd_component = first_comp != 0xFFFF ? first_comp : 0;
1208 bool employing_color_transform = cod.is_employing_color_transform();
1209 qcd_num_decompositions = cod.get_num_decompositions();
1210 qcd_bit_depth = siz.get_bit_depth(qcd_component);
1211 qcd_is_signed = siz.is_signed(qcd_component);
1212 qcd_wavelet_kern = cod.get_wavelet_kern();
1213 this->num_subbands = 1 + 3 * qcd_num_decompositions;
1214 if (qcd_wavelet_kern == param_cod::DWT_REV53)
1215 set_rev_quant(qcd_num_decompositions, qcd_bit_depth,
1216 qcd_component < 3 ? employing_color_transform : false);
1217 else if (qcd_wavelet_kern == param_cod::DWT_IRV97)
1218 {
1219 if (this->base_delta == -1.0f) {
1220 ui32 t = ojph_min(16, qcd_bit_depth);
1221 this->base_delta = 1.0f / (float)(1 << t);
1222 }
1223 set_irrev_quant(qcd_num_decompositions);
1224 }
1225 else
1226 assert(0);
1227 }
1228
1229 // if not all the same and captured by QCD, then create QCC for them
1230 if (!all_same)
1231 {
1232 bool employing_color_transform = cod.is_employing_color_transform();
1233 for (ui32 c = 0; c < num_comps; ++c)
1234 {
1235 const param_cod *cp = cod.get_coc(c);
1236 if (qcd_num_decompositions == cp->get_num_decompositions()
1237 && qcd_bit_depth == siz.get_bit_depth(c)
1238 && qcd_is_signed == siz.is_signed(c)
1239 && qcd_wavelet_kern == cp->get_wavelet_kern())
1240 continue; // captured by QCD
1241
1242 // Does not match QCD, must have QCC
1243 param_qcd *qp = get_qcc(c);
1244 if (qp == this) // no QCC was defined, create QCC
1245 qp = this->add_qcc_object(c);
1246
1247 ui32 num_decompositions = cp->get_num_decompositions();
1248 qp->num_subbands = 1 + 3 * num_decompositions;
1249 ui32 bit_depth = siz.get_bit_depth(c);
1251 qp->set_rev_quant(num_decompositions, bit_depth,
1252 c < 3 ? employing_color_transform : false);
1253 else if (cp->get_wavelet_kern() == param_cod::DWT_IRV97)
1254 {
1255 if (qp->base_delta == -1.0f) {
1256 if (qcd_wavelet_kern == param_cod::DWT_IRV97) {
1257 assert(this->base_delta != -1.0f);
1258 qp->base_delta = this->base_delta;
1259 }
1260 else {
1261 ui32 t = ojph_min(16, qcd_bit_depth);
1262 qp->base_delta = 1.0f / (float)(1 << t);
1263 }
1264 }
1265 qp->set_irrev_quant(num_decompositions);
1266 }
1267 else
1268 assert(0);
1269 }
1270 }
1271 else if (other_comps_exist) // Some are captured by QCD
1272 {
1273 bool employing_color_transform = cod.is_employing_color_transform();
1274 for (ui32 c = 0; c < num_comps; ++c)
1275 {
1276 param_qcd *qp = get_qcc(c);
1277 if (qp == this) // if captured by QCD continue
1278 continue;
1279 const param_cod *cp = cod.get_coc(c);
1280 ui32 num_decompositions = cp->get_num_decompositions();
1281 qp->num_subbands = 1 + 3 * num_decompositions;
1282 ui32 bit_depth = siz.get_bit_depth(c);
1284 qp->set_rev_quant(num_decompositions, bit_depth,
1285 c < 3 ? employing_color_transform : false);
1286 else if (cp->get_wavelet_kern() == param_cod::DWT_IRV97)
1287 {
1288 if (qp->base_delta == -1.0f) {
1289 if (qcd_wavelet_kern == param_cod::DWT_IRV97) {
1290 assert(this->base_delta != -1.0f);
1291 qp->base_delta = this->base_delta;
1292 }
1293 else {
1294 ui32 t = ojph_min(16, qcd_bit_depth);
1295 qp->base_delta = 1.0f / (float)(1 << t);
1296 }
1297 }
1298 qp->set_irrev_quant(num_decompositions);
1299 }
1300 else
1301 assert(0);
1302 }
1303 }
1304 }
1305
1308 {
1309 assert(type == QCD_MAIN);
1311 if (p == NULL)
1313 p->set_delta(delta);
1314 }
1315
1317 void param_qcd::set_rev_quant(ui32 num_decomps, ui32 bit_depth,
1318 bool is_employing_color_transform)
1319 {
1320 ui32 B = bit_depth;
1321 B += is_employing_color_transform ? 1 : 0; //1 bit for RCT
1322 int s = 0;
1323 double bibo_l = bibo_gains::get_bibo_gain_l(num_decomps, true);
1324 ui32 X = (ui32) ceil(log(bibo_l * bibo_l) / M_LN2);
1325 SPqcd.u8[s++] = (ui8)(B + X);
1326 ui32 max_B_plus_X = (ui32)(B + X);
1327 for (ui32 d = num_decomps; d > 0; --d)
1328 {
1329 double bibo_l = bibo_gains::get_bibo_gain_l(d, true);
1330 double bibo_h = bibo_gains::get_bibo_gain_h(d - 1, true);
1331 X = (ui32) ceil(log(bibo_h * bibo_l) / M_LN2);
1332 SPqcd.u8[s++] = (ui8)(B + X);
1333 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1334 SPqcd.u8[s++] = (ui8)(B + X);
1335 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1336 X = (ui32) ceil(log(bibo_h * bibo_h) / M_LN2);
1337 SPqcd.u8[s++] = (ui8)(B + X);
1338 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1339 }
1340
1341 if (max_B_plus_X > 38)
1342 OJPH_ERROR(0x00050151, "The specified combination of bit_depth, "
1343 "colour transform, and type of wavelet transform requires more than "
1344 "38 bits; it requires %d bits. This is beyond what is allowed in "
1345 "the JPEG2000 image coding format.", max_B_plus_X);
1346
1347 int guard_bits = ojph_max(1, (si32)max_B_plus_X - 31);
1348 Sqcd = (ui8)(guard_bits << 5);
1349 s = 0;
1350 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1351 s++;
1352 for (ui32 d = num_decomps; d > 0; --d)
1353 {
1354 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1355 s++;
1356 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1357 s++;
1358 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1359 s++;
1360 }
1361 }
1362
1365 {
1366 int guard_bits = 1;
1367 Sqcd = (ui8)((guard_bits<<5)|0x2);//one guard bit, scalar quantization
1368 int s = 0;
1369 float gain_l = sqrt_energy_gains::get_gain_l(num_decomps, false);
1370 float delta_b = base_delta / (gain_l * gain_l);
1371 int exp = 0, mantissa;
1372 while (delta_b < 1.0f)
1373 { exp++; delta_b *= 2.0f; }
1374 //with rounding, there is a risk of becoming equal to 1<<12
1375 // but that should not happen in reality
1376 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1377 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1378 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1379 for (ui32 d = num_decomps; d > 0; --d)
1380 {
1381 float gain_l = sqrt_energy_gains::get_gain_l(d, false);
1382 float gain_h = sqrt_energy_gains::get_gain_h(d - 1, false);
1383
1384 delta_b = base_delta / (gain_l * gain_h);
1385
1386 int exp = 0, mantissa;
1387 while (delta_b < 1.0f)
1388 { exp++; delta_b *= 2.0f; }
1389 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1390 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1391 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1392 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1393
1394 delta_b = base_delta / (gain_h * gain_h);
1395
1396 exp = 0;
1397 while (delta_b < 1)
1398 { exp++; delta_b *= 2.0f; }
1399 mantissa = (int)round(delta_b * (float)(1<<11)) - (1<<11);
1400 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1401 SPqcd.u16[s++] = (ui16)((exp << 11) | mantissa);
1402 }
1403 }
1404
1407 {
1408 ui32 B = 0;
1409
1410 const param_qcd *p = this;
1411 while (p)
1412 {
1413 //this can be written better, but it is only executed once
1414 // this assumes a bi-directional wavelet (conventional DWT)
1415 ui32 num_decomps = (p->num_subbands - 1) / 3;
1416
1417 int irrev = p->Sqcd & 0x1F;
1418 if (irrev == 0) //reversible
1419 for (ui32 i = 0; i < p->num_subbands; ++i) {
1420 ui32 t = p->decode_SPqcd(p->SPqcd.u8[i]);
1421 t += p->get_num_guard_bits() - 1u;
1422 B = ojph_max(B, t);
1423 }
1424 else if (irrev == 2) //scalar expounded
1425 for (ui32 i = 0; i < p->num_subbands; ++i)
1426 {
1427 ui32 nb = num_decomps - (i ? (i - 1) / 3 : 0); //decompsition level
1428 ui32 t = (p->SPqcd.u16[i] >> 11) + p->get_num_guard_bits() - nb;
1429 B = ojph_max(B, t);
1430 }
1431 else
1432 assert(0);
1433
1434 p = p->next;
1435 }
1436
1437 return B;
1438 }
1439
1442 ui32 num_decompositions, ui32 comp_num,
1443 ui32 resolution, ui32 subband) const
1444 {
1445 float arr[] = { 1.0f, 2.0f, 2.0f, 4.0f };
1446 if ((Sqcd & 0x1F) != 2)
1447 OJPH_ERROR(0x00050101, "There is something wrong in the configuration "
1448 "of the codestream; for component %d, the codestream defines an "
1449 "irreversible transform, for which the codestream provides a "
1450 "reversible (no quantization) step sizes in Sqcd/Sqcc.", comp_num);
1451
1452 ui32 idx;
1453 if (dfs != NULL && dfs->exists())
1454 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1455 else
1456 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1457 if (idx >= num_subbands) {
1458 OJPH_INFO(0x00050101, "Trying to access quantization step size for "
1459 "subband %d when the QCD/QCC marker segment specifies "
1460 "quantization step sizes for %d subbands only. To continue "
1461 "decoding, we are using the step size for subband %d, which can "
1462 "produce incorrect results",
1463 idx + 1, num_subbands, num_subbands - 1);
1464 idx = num_subbands - 1;
1465 }
1466 int eps = SPqcd.u16[idx] >> 11;
1467 float mantissa;
1468 mantissa = (float)((SPqcd.u16[idx] & 0x7FF) | 0x800) * arr[subband];
1469 mantissa /= (float)(1 << 11);
1470 mantissa /= (float)(1u << eps);
1471 return mantissa;
1472 }
1473
1476 {
1477 ui32 comp_idx = cod->get_comp_idx();
1478 ui32 precision = 0;
1479 const param_cod *main =
1481 if (main->is_employing_color_transform() && comp_idx < 3)
1482 {
1483 for (ui32 i = 0; i < 3; ++i) {
1484 const param_qcd* p = this->get_qcc(i);
1485 precision = ojph_max(precision, p->get_largest_Kmax());
1486 }
1487 }
1488 else {
1489 precision = get_largest_Kmax();
1490 }
1491 // ``precision'' now holds the largest K_max, which excludes the sign
1492 // bit.
1493 // + 1 for the sign bit
1494 // + 1 because my block decoder/encoder does not supports up to 30
1495 // bits (not 31), so we bump it by one more bit.
1496 return precision + 1 + 1;
1497 }
1498
1501 {
1502 return (Sqcd >> 5);
1503 }
1504
1506 ui32 param_qcd::get_Kmax(const param_dfs* dfs, ui32 num_decompositions,
1507 ui32 resolution, ui32 subband) const
1508 {
1509 ui32 idx;
1510 if (dfs != NULL && dfs->exists())
1511 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1512 else
1513 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1514 if (idx >= num_subbands) {
1515 OJPH_INFO(0x00050111, "Trying to access quantization step size for "
1516 "subband %d when the QCD/QCC marker segment specifies "
1517 "quantization step sizes for %d subbands only. To continue "
1518 "decoding, we are using the step size for subband %d, which can "
1519 "produce incorrect results",
1520 idx + 1, num_subbands, num_subbands - 1);
1521 idx = num_subbands - 1;
1522 }
1523
1524 int irrev = Sqcd & 0x1F;
1525 ui32 num_bits = 0;
1526 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1527 {
1528 num_bits = decode_SPqcd(SPqcd.u8[idx]);
1529 num_bits = num_bits == 0 ? 0 : num_bits - 1;
1530 }
1531 else if (irrev == 1)
1532 assert(0);
1533 else if (irrev == 2) //scalar expounded
1534 num_bits = (SPqcd.u16[idx] >> 11) - 1;
1535 else
1536 assert(0);
1537
1538 return num_bits + get_num_guard_bits();
1539 }
1540
1543 {
1544 int irrev = Sqcd & 0x1F;
1545 ui32 num_bits = 0;
1546 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1547 {
1548 for (ui32 i = 0; i < num_subbands; ++i) {
1549 ui32 t = decode_SPqcd(SPqcd.u8[i]);
1550 num_bits = ojph_max(num_bits, t == 0 ? 0 : t - 1);
1551 }
1552 }
1553 else if (irrev == 1)
1554 assert(0);
1555 else if (irrev == 2) //scalar expounded
1556 {
1557 for (ui32 i = 0; i < num_subbands; ++i) {
1558 ui32 t = (SPqcd.u16[i] >> 11) - 1;
1559 num_bits = ojph_max(num_bits, t);
1560 }
1561 }
1562 else
1563 assert(0);
1564
1565 return num_bits + get_num_guard_bits();
1566 }
1567
1570 {
1571 int irrev = Sqcd & 0x1F;
1572
1573 //marker size excluding header
1574 Lqcd = 3;
1575 if (irrev == 0)
1576 Lqcd = (ui16)(Lqcd + num_subbands);
1577 else if (irrev == 2)
1578 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1579 else
1580 assert(0);
1581
1582 char buf[4];
1583 bool result = true;
1584
1585 *(ui16*)buf = JP2K_MARKER::QCD;
1586 *(ui16*)buf = swap_byte(*(ui16*)buf);
1587 result &= file->write(&buf, 2) == 2;
1588 *(ui16*)buf = swap_byte(Lqcd);
1589 result &= file->write(&buf, 2) == 2;
1590 *(ui8*)buf = Sqcd;
1591 result &= file->write(&buf, 1) == 1;
1592
1593 if (irrev == 0)
1594 for (ui32 i = 0; i < num_subbands; ++i)
1595 {
1596 *(ui8*)buf = SPqcd.u8[i];
1597 result &= file->write(&buf, 1) == 1;
1598 }
1599 else if (irrev == 2)
1600 for (ui32 i = 0; i < num_subbands; ++i)
1601 {
1602 *(ui16*)buf = swap_byte(SPqcd.u16[i]);
1603 result &= file->write(&buf, 2) == 2;
1604 }
1605 else
1606 assert(0);
1607
1608 return result;
1609 }
1610
1613 {
1614 assert(type == QCD_MAIN);
1615 bool result = true;
1616 param_qcd *p = this->next;
1617 while (p)
1618 {
1619 if (p->enabled)
1620 result &= p->internal_write_qcc(file, num_comps);
1621 p = p->next;
1622 }
1623 return result;
1624 }
1625
1628 {
1629 int irrev = Sqcd & 0x1F;
1630
1631 //marker size excluding header
1632 Lqcd = (ui16)(4 + (num_comps < 257 ? 0 : 1));
1633 if (irrev == 0)
1634 Lqcd = (ui16)(Lqcd + num_subbands);
1635 else if (irrev == 2)
1636 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1637 else
1638 assert(0);
1639
1640 char buf[4];
1641 bool result = true;
1642
1643 *(ui16*)buf = JP2K_MARKER::QCC;
1644 *(ui16*)buf = swap_byte(*(ui16*)buf);
1645 result &= file->write(&buf, 2) == 2;
1646 *(ui16*)buf = swap_byte(Lqcd);
1647 result &= file->write(&buf, 2) == 2;
1648 if (num_comps < 257)
1649 {
1650 *(ui8*)buf = (ui8)comp_idx;
1651 result &= file->write(&buf, 1) == 1;
1652 }
1653 else
1654 {
1655 *(ui16*)buf = swap_byte(comp_idx);
1656 result &= file->write(&buf, 2) == 2;
1657 }
1658 *(ui8*)buf = Sqcd;
1659 result &= file->write(&buf, 1) == 1;
1660 if (irrev == 0)
1661 for (ui32 i = 0; i < num_subbands; ++i)
1662 {
1663 *(ui8*)buf = SPqcd.u8[i];
1664 result &= file->write(&buf, 1) == 1;
1665 }
1666 else if (irrev == 2)
1667 for (ui32 i = 0; i < num_subbands; ++i)
1668 {
1669 *(ui16*)buf = swap_byte(SPqcd.u16[i]);
1670 result &= file->write(&buf, 2) == 2;
1671 }
1672 else
1673 assert(0);
1674
1675 return result;
1676 }
1677
1680 {
1681 assert(type == QCD_MAIN && comp_idx == OJPH_QCD_DEFAULT);
1682 param_qcd *p = this->next;
1683 while (p)
1684 {
1685 assert(p->type == QCC_MAIN);
1686 p->enabled = p->comp_idx < num_comps;
1687 p = p->next;
1688 }
1689 }
1690
1693 {
1694 if (file->read(&Lqcd, 2) != 2)
1695 OJPH_ERROR(0x00050081, "error reading QCD marker");
1696 Lqcd = swap_byte(Lqcd);
1697 if (file->read(&Sqcd, 1) != 1)
1698 OJPH_ERROR(0x00050082, "error reading QCD marker");
1699 if ((Sqcd & 0x1F) == 0)
1700 {
1701 num_subbands = (Lqcd - 3);
1702 if (num_subbands == 0)
1703 OJPH_ERROR(0x0005008A, "QCD marker segment that specifies no "
1704 "quantization informtion");
1705 if (num_subbands > 97 || Lqcd != 3 + num_subbands)
1706 OJPH_ERROR(0x00050083, "wrong Lqcd value of %d in QCD marker", Lqcd);
1707 for (ui32 i = 0; i < num_subbands; ++i)
1708 if (file->read(&SPqcd.u8[i], 1) != 1)
1709 OJPH_ERROR(0x00050084, "error reading QCD marker");
1710 }
1711 else if ((Sqcd & 0x1F) == 1)
1712 {
1713 num_subbands = 0;
1714 OJPH_ERROR(0x00050089,
1715 "Scalar derived quantization is not supported yet in QCD marker");
1716 if (Lqcd != 5)
1717 OJPH_ERROR(0x00050085, "wrong Lqcd value in QCD marker");
1718 }
1719 else if ((Sqcd & 0x1F) == 2)
1720 {
1721 num_subbands = (Lqcd - 3) / 2;
1722 if (num_subbands == 0)
1723 OJPH_ERROR(0x0005008B, "QCD marker segment that specifies no "
1724 "quantization informtion");
1725 if (num_subbands > 97 || Lqcd != 3 + 2 * num_subbands)
1726 OJPH_ERROR(0x00050086, "wrong Lqcd value of %d in QCD marker", Lqcd);
1727 for (ui32 i = 0; i < num_subbands; ++i)
1728 {
1729 if (file->read(&SPqcd.u16[i], 2) != 2)
1730 OJPH_ERROR(0x00050087, "error reading QCD marker");
1731 SPqcd.u16[i] = swap_byte(SPqcd.u16[i]);
1732 }
1733 }
1734 else
1735 OJPH_ERROR(0x00050088, "wrong Sqcd value in QCD marker");
1736 }
1737
1739 void param_qcd::read_qcc(infile_base *file, ui32 num_comps)
1740 {
1741 if (file->read(&Lqcd, 2) != 2)
1742 OJPH_ERROR(0x000500A1, "error reading QCC marker");
1743 Lqcd = swap_byte(Lqcd);
1744 if (num_comps < 257)
1745 {
1746 ui8 v;
1747 if (file->read(&v, 1) != 1)
1748 OJPH_ERROR(0x000500A2, "error reading QCC marker");
1749 comp_idx = v;
1750 }
1751 else
1752 {
1753 if (file->read(&comp_idx, 2) != 2)
1754 OJPH_ERROR(0x000500A3, "error reading QCC marker");
1756 }
1757 if (file->read(&Sqcd, 1) != 1)
1758 OJPH_ERROR(0x000500A4, "error reading QCC marker");
1759 ui32 offset = num_comps < 257 ? 4 : 5;
1760 if ((Sqcd & 0x1F) == 0)
1761 {
1762 num_subbands = (Lqcd - offset);
1763 if (num_subbands == 0)
1764 OJPH_ERROR(0x000500AC, "QCC marker segment that specifies no "
1765 "quantization informtion");
1766 if (num_subbands > 97 || Lqcd != offset + num_subbands)
1767 OJPH_ERROR(0x000500A5, "wrong Lqcd value of %d in QCC marker", Lqcd);
1768 for (ui32 i = 0; i < num_subbands; ++i)
1769 if (file->read(&SPqcd.u8[i], 1) != 1)
1770 OJPH_ERROR(0x000500A6, "error reading QCC marker");
1771 }
1772 else if ((Sqcd & 0x1F) == 1)
1773 {
1774 num_subbands = 0;
1775 OJPH_ERROR(0x000500AB,
1776 "Scalar derived quantization is not supported yet in QCC marker");
1777 if (Lqcd != offset)
1778 OJPH_ERROR(0x000500A7, "wrong Lqcc value in QCC marker");
1779 }
1780 else if ((Sqcd & 0x1F) == 2)
1781 {
1782 num_subbands = (Lqcd - offset) / 2;
1783 if (num_subbands == 0)
1784 OJPH_ERROR(0x000500AD, "QCC marker segment that specifies no "
1785 "quantization informtion");
1786 if (num_subbands > 97 || Lqcd != offset + 2 * num_subbands)
1787 OJPH_ERROR(0x000500A8, "wrong Lqcc value of %d in QCC marker", Lqcd);
1788 for (ui32 i = 0; i < num_subbands; ++i)
1789 {
1790 if (file->read(&SPqcd.u16[i], 2) != 2)
1791 OJPH_ERROR(0x000500A9, "error reading QCC marker");
1792 SPqcd.u16[i] = swap_byte(SPqcd.u16[i]);
1793 }
1794 }
1795 else
1796 OJPH_ERROR(0x000500AA, "wrong Sqcc value in QCC marker");
1797 }
1798
1801 {
1802 // cast object to constant
1803 const param_qcd* const_p = const_cast<const param_qcd*>(this);
1804 // call using the constant object, then cast to non-const
1805 return const_cast<param_qcd*>(const_p->get_qcc(comp_idx));
1806 }
1807
1810 {
1811 assert(this->type == QCD_MAIN || this->top_qcd->type == QCD_MAIN);
1812 const param_qcd *p, *q;
1813 if (this->type == QCD_MAIN)
1814 q = p = this;
1815 else
1816 q = p = this->top_qcd;
1817 while (p && p->comp_idx != comp_idx)
1818 p = p->next;
1819 return p ? p : q;
1820 }
1821
1824 {
1825 assert(type == QCD_MAIN);
1826 param_qcd *p = this;
1827 while (p->next != NULL)
1828 p = p->next;
1829 if (avail)
1830 {
1831 p->next = avail;
1832 avail = avail->next;
1833 p->next->init(this, (ui16)comp_idx);
1834 }
1835 else
1836 p->next = new param_qcd(this, (ui16)comp_idx);
1837 return p->next;
1838 }
1839
1841 //
1842 //
1843 //
1844 //
1845 //
1847
1850 {
1851 if (is_any_enabled() == false)
1852 return;
1853
1854 if (this->enabled && this->Tnlt == nonlinearity::OJPH_NLT_NO_NLT)
1855 this->enabled = false;
1856
1857 if (this->enabled &&
1858 this->Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
1859 {
1860 bool all_same = true;
1861 ui32 num_comps = siz.get_num_components();
1862
1863 // first stage; find out if all components captured by the default
1864 // entry (ALL_COMPS) has the same bit_depth/signedness,
1865 // while doing this, set the BDnlt for components not captured by the
1866 // default entry (ALL_COMPS)
1867 ui32 bit_depth = 0; // unknown yet
1868 bool is_signed = false; // unknown yet
1869 for (ui32 c = 0; c < num_comps; ++c)
1870 { // captured by ALL_COMPS
1871 param_nlt* p = get_nlt_object(c);
1872 if (p == NULL || !p->enabled)
1873 {
1874 if (bit_depth != 0)
1875 {
1876 // we have seen an undefined component previously
1877 all_same = all_same && (bit_depth == siz.get_bit_depth(c));
1878 all_same = all_same && (is_signed == siz.is_signed(c));
1879 }
1880 else
1881 {
1882 // this is the first component which has not type 3 nlt definition
1883 bit_depth = siz.get_bit_depth(c);
1884 is_signed = siz.is_signed(c);
1885 }
1886 }
1887 else
1888 { // can be type 0 or type 3
1889 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1890 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1891 }
1892 }
1893
1894 if (all_same && bit_depth != 0)
1895 { // all the same, and some components are captured by ALL_COMPS
1896 this->BDnlt = (ui8)(bit_depth - 1);
1897 this->BDnlt = (ui8)(this->BDnlt | (is_signed ? 0x80 : 0));
1898 }
1899 else if (!all_same)
1900 { // have different settings or no component is captured by ALL_COMPS
1901 this->enabled = false;
1902 for (ui32 c = 0; c < num_comps; ++c)
1903 {
1904 param_nlt* p = get_nlt_object(c);
1905 if (p == NULL || !p->enabled)
1906 { // captured by ALL_COMPS
1907 if (p == NULL)
1908 p = add_object(c);
1909 p->enabled = true;
1910 p->Tnlt = nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
1911 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1912 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1913 }
1914 }
1915 }
1916 }
1917 else {
1918 // fill NLT segment markers with correct information
1919 ui32 num_comps = siz.get_num_components();
1920 for (ui32 c = 0; c < num_comps; ++c)
1921 { // captured by ALL_COMPS
1922 param_nlt* p = get_nlt_object(c);
1923 if (p != NULL && p->enabled)
1924 { // can be type 0 or type 3
1925 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
1926 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
1927 }
1928 }
1929 }
1930
1932
1933 if (is_any_enabled() == true)
1935 }
1936
1939 {
1940 if (nl_type != ojph::param_nlt::OJPH_NLT_NO_NLT &&
1942 OJPH_ERROR(0x00050171, "Nonliearities other than type 0 "
1943 "(No Nonlinearity) or type 3 (Binary Binary Complement to Sign "
1944 "Magnitude Conversion) are not supported yet");
1945 param_nlt* p = get_nlt_object(comp_num);
1946 if (p == NULL)
1947 p = add_object(comp_num);
1948 p->Tnlt = nl_type;
1949 p->enabled = true;
1950 }
1951
1953 bool
1955 bool& is_signed, ui8& nl_type) const
1956 {
1957 assert(Cnlt == special_comp_num::ALL_COMPS);
1958 const param_nlt* p = get_nlt_object(comp_num);
1959 p = (p && p->enabled) ? p : this;
1960 if (p->enabled)
1961 {
1962 bit_depth = (ui8)((p->BDnlt & 0x7F) + 1);
1963 bit_depth = bit_depth <= 38 ? bit_depth : 38;
1964 is_signed = (p->BDnlt & 0x80) == 0x80;
1965 nl_type = (nonlinearity)p->Tnlt;
1966 return true;
1967 }
1968 return false;
1969 }
1970
1973 {
1974 if (is_any_enabled() == false)
1975 return true;
1976
1977 char buf[2];
1978 bool result = true;
1979 const param_nlt* p = this;
1980 while (p)
1981 {
1982 if (p->enabled)
1983 {
1984 *(ui16*)buf = JP2K_MARKER::NLT;
1985 *(ui16*)buf = swap_byte(*(ui16*)buf);
1986 result &= file->write(&buf, 2) == 2;
1987 *(ui16*)buf = swap_byte(p->Lnlt);
1988 result &= file->write(&buf, 2) == 2;
1989 *(ui16*)buf = swap_byte(p->Cnlt);
1990 result &= file->write(&buf, 2) == 2;
1991 result &= file->write(&p->BDnlt, 1) == 1;
1992 result &= file->write(&p->Tnlt, 1) == 1;
1993 }
1994 p = p->next;
1995 }
1996 return result;
1997 }
1998
2001 {
2002 ui8 buf[6];
2003
2004 if (file->read(buf, 6) != 6)
2005 OJPH_ERROR(0x00050141, "error reading NLT marker segment");
2006
2007 ui16 length = swap_byte(*(ui16*)buf);
2008 if (length != 6 || (buf[5] != 3 && buf[5] != 0)) // wrong length or type
2009 OJPH_ERROR(0x00050142, "Unsupported NLT type %d\n", buf[5]);
2010
2011 ui16 comp = swap_byte(*(ui16*)(buf + 2));
2012 param_nlt* p = get_nlt_object(comp);
2013 if (p == NULL)
2014 p = add_object(comp);
2015 p->enabled = true;
2016 p->Cnlt = comp;
2017 p->BDnlt = buf[4];
2018 p->Tnlt = buf[5];
2019 }
2020
2023 {
2024 // cast object to constant
2025 const param_nlt* const_p = const_cast<const param_nlt*>(this);
2026 // call using the constant object, then cast to non-const
2027 return const_cast<param_nlt*>(const_p->get_nlt_object(comp_num));
2028 }
2029
2032 {
2033 const param_nlt* p = this;
2034 while (p && p->Cnlt != comp_num)
2035 p = p->next;
2036 return p;
2037 }
2038
2041 {
2042 assert(comp_num != special_comp_num::ALL_COMPS);
2043 assert(Cnlt == special_comp_num::ALL_COMPS);
2044 param_nlt* p = this;
2045 while (p->next != NULL) {
2046 assert(p->Cnlt != comp_num);
2047 p = p->next;
2048 }
2049 if (avail)
2050 {
2051 p->next = avail;
2052 avail = avail->next;
2053 p->next->init();
2054 }
2055 else
2056 p->next = new param_nlt;
2057 p = p->next;
2058 p->Cnlt = (ui16)comp_num;
2059 return p;
2060 }
2061
2064 {
2065 // check if any field is enabled
2066 const param_nlt* p = this;
2067 while (p && p->enabled == false)
2068 p = p->next;
2069 return (p != NULL);
2070 }
2071
2074 {
2075 param_nlt* p = this->next;
2076 while (p) {
2077 if (p->enabled == true && p->Cnlt >= num_comps) {
2078 p->enabled = false;
2079 OJPH_INFO(0x00050161, "The NLT marker segment for the "
2080 "non-existing component %d has been removed.", p->Cnlt);
2081 }
2082 p = p->next;
2083 }
2084 }
2085
2086
2088 //
2089 //
2090 //
2091 //
2092 //
2094
2096 bool param_sot::write(outfile_base *file, ui32 payload_len)
2097 {
2098 char buf[4];
2099 bool result = true;
2100
2101 this->Psot = payload_len + 14; //inc. SOT marker, field & SOD
2102
2103 *(ui16*)buf = JP2K_MARKER::SOT;
2104 *(ui16*)buf = swap_byte(*(ui16*)buf);
2105 result &= file->write(&buf, 2) == 2;
2106 *(ui16*)buf = swap_byte(Lsot);
2107 result &= file->write(&buf, 2) == 2;
2108 *(ui16*)buf = swap_byte(Isot);
2109 result &= file->write(&buf, 2) == 2;
2110 *(ui32*)buf = swap_byte(Psot);
2111 result &= file->write(&buf, 4) == 4;
2112 result &= file->write(&TPsot, 1) == 1;
2113 result &= file->write(&TNsot, 1) == 1;
2114
2115 return result;
2116 }
2117
2119 bool param_sot::write(outfile_base *file, ui32 payload_len,
2120 ui8 TPsot, ui8 TNsot)
2121 {
2122 char buf[4];
2123 bool result = true;
2124
2125 *(ui16*)buf = JP2K_MARKER::SOT;
2126 *(ui16*)buf = swap_byte(*(ui16*)buf);
2127 result &= file->write(&buf, 2) == 2;
2128 *(ui16*)buf = swap_byte(Lsot);
2129 result &= file->write(&buf, 2) == 2;
2130 *(ui16*)buf = swap_byte(Isot);
2131 result &= file->write(&buf, 2) == 2;
2132 *(ui32*)buf = swap_byte(payload_len + 14);
2133 result &= file->write(&buf, 4) == 4;
2134 result &= file->write(&TPsot, 1) == 1;
2135 result &= file->write(&TNsot, 1) == 1;
2136
2137 return result;
2138 }
2139
2141 bool param_sot::read(infile_base *file, bool resilient)
2142 {
2143 if (resilient)
2144 {
2145 if (file->read(&Lsot, 2) != 2)
2146 {
2147 OJPH_INFO(0x00050091, "error reading SOT marker");
2148 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2149 return false;
2150 }
2151 Lsot = swap_byte(Lsot);
2152 if (Lsot != 10)
2153 {
2154 OJPH_INFO(0x00050092, "error in SOT length");
2155 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2156 return false;
2157 }
2158 if (file->read(&Isot, 2) != 2)
2159 {
2160 OJPH_INFO(0x00050093, "error reading tile index");
2161 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2162 return false;
2163 }
2164 Isot = swap_byte(Isot);
2165 if (Isot == 0xFFFF)
2166 {
2167 OJPH_INFO(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2168 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2169 return false;
2170 }
2171 if (file->read(&Psot, 4) != 4)
2172 {
2173 OJPH_INFO(0x00050095, "error reading SOT marker");
2174 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2175 return false;
2176 }
2177 Psot = swap_byte(Psot);
2178 if (file->read(&TPsot, 1) != 1)
2179 {
2180 OJPH_INFO(0x00050096, "error reading SOT marker");
2181 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2182 return false;
2183 }
2184 if (file->read(&TNsot, 1) != 1)
2185 {
2186 OJPH_INFO(0x00050097, "error reading SOT marker");
2187 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2188 return false;
2189 }
2190 }
2191 else
2192 {
2193 if (file->read(&Lsot, 2) != 2)
2194 OJPH_ERROR(0x00050091, "error reading SOT marker");
2195 Lsot = swap_byte(Lsot);
2196 if (Lsot != 10)
2197 OJPH_ERROR(0x00050092, "error in SOT length");
2198 if (file->read(&Isot, 2) != 2)
2199 OJPH_ERROR(0x00050093, "error reading SOT tile index");
2200 Isot = swap_byte(Isot);
2201 if (Isot == 0xFFFF)
2202 OJPH_ERROR(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2203 if (file->read(&Psot, 4) != 4)
2204 OJPH_ERROR(0x00050095, "error reading SOT marker");
2205 Psot = swap_byte(Psot);
2206 if (file->read(&TPsot, 1) != 1)
2207 OJPH_ERROR(0x00050096, "error reading SOT marker");
2208 if (file->read(&TNsot, 1) != 1)
2209 OJPH_ERROR(0x00050097, "error reading SOT marker");
2210 }
2211 return true;
2212 }
2213
2215 //
2216 //
2217 //
2218 //
2219 //
2221
2224 {
2225 if (4 + 6 * num_pairs > 65535)
2226 OJPH_ERROR(0x000500B1, "Trying to allocate more than 65535 bytes for "
2227 "a TLM marker; this can be resolved by having more than "
2228 "one TLM marker, but the code does not support this. "
2229 "In any case, this limit means that we have 10922 "
2230 "tileparts or more, which is a huge number.");
2231 this->num_pairs = num_pairs;
2232 pairs = store;
2233 Ltlm = (ui16)(4 + 6 * num_pairs);
2234 Ztlm = 0;
2235 Stlm = 0x60;
2236 }
2237
2240 {
2241 assert(next_pair_index < num_pairs);
2242 pairs[next_pair_index].Ttlm = Ttlm;
2243 pairs[next_pair_index].Ptlm = Ptlm + 14;
2245 }
2246
2249 {
2250 assert(next_pair_index == num_pairs);
2251 char buf[4];
2252 bool result = true;
2253
2254 *(ui16*)buf = JP2K_MARKER::TLM;
2255 *(ui16*)buf = swap_byte(*(ui16*)buf);
2256 result &= file->write(&buf, 2) == 2;
2257 *(ui16*)buf = swap_byte(Ltlm);
2258 result &= file->write(&buf, 2) == 2;
2259 result &= file->write(&Ztlm, 1) == 1;
2260 result &= file->write(&Stlm, 1) == 1;
2261 for (ui32 i = 0; i < num_pairs; ++i)
2262 {
2263 *(ui16*)buf = swap_byte(pairs[i].Ttlm);
2264 result &= file->write(&buf, 2) == 2;
2265 *(ui32*)buf = swap_byte(pairs[i].Ptlm);
2266 result &= file->write(&buf, 4) == 4;
2267 }
2268 return result;
2269 }
2270
2272 //
2273 //
2274 //
2275 //
2276 //
2278
2280 const param_dfs* param_dfs::get_dfs(int index) const
2281 {
2282 const param_dfs* p = this;
2283 while (p && p->Sdfs != index)
2284 p = p->next;
2285 return p;
2286 }
2287
2290 {
2291 decomp_level = ojph_min(decomp_level, Ids);
2292 ui32 d = decomp_level - 1; // decomp_level starts from 1
2293 ui32 idx = d >> 2; // complete bytes
2294 ui32 bits = d & 0x3; // bit within the bytes
2295 ui32 val = (Ddfs[idx] >> (6 - 2 * bits)) & 0x3;
2296 return (dfs_dwt_type)val;
2297 }
2298
2301 ui32 subband) const
2302 {
2303 assert((resolution == 0 && subband == 0) ||
2304 (resolution > 0 && subband > 0 && subband < 4));
2305
2306 ui32 ns[4] = { 0, 3, 1, 1 };
2307
2308 ui32 idx = 0;
2309 if (resolution > 0)
2310 {
2311 idx = 0;
2312 ui32 i = 1;
2313 for (; i < resolution; ++i)
2314 idx += ns[get_dwt_type(num_decompositions - i + 1)];
2315 dfs_dwt_type t = get_dwt_type(num_decompositions - i + 1);
2316 idx += subband;
2317 if (t == VERT_DWT && subband == 2)
2318 --idx;
2319 }
2320
2321 return idx;
2322 }
2323
2325 point param_dfs::get_res_downsamp(ui32 skipped_resolutions) const
2326 {
2327 point factor(1, 1);
2328 ui32 decomp_level = 1;
2329 while (skipped_resolutions > 0)
2330 {
2331 param_dfs::dfs_dwt_type type = get_dwt_type(decomp_level);
2332 if (type == BIDIR_DWT)
2333 { factor.x *= 2; factor.y *= 2; }
2334 else if (type == HORZ_DWT)
2335 factor.x *= 2;
2336 else if (type == VERT_DWT)
2337 factor.y *= 2;
2338
2339 ++decomp_level;
2340 --skipped_resolutions;
2341 }
2342 return factor;
2343 }
2344
2347 {
2348 if (Ldfs != 0) { // this param_dfs is used
2349 param_dfs* p = this;
2350 while (p->next != NULL)
2351 p = p->next;
2352 if (avail)
2353 {
2354 p->next = avail;
2355 avail = avail->next;
2356 p->next->init();
2357 }
2358 else
2359 p->next = new param_dfs;
2360 p = p->next;
2361 return p->read(file);
2362 }
2363
2364 if (file->read(&Ldfs, 2) != 2)
2365 OJPH_ERROR(0x000500D1, "error reading DFS-Ldfs parameter");
2366 Ldfs = swap_byte(Ldfs);
2367 if (file->read(&Sdfs, 2) != 2)
2368 OJPH_ERROR(0x000500D2, "error reading DFS-Sdfs parameter");
2369 Sdfs = swap_byte(Sdfs);
2370 if (Sdfs > 15)
2371 OJPH_ERROR(0x000500D3, "The DFS-Sdfs parameter is %d, which is "
2372 "larger than the permissible 15", Sdfs);
2373 ui8 t, l_Ids = 0;
2374 if (file->read(&l_Ids, 1) != 1)
2375 OJPH_ERROR(0x000500D4, "error reading DFS-Ids parameter");
2376 constexpr int max_Ddfs = sizeof(Ddfs) * 4;
2377 if (l_Ids > max_Ddfs)
2378 OJPH_INFO(0x000500D5, "The DFS-Ids parameter is %d; while this is "
2379 "valid, the number is unnessarily large -- you do not need more "
2380 "than %d. Please contact me regarding this issue.",
2381 l_Ids, max_Ddfs);
2382 Ids = l_Ids < max_Ddfs ? l_Ids : max_Ddfs;
2383 for (int i = 0; i < Ids; i += 4)
2384 if (file->read(&Ddfs[i / 4], 1) != 1)
2385 OJPH_ERROR(0x000500D6, "error reading DFS-Ddfs parameters");
2386 for (int i = Ids; i < l_Ids; i += 4)
2387 if (file->read(&t, 1) != 1)
2388 OJPH_ERROR(0x000500D7, "error reading DFS-Ddfs parameters");
2389 return true;
2390 }
2391
2393 //
2394 //
2395 //
2396 //
2397 //
2399
2402 {
2403 assert(top_atk == NULL);
2404
2405 if (Latk == 0)
2406 {
2407 // This atk object is not used, initialize it to either 0 (irv97)
2408 // or 1 (rev53), and use it. If index is not 0 nor 1, then index
2409 // must have been read from file previously, otherwise it is an
2410 // error.
2411 if (index == 0) { this->init_irv97(); return this; }
2412 else if (index == 1) { this->init_rev53(); return this; }
2413 }
2414
2415 param_atk* p = this;
2416 while (p && p->get_index() != index)
2417 p = p->next;
2418
2419 if (p == NULL && (index == 0 || index == 1))
2420 {
2421 // The index was not found, add an atk object only if the index is
2422 // either 0 or 1
2423 p = add_object();
2424 if (index == 0)
2425 p->init_irv97();
2426 else if (index == 1)
2427 p->init_rev53();
2428 }
2429
2430 return p;
2431 }
2432
2434 bool param_atk::read_coefficient(infile_base *file, float &K, si32& bytes)
2435 {
2436 int coeff_type = get_coeff_type();
2437 if (coeff_type == 0) { // 8bit
2438 ui8 v;
2439 if (file->read(&v, 1) != 1) return false;
2440 bytes -= 1;
2441 K = v;
2442 }
2443 else if (coeff_type == 1) { // 16bit
2444 ui16 v;
2445 if (file->read(&v, 2) != 2) return false;
2446 bytes -= 2;
2447 K = swap_byte(v);
2448 }
2449 else if (coeff_type == 2) { // float
2450 union {
2451 float f;
2452 ui32 i;
2453 } v;
2454 if (file->read(&v.i, 4) != 4) return false;
2455 bytes -= 4;
2456 v.i = swap_byte(v.i);
2457 K = v.f;
2458 }
2459 else if (coeff_type == 3) { // double
2460 union {
2461 double d;
2462 ui64 i;
2463 } v;
2464 if (file->read(&v.i, 8) != 8) return false;
2465 bytes -= 8;
2466 v.i = swap_byte(v.i);
2467 K = (float)v.d;
2468 }
2469 else if (coeff_type == 4) { // 128 bit float
2470 ui64 v, v1;
2471 if (file->read(&v, 8) != 8) return false;
2472 bytes -= 8;
2473 if (file->read(&v1, 8) != 8) return false; // v1 not needed
2474 bytes -= 8;
2475 v = swap_byte(v);
2476
2477 union {
2478 float f;
2479 ui32 i;
2480 } s;
2481 // convert the MSB of 128b float to 32b float
2482 // 32b float has 1 sign bit, 8 exponent (offset 127), 23 mantissa
2483 // 128b float has 1 sign bit, 15 exponent (offset 16383), 112 mantissa
2484 si32 e = (si32)((v >> 48) & 0x7FFF); // exponent
2485 e -= 16383;
2486 e += 127;
2487 e = e & 0xFF; // removes MSBs if negative
2488 e <<= 23; // move bits to their location
2489 s.i = 0;
2490 s.i |= ((ui32)(v >> 32) & 0x80000000); // copy sign bit
2491 s.i |= (ui32)e; // copy exponent
2492 s.i |= (ui32)((v >> 25) & 0x007FFFFF); // copy 23 mantissa
2493 K = s.f;
2494 }
2495 return true;
2496 }
2497
2498
2501 {
2502 int coeff_type = get_coeff_type();
2503 if (coeff_type == 0) {
2504 si8 v;
2505 if (file->read(&v, 1) != 1) return false;
2506 bytes -= 1;
2507 K = v;
2508 }
2509 else if (coeff_type == 1) {
2510 si16 v;
2511 if (file->read(&v, 2) != 2) return false;
2512 bytes -= 2;
2513 K = (si16)swap_byte((ui16)v);
2514 }
2515 else
2516 return false;
2517 return true;
2518 }
2519
2522 {
2523 if (Latk != 0) // this param_atk is used
2524 return add_object()->read(file);
2525
2526 if (file->read(&Latk, 2) != 2)
2527 OJPH_ERROR(0x000500E1, "error reading ATK-Latk parameter");
2528 Latk = swap_byte(Latk);
2529 si32 bytes = Latk - 2;
2530 ojph::ui16 temp_Satk;
2531 if (file->read(&temp_Satk, 2) != 2)
2532 OJPH_ERROR(0x000500E2, "error reading ATK-Satk parameter");
2533 bytes -= 2;
2534 temp_Satk = swap_byte(temp_Satk);
2535 int tmp_idx = temp_Satk & 0xFF;
2536 if ((top_atk && top_atk->get_atk(tmp_idx) != NULL)
2537 || tmp_idx == 0 || tmp_idx == 1)
2538 OJPH_ERROR(0x000500F3, "ATK-Satk parameter sets ATK marker index to "
2539 "the illegal value of %d. ATK-Satk should be in (2-255) and, I "
2540 "believe, must not be repeated; otherwise, it would be unclear "
2541 "what marker segment must be employed when an index is repeated.",
2542 tmp_idx);
2543 Satk = temp_Satk;
2544 if (is_m_init0() == false) // only even-indexed is supported
2545 OJPH_ERROR(0x000500E3, "ATK-Satk parameter sets m_init to 1, "
2546 "requiring odd-indexed subsequence in first reconstruction step, "
2547 "which is not supported yet.");
2548 if (is_whole_sample() == false) // ARB filter not supported
2549 OJPH_ERROR(0x000500E4, "ATK-Satk parameter specified ARB filter, "
2550 "which is not supported yet.");
2551 if (is_reversible() && get_coeff_type() >= 2) // reversible & float
2552 OJPH_ERROR(0x000500E5, "ATK-Satk parameter does not make sense. "
2553 "It employs floats with reversible filtering.");
2554 if (is_using_ws_extension() == false) // only sym. ext is supported
2555 OJPH_ERROR(0x000500E6, "ATK-Satk parameter requires constant "
2556 "boundary extension, which is not supported yet.");
2557 if (is_reversible() == false)
2558 if (read_coefficient(file, Katk, bytes) == false)
2559 OJPH_ERROR(0x000500E7, "error reading ATK-Katk parameter");
2560 if (file->read(&Natk, 1) != 1)
2561 OJPH_ERROR(0x000500E8, "error reading ATK-Natk parameter");
2562 bytes -= 1;
2563 if (Natk > max_steps) {
2564 if (d != d_store) // was this allocated -- very unlikely
2565 delete[] d;
2566 d = new lifting_step[Natk];
2567 max_steps = Natk;
2568 }
2569
2570 if (is_reversible())
2571 {
2572 for (int s = 0; s < Natk; ++s)
2573 {
2574 if (file->read(&d[s].rev.Eatk, 1) != 1)
2575 OJPH_ERROR(0x000500E9, "error reading ATK-Eatk parameter");
2576 bytes -= 1;
2577 if (file->read(&d[s].rev.Batk, 2) != 2)
2578 OJPH_ERROR(0x000500EA, "error reading ATK-Batk parameter");
2579 bytes -= 2;
2580 d[s].rev.Batk = (si16)swap_byte((ui16)d[s].rev.Batk);
2581 ui8 LCatk;
2582 if (file->read(&LCatk, 1) != 1)
2583 OJPH_ERROR(0x000500EB, "error reading ATK-LCatk parameter");
2584 bytes -= 1;
2585 if (LCatk == 0)
2586 OJPH_ERROR(0x000500EC, "Encountered a ATK-LCatk value of zero; "
2587 "something is wrong.");
2588 if (LCatk > 1)
2589 OJPH_ERROR(0x000500ED, "ATK-LCatk value greater than 1; "
2590 "that is, a multitap filter is not supported");
2591 if (read_coefficient(file, d[s].rev.Aatk, bytes) == false)
2592 OJPH_ERROR(0x000500EE, "Error reding ATK-Aatk parameter");
2593 }
2594 }
2595 else
2596 {
2597 for (int s = 0; s < Natk; ++s)
2598 {
2599 ui8 LCatk;
2600 if (file->read(&LCatk, 1) != 1)
2601 OJPH_ERROR(0x000500EF, "error reading ATK-LCatk parameter");
2602 bytes -= 1;
2603 if (LCatk == 0)
2604 OJPH_ERROR(0x000500F0, "Encountered a ATK-LCatk value of zero; "
2605 "something is wrong.");
2606 if (LCatk > 1)
2607 OJPH_ERROR(0x000500F1, "ATK-LCatk value greater than 1; "
2608 "that is, a multitap filter is not supported.");
2609 if (read_coefficient(file, d[s].irv.Aatk, bytes) == false)
2610 OJPH_ERROR(0x000500F2, "Error reding ATK-Aatk parameter");
2611 }
2612 }
2613 if (bytes != 0)
2614 OJPH_ERROR(0x000500F3, "The length of an ATK marker segment "
2615 "(ATK-Latk) is not correct");
2616
2617 return true;
2618 }
2619
2622 {
2623 Satk = 0x4a00; // illegal because ATK = 0
2624 Katk = (float)1.230174104914001;
2625 Natk = 4;
2626 // next is (A-4) in T.801 second line
2627 Latk = (ui16)(5 + Natk + sizeof(float) * (1 + Natk));
2628 d[0].irv.Aatk = (float)0.443506852043971;
2629 d[1].irv.Aatk = (float)0.882911075530934;
2630 d[2].irv.Aatk = (float)-0.052980118572961;
2631 d[3].irv.Aatk = (float)-1.586134342059924;
2632 }
2633
2636 {
2637 Satk = 0x5801; // illegal because ATK = 1
2638 Natk = 2;
2639 // next is (A-4) in T.801 fourth line
2640 Latk = (ui16)(5 + 2 * Natk + sizeof(ui8) * (Natk + Natk));
2641 d[0].rev.Aatk = 1;
2642 d[0].rev.Batk = 2;
2643 d[0].rev.Eatk = 2;
2644 d[1].rev.Aatk = -1;
2645 d[1].rev.Batk = 1;
2646 d[1].rev.Eatk = 1;
2647 }
2648
2651 {
2652 assert(top_atk = NULL);
2653 param_atk *p = this;
2654 while (p->next != NULL)
2655 p = p->next;
2656 if (avail)
2657 {
2658 p->next = avail;
2659 avail = avail->next;
2660 }
2661 else
2662 p->next = new param_atk;
2663 p = p->next;
2664 p->init(this);
2665 return p;
2666 }
2667
2668 } // !local namespace
2669} // !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:156
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:177
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
bool write_qcc(outfile_base *file, ui32 num_comps)
float get_irrev_delta(const param_dfs *dfs, ui32 num_decompositions, ui32 comp_num, ui32 resolution, ui32 subband) const
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
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)
union ojph::local::param_qcd::@140013103227173134364232343330020031205064137337 SPqcd
ui32 get_bit_depth(ui32 comp_num) const
bool is_signed(ui32 comp_num) const
void set_image_offset(point offset)
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 set_tile_offset(point offset)
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)