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_arch.h"
42#include "ojph_base.h"
43#include "ojph_file.h"
44#include "ojph_params.h"
45
46#include "ojph_params_local.h"
47#include "ojph_message.h"
48
49namespace ojph {
50
52 //
53 //
54 //
55 //
56 //
58
61 {
62 state->set_image_extent(dims);
63 }
64
67 {
68 state->set_tile_size(s);
69 }
70
73 {
74 state->set_image_offset(offset);
75 }
76
79 {
80 state->set_tile_offset(offset);
81 }
82
85 {
86 state->set_num_components(num_comps);
87 }
88
90 void param_siz::set_component(ui32 comp_num, const point& downsampling,
91 ui32 bit_depth, bool is_signed)
92 {
93 state->set_comp_info(comp_num, downsampling, bit_depth, is_signed);
94 }
95
98 {
99 return point(state->Xsiz, state->Ysiz);
100 }
101
104 {
105 return point(state->XOsiz, state->YOsiz);
106 }
107
110 {
111 return size(state->XTsiz, state->YTsiz);
112 }
113
116 {
117 return point(state->XTOsiz, state->YTOsiz);
118 }
119
122 {
123 return state->Csiz;
124 }
125
128 {
129 return state->get_bit_depth(comp_num);
130 }
131
133 bool param_siz::is_signed(ui32 comp_num) const
134 {
135 return state->is_signed(comp_num);
136 }
137
140 {
141 return state->get_downsampling(comp_num);
142 }
143
146 {
147 return state->get_recon_width(comp_num);
148 }
149
152 {
153 return state->get_recon_height(comp_num);
154 }
155
157 //
158 //
159 //
160 //
161 //
163
165 void param_cod::set_num_decomposition(ui32 num_decompositions)
166 {
167 if (num_decompositions > 32)
168 OJPH_ERROR(0x00050001,
169 "maximum number of decompositions cannot exceed 32");
170 state->SPcod.num_decomp = (ui8)num_decompositions;
171 }
172
175 {
176 ui32 log_width = 31 - count_leading_zeros(width);
177 ui32 log_height = 31 - count_leading_zeros(height);
178 if (width == 0 || width != (1u << log_width)
179 || height == 0 || height != (1u << log_height)
180 || log_width < 2 || log_height < 2
181 || log_width + log_height > 12)
182 OJPH_ERROR(0x00050011, "incorrect code block dimensions");
183 state->SPcod.block_width = (ui8)(log_width - 2);
184 state->SPcod.block_height = (ui8)(log_height - 2);
185 }
186
188 void param_cod::set_precinct_size(int num_levels, size* precinct_size)
189 {
190 if (num_levels == 0 || precinct_size == NULL)
191 state->Scod &= 0xFE;
192 else
193 {
194 state->Scod |= 1;
195 for (int i = 0; i <= state->SPcod.num_decomp; ++i)
196 {
197 size t = precinct_size[i < num_levels ? i : num_levels - 1];
198
199 ui32 PPx = 31 - count_leading_zeros(t.w);
200 ui32 PPy = 31 - count_leading_zeros(t.h);
201 if (t.w == 0 || t.h == 0)
202 OJPH_ERROR(0x00050021, "precinct width or height cannot be 0");
203 if (t.w != (1u<<PPx) || t.h != (1u<<PPy))
204 OJPH_ERROR(0x00050022,
205 "precinct width and height should be a power of 2");
206 if (PPx > 15 || PPy > 15)
207 OJPH_ERROR(0x00050023, "precinct size is too large");
208 if (i > 0 && (PPx == 0 || PPy == 0))
209 OJPH_ERROR(0x00050024, "precinct size is too small");
210 state->SPcod.precinct_size[i] = (ui8)(PPx | (PPy << 4));
211 }
212 }
213 }
214
216 void param_cod::set_progression_order(const char *name)
217 {
218 int prog_order = 0;
219 size_t len = strlen(name);
220 if (len == 4)
221 {
222 if (strncmp(name, OJPH_PO_STRING_LRCP, 4) == 0)
223 prog_order = OJPH_PO_LRCP;
224 else if (strncmp(name, OJPH_PO_STRING_RLCP, 4) == 0)
225 prog_order = OJPH_PO_RLCP;
226 else if (strncmp(name, OJPH_PO_STRING_RPCL, 4) == 0)
227 prog_order = OJPH_PO_RPCL;
228 else if (strncmp(name, OJPH_PO_STRING_PCRL, 4) == 0)
229 prog_order = OJPH_PO_PCRL;
230 else if (strncmp(name, OJPH_PO_STRING_CPRL, 4) == 0)
231 prog_order = OJPH_PO_CPRL;
232 else
233 OJPH_ERROR(0x00050031, "unknown progression order");
234 }
235 else
236 OJPH_ERROR(0x00050032, "improper progression order");
237
238
239 state->SGCod.prog_order = (ui8)prog_order;
240 }
241
243 void param_cod::set_color_transform(bool color_transform)
244 {
245 state->employ_color_transform(color_transform ? 1 : 0);
246 }
247
249 void param_cod::set_reversible(bool reversible)
250 {
251 state->set_reversible(reversible);
252 }
253
255 void param_cod::set_num_decomposition(ui32 comp_idx, ui32 num_decompositions)
256 {
257 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
258 ojph::param_cod(cdp).set_num_decomposition(num_decompositions);
259 }
260
262 void param_cod::set_block_dims(ui32 comp_idx, ui32 width, ui32 height)
263 {
264 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
265 ojph::param_cod(cdp).set_block_dims(width, height);
266 }
267
269 void param_cod::set_precinct_size(ui32 comp_idx, int num_levels,
270 size* precinct_size)
271 {
272 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
273 ojph::param_cod(cdp).set_precinct_size(num_levels, precinct_size);
274 }
275
277 void param_cod::set_reversible(ui32 comp_idx, bool reversible)
278 {
279 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
280 ojph::param_cod(cdp).set_reversible(reversible);
281 }
282
285 {
286 return state->get_num_decompositions();
287 }
288
291 {
292 return state->get_block_dims();
293 }
294
297 {
298 return state->get_log_block_dims();
299 }
300
303 {
304 return state->is_reversible();
305 }
306
309 {
310 return state->get_precinct_size(level_num);
311 }
312
315 {
316 return state->get_log_precinct_size(level_num);
317 }
318
321 {
322 return state->SGCod.prog_order;
323 }
324
327 {
328 if (state->SGCod.prog_order == OJPH_PO_LRCP)
329 return OJPH_PO_STRING_LRCP;
330 else if (state->SGCod.prog_order == OJPH_PO_RLCP)
331 return OJPH_PO_STRING_RLCP;
332 else if (state->SGCod.prog_order == OJPH_PO_RPCL)
333 return OJPH_PO_STRING_RPCL;
334 else if (state->SGCod.prog_order == OJPH_PO_PCRL)
335 return OJPH_PO_STRING_PCRL;
336 else if (state->SGCod.prog_order == OJPH_PO_CPRL)
337 return OJPH_PO_STRING_CPRL;
338 else
339 assert(0);
340 return "";
341 }
342
345 {
346 return state->SGCod.num_layers;
347 }
348
351 {
352 return state->is_employing_color_transform();
353 }
354
357 {
358 return state->packets_may_use_sop();
359 }
360
363 {
364 return state->packets_use_eph();
365 }
366
369 {
370 return state->get_block_vertical_causality();
371 }
372
375 { return state->get_coc(comp_idx)->get_num_decompositions(); }
376
379 { return state->get_coc(comp_idx)->get_block_dims(); }
380
383 { return state->get_coc(comp_idx)->get_log_block_dims(); }
384
386 bool param_cod::is_reversible(ui32 comp_idx) const
387 { return state->get_coc(comp_idx)->is_reversible(); }
388
390 size param_cod::get_precinct_size(ui32 comp_idx, ui32 level_num) const
391 { return state->get_coc(comp_idx)->get_precinct_size(level_num); }
392
395 { return state->get_coc(comp_idx)->get_log_precinct_size(level_num); }
396
399 { return state->get_coc(comp_idx)->get_block_vertical_causality(); }
400
401
403 //
404 //
405 //
406 //
407 //
409
412 {
413 state->set_delta(delta);
414 }
415
418 state->set_qfactor(qfactor);
419 }
420
422 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta)
423 {
424 state->set_delta(comp_idx, delta);
425 }
426
428 void param_qcd::set_qfactor(ui32 comp_idx, comp_type ctype, ui8 qfactor) {
429 state->set_qfactor(comp_idx, ctype, qfactor);
430 }
431
433 //
434 //
435 //
436 //
437 //
439
442 {
443 state->set_nonlinear_transform(comp_num, nl_type);
444 }
445
447 bool param_nlt::get_nonlinear_transform(ui32 comp_num, ui8& bit_depth,
448 bool& is_signed, ui8& nl_type) const
449 {
450 return state->get_nonlinear_transform(comp_num, bit_depth, is_signed,
451 nl_type);
452 }
453
455 //
456 //
457 //
458 //
459 //
461
463 void comment_exchange::set_string(const char* str)
464 {
465 size_t t = strlen(str);
466 if (len > 65531)
467 OJPH_ERROR(0x000500C1,
468 "COM marker string length cannot be larger than 65531");
469 this->data = str;
470 this->len = (ui16)t;
471 this->Rcom = 1;
472 }
473
476 {
477 if (len > 65531)
478 OJPH_ERROR(0x000500C2,
479 "COM marker string length cannot be larger than 65531");
480 this->data = data;
481 this->len = len;
482 this->Rcom = 0;
483 }
484
486 //
487 //
488 // LOCAL
489 //
490 //
492
493 namespace local {
494
496 //static
498 {
499 public:
500 static float get_gain_l(ui32 num_decomp, bool reversible)
501 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
502 static float get_gain_h(ui32 num_decomp, bool reversible)
503 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
504
505 private:
506 static const float gain_9x7_l[34];
507 static const float gain_9x7_h[34];
508 static const float gain_5x3_l[34];
509 static const float gain_5x3_h[34];
510 };
511
513 const float sqrt_energy_gains::gain_9x7_l[34] = { 1.0000e+00f,
514 1.4021e+00f, 2.0304e+00f, 2.9012e+00f, 4.1153e+00f, 5.8245e+00f,
515 8.2388e+00f, 1.1652e+01f, 1.6479e+01f, 2.3304e+01f, 3.2957e+01f,
516 4.6609e+01f, 6.5915e+01f, 9.3217e+01f, 1.3183e+02f, 1.8643e+02f,
517 2.6366e+02f, 3.7287e+02f, 5.2732e+02f, 7.4574e+02f, 1.0546e+03f,
518 1.4915e+03f, 2.1093e+03f, 2.9830e+03f, 4.2185e+03f, 5.9659e+03f,
519 8.4371e+03f, 1.1932e+04f, 1.6874e+04f, 2.3864e+04f, 3.3748e+04f,
520 4.7727e+04f, 6.7496e+04f, 9.5454e+04f };
521 const float sqrt_energy_gains::gain_9x7_h[34] = { 1.4425e+00f,
522 1.9669e+00f, 2.8839e+00f, 4.1475e+00f, 5.8946e+00f, 8.3472e+00f,
523 1.1809e+01f, 1.6701e+01f, 2.3620e+01f, 3.3403e+01f, 4.7240e+01f,
524 6.6807e+01f, 9.4479e+01f, 1.3361e+02f, 1.8896e+02f, 2.6723e+02f,
525 3.7792e+02f, 5.3446e+02f, 7.5583e+02f, 1.0689e+03f, 1.5117e+03f,
526 2.1378e+03f, 3.0233e+03f, 4.2756e+03f, 6.0467e+03f, 8.5513e+03f,
527 1.2093e+04f, 1.7103e+04f, 2.4187e+04f, 3.4205e+04f, 4.8373e+04f,
528 6.8410e+04f, 9.6747e+04f, 1.3682e+05f };
529 const float sqrt_energy_gains::gain_5x3_l[34] = { 1.0000e+00f,
530 1.2247e+00f, 1.3229e+00f, 1.5411e+00f, 1.7139e+00f, 1.9605e+00f,
531 2.2044e+00f, 2.5047e+00f, 2.8277e+00f, 3.2049e+00f, 3.6238e+00f,
532 4.1033e+00f, 4.6423e+00f, 5.2548e+00f, 5.9462e+00f, 6.7299e+00f,
533 7.6159e+00f, 8.6193e+00f, 9.7544e+00f, 1.1039e+01f, 1.2493e+01f,
534 1.4139e+01f, 1.6001e+01f, 1.8108e+01f, 2.0493e+01f, 2.3192e+01f,
535 2.6246e+01f, 2.9702e+01f, 3.3614e+01f, 3.8041e+01f, 4.3051e+01f,
536 4.8721e+01f, 5.5138e+01f, 6.2399e+01f };
537 const float sqrt_energy_gains::gain_5x3_h[34] = { 1.0458e+00f,
538 1.3975e+00f, 1.4389e+00f, 1.7287e+00f, 1.8880e+00f, 2.1841e+00f,
539 2.4392e+00f, 2.7830e+00f, 3.1341e+00f, 3.5576e+00f, 4.0188e+00f,
540 4.5532e+00f, 5.1494e+00f, 5.8301e+00f, 6.5963e+00f, 7.4663e+00f,
541 8.4489e+00f, 9.5623e+00f, 1.0821e+01f, 1.2247e+01f, 1.3860e+01f,
542 1.5685e+01f, 1.7751e+01f, 2.0089e+01f, 2.2735e+01f, 2.5729e+01f,
543 2.9117e+01f, 3.2952e+01f, 3.7292e+01f, 4.2203e+01f, 4.7761e+01f,
544 5.4051e+01f, 6.1170e+01f, 6.9226e+01f };
545
547 //static
549 {
550 public:
551 static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
552 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
553 static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
554 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
555
556 private:
557 static const float gain_9x7_l[34];
558 static const float gain_9x7_h[34];
559 static const float gain_5x3_l[34];
560 static const float gain_5x3_h[34];
561 };
562
564 const float bibo_gains::gain_9x7_l[34] = { 1.0000e+00f, 1.3803e+00f,
565 1.3328e+00f, 1.3067e+00f, 1.3028e+00f, 1.3001e+00f, 1.2993e+00f,
566 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
567 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
568 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
569 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
570 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
571 1.2992e+00f, 1.2992e+00f };
572 const float bibo_gains::gain_9x7_h[34] = { 1.2976e+00f, 1.3126e+00f,
573 1.2757e+00f, 1.2352e+00f, 1.2312e+00f, 1.2285e+00f, 1.2280e+00f,
574 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
575 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
576 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
577 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
578 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
579 1.2278e+00f, 1.2278e+00f };
580 const float bibo_gains::gain_5x3_l[34] = { 1.0000e+00f, 1.5000e+00f,
581 1.6250e+00f, 1.6875e+00f, 1.6963e+00f, 1.7067e+00f, 1.7116e+00f,
582 1.7129e+00f, 1.7141e+00f, 1.7145e+00f, 1.7151e+00f, 1.7152e+00f,
583 1.7155e+00f, 1.7155e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
584 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
585 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
586 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
587 1.7156e+00f, 1.7156e+00f };
588 const float bibo_gains::gain_5x3_h[34] = { 2.0000e+00f, 2.5000e+00f,
589 2.7500e+00f, 2.8047e+00f, 2.8198e+00f, 2.8410e+00f, 2.8558e+00f,
590 2.8601e+00f, 2.8628e+00f, 2.8656e+00f, 2.8662e+00f, 2.8667e+00f,
591 2.8669e+00f, 2.8670e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
592 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
593 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
594 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
595 2.8671e+00f, 2.8671e+00f };
596
598 //static
600 {
601 public:
611
612 public:
613 static colour_format get_format(const point& component_subsampling)
614 {
615 if (component_subsampling.x == 2 && component_subsampling.y == 2)
617 else if (component_subsampling.x == 2 && component_subsampling.y == 1)
619 else if (component_subsampling.x == 1 && component_subsampling.y == 1)
621 else
623 }
624
625 public:
626 static const float* get_weights(ui32 format, ui32 comp_type)
627 {
628 if (comp_type == comp_type::OJPH_COMP_Y)
629 return y;
630 else if (comp_type == comp_type::OJPH_COMP_CB)
631 {
632 if (format == VW_COLOUR_FORMAT_420) return cb420;
633 else if (format == VW_COLOUR_FORMAT_422) return cb422;
634 else if (format == VW_COLOUR_FORMAT_444) return cb444;
635 else {
636 assert(0);
637 return y;
638 }
639 }
640 else if (comp_type == comp_type::OJPH_COMP_CR)
641 {
642 if (format == VW_COLOUR_FORMAT_420) return cr420;
643 else if (format == VW_COLOUR_FORMAT_422) return cr422;
644 else if (format == VW_COLOUR_FORMAT_444) return cr444;
645 else {
646 assert(0);
647 return y;
648 }
649 }
650 else {
651 assert(0);
652 return y;
653 }
654 }
655
656 static const float* get_no_weights()
657 { return no_weights; }
658
659 static float get_weight(const float *v, ui32 decomposition_level,
660 ui32 subband_idx)
661
662 {
663 if (subband_idx == 0)
664 return v[18];
665 else {
666 assert(subband_idx >= 1 && subband_idx <= 3);
667 assert(decomposition_level > 0);
668 decomposition_level = ojph_min(decomposition_level, 6);
669 ui32 index = (decomposition_level - 1) * 3 + (3 - subband_idx);
670 return v[index];
671 }
672 }
673
675 static float get_gain(ui32 comp_type)
676 {
677 if (comp_type == comp_type::OJPH_COMP_Y)
678 return 1.0f;
679 else if (comp_type == comp_type::OJPH_COMP_CB)
680 return 1.8051f / 1.7321f;
681 else if (comp_type == comp_type::OJPH_COMP_CR)
682 return 1.5734f / 1.7321f;
683 else {
684 assert(0);
685 return 0.0f;
686 }
687 }
688
690 static float get_delta_ref(ui32 qfactor, ui32 bit_depth,
691 float& power)
692 {
693 // returns delta_ref & power to be used with visual weights
694 constexpr uint8_t t0 = 65, t1 = 97;
695 constexpr float alpha_t0 = 0.04f, alpha_t1 = 0.10f;
696 constexpr float m_t0 = 2.0f * (1.0f - t0 / 100.0f);
697 constexpr float m_t1 = 2.0f * (1.0f - t1 / 100.0f);
698
699 float m_q;
700 if (qfactor < 50)
701 m_q = 50.0f / (float)qfactor;
702 else
703 m_q = 2.0f * (1.0f - (float)qfactor / 100.0f);
704
705 float alpha_q;
706 if (qfactor <= t0)
707 {
708 power = 1.0f;
709 alpha_q = alpha_t0;
710 }
711 else if (qfactor < t1)
712 {
713 power = std::log(m_q) - std::log(m_t1);
714 power /= std::log(m_t0) - std::log(m_t1);
715 alpha_q = alpha_t1 * std::pow(alpha_t0 / alpha_t1, power);
716 }
717 else
718 {
719 power = 0.0f;
720 alpha_q = alpha_t1;
721 }
722 const float eps = std::sqrt(0.5f) * std::ldexp(1.0f, -(int)bit_depth);
723 return alpha_q * m_q + eps;
724 }
725
726 private:
727 static const float cb420[19];
728 static const float cr420[19];
729 static const float cb422[19];
730 static const float cr422[19];
731 static const float cb444[19];
732 static const float cr444[19];
733 static const float y[19];
734 static const float no_weights[19];
735 };
736
738 const float visual_weights::cb420[19] = {
739 0.2724f, 0.5128f, 0.5128f, // level 1
740 0.6692f, 0.9382f, 0.9382f, // level 2
741 1.0888f, 1.3046f, 1.3046f, // level 3
742 1.4156f, 1.5594f, 1.5594f, // level 4
743 2.0f, 2.0f, 2.0f, // level 5
744 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
745 const float visual_weights::cr420[19] = {
746 0.5196f, 0.8260f, 0.8260f, // level 1
747 1.0080f, 1.2928f, 1.2928f, // level 2
748 1.4440f, 1.6508f, 1.6508f, // level 3
749 1.7538f, 1.8848f, 1.8848f, // level 4
750 2.0f, 2.0f, 2.0f, // level 5
751 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
752 const float visual_weights::cb422[19] = {
753 0.1220f, 0.1220f, 0.3626f, // level 1
754 0.3626f, 0.3626f, 0.6634f, // level 2
755 0.6634f, 0.6634f, 0.9225f, // level 3
756 0.9225f, 0.9225f, 1.1027f, // level 4
757 1.1027f, 1.1027f, 1.4142f, // level 5
758 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
759 const float visual_weights::cr422[19] = {
760 0.2595f, 0.2595f, 0.5841f, // level 1
761 0.5841f, 0.5841f, 0.9141f, // level 2
762 0.9141f, 0.9141f, 1.1673f, // level 3
763 1.1673f, 1.1673f, 1.3328f, // level 4
764 1.3328f, 1.3328f, 1.4142f, // level 5
765 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
766 const float visual_weights::cb444[19] = {
767 0.0263f, 0.0863f, 0.0863f, // level 1
768 0.1362f, 0.2564f, 0.2564f, // level 2
769 0.3346f, 0.4691f, 0.4691f, // level 3
770 0.5444f, 0.6523f, 0.6523f, // level 4
771 0.7078f, 0.7797f, 0.7797f, // level 5
772 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
773 const float visual_weights::cr444[19] = {
774 0.0773f, 0.1835f, 0.1835f, // level 1
775 0.2598f, 0.4130f, 0.4130f, // level 2
776 0.5040f, 0.6464f, 0.6464f, // level 3
777 0.7220f, 0.8254f, 0.8254f, // level 4
778 0.8769f, 0.9424f, 0.9424f, // level 5
779 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
780 const float visual_weights::y[19] = {
781 0.0901f, 0.2758f, 0.2758f, // level 1
782 0.7018f, 0.8378f, 0.8378f, // level 2
783 1.0f, 1.0f, 1.0f, // level 3
784 1.0f, 1.0f, 1.0f, // level 4
785 1.0f, 1.0f, 1.0f, // level 5
786 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
787 const float visual_weights::no_weights[19] = {
788 1.0f, 1.0f, 1.0f, // level 1
789 1.0f, 1.0f, 1.0f, // level 2
790 1.0f, 1.0f, 1.0f, // level 3
791 1.0f, 1.0f, 1.0f, // level 4
792 1.0f, 1.0f, 1.0f, // level 5
793 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
794
795
797 //
798 //
799 //
800 //
801 //
803
806 {
807 //marker size excluding header
808 Lsiz = (ui16)(38 + 3 * Csiz);
809
810 ui8 buf1;
811 ui16 buf2;
812 ui32 buf4;
813 bool result = true;
814
815 buf2 = JP2K_MARKER::SIZ;
816 buf2 = swap_bytes_if_le(buf2);
817 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
818 buf2 = swap_bytes_if_le(Lsiz);
819 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
820 buf2 = swap_bytes_if_le(Rsiz);
821 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
822 buf4 = swap_bytes_if_le(Xsiz);
823 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
824 buf4 = swap_bytes_if_le(Ysiz);
825 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
826 buf4 = swap_bytes_if_le(XOsiz);
827 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
828 buf4 = swap_bytes_if_le(YOsiz);
829 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
830 buf4 = swap_bytes_if_le(XTsiz);
831 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
832 buf4 = swap_bytes_if_le(YTsiz);
833 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
834 buf4 = swap_bytes_if_le(XTOsiz);
835 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
836 buf4 = swap_bytes_if_le(YTOsiz);
837 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
838 buf2 = swap_bytes_if_le(Csiz);
839 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
840 for (int c = 0; c < Csiz; ++c)
841 {
842 buf1 = cptr[c].SSiz;
843 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
844 buf1 = cptr[c].XRsiz;
845 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
846 buf1 = cptr[c].YRsiz;
847 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
848 }
849
850 return result;
851 }
852
855 {
856 if (file->read(&Lsiz, 2) != 2)
857 OJPH_ERROR(0x00050041, "error reading SIZ marker");
859 int num_comps = (Lsiz - 38) / 3;
860 if (Lsiz != 38 + 3 * num_comps)
861 OJPH_ERROR(0x00050042, "error in SIZ marker length");
862 if (file->read(&Rsiz, 2) != 2)
863 OJPH_ERROR(0x00050043, "error reading SIZ marker");
865 if ((Rsiz & 0x4000) == 0)
866 OJPH_ERROR(0x00050044,
867 "Rsiz bit 14 is not set (this is not a JPH file)");
868 if ((Rsiz & 0x8000) != 0 && (Rsiz & 0xD5F) != 0)
869 OJPH_WARN(0x00050001, "Rsiz in SIZ has unimplemented fields");
870 if (file->read(&Xsiz, 4) != 4)
871 OJPH_ERROR(0x00050045, "error reading SIZ marker");
873 if (file->read(&Ysiz, 4) != 4)
874 OJPH_ERROR(0x00050046, "error reading SIZ marker");
876 ui32 t_XOsiz, t_YOsiz;
877 if (file->read(&t_XOsiz, 4) != 4)
878 OJPH_ERROR(0x00050047, "error reading SIZ marker");
879 if (file->read(&t_YOsiz, 4) != 4)
880 OJPH_ERROR(0x00050048, "error reading SIZ marker");
882 swap_bytes_if_le(t_XOsiz),
883 swap_bytes_if_le(t_YOsiz)));
884 ui32 t_XTsiz, t_YTsiz;
885 if (file->read(&t_XTsiz, 4) != 4)
886 OJPH_ERROR(0x00050049, "error reading SIZ marker");
887 if (file->read(&t_YTsiz, 4) != 4)
888 OJPH_ERROR(0x0005004A, "error reading SIZ marker");
890 swap_bytes_if_le(t_XTsiz),
891 swap_bytes_if_le(t_YTsiz)));
892 ui32 t_XTOsiz, t_YTOsiz;
893 if (file->read(&t_XTOsiz, 4) != 4)
894 OJPH_ERROR(0x0005004B, "error reading SIZ marker");
895 if (file->read(&t_YTOsiz, 4) != 4)
896 OJPH_ERROR(0x0005004C, "error reading SIZ marker");
898 swap_bytes_if_le(t_XTOsiz),
899 swap_bytes_if_le(t_YTOsiz)));
900 if (file->read(&Csiz, 2) != 2)
901 OJPH_ERROR(0x0005004D, "error reading SIZ marker");
903 if (Csiz != num_comps)
904 OJPH_ERROR(0x0005004E, "Csiz does not match the SIZ marker size");
905 if (Csiz == 0)
906 OJPH_ERROR(0x0005004F, "Wrong Csiz value of 0 in SIZ marker segment");
908 for (int c = 0; c < Csiz; ++c)
909 {
910 if (file->read(&cptr[c].SSiz, 1) != 1)
911 OJPH_ERROR(0x00050051, "error reading SIZ marker");
912 if (file->read(&cptr[c].XRsiz, 1) != 1)
913 OJPH_ERROR(0x00050052, "error reading SIZ marker");
914 if (file->read(&cptr[c].YRsiz, 1) != 1)
915 OJPH_ERROR(0x00050053, "error reading SIZ marker");
916 if ((cptr[c].SSiz & 0x7F) > 37)
917 OJPH_ERROR(0x00050054, "Wrong SIZ-SSiz value of %d", cptr[c].SSiz);
918 if (cptr[c].XRsiz == 0)
919 OJPH_ERROR(0x00050055, "Wrong SIZ-XRsiz value of %d", cptr[c].XRsiz);
920 if (cptr[c].YRsiz == 0)
921 OJPH_ERROR(0x00050056, "Wrong SIZ-YRsiz value of %d", cptr[c].YRsiz);
922 }
923
924 ws_kern_support_needed = (Rsiz & 0x20) != 0;
925 dfs_support_needed = (Rsiz & 0x80) != 0;
926
928 }
929
932 {
933 assert(comp_num < get_num_components());
934
935 point factor(1u << skipped_resolutions, 1u << skipped_resolutions);
936 const param_cod* cdp = cod->get_coc(comp_num);
937 if (dfs && cdp && cdp->is_dfs_defined()) {
938 const param_dfs* d = dfs->get_dfs(cdp->get_dfs_index());
940 }
941 factor.x *= (ui32)cptr[comp_num].XRsiz;
942 factor.y *= (ui32)cptr[comp_num].YRsiz;
943 return factor;
944 }
945
948 {
949 assert(comp_num < get_num_components());
950
951 point factor = get_recon_downsampling(comp_num);
952 point r;
953 r.x = ojph_div_ceil(Xsiz, factor.x) - ojph_div_ceil(XOsiz, factor.x);
954 r.y = ojph_div_ceil(Ysiz, factor.y) - ojph_div_ceil(YOsiz, factor.y);
955 return r;
956 }
957
958
960 //
961 //
962 //
963 //
964 //
966
969 {
970 //marker size excluding header
971 Lcap = 8;
972
973 ui16 buf2;
974 ui32 buf4;
975 bool result = true;
976
977 buf2 = JP2K_MARKER::CAP;
978 buf2 = swap_bytes_if_le(buf2);
979 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
980 buf2 = swap_bytes_if_le(Lcap);
981 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
982 buf4 = swap_bytes_if_le(Pcap);
983 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
984
985 buf2 = swap_bytes_if_le(Ccap[0]);
986 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
987
988 return result;
989 }
990
993 {
994 if (file->read(&Lcap, 2) != 2)
995 OJPH_ERROR(0x00050061, "error reading CAP marker");
997 if (file->read(&Pcap, 4) != 4)
998 OJPH_ERROR(0x00050062, "error reading CAP marker");
1000 ui32 count = population_count(Pcap);
1001 if (Pcap & 0xFFFDFFFF)
1002 OJPH_ERROR(0x00050063,
1003 "error Pcap in CAP has options that are not supported");
1004 if ((Pcap & 0x00020000) == 0)
1005 OJPH_ERROR(0x00050064,
1006 "error Pcap should have its 15th MSB set, Pcap^15. "
1007 " This is not a JPH file");
1008 for (ui32 i = 0; i < count; ++i)
1009 if (file->read(Ccap+i, 2) != 2)
1010 OJPH_ERROR(0x00050065, "error reading CAP marker");
1011 if (Lcap != 6 + 2 * count)
1012 OJPH_ERROR(0x00050066, "error in CAP marker length");
1013 }
1014
1016 //
1017 //
1018 //
1019 //
1020 //
1022
1025 {
1026 if (SPcod.wavelet_trans <= 1)
1028 else {
1029 assert(atk != NULL);
1030 return atk->is_reversible();
1031 }
1032 }
1033
1036 {
1037 assert(type == COD_MAIN);
1038
1039 //marker size excluding header
1040 Lcod = 12;
1041 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1042
1043 ui8 buf1;
1044 ui16 buf2;
1045 bool result = true;
1046
1047 buf2 = JP2K_MARKER::COD;
1048 buf2 = swap_bytes_if_le(buf2);
1049 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1050 buf2 = swap_bytes_if_le(Lcod);
1051 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1052 buf1 = Scod;
1053 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1054 buf1 = SGCod.prog_order;
1055 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1056 buf2 = swap_bytes_if_le(SGCod.num_layers);
1057 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1058 buf1 = SGCod.mc_trans;
1059 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1060 buf1 = SPcod.num_decomp;
1061 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1062 buf1 = SPcod.block_width;
1063 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1064 buf1 = SPcod.block_height;
1065 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1066 buf1 = SPcod.block_style;
1067 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1068 buf1 = SPcod.wavelet_trans;
1069 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1070 if (Scod & 1)
1071 for (int i = 0; i <= SPcod.num_decomp; ++i)
1072 {
1073 buf1 = SPcod.precinct_size[i];
1074 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1075 }
1076
1077 return result;
1078 }
1079
1082 {
1083 assert(type == COD_MAIN);
1084 bool result = true;
1085 param_cod *p = this->next;
1086 while (p)
1087 {
1088 if (p->comp_idx < num_comps)
1089 result &= p->internal_write_coc(file, num_comps);
1090 p = p->next;
1091 }
1092 return result;
1093 }
1094
1097 {
1098 assert(type == COC_MAIN);
1099
1100 //marker size excluding header
1101 Lcod = num_comps < 257 ? 9 : 10;
1102 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1103
1104 ui8 buf1;
1105 ui16 buf2;
1106 bool result = true;
1107
1108 buf2 = JP2K_MARKER::COC;
1109 buf2 = swap_bytes_if_le(buf2);
1110 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1111 buf2 = swap_bytes_if_le(Lcod);
1112 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1113 if (num_comps < 257)
1114 {
1115 buf1 = (ui8)comp_idx;
1116 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1117 }
1118 else
1119 {
1120 buf2 = swap_bytes_if_le(comp_idx);
1121 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1122 }
1123 buf1 = Scod;
1124 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1125 buf1 = SPcod.num_decomp;
1126 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1127 buf1 = SPcod.block_width;
1128 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1129 buf1 = SPcod.block_height;
1130 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1131 buf1 = SPcod.block_style;
1132 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1133 buf1 = SPcod.wavelet_trans;
1134 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1135 if (Scod & 1)
1136 for (int i = 0; i <= SPcod.num_decomp; ++i)
1137 {
1138 buf1 = SPcod.precinct_size[i];
1139 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1140 }
1141
1142 return result;
1143 }
1144
1147 {
1148 assert(type == COD_MAIN);
1149
1150 if (file->read(&Lcod, 2) != 2)
1151 OJPH_ERROR(0x00050071, "error reading COD segment");
1153 if (file->read(&Scod, 1) != 1)
1154 OJPH_ERROR(0x00050072, "error reading COD segment");
1155 if (file->read(&SGCod.prog_order, 1) != 1)
1156 OJPH_ERROR(0x00050073, "error reading COD segment");
1157 if (file->read(&SGCod.num_layers, 2) != 2)
1158 { OJPH_ERROR(0x00050074, "error reading COD segment"); }
1159 else
1160 SGCod.num_layers = swap_bytes_if_le(SGCod.num_layers);
1161 if (file->read(&SGCod.mc_trans, 1) != 1)
1162 OJPH_ERROR(0x00050075, "error reading COD segment");
1163 if (file->read(&SPcod.num_decomp, 1) != 1)
1164 OJPH_ERROR(0x00050076, "error reading COD segment");
1165 if (file->read(&SPcod.block_width, 1) != 1)
1166 OJPH_ERROR(0x00050077, "error reading COD segment");
1167 if (file->read(&SPcod.block_height, 1) != 1)
1168 OJPH_ERROR(0x00050078, "error reading COD segment");
1169 if (file->read(&SPcod.block_style, 1) != 1)
1170 OJPH_ERROR(0x00050079, "error reading COD segment");
1171 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1172 OJPH_ERROR(0x0005007A, "error reading COD segment");
1173
1174 if (get_num_decompositions() > 32
1175 || SPcod.block_width > 8
1176 || SPcod.block_height > 8
1177 || SPcod.block_width + SPcod.block_height > 8
1178 || (SPcod.block_style & 0x40) != 0x40
1179 || (SPcod.block_style & 0xB7) != 0x00)
1180 OJPH_ERROR(0x0005007D, "wrong settings in a COD-SPcod parameter");
1181 if ((SPcod.block_style & 0x40) != 0x40
1182 || (SPcod.block_style & 0xB7) != 0x00)
1183 OJPH_ERROR(0x0005007E, "unsupported settings in a COD-SPcod parameter");
1184
1185 ui8 num_decompositions = get_num_decompositions();
1186 if (Scod & 1) {
1187 for (int i = 0; i <= num_decompositions; ++i) {
1188 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1189 OJPH_ERROR(0x0005007B, "error reading COD segment");
1190 if (i)
1191 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1192 (SPcod.precinct_size[i] >> 4) == 0)
1193 OJPH_ERROR(0x0005007F,
1194 "Precinct width or height for resolutions other than the"
1195 " coarsest must be larger than 1; here, they are %d and %d,"
1196 " respectively.",
1197 1 << (SPcod.precinct_size[i] & 0x0F),
1198 1 << (SPcod.precinct_size[i] >> 4));
1199 }
1200 }
1201 if (Lcod != 12 + ((Scod & 1) ? 1 + SPcod.num_decomp : 0))
1202 OJPH_ERROR(0x0005007C, "error in COD segment length");
1203 }
1204
1206 void param_cod::read_coc(infile_base* file, ui32 num_comps,
1208 {
1209 assert(type == COC_MAIN);
1210 assert(top_cod != NULL);
1211
1212 this->SGCod = top_cod->SGCod;
1213 this->top_cod = top_cod;
1214 if (file->read(&Lcod, 2) != 2)
1215 OJPH_ERROR(0x00050121, "error reading COC segment");
1217 if (num_comps < 257) {
1218 ui8 t;
1219 if (file->read(&t, 1) != 1)
1220 OJPH_ERROR(0x00050122, "error reading COC segment");
1221 comp_idx = t;
1222 }
1223 else {
1224 if (file->read(&comp_idx, 2) != 2)
1225 OJPH_ERROR(0x00050123, "error reading COC segment");
1227 }
1228 if (file->read(&Scod, 1) != 1)
1229 OJPH_ERROR(0x00050124, "error reading COC segment");
1230 if (Scod & 0xF8)
1231 OJPH_WARN(0x00050011,
1232 "Unsupported options in Scoc field of the COC segment");
1233 if (file->read(&SPcod.num_decomp, 1) != 1)
1234 OJPH_ERROR(0x00050125, "error reading COC segment");
1235 if (file->read(&SPcod.block_width, 1) != 1)
1236 OJPH_ERROR(0x00050126, "error reading COC segment");
1237 if (file->read(&SPcod.block_height, 1) != 1)
1238 OJPH_ERROR(0x00050127, "error reading COC segment");
1239 if (file->read(&SPcod.block_style, 1) != 1)
1240 OJPH_ERROR(0x00050128, "error reading COC segment");
1241 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1242 OJPH_ERROR(0x00050129, "error reading COC segment");
1243
1244 if (get_num_decompositions() > 32
1245 || SPcod.block_width > 8
1246 || SPcod.block_height > 8
1247 || SPcod.block_width + SPcod.block_height > 8
1248 || (SPcod.block_style & 0x40) != 0x40
1249 || (SPcod.block_style & 0xB7) != 0x00)
1250 OJPH_ERROR(0x0005012C, "wrong settings in a COC-SPcoc parameter");
1251 if ((SPcod.block_style & 0x40) != 0x40
1252 || (SPcod.block_style & 0xB7) != 0x00)
1253 OJPH_ERROR(0x0005012D, "unsupported settings in a COC-SPcoc parameter");
1254
1255 ui8 num_decompositions = get_num_decompositions();
1256 if (Scod & 1) {
1257 for (int i = 0; i <= num_decompositions; ++i) {
1258 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1259 OJPH_ERROR(0x0005012A, "error reading COC segment");
1260 if (i)
1261 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1262 (SPcod.precinct_size[i] >> 4) == 0)
1263 OJPH_ERROR(0x0005012E,
1264 "Precinct width or height for resolutions other than the"
1265 " coarsest must be larger than 1; here, they are %d and %d,"
1266 " respectively.",
1267 1 << (SPcod.precinct_size[i] & 0x0F),
1268 1 << (SPcod.precinct_size[i] >> 4));
1269 }
1270 }
1271 ui32 t = 9;
1272 t += num_comps < 257 ? 0 : 1;
1273 t += (Scod & 1) ? 1 + num_decompositions : 0;
1274 if (Lcod != t)
1275 OJPH_ERROR(0x0005012B, "error in COC segment length");
1276 }
1277
1280 {
1281 assert(type == COD_MAIN);
1282 this->atk = atk->get_atk(SPcod.wavelet_trans);
1283 if (this->atk == NULL)
1284 OJPH_ERROR(0x00050131, "A COD segment employs the DWT kernel "
1285 "atk = %d, but a corresponding ATK segment cannot be found.",
1286 SPcod.wavelet_trans);
1287 param_cod *p = next;
1288 while (p)
1289 {
1290 p->atk = atk->get_atk(p->SPcod.wavelet_trans);
1291 if (p->atk == NULL)
1292 OJPH_ERROR(0x00050132, "A COC segment employs the DWT kernel "
1293 "atk = %d, but a corresponding ATK segment cannot be found",
1294 SPcod.wavelet_trans);
1295 p = p->next;
1296 }
1297 }
1298
1301 {
1302 assert(this->type == COD_MAIN || this->top_cod->type == COD_MAIN);
1303 const param_cod *p, *q;
1304 if (this->type == COD_MAIN)
1305 q = p = this;
1306 else
1307 q = p = this->top_cod;
1308 while (p && p->comp_idx != comp_idx)
1309 p = p->next;
1310 return p ? p : q;
1311 }
1312
1315 {
1316 // cast object to constant
1317 const param_cod* const_p = const_cast<const param_cod*>(this);
1318 // call using the constant object, then cast to non-const
1319 return const_cast<param_cod*>(const_p->get_coc(comp_idx));
1320 }
1321
1324 {
1325 assert(type == COD_MAIN);
1326 param_cod *p = this;
1327 while (p->next != NULL)
1328 p = p->next;
1329 if (avail)
1330 {
1331 p->next = avail;
1332 avail = avail->next;
1333 p->next->init(this, (ui16)comp_idx);
1334 }
1335 else
1336 p->next = new param_cod(this, (ui16)comp_idx);
1337 return p->next;
1338 }
1339
1342 {
1343 assert(type == COD_MAIN);
1345 if (p == this)
1347 return p;
1348 }
1349
1351 //
1352 //
1353 //
1354 //
1355 //
1357
1359 void param_qcd::check_validity(const param_siz& siz, const param_cod& cod)
1360 {
1361 assert(this->type == QCD_MAIN);
1362
1363 ui32 num_comps = siz.get_num_components();
1365
1366 // initialize QCD based on the first component that is (a) associated with
1367 // COD and (b) does not have a COC, or the first component othewise.
1368 ui32 qcd_comp = 0;
1369 for (ui32 c = 0; c < num_comps; ++c)
1370 {
1371 if (cod.get_coc(c) == &cod && get_qcc(c) == this)
1372 {
1373 qcd_comp = c;
1374 break;
1375 }
1376 }
1377
1378 // check if only the top QCD has qfactor set, if so, check if any
1379 // of the first component has COC and qfactor set properly
1380 if (this->qfactor != QFACTOR_UNSET)
1381 {
1382 if (num_comps < 3) // one or two components
1383 {
1384 for (ui32 i = 0; i < num_comps; ++i)
1385 {
1386 param_qcd* q = get_qcc(i);
1387 if (q == this)
1388 {
1389 q = add_qcc_object(i);
1390 set_qfactor(i, comp_type::OJPH_COMP_Y, this->qfactor);
1391 }
1392 }
1393 }
1394 else if (num_comps >= 3)
1395 {
1396 for (ui32 i = 0; i < num_comps; ++i) {
1397 param_qcd* q = get_qcc(i);
1398 if (q == this)
1399 {
1400 q = add_qcc_object(i);
1401 ui8 ci = (ui8)(i < 3u ? i : 0u);
1403 set_qfactor(i, t, this->qfactor);
1404 }
1405 }
1406 }
1407 }
1408
1409 this->make_quant_steps(qcd_comp, cod, siz);
1410
1411 // initialize every QCC, creating one for every component that (a) cannot
1412 // use QCD and (b) does not already have a QCC
1413 // NOTE: Qfactor always creates a QCC and QCD cannot be reused
1414 for (ui32 c = 0; c < num_comps; ++c)
1415 {
1416 param_qcd *qcc = this->get_qcc(c);
1417 const param_cod *coc = cod.get_coc(c);
1418
1419 // check if a QCC exists for the component
1420 if (qcc == this)
1421 {
1422 // if none exists, do not create one if QCD can be reused
1423 if (!this->is_qcc_needed(c, *coc, siz))
1424 continue;
1425
1426 qcc = this->add_qcc_object(c);
1427 qcc->set_delta(this->base_delta);
1428 }
1429
1430 qcc->make_quant_steps(c, *coc, siz);
1431 }
1432 }
1433
1435 void param_qcd::make_quant_steps(ui32 comp_num, const param_cod &cod,
1436 const param_siz &siz)
1437 {
1438 if (this->is_init)
1439 OJPH_ERROR(0x00040001, "Quantization step sizes already initialized.");
1440
1441 this->is_init = true;
1442
1443 this->num_decomps = cod.get_num_decompositions();
1444 this->bit_depth = siz.get_bit_depth(comp_num);
1445 this->is_signed = siz.is_signed(comp_num);
1447 this->wavelet_kern = cod.get_wavelet_kern();
1448 this->sampling = siz.get_downsampling(comp_num);
1449 this->num_subbands = 1 + 3 * this->num_decomps;
1450
1452 this->set_rev_quant(this->num_decomps, this->bit_depth,
1453 comp_num < 3 ? this->is_color_trans : false);
1454 else if (this->wavelet_kern == param_cod::DWT_IRV97)
1455 {
1456 if (this->base_delta == -1.0f)
1457 {
1458 ui32 t = ojph_min(16, bit_depth);
1459 this->base_delta = 1.0f / (float)(1 << t);
1460 }
1461 else if (qfactor != QFACTOR_UNSET)
1462 OJPH_WARN(0x00040002, "qstep for component %d is ignored, because "
1463 "qfactor is set.", comp_num);
1464
1465 this->set_irrev_quant(this->num_decomps);
1466 }
1467 }
1468
1470 bool param_qcd::is_qcc_needed(ui32 comp_num, const param_cod &cod,
1471 const param_siz &siz)
1472 {
1473 if (! this->is_init)
1474 OJPH_ERROR(0x00040001, "Quantization step sizes not initialized.");
1475
1476 return this->num_decomps != cod.get_num_decompositions() ||
1477 this->bit_depth != siz.get_bit_depth(comp_num) ||
1478 this->is_signed != siz.is_signed(comp_num) ||
1480 this->wavelet_kern != cod.get_wavelet_kern();
1481 }
1482
1485 assert(this->type == QCD_MAIN);
1486
1488 OJPH_ERROR(0x00050181, "Qfactor must be between 1 and 100, "
1489 "but was set to %i.", qfactor);
1490
1491 this->qfactor = qfactor;
1492 }
1493
1496 bool is_employing_color_transform)
1497 {
1498 ui32 B = bit_depth;
1499 B += is_employing_color_transform ? 1 : 0; //1 bit for RCT
1500 int s = 0;
1501 double bibo_l = bibo_gains::get_bibo_gain_l(num_decomps, true);
1502 ui32 X = (ui32) ceil(log(bibo_l * bibo_l) / M_LN2);
1503 SPqcd.u8[s++] = (ui8)(B + X);
1504 ui32 max_B_plus_X = (ui32)(B + X);
1505 for (ui32 d = num_decomps; d > 0; --d)
1506 {
1507 double bibo_l = bibo_gains::get_bibo_gain_l(d, true);
1508 double bibo_h = bibo_gains::get_bibo_gain_h(d - 1, true);
1509 X = (ui32) ceil(log(bibo_h * bibo_l) / M_LN2);
1510 SPqcd.u8[s++] = (ui8)(B + X);
1511 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1512 SPqcd.u8[s++] = (ui8)(B + X);
1513 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1514 X = (ui32) ceil(log(bibo_h * bibo_h) / M_LN2);
1515 SPqcd.u8[s++] = (ui8)(B + X);
1516 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1517 }
1518
1519 if (max_B_plus_X > 38)
1520 OJPH_ERROR(0x00050151, "The specified combination of bit_depth, "
1521 "colour transform, and type of wavelet transform requires more than "
1522 "38 bits; it requires %d bits. This is beyond what is allowed in "
1523 "the JPEG2000 image coding format.", max_B_plus_X);
1524
1525 int guard_bits = ojph_max(1, (si32)max_B_plus_X - 31);
1526 Sqcd = (ui8)(guard_bits << 5);
1527 s = 0;
1528 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1529 s++;
1530 for (ui32 d = num_decomps; d > 0; --d)
1531 {
1532 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1533 s++;
1534 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1535 s++;
1536 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1537 s++;
1538 }
1539 }
1540
1543 {
1544 int guard_bits = 1;
1545 Sqcd = (ui8)((guard_bits<<5)|0x2); //one guard bit, scalar quantization
1546
1547 float g_c = 1.0f;
1548 float delta_ref = base_delta;
1549 float power = 1.0f;
1550 const float* weights = visual_weights::get_no_weights();
1551
1552 if (qfactor != QFACTOR_UNSET)
1553 {
1557 OJPH_ERROR(0x00050161, "Qfactor can only be used on components "
1558 "with 4:4:4, 4:2:2 or 4:2:0 sampling");
1559 if (this->ctype == comp_type::OJPH_COMP_Y &&
1560 this->sampling.x != 1 && this->sampling.y != 1)
1561 OJPH_ERROR(0x00050162, "Qfactor can only be used for a Y or "
1562 "luminance component when it is not downsampled.");
1563
1564 // calculate component gain
1565 g_c = visual_weights::get_gain(this->ctype);
1566
1567 // calculate delta_ref & power
1568 delta_ref = visual_weights::get_delta_ref(qfactor, bit_depth, power);
1569
1570 // find visual weight
1571 weights = visual_weights::get_weights(format, this->ctype);
1572 }
1573
1574 // LL band
1575 ui32 b = 0;
1576 float w_b;
1577 float gain_l = sqrt_energy_gains::get_gain_l(num_decomps, false);
1578 w_b = visual_weights::get_weight(weights, num_decomps, b);
1579 w_b = std::pow(w_b, power);
1580 encode_SPqcd(b++, delta_ref / (gain_l * gain_l * g_c * w_b));
1581
1582 // LL, HL, LH, HH, HL, LH, HH...
1583 for (ui32 d = num_decomps; d > 0; --d)
1584 {
1585 // compute square root of the enery gain factor W_g
1586 float gain_l = sqrt_energy_gains::get_gain_l(d, false);
1587 float gain_h = sqrt_energy_gains::get_gain_h(d - 1, false);
1588
1589 w_b = visual_weights::get_weight(weights, d, 1);
1590 w_b = std::pow(w_b, power);
1591 encode_SPqcd(b++, delta_ref / (gain_h * gain_l * g_c * w_b));
1592 w_b = visual_weights::get_weight(weights, d, 2);
1593 w_b = std::pow(w_b, power);
1594 encode_SPqcd(b++, delta_ref / (gain_l * gain_h * g_c * w_b));
1595 w_b = visual_weights::get_weight(weights, d, 3);
1596 w_b = std::pow(w_b, power);
1597 encode_SPqcd(b++, delta_ref / (gain_h * gain_h * g_c * w_b));
1598 }
1599 }
1600
1602 void param_qcd::encode_SPqcd(ui32 subband_index, float delta)
1603 {
1604 int exp = 0, mantissa;
1605 while (delta < 1.0f)
1606 { exp++; delta *= 2.0f; }
1607 mantissa = (int)round(delta * (float)(1<<11)) - (1<<11);
1608 // with rounding, there is a risk that the mantissa becomes
1609 // equal to 1<<11
1610 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1611 SPqcd.u16[subband_index] = (ui16)((exp << 11) | mantissa);
1612 }
1613
1616 {
1617 ui32 B = 0;
1618
1619 const param_qcd *p = this;
1620 while (p)
1621 {
1622 //this can be written better, but it is only executed once
1623 // this assumes a bi-directional wavelet (conventional DWT)
1624 ui32 num_decomps = (p->num_subbands - 1) / 3;
1625
1626 int irrev = p->Sqcd & 0x1F;
1627 if (irrev == 0) //reversible
1628 for (ui32 i = 0; i < p->num_subbands; ++i) {
1629 ui32 t = p->decode_SPqcd(p->SPqcd.u8[i]);
1630 t += p->get_num_guard_bits() - 1u;
1631 B = ojph_max(B, t);
1632 }
1633 else if (irrev == 2) //scalar expounded
1634 for (ui32 i = 0; i < p->num_subbands; ++i)
1635 {
1636 ui32 nb = num_decomps - (i ? (i - 1) / 3 : 0); //decompsition level
1637 ui32 t = (p->SPqcd.u16[i] >> 11) + p->get_num_guard_bits() - nb;
1638 B = ojph_max(B, t);
1639 }
1640 else
1641 assert(0);
1642
1643 p = p->next;
1644 }
1645
1646 return B;
1647 }
1648
1651 ui32 num_decompositions, ui32 comp_num,
1652 ui32 resolution, ui32 subband) const
1653 {
1654 float arr[] = { 1.0f, 2.0f, 2.0f, 4.0f };
1655 if ((Sqcd & 0x1F) != 2)
1656 OJPH_ERROR(0x00050101, "There is something wrong in the configuration "
1657 "of the codestream; for component %d, the codestream defines an "
1658 "irreversible transform, for which the codestream provides a "
1659 "reversible (no quantization) step sizes in Sqcd/Sqcc.", comp_num);
1660
1661 ui32 idx;
1662 if (dfs != NULL && dfs->exists())
1663 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1664 else
1665 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1666 if (idx >= num_subbands) {
1667 OJPH_INFO(0x00050102, "Trying to access quantization step size for "
1668 "subband %d when the QCD/QCC marker segment specifies "
1669 "quantization step sizes for %d subbands only. To continue "
1670 "decoding, we are using the step size for subband %d, which can "
1671 "produce incorrect results",
1672 idx + 1, num_subbands, num_subbands - 1);
1673 idx = num_subbands - 1;
1674 }
1675 int eps = SPqcd.u16[idx] >> 11;
1676 float mantissa;
1677 mantissa = (float)((SPqcd.u16[idx] & 0x7FF) | 0x800) * arr[subband];
1678 mantissa /= (float)(1 << 11);
1679 mantissa /= (float)(1u << eps);
1680 return mantissa;
1681 }
1682
1685 {
1686 ui32 comp_idx = cod->get_comp_idx();
1687 ui32 precision = 0;
1688 const param_cod *main =
1690 if (main->is_employing_color_transform() && comp_idx < 3)
1691 {
1692 for (ui32 i = 0; i < 3; ++i) {
1693 const param_qcd* p = this->get_qcc(i);
1694 precision = ojph_max(precision, p->get_largest_Kmax());
1695 }
1696 }
1697 else {
1698 precision = get_largest_Kmax();
1699 }
1700 // ``precision'' now holds the largest K_max, which excludes the sign
1701 // bit.
1702 // + 1 for the sign bit
1703 // + 1 because my block decoder/encoder does not supports up to 30
1704 // bits (not 31), so we bump it by one more bit.
1705 return precision + 1 + 1;
1706 }
1707
1710 {
1711 return (Sqcd >> 5);
1712 }
1713
1715 ui32 param_qcd::get_Kmax(const param_dfs* dfs, ui32 num_decompositions,
1716 ui32 resolution, ui32 subband) const
1717 {
1718 ui32 idx;
1719 if (dfs != NULL && dfs->exists())
1720 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1721 else
1722 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1723 if (idx >= num_subbands) {
1724 OJPH_INFO(0x00050111, "Trying to access quantization step size for "
1725 "subband %d when the QCD/QCC marker segment specifies "
1726 "quantization step sizes for %d subbands only. To continue "
1727 "decoding, we are using the step size for subband %d, which can "
1728 "produce incorrect results",
1729 idx + 1, num_subbands, num_subbands - 1);
1730 idx = num_subbands - 1;
1731 }
1732
1733 int irrev = Sqcd & 0x1F;
1734 ui32 num_bits = 0;
1735 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1736 {
1737 num_bits = decode_SPqcd(SPqcd.u8[idx]);
1738 num_bits = num_bits == 0 ? 0 : num_bits - 1;
1739 }
1740 else if (irrev == 1)
1741 assert(0);
1742 else if (irrev == 2) //scalar expounded
1743 num_bits = (SPqcd.u16[idx] >> 11) - 1;
1744 else
1745 assert(0);
1746
1747 return num_bits + get_num_guard_bits();
1748 }
1749
1752 {
1753 int irrev = Sqcd & 0x1F;
1754 ui32 num_bits = 0;
1755 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1756 {
1757 for (ui32 i = 0; i < num_subbands; ++i) {
1758 ui32 t = decode_SPqcd(SPqcd.u8[i]);
1759 num_bits = ojph_max(num_bits, t == 0 ? 0 : t - 1);
1760 }
1761 }
1762 else if (irrev == 1)
1763 assert(0);
1764 else if (irrev == 2) //scalar expounded
1765 {
1766 for (ui32 i = 0; i < num_subbands; ++i) {
1767 ui32 t = (SPqcd.u16[i] >> 11) - 1;
1768 num_bits = ojph_max(num_bits, t);
1769 }
1770 }
1771 else
1772 assert(0);
1773
1774 return num_bits + get_num_guard_bits();
1775 }
1776
1779 {
1780 int irrev = Sqcd & 0x1F;
1781
1782 //marker size excluding header
1783 Lqcd = 3;
1784 if (irrev == 0)
1785 Lqcd = (ui16)(Lqcd + num_subbands);
1786 else if (irrev == 2)
1787 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1788 else
1789 assert(0);
1790
1791 ui8 buf1;
1792 ui16 buf2;
1793 bool result = true;
1794
1795 buf2 = JP2K_MARKER::QCD;
1796 buf2 = swap_bytes_if_le(buf2);
1797 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1798 buf2 = swap_bytes_if_le(Lqcd);
1799 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1800 buf1 = Sqcd;
1801 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1802
1803 if (irrev == 0)
1804 for (ui32 i = 0; i < num_subbands; ++i)
1805 {
1806 buf1 = SPqcd.u8[i];
1807 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1808 }
1809 else if (irrev == 2)
1810 for (ui32 i = 0; i < num_subbands; ++i)
1811 {
1812 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1813 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1814 }
1815 else
1816 assert(0);
1817
1818 return result;
1819 }
1820
1823 {
1824 assert(type == QCD_MAIN);
1825 bool result = true;
1826 param_qcd *p = this->next;
1827 while (p)
1828 {
1829 if (p->enabled)
1830 result &= p->internal_write_qcc(file, num_comps);
1831 p = p->next;
1832 }
1833 return result;
1834 }
1835
1838 {
1839 int irrev = Sqcd & 0x1F;
1840
1841 //marker size excluding header
1842 Lqcd = (ui16)(4 + (num_comps < 257 ? 0 : 1));
1843 if (irrev == 0)
1844 Lqcd = (ui16)(Lqcd + num_subbands);
1845 else if (irrev == 2)
1846 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1847 else
1848 assert(0);
1849
1850 ui8 buf1;
1851 ui16 buf2;
1852 bool result = true;
1853
1854 buf2 = JP2K_MARKER::QCC;
1855 buf2 = swap_bytes_if_le(buf2);
1856 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1857 buf2 = swap_bytes_if_le(Lqcd);
1858 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1859 if (num_comps < 257)
1860 {
1861 buf1 = (ui8)comp_idx;
1862 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1863 }
1864 else
1865 {
1866 buf2 = swap_bytes_if_le(comp_idx);
1867 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1868 }
1869 buf1 = Sqcd;
1870 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1871 if (irrev == 0)
1872 for (ui32 i = 0; i < num_subbands; ++i)
1873 {
1874 buf1 = SPqcd.u8[i];
1875 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1876 }
1877 else if (irrev == 2)
1878 for (ui32 i = 0; i < num_subbands; ++i)
1879 {
1880 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1881 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1882 }
1883 else
1884 assert(0);
1885
1886 return result;
1887 }
1888
1891 {
1892 assert(type == QCD_MAIN && comp_idx == OJPH_QCD_DEFAULT);
1893 param_qcd *p = this->next;
1894 while (p)
1895 {
1896 assert(p->type == QCC_MAIN);
1897 p->enabled = p->comp_idx < num_comps;
1898 p = p->next;
1899 }
1900 }
1901
1904 {
1905 if (file->read(&Lqcd, 2) != 2)
1906 OJPH_ERROR(0x00050081, "error reading QCD marker");
1908 if (file->read(&Sqcd, 1) != 1)
1909 OJPH_ERROR(0x00050082, "error reading QCD marker");
1910 if ((Sqcd & 0x1F) == 0)
1911 {
1912 num_subbands = (Lqcd - 3);
1913 if (num_subbands == 0)
1914 OJPH_ERROR(0x0005008A, "QCD marker segment that specifies no "
1915 "quantization informtion");
1916 if (num_subbands > 97 || Lqcd != 3 + num_subbands)
1917 OJPH_ERROR(0x00050083, "wrong Lqcd value of %d in QCD marker", Lqcd);
1918 for (ui32 i = 0; i < num_subbands; ++i)
1919 if (file->read(&SPqcd.u8[i], 1) != 1)
1920 OJPH_ERROR(0x00050084, "error reading QCD marker");
1921 }
1922 else if ((Sqcd & 0x1F) == 1)
1923 {
1924 num_subbands = 0;
1925 OJPH_ERROR(0x00050089,
1926 "Scalar derived quantization is not supported yet in QCD marker");
1927 if (Lqcd != 5)
1928 OJPH_ERROR(0x00050085, "wrong Lqcd value in QCD marker");
1929 }
1930 else if ((Sqcd & 0x1F) == 2)
1931 {
1932 num_subbands = (Lqcd - 3) / 2;
1933 if (num_subbands == 0)
1934 OJPH_ERROR(0x0005008B, "QCD marker segment that specifies no "
1935 "quantization informtion");
1936 if (num_subbands > 97 || Lqcd != 3 + 2 * num_subbands)
1937 OJPH_ERROR(0x00050086, "wrong Lqcd value of %d in QCD marker", Lqcd);
1938 for (ui32 i = 0; i < num_subbands; ++i)
1939 {
1940 if (file->read(&SPqcd.u16[i], 2) != 2)
1941 OJPH_ERROR(0x00050087, "error reading QCD marker");
1942 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
1943 }
1944 }
1945 else
1946 OJPH_ERROR(0x00050088, "wrong Sqcd value in QCD marker");
1947 }
1948
1950 void param_qcd::read_qcc(infile_base *file, ui32 num_comps)
1951 {
1952 if (file->read(&Lqcd, 2) != 2)
1953 OJPH_ERROR(0x000500A1, "error reading QCC marker");
1955 if (num_comps < 257)
1956 {
1957 ui8 v;
1958 if (file->read(&v, 1) != 1)
1959 OJPH_ERROR(0x000500A2, "error reading QCC marker");
1960 comp_idx = v;
1961 }
1962 else
1963 {
1964 if (file->read(&comp_idx, 2) != 2)
1965 OJPH_ERROR(0x000500A3, "error reading QCC marker");
1967 }
1968 if (file->read(&Sqcd, 1) != 1)
1969 OJPH_ERROR(0x000500A4, "error reading QCC marker");
1970 ui32 offset = num_comps < 257 ? 4 : 5;
1971 if ((Sqcd & 0x1F) == 0)
1972 {
1973 num_subbands = (Lqcd - offset);
1974 if (num_subbands == 0)
1975 OJPH_ERROR(0x000500AC, "QCC marker segment that specifies no "
1976 "quantization informtion");
1977 if (num_subbands > 97 || Lqcd != offset + num_subbands)
1978 OJPH_ERROR(0x000500A5, "wrong Lqcd value of %d in QCC marker", Lqcd);
1979 for (ui32 i = 0; i < num_subbands; ++i)
1980 if (file->read(&SPqcd.u8[i], 1) != 1)
1981 OJPH_ERROR(0x000500A6, "error reading QCC marker");
1982 }
1983 else if ((Sqcd & 0x1F) == 1)
1984 {
1985 num_subbands = 0;
1986 OJPH_ERROR(0x000500AB,
1987 "Scalar derived quantization is not supported yet in QCC marker");
1988 if (Lqcd != offset)
1989 OJPH_ERROR(0x000500A7, "wrong Lqcc value in QCC marker");
1990 }
1991 else if ((Sqcd & 0x1F) == 2)
1992 {
1993 num_subbands = (Lqcd - offset) / 2;
1994 if (num_subbands == 0)
1995 OJPH_ERROR(0x000500AD, "QCC marker segment that specifies no "
1996 "quantization informtion");
1997 if (num_subbands > 97 || Lqcd != offset + 2 * num_subbands)
1998 OJPH_ERROR(0x000500A8, "wrong Lqcc value of %d in QCC marker", Lqcd);
1999 for (ui32 i = 0; i < num_subbands; ++i)
2000 {
2001 if (file->read(&SPqcd.u16[i], 2) != 2)
2002 OJPH_ERROR(0x000500A9, "error reading QCC marker");
2003 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
2004 }
2005 }
2006 else
2007 OJPH_ERROR(0x000500AA, "wrong Sqcc value in QCC marker");
2008 }
2009
2012 {
2013 assert(type == QCD_MAIN);
2015 if (p == NULL)
2017 p->set_delta(delta);
2018 }
2019
2022 {
2023 assert(this->type == QCD_MAIN);
2024
2026 OJPH_ERROR(0x00050191, "Qfactor must be between 1 and 100, "
2027 "but was set to %i.", qfactor);
2028
2030 if (p == this)
2032
2033 p->qfactor = qfactor;
2034 p->ctype = ctype;
2035 }
2036
2039 {
2040 // cast object to constant
2041 const param_qcd* const_p = const_cast<const param_qcd*>(this);
2042 // call using the constant object, then cast to non-const
2043 return const_cast<param_qcd*>(const_p->get_qcc(comp_idx));
2044 }
2045
2048 {
2049 assert(this->type == QCD_MAIN || this->top_qcd->type == QCD_MAIN);
2050 const param_qcd *p, *q;
2051 if (this->type == QCD_MAIN)
2052 q = p = this;
2053 else
2054 q = p = this->top_qcd;
2055 while (p && p->comp_idx != comp_idx)
2056 p = p->next;
2057 return p ? p : q;
2058 }
2059
2062 {
2063 assert(type == QCD_MAIN);
2064 param_qcd *p = this;
2065 while (p->next != NULL)
2066 p = p->next;
2067 if (avail)
2068 {
2069 p->next = avail;
2070 avail = avail->next;
2071 p->next->init(this, (ui16)comp_idx);
2072 }
2073 else
2074 p->next = new param_qcd(this, (ui16)comp_idx);
2075 return p->next;
2076 }
2077
2079 //
2080 //
2081 //
2082 //
2083 //
2085
2088 {
2089 if (is_any_enabled() == false)
2090 return;
2091
2092 if (this->enabled && this->Tnlt == nonlinearity::OJPH_NLT_NO_NLT)
2093 this->enabled = false;
2094
2095 if (this->enabled &&
2096 this->Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
2097 {
2098 bool all_same = true;
2099 ui32 num_comps = siz.get_num_components();
2100
2101 // first stage; find out if all components captured by the default
2102 // entry (ALL_COMPS) has the same bit_depth/signedness,
2103 // while doing this, set the BDnlt for components not captured by the
2104 // default entry (ALL_COMPS)
2105 ui32 bit_depth = 0; // unknown yet
2106 bool is_signed = false; // unknown yet
2107 for (ui32 c = 0; c < num_comps; ++c)
2108 { // captured by ALL_COMPS
2109 param_nlt* p = get_nlt_object(c);
2110 if (p == NULL || !p->enabled)
2111 {
2112 if (bit_depth != 0)
2113 {
2114 // we have seen an undefined component previously
2115 all_same = all_same && (bit_depth == siz.get_bit_depth(c));
2116 all_same = all_same && (is_signed == siz.is_signed(c));
2117 }
2118 else
2119 {
2120 // this is the first component which has not type 3 nlt definition
2121 bit_depth = siz.get_bit_depth(c);
2122 is_signed = siz.is_signed(c);
2123 }
2124 }
2125 else
2126 { // can be type 0 or type 3
2127 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2128 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2129 }
2130 }
2131
2132 if (all_same && bit_depth != 0)
2133 { // all the same, and some components are captured by ALL_COMPS
2134 this->BDnlt = (ui8)(bit_depth - 1);
2135 this->BDnlt = (ui8)(this->BDnlt | (is_signed ? 0x80 : 0));
2136 }
2137 else if (!all_same)
2138 { // have different settings or no component is captured by ALL_COMPS
2139 this->enabled = false;
2140 for (ui32 c = 0; c < num_comps; ++c)
2141 {
2142 param_nlt* p = get_nlt_object(c);
2143 if (p == NULL || !p->enabled)
2144 { // captured by ALL_COMPS
2145 if (p == NULL)
2146 p = add_object(c);
2147 p->enabled = true;
2148 p->Tnlt = nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
2149 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2150 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2151 }
2152 }
2153 }
2154 }
2155 else {
2156 // fill NLT segment markers with correct information
2157 ui32 num_comps = siz.get_num_components();
2158 for (ui32 c = 0; c < num_comps; ++c)
2159 { // captured by ALL_COMPS
2160 param_nlt* p = get_nlt_object(c);
2161 if (p != NULL && p->enabled)
2162 { // can be type 0 or type 3
2163 p->BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2164 p->BDnlt = (ui8)(p->BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2165 }
2166 }
2167 }
2168
2170
2171 if (is_any_enabled() == true)
2173 }
2174
2177 {
2178 if (nl_type != ojph::param_nlt::OJPH_NLT_NO_NLT &&
2180 OJPH_ERROR(0x00050171, "Nonliearities other than type 0 "
2181 "(No Nonlinearity) or type 3 (Binary Binary Complement to Sign "
2182 "Magnitude Conversion) are not supported yet");
2183 param_nlt* p = get_nlt_object(comp_num);
2184 if (p == NULL)
2185 p = add_object(comp_num);
2186 p->Tnlt = nl_type;
2187 p->enabled = true;
2188 }
2189
2191 bool
2193 bool& is_signed, ui8& nl_type) const
2194 {
2195 assert(Cnlt == special_comp_num::ALL_COMPS);
2196 const param_nlt* p = get_nlt_object(comp_num);
2197 p = (p && p->enabled) ? p : this;
2198 if (p->enabled)
2199 {
2200 bit_depth = (ui8)((p->BDnlt & 0x7F) + 1);
2201 bit_depth = bit_depth <= 38 ? bit_depth : 38;
2202 is_signed = (p->BDnlt & 0x80) == 0x80;
2203 nl_type = (nonlinearity)p->Tnlt;
2204 return true;
2205 }
2206 return false;
2207 }
2208
2211 {
2212 if (is_any_enabled() == false)
2213 return true;
2214
2215 ui16 buf2;
2216 bool result = true;
2217 const param_nlt* p = this;
2218 while (p)
2219 {
2220 if (p->enabled)
2221 {
2222 buf2 = JP2K_MARKER::NLT;
2223 buf2 = swap_bytes_if_le(buf2);
2224 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2225 buf2 = swap_bytes_if_le(p->Lnlt);
2226 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2227 buf2 = swap_bytes_if_le(p->Cnlt);
2228 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2229 result &= file->write(&p->BDnlt, 1) == 1;
2230 result &= file->write(&p->Tnlt, 1) == 1;
2231 }
2232 p = p->next;
2233 }
2234 return result;
2235 }
2236
2239 {
2240 ui16 buf2_len;
2241 ui16 buf2_comp;
2242 ui8 buf1_BDnlt;
2243 ui8 buf1_Tnlt;
2244
2245 if (file->read(&buf2_len, sizeof(ui16)) != sizeof(ui16))
2246 OJPH_ERROR(0x00050141, "error reading NLT marker segment");
2247 if (file->read(&buf2_comp, sizeof(ui16)) != sizeof(ui16))
2248 OJPH_ERROR(0x00050142, "error reading NLT marker segment");
2249 if (file->read(&buf1_BDnlt, sizeof(ui8)) != sizeof(ui8))
2250 OJPH_ERROR(0x00050143, "error reading NLT marker segment");
2251 if (file->read(&buf1_Tnlt, sizeof(ui8)) != sizeof(ui8))
2252 OJPH_ERROR(0x00050144, "error reading NLT marker segment");
2253
2254 ui16 length = swap_bytes_if_le(buf2_len);
2255 if (length != 6 || (buf1_Tnlt != 3 && buf1_Tnlt != 0))
2256 OJPH_ERROR(0x00050145, "Unsupported NLT type %d\n", buf1_Tnlt);
2257
2258 ui16 comp = swap_bytes_if_le(buf2_comp);
2259 param_nlt* p = get_nlt_object(comp);
2260 if (p == NULL)
2261 p = add_object(comp);
2262 p->enabled = true;
2263 p->Cnlt = comp;
2264 p->BDnlt = buf1_BDnlt;
2265 p->Tnlt = buf1_Tnlt;
2266 }
2267
2270 {
2271 // cast object to constant
2272 const param_nlt* const_p = const_cast<const param_nlt*>(this);
2273 // call using the constant object, then cast to non-const
2274 return const_cast<param_nlt*>(const_p->get_nlt_object(comp_num));
2275 }
2276
2279 {
2280 const param_nlt* p = this;
2281 while (p && p->Cnlt != comp_num)
2282 p = p->next;
2283 return p;
2284 }
2285
2288 {
2289 assert(comp_num != special_comp_num::ALL_COMPS);
2290 assert(Cnlt == special_comp_num::ALL_COMPS);
2291 param_nlt* p = this;
2292 while (p->next != NULL) {
2293 assert(p->Cnlt != comp_num);
2294 p = p->next;
2295 }
2296 if (avail)
2297 {
2298 p->next = avail;
2299 avail = avail->next;
2300 p->next->init();
2301 }
2302 else
2303 p->next = new param_nlt;
2304 p = p->next;
2305 p->Cnlt = (ui16)comp_num;
2306 return p;
2307 }
2308
2311 {
2312 // check if any field is enabled
2313 const param_nlt* p = this;
2314 while (p && p->enabled == false)
2315 p = p->next;
2316 return (p != NULL);
2317 }
2318
2321 {
2322 param_nlt* p = this->next;
2323 while (p) {
2324 if (p->enabled == true && p->Cnlt >= num_comps) {
2325 p->enabled = false;
2326 OJPH_INFO(0x00050161, "The NLT marker segment for the "
2327 "non-existing component %d has been removed.", p->Cnlt);
2328 }
2329 p = p->next;
2330 }
2331 }
2332
2333
2335 //
2336 //
2337 //
2338 //
2339 //
2341
2343 bool param_sot::write(outfile_base *file, ui32 payload_len)
2344 {
2345 ui16 buf2;
2346 ui32 buf4;
2347 bool result = true;
2348
2349 this->Psot = payload_len + 14; //inc. SOT marker, field & SOD
2350
2351 buf2 = JP2K_MARKER::SOT;
2352 buf2 = swap_bytes_if_le(buf2);
2353 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2354 buf2 = swap_bytes_if_le(Lsot);
2355 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2356 buf2 = swap_bytes_if_le(Isot);
2357 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2358 buf4 = swap_bytes_if_le(Psot);
2359 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2360 result &= file->write(&TPsot, 1) == 1;
2361 result &= file->write(&TNsot, 1) == 1;
2362
2363 return result;
2364 }
2365
2367 bool param_sot::write(outfile_base *file, ui32 payload_len,
2368 ui8 TPsot, ui8 TNsot)
2369 {
2370 ui32 buf4;
2371 ui16 buf2;
2372 bool result = true;
2373
2374 buf2 = JP2K_MARKER::SOT;
2375 buf2 = swap_bytes_if_le(buf2);
2376 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2377 buf2 = swap_bytes_if_le(Lsot);
2378 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2379 buf2 = swap_bytes_if_le(Isot);
2380 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2381 buf4 = swap_bytes_if_le(payload_len + 14);
2382 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2383 result &= file->write(&TPsot, 1) == 1;
2384 result &= file->write(&TNsot, 1) == 1;
2385
2386 return result;
2387 }
2388
2390 bool param_sot::read(infile_base *file, bool resilient)
2391 {
2392 if (resilient)
2393 {
2394 if (file->read(&Lsot, 2) != 2)
2395 {
2396 OJPH_INFO(0x00050091, "error reading SOT marker");
2397 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2398 return false;
2399 }
2401 if (Lsot != 10)
2402 {
2403 OJPH_INFO(0x00050092, "error in SOT length");
2404 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2405 return false;
2406 }
2407 if (file->read(&Isot, 2) != 2)
2408 {
2409 OJPH_INFO(0x00050093, "error reading tile index");
2410 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2411 return false;
2412 }
2414 if (Isot == 0xFFFF)
2415 {
2416 OJPH_INFO(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2417 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2418 return false;
2419 }
2420 if (file->read(&Psot, 4) != 4)
2421 {
2422 OJPH_INFO(0x00050095, "error reading SOT marker");
2423 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2424 return false;
2425 }
2427 if (file->read(&TPsot, 1) != 1)
2428 {
2429 OJPH_INFO(0x00050096, "error reading SOT marker");
2430 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2431 return false;
2432 }
2433 if (file->read(&TNsot, 1) != 1)
2434 {
2435 OJPH_INFO(0x00050097, "error reading SOT marker");
2436 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2437 return false;
2438 }
2439 }
2440 else
2441 {
2442 if (file->read(&Lsot, 2) != 2)
2443 OJPH_ERROR(0x00050091, "error reading SOT marker");
2445 if (Lsot != 10)
2446 OJPH_ERROR(0x00050092, "error in SOT length");
2447 if (file->read(&Isot, 2) != 2)
2448 OJPH_ERROR(0x00050093, "error reading SOT tile index");
2450 if (Isot == 0xFFFF)
2451 OJPH_ERROR(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2452 if (file->read(&Psot, 4) != 4)
2453 OJPH_ERROR(0x00050095, "error reading SOT marker");
2455 if (file->read(&TPsot, 1) != 1)
2456 OJPH_ERROR(0x00050096, "error reading SOT marker");
2457 if (file->read(&TNsot, 1) != 1)
2458 OJPH_ERROR(0x00050097, "error reading SOT marker");
2459 }
2460 return true;
2461 }
2462
2464 //
2465 //
2466 //
2467 //
2468 //
2470
2473 {
2474 if (4 + 6 * num_pairs > 65535)
2475 OJPH_ERROR(0x000500B1, "Trying to allocate more than 65535 bytes for "
2476 "a TLM marker; this can be resolved by having more than "
2477 "one TLM marker, but the code does not support this. "
2478 "In any case, this limit means that we have 10922 "
2479 "tileparts or more, which is a huge number.");
2480 this->num_pairs = num_pairs;
2481 pairs = store;
2482 Ltlm = (ui16)(4 + 6 * num_pairs);
2483 Ztlm = 0;
2484 Stlm = 0x60;
2485 }
2486
2489 {
2490 assert(next_pair_index < num_pairs);
2491 pairs[next_pair_index].Ttlm = Ttlm;
2492 pairs[next_pair_index].Ptlm = Ptlm + 14;
2494 }
2495
2498 {
2499 assert(next_pair_index == num_pairs);
2500 ui16 buf2;
2501 ui32 buf4;
2502 bool result = true;
2503
2504 buf2 = JP2K_MARKER::TLM;
2505 buf2 = swap_bytes_if_le(buf2);
2506 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2507 buf2 = swap_bytes_if_le(Ltlm);
2508 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2509 result &= file->write(&Ztlm, 1) == 1;
2510 result &= file->write(&Stlm, 1) == 1;
2511 for (ui32 i = 0; i < num_pairs; ++i)
2512 {
2513 buf2 = swap_bytes_if_le(pairs[i].Ttlm);
2514 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2515 buf4 = swap_bytes_if_le(pairs[i].Ptlm);
2516 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2517 }
2518 return result;
2519 }
2520
2522 //
2523 //
2524 //
2525 //
2526 //
2528
2530 const param_dfs* param_dfs::get_dfs(int index) const
2531 {
2532 const param_dfs* p = this;
2533 while (p && p->Sdfs != index)
2534 p = p->next;
2535 return p;
2536 }
2537
2540 {
2541 decomp_level = ojph_min(decomp_level, Ids);
2542 ui32 d = decomp_level - 1; // decomp_level starts from 1
2543 ui32 idx = d >> 2; // complete bytes
2544 ui32 bits = d & 0x3; // bit within the bytes
2545 ui32 val = (Ddfs[idx] >> (6 - 2 * bits)) & 0x3;
2546 return (dfs_dwt_type)val;
2547 }
2548
2551 ui32 subband) const
2552 {
2553 assert((resolution == 0 && subband == 0) ||
2554 (resolution > 0 && subband > 0 && subband < 4));
2555
2556 ui32 ns[4] = { 0, 3, 1, 1 };
2557
2558 ui32 idx = 0;
2559 if (resolution > 0)
2560 {
2561 idx = 0;
2562 ui32 i = 1;
2563 for (; i < resolution; ++i)
2564 idx += ns[get_dwt_type(num_decompositions - i + 1)];
2565 dfs_dwt_type t = get_dwt_type(num_decompositions - i + 1);
2566 idx += subband;
2567 if (t == VERT_DWT && subband == 2)
2568 --idx;
2569 }
2570
2571 return idx;
2572 }
2573
2575 point param_dfs::get_res_downsamp(ui32 skipped_resolutions) const
2576 {
2577 point factor(1, 1);
2578 ui32 decomp_level = 1;
2579 while (skipped_resolutions > 0)
2580 {
2581 param_dfs::dfs_dwt_type type = get_dwt_type(decomp_level);
2582 if (type == BIDIR_DWT)
2583 { factor.x *= 2; factor.y *= 2; }
2584 else if (type == HORZ_DWT)
2585 factor.x *= 2;
2586 else if (type == VERT_DWT)
2587 factor.y *= 2;
2588
2589 ++decomp_level;
2590 --skipped_resolutions;
2591 }
2592 return factor;
2593 }
2594
2597 {
2598 if (Ldfs != 0) { // this param_dfs is used
2599 param_dfs* p = this;
2600 while (p->next != NULL)
2601 p = p->next;
2602 if (avail)
2603 {
2604 p->next = avail;
2605 avail = avail->next;
2606 p->next->init();
2607 }
2608 else
2609 p->next = new param_dfs;
2610 p = p->next;
2611 return p->read(file);
2612 }
2613
2614 if (file->read(&Ldfs, 2) != 2)
2615 OJPH_ERROR(0x000500D1, "error reading DFS-Ldfs parameter");
2617 if (file->read(&Sdfs, 2) != 2)
2618 OJPH_ERROR(0x000500D2, "error reading DFS-Sdfs parameter");
2620 if (Sdfs > 15)
2621 OJPH_ERROR(0x000500D3, "The DFS-Sdfs parameter is %d, which is "
2622 "larger than the permissible 15", Sdfs);
2623 ui8 t, l_Ids = 0;
2624 if (file->read(&l_Ids, 1) != 1)
2625 OJPH_ERROR(0x000500D4, "error reading DFS-Ids parameter");
2626 if (l_Ids == 0)
2627 OJPH_ERROR(0x000500D8,
2628 "The value of the Ids member in the DFS marker segment cannot be 0");
2629 constexpr int max_Ddfs = sizeof(Ddfs) * 4;
2630 if (l_Ids > max_Ddfs)
2631 OJPH_INFO(0x000500D5, "The DFS-Ids parameter is %d; while this is "
2632 "valid, the number is unnessarily large -- you do not need more "
2633 "than %d. Please contact me regarding this issue.",
2634 l_Ids, max_Ddfs);
2635 Ids = l_Ids < max_Ddfs ? l_Ids : max_Ddfs;
2636 for (int i = 0; i < Ids; i += 4)
2637 if (file->read(&Ddfs[i / 4], 1) != 1)
2638 OJPH_ERROR(0x000500D6, "error reading DFS-Ddfs parameters");
2639 for (int i = Ids; i < l_Ids; i += 4)
2640 if (file->read(&t, 1) != 1)
2641 OJPH_ERROR(0x000500D7, "error reading DFS-Ddfs parameters");
2642 return true;
2643 }
2644
2646 //
2647 //
2648 //
2649 //
2650 //
2652
2655 {
2656 assert(top_atk == NULL);
2657
2658 if (Latk == 0)
2659 {
2660 // This atk object is not used, initialize it to either 0 (irv97)
2661 // or 1 (rev53), and use it. If index is not 0 nor 1, then index
2662 // must have been read from file previously, otherwise it is an
2663 // error.
2664 if (index == 0) { this->init_irv97(); return this; }
2665 else if (index == 1) { this->init_rev53(); return this; }
2666 }
2667
2668 param_atk* p = this;
2669 while (p && p->get_index() != index)
2670 p = p->next;
2671
2672 if (p == NULL && (index == 0 || index == 1))
2673 {
2674 // The index was not found, add an atk object only if the index is
2675 // either 0 or 1
2676 p = add_object();
2677 if (index == 0)
2678 p->init_irv97();
2679 else if (index == 1)
2680 p->init_rev53();
2681 }
2682
2683 return p;
2684 }
2685
2687 bool param_atk::read_coefficient(infile_base *file, float &K, si32& bytes)
2688 {
2689 int coeff_type = get_coeff_type();
2690 if (coeff_type == 0) { // 8bit
2691 ui8 v;
2692 if (file->read(&v, 1) != 1) return false;
2693 bytes -= 1;
2694 K = v;
2695 }
2696 else if (coeff_type == 1) { // 16bit
2697 ui16 v;
2698 if (file->read(&v, 2) != 2) return false;
2699 bytes -= 2;
2700 K = swap_bytes_if_le(v);
2701 }
2702 else if (coeff_type == 2) { // float
2703 ui32 i;
2704 if (file->read(&i, sizeof(ui32)) != sizeof(ui32)) return false;
2705 bytes -= 4;
2706 i = swap_bytes_if_le(i);
2707 float f;
2708 memcpy(&f, &i, sizeof(float));
2709 K = f;
2710 }
2711 else if (coeff_type == 3) { // double
2712 ui64 i;
2713 if (file->read(&i, sizeof(ui64)) != sizeof(ui64)) return false;
2714 bytes -= 8;
2715 i = swap_bytes_if_le(i);
2716 double d;
2717 memcpy(&d, &i, sizeof(double));
2718 K = (float)d;
2719 }
2720 else if (coeff_type == 4) { // 128 bit float
2721 ui64 v, v1;
2722 if (file->read(&v, 8) != 8) return false;
2723 bytes -= 8;
2724 if (file->read(&v1, 8) != 8) return false; // v1 not needed
2725 bytes -= 8;
2726 v = swap_bytes_if_le(v);
2727
2728 // convert the MSB of 128b float to 32b float
2729 // 32b float has 1 sign bit, 8 exponent (offset 127), 23 mantissa
2730 // 128b float has 1 sign bit, 15 exponent (offset 16383), 112 mantissa
2731 si32 e = (si32)((v >> 48) & 0x7FFF); // exponent
2732 e -= 16383;
2733 e += 127;
2734 e = e & 0xFF; // removes MSBs if negative
2735 e <<= 23; // move bits to their location
2736 ui32 i = 0;
2737 i |= ((ui32)(v >> 32) & 0x80000000); // copy sign bit
2738 i |= (ui32)e; // copy exponent
2739 i |= (ui32)((v >> 25) & 0x007FFFFF); // copy 23 mantissa
2740 float f;
2741 memcpy(&f, &i, sizeof(float));
2742 K = f;
2743 }
2744 return true;
2745 }
2746
2747
2750 {
2751 int coeff_type = get_coeff_type();
2752 if (coeff_type == 0) {
2753 si8 v;
2754 if (file->read(&v, 1) != 1) return false;
2755 bytes -= 1;
2756 K = v;
2757 }
2758 else if (coeff_type == 1) {
2759 si16 v;
2760 if (file->read(&v, 2) != 2) return false;
2761 bytes -= 2;
2762 K = (si16)swap_bytes_if_le((ui16)v);
2763 }
2764 else
2765 return false;
2766 return true;
2767 }
2768
2771 {
2772 if (Latk != 0) // this param_atk is used
2773 return add_object()->read(file);
2774
2775 if (file->read(&Latk, 2) != 2)
2776 OJPH_ERROR(0x000500E1, "error reading ATK-Latk parameter");
2778 si32 bytes = Latk - 2;
2779 ojph::ui16 temp_Satk;
2780 if (file->read(&temp_Satk, 2) != 2)
2781 OJPH_ERROR(0x000500E2, "error reading ATK-Satk parameter");
2782 bytes -= 2;
2783 temp_Satk = swap_bytes_if_le(temp_Satk);
2784 int tmp_idx = temp_Satk & 0xFF;
2785 if ((top_atk && top_atk->get_atk(tmp_idx) != NULL)
2786 || tmp_idx == 0 || tmp_idx == 1)
2787 OJPH_ERROR(0x000500F3, "ATK-Satk parameter sets ATK marker index to "
2788 "the illegal value of %d. ATK-Satk should be in (2-255) and, I "
2789 "believe, must not be repeated; otherwise, it would be unclear "
2790 "what marker segment must be employed when an index is repeated.",
2791 tmp_idx);
2792 Satk = temp_Satk;
2793 if (is_m_init0() == false) // only even-indexed is supported
2794 OJPH_ERROR(0x000500E3, "ATK-Satk parameter sets m_init to 1, "
2795 "requiring odd-indexed subsequence in first reconstruction step, "
2796 "which is not supported yet.");
2797 if (is_whole_sample() == false) // ARB filter not supported
2798 OJPH_ERROR(0x000500E4, "ATK-Satk parameter specified ARB filter, "
2799 "which is not supported yet.");
2800 if (is_reversible() && get_coeff_type() >= 2) // reversible & float
2801 OJPH_ERROR(0x000500E5, "ATK-Satk parameter does not make sense. "
2802 "It employs floats with reversible filtering.");
2803 if (is_using_ws_extension() == false) // only sym. ext is supported
2804 OJPH_ERROR(0x000500E6, "ATK-Satk parameter requires constant "
2805 "boundary extension, which is not supported yet.");
2806 if (is_reversible() == false)
2807 if (read_coefficient(file, Katk, bytes) == false)
2808 OJPH_ERROR(0x000500E7, "error reading ATK-Katk parameter");
2809 if (file->read(&Natk, 1) != 1)
2810 OJPH_ERROR(0x000500E8, "error reading ATK-Natk parameter");
2811 bytes -= 1;
2812 if (Natk > max_steps) {
2813 if (d != d_store) // was this allocated -- very unlikely
2814 delete[] d;
2815 d = new lifting_step[Natk];
2816 max_steps = Natk;
2817 }
2818
2819 if (is_reversible())
2820 {
2821 for (int s = 0; s < Natk; ++s)
2822 {
2823 if (file->read(&d[s].rev.Eatk, 1) != 1)
2824 OJPH_ERROR(0x000500E9, "error reading ATK-Eatk parameter");
2825 bytes -= 1;
2826 if (file->read(&d[s].rev.Batk, 2) != 2)
2827 OJPH_ERROR(0x000500EA, "error reading ATK-Batk parameter");
2828 bytes -= 2;
2829 d[s].rev.Batk = (si16)swap_bytes_if_le((ui16)d[s].rev.Batk);
2830 ui8 LCatk;
2831 if (file->read(&LCatk, 1) != 1)
2832 OJPH_ERROR(0x000500EB, "error reading ATK-LCatk parameter");
2833 bytes -= 1;
2834 if (LCatk == 0)
2835 OJPH_ERROR(0x000500EC, "Encountered a ATK-LCatk value of zero; "
2836 "something is wrong.");
2837 if (LCatk > 1)
2838 OJPH_ERROR(0x000500ED, "ATK-LCatk value greater than 1; "
2839 "that is, a multitap filter is not supported");
2840 if (read_coefficient(file, d[s].rev.Aatk, bytes) == false)
2841 OJPH_ERROR(0x000500EE, "Error reding ATK-Aatk parameter");
2842 }
2843 }
2844 else
2845 {
2846 for (int s = 0; s < Natk; ++s)
2847 {
2848 ui8 LCatk;
2849 if (file->read(&LCatk, 1) != 1)
2850 OJPH_ERROR(0x000500EF, "error reading ATK-LCatk parameter");
2851 bytes -= 1;
2852 if (LCatk == 0)
2853 OJPH_ERROR(0x000500F0, "Encountered a ATK-LCatk value of zero; "
2854 "something is wrong.");
2855 if (LCatk > 1)
2856 OJPH_ERROR(0x000500F1, "ATK-LCatk value greater than 1; "
2857 "that is, a multitap filter is not supported.");
2858 if (read_coefficient(file, d[s].irv.Aatk, bytes) == false)
2859 OJPH_ERROR(0x000500F2, "Error reding ATK-Aatk parameter");
2860 }
2861 }
2862 if (bytes != 0)
2863 OJPH_ERROR(0x000500F3, "The length of an ATK marker segment "
2864 "(ATK-Latk) is not correct");
2865
2866 return true;
2867 }
2868
2871 {
2872 Satk = 0x4a00; // illegal because ATK = 0
2873 Katk = (float)1.230174104914001;
2874 Natk = 4;
2875 // next is (A-4) in T.801 second line
2876 Latk = (ui16)(5 + Natk + sizeof(float) * (1 + Natk));
2877 d[0].irv.Aatk = (float)0.443506852043971;
2878 d[1].irv.Aatk = (float)0.882911075530934;
2879 d[2].irv.Aatk = (float)-0.052980118572961;
2880 d[3].irv.Aatk = (float)-1.586134342059924;
2881 }
2882
2885 {
2886 Satk = 0x5801; // illegal because ATK = 1
2887 Natk = 2;
2888 // next is (A-4) in T.801 fourth line
2889 Latk = (ui16)(5 + 2 * Natk + sizeof(ui8) * (Natk + Natk));
2890 d[0].rev.Aatk = 1;
2891 d[0].rev.Batk = 2;
2892 d[0].rev.Eatk = 2;
2893 d[1].rev.Aatk = -1;
2894 d[1].rev.Batk = 1;
2895 d[1].rev.Eatk = 1;
2896 }
2897
2900 {
2901 assert(top_atk == NULL);
2902 param_atk *p = this;
2903 while (p->next != NULL)
2904 p = p->next;
2905 if (avail)
2906 {
2907 p->next = avail;
2908 avail = avail->next;
2909 }
2910 else
2911 p->next = new param_atk;
2912 p = p->next;
2913 p->init(this);
2914 return p;
2915 }
2916
2917 } // !local namespace
2918} // !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]
static const float * get_weights(ui32 format, ui32 comp_type)
static const float no_weights[19]
static const float * get_no_weights()
static const float cr444[19]
static const float cb422[19]
static const float cr422[19]
static const float cb420[19]
static const float cr420[19]
static colour_format get_format(const point &component_subsampling)
static const float cb444[19]
param_qcd::comp_type comp_type
static const float y[19]
static float get_weight(const float *v, ui32 decomposition_level, ui32 subband_idx)
static float get_gain(ui32 comp_type)
static float get_delta_ref(ui32 qfactor, ui32 bit_depth, float &power)
virtual size_t write(const void *ptr, size_t size)=0
size get_block_dims() const
int get_progression_order() const
bool is_using_color_transform() const
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.
void set_qfactor(ui8 qfactor)
Sets Qfactor.
local::param_qcd * state
static comp_type ui8_2_comp_type(ui8 c)
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:97
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_bytes_if_le(ui16 t)
Definition ojph_arch.h:414
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:185
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:206
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 * get_or_add_coc(ui32 comp_idx)
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)
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_qfactor(ui8 qfactor)
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)
bool is_qcc_needed(ui32 comp_num, const param_cod &cod, const param_siz &siz)
void make_quant_steps(ui32 comp_num, const param_cod &cod, const param_siz &siz)
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
ojph::param_qcd::comp_type comp_type
void encode_SPqcd(ui32 subband_index, float delta)
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
point get_downsampling(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)