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#include <climits>
41#include <new>
42
43#include "ojph_arch.h"
44#include "ojph_base.h"
45#include "ojph_file.h"
46#include "ojph_params.h"
47
48#include "ojph_params_local.h"
49#include "ojph_message.h"
50
51namespace ojph {
52
54 //
55 //
56 //
57 //
58 //
60
66
72
75 {
76 state->set_image_offset(offset);
77 }
78
81 {
82 state->set_tile_offset(offset);
83 }
84
87 {
88 state->set_num_components(num_comps);
89 }
90
92 void param_siz::set_component(ui32 comp_num, const point& downsampling,
93 ui32 bit_depth, bool is_signed)
94 {
95 state->set_comp_info(comp_num, downsampling, bit_depth, is_signed);
96 }
97
100 {
101 return point(state->Xsiz, state->Ysiz);
102 }
103
106 {
107 return point(state->XOsiz, state->YOsiz);
108 }
109
112 {
113 return size(state->XTsiz, state->YTsiz);
114 }
115
118 {
119 return point(state->XTOsiz, state->YTOsiz);
120 }
121
124 {
125 return state->Csiz;
126 }
127
130 {
131 return state->get_bit_depth(comp_num);
132 }
133
135 bool param_siz::is_signed(ui32 comp_num) const
136 {
137 return state->is_signed(comp_num);
138 }
139
142 {
143 return state->get_downsampling(comp_num);
144 }
145
148 {
149 return state->get_recon_width(comp_num);
150 }
151
154 {
155 return state->get_recon_height(comp_num);
156 }
157
159 //
160 //
161 //
162 //
163 //
165
167 void param_cod::set_num_decomposition(ui32 num_decompositions)
168 {
169 if (num_decompositions > 32)
170 OJPH_ERROR(0x00050001,
171 "maximum number of decompositions cannot exceed 32");
172 state->SPcod.num_decomp = (ui8)num_decompositions;
173 }
174
177 {
178 ui32 log_width = 31 - count_leading_zeros(width);
179 ui32 log_height = 31 - count_leading_zeros(height);
180 if (width == 0 || width != (1u << log_width)
181 || height == 0 || height != (1u << log_height)
182 || log_width < 2 || log_height < 2
183 || log_width + log_height > 12)
184 OJPH_ERROR(0x00050011, "incorrect code block dimensions");
185 state->SPcod.block_width = (ui8)(log_width - 2);
186 state->SPcod.block_height = (ui8)(log_height - 2);
187 }
188
190 void param_cod::set_precinct_size(int num_levels, size* precinct_size)
191 {
192 if (num_levels == 0 || precinct_size == NULL)
193 state->Scod &= 0xFE;
194 else
195 {
196 state->Scod |= 1;
197 for (int i = 0; i <= state->SPcod.num_decomp; ++i)
198 {
199 size t = precinct_size[i < num_levels ? i : num_levels - 1];
200
201 ui32 PPx = 31 - count_leading_zeros(t.w);
202 ui32 PPy = 31 - count_leading_zeros(t.h);
203 if (t.w == 0 || t.h == 0)
204 OJPH_ERROR(0x00050021, "precinct width or height cannot be 0");
205 if (t.w != (1u<<PPx) || t.h != (1u<<PPy))
206 OJPH_ERROR(0x00050022,
207 "precinct width and height should be a power of 2");
208 if (PPx > 15 || PPy > 15)
209 OJPH_ERROR(0x00050023, "precinct size is too large");
210 if (i > 0 && (PPx == 0 || PPy == 0))
211 OJPH_ERROR(0x00050024, "precinct size is too small");
212 state->SPcod.precinct_size[i] = (ui8)(PPx | (PPy << 4));
213 }
214 }
215 }
216
218 void param_cod::set_progression_order(const char *name)
219 {
220 int prog_order = 0;
221 size_t len = strlen(name);
222 if (len == 4)
223 {
224 if (strncmp(name, OJPH_PO_STRING_LRCP, 4) == 0)
225 prog_order = OJPH_PO_LRCP;
226 else if (strncmp(name, OJPH_PO_STRING_RLCP, 4) == 0)
227 prog_order = OJPH_PO_RLCP;
228 else if (strncmp(name, OJPH_PO_STRING_RPCL, 4) == 0)
229 prog_order = OJPH_PO_RPCL;
230 else if (strncmp(name, OJPH_PO_STRING_PCRL, 4) == 0)
231 prog_order = OJPH_PO_PCRL;
232 else if (strncmp(name, OJPH_PO_STRING_CPRL, 4) == 0)
233 prog_order = OJPH_PO_CPRL;
234 else
235 OJPH_ERROR(0x00050031, "unknown progression order");
236 }
237 else
238 OJPH_ERROR(0x00050032, "improper progression order");
239
240
241 state->SGCod.prog_order = (ui8)prog_order;
242 }
243
245 void param_cod::set_color_transform(bool color_transform)
246 {
247 state->employ_color_transform(color_transform ? 1 : 0);
248 }
249
251 void param_cod::set_reversible(bool reversible)
252 {
253 state->set_reversible(reversible);
254 }
255
257 void param_cod::set_num_decomposition(ui32 comp_idx, ui32 num_decompositions)
258 {
259 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
260 ojph::param_cod(cdp).set_num_decomposition(num_decompositions);
261 }
262
264 void param_cod::set_block_dims(ui32 comp_idx, ui32 width, ui32 height)
265 {
266 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
267 ojph::param_cod(cdp).set_block_dims(width, height);
268 }
269
271 void param_cod::set_precinct_size(ui32 comp_idx, int num_levels,
272 size* precinct_size)
273 {
274 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
275 ojph::param_cod(cdp).set_precinct_size(num_levels, precinct_size);
276 }
277
279 void param_cod::set_reversible(ui32 comp_idx, bool reversible)
280 {
281 local::param_cod* cdp = state->get_or_add_coc(comp_idx);
282 ojph::param_cod(cdp).set_reversible(reversible);
283 }
284
290
293 {
294 return state->get_block_dims();
295 }
296
299 {
300 return state->get_log_block_dims();
301 }
302
305 {
306 return state->is_reversible();
307 }
308
311 {
312 return state->get_precinct_size(level_num);
313 }
314
317 {
318 return state->get_log_precinct_size(level_num);
319 }
320
323 {
324 return state->SGCod.prog_order;
325 }
326
329 {
331 return OJPH_PO_STRING_LRCP;
332 else if (state->SGCod.prog_order == OJPH_PO_RLCP)
333 return OJPH_PO_STRING_RLCP;
334 else if (state->SGCod.prog_order == OJPH_PO_RPCL)
335 return OJPH_PO_STRING_RPCL;
336 else if (state->SGCod.prog_order == OJPH_PO_PCRL)
337 return OJPH_PO_STRING_PCRL;
338 else if (state->SGCod.prog_order == OJPH_PO_CPRL)
339 return OJPH_PO_STRING_CPRL;
340 else
341 assert(0);
342 return "";
343 }
344
347 {
348 return state->SGCod.num_layers;
349 }
350
356
359 {
360 return state->packets_may_use_sop();
361 }
362
365 {
366 return state->packets_use_eph();
367 }
368
374
377 { return state->get_coc(comp_idx)->get_num_decompositions(); }
378
381 { return state->get_coc(comp_idx)->get_block_dims(); }
382
385 { return state->get_coc(comp_idx)->get_log_block_dims(); }
386
388 bool param_cod::is_reversible(ui32 comp_idx) const
389 { return state->get_coc(comp_idx)->is_reversible(); }
390
392 size param_cod::get_precinct_size(ui32 comp_idx, ui32 level_num) const
393 { return state->get_coc(comp_idx)->get_precinct_size(level_num); }
394
397 { return state->get_coc(comp_idx)->get_log_precinct_size(level_num); }
398
402
403
405 //
406 //
407 //
408 //
409 //
411
414 {
415 state->set_delta(delta);
416 }
417
419 void param_qcd::set_qfactor(float qfactor) {
420 state->set_qfactor(qfactor);
421 }
422
424 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta)
425 {
426 state->set_delta(comp_idx, delta);
427 }
428
430 void param_qcd::set_qfactor(ui32 comp_idx, comp_type ctype, float qfactor)
431 {
432 state->set_qfactor(comp_idx, ctype, qfactor);
433 }
434
436 //
437 //
438 //
439 //
440 //
442
445 {
446 state->set_nonlinear_transform(comp_num, nl_type);
447 }
448
451 ui8 decoded_bit_depth,
452 bool decoded_signedness,
453 ui32 d_min, ui32 d_max, ui8 pt_val,
454 ui16 num_points, void* points,
455 ui8 nl_type)
456 {
457 state->set_nonlinear_transform(comp_num, decoded_bit_depth,
458 decoded_signedness, d_min, d_max, pt_val, num_points, points, nl_type);
459 }
460
463 ui8& decoded_bit_depth,
464 bool& decoded_signedness,
465 ui8& nl_type) const
466 {
467 return state->get_nonlinear_transform(comp_num, decoded_bit_depth,
468 decoded_signedness, nl_type);
469 }
470
472 //
473 //
474 //
475 //
476 //
478
480 void comment_exchange::set_string(const char* str)
481 {
482 size_t t = strlen(str);
483 if (len > 65531)
484 OJPH_ERROR(0x000500C1,
485 "COM marker string length cannot be larger than 65531");
486 this->data = str;
487 this->len = (ui16)t;
488 this->Rcom = 1;
489 }
490
493 {
494 if (len > 65531)
495 OJPH_ERROR(0x000500C2,
496 "COM marker string length cannot be larger than 65531");
497 this->data = data;
498 this->len = len;
499 this->Rcom = 0;
500 }
501
503 //
504 //
505 // LOCAL
506 //
507 //
509
510 namespace local {
511
513 //static
515 {
516 public:
517 static float get_gain_l(ui32 num_decomp, bool reversible)
518 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
519 static float get_gain_h(ui32 num_decomp, bool reversible)
520 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
521
522 private:
523 static const float gain_9x7_l[34];
524 static const float gain_9x7_h[34];
525 static const float gain_5x3_l[34];
526 static const float gain_5x3_h[34];
527 };
528
530 const float sqrt_energy_gains::gain_9x7_l[34] = { 1.0000e+00f,
531 1.4021e+00f, 2.0304e+00f, 2.9012e+00f, 4.1153e+00f, 5.8245e+00f,
532 8.2388e+00f, 1.1652e+01f, 1.6479e+01f, 2.3304e+01f, 3.2957e+01f,
533 4.6609e+01f, 6.5915e+01f, 9.3217e+01f, 1.3183e+02f, 1.8643e+02f,
534 2.6366e+02f, 3.7287e+02f, 5.2732e+02f, 7.4574e+02f, 1.0546e+03f,
535 1.4915e+03f, 2.1093e+03f, 2.9830e+03f, 4.2185e+03f, 5.9659e+03f,
536 8.4371e+03f, 1.1932e+04f, 1.6874e+04f, 2.3864e+04f, 3.3748e+04f,
537 4.7727e+04f, 6.7496e+04f, 9.5454e+04f };
538 const float sqrt_energy_gains::gain_9x7_h[34] = { 1.4425e+00f,
539 1.9669e+00f, 2.8839e+00f, 4.1475e+00f, 5.8946e+00f, 8.3472e+00f,
540 1.1809e+01f, 1.6701e+01f, 2.3620e+01f, 3.3403e+01f, 4.7240e+01f,
541 6.6807e+01f, 9.4479e+01f, 1.3361e+02f, 1.8896e+02f, 2.6723e+02f,
542 3.7792e+02f, 5.3446e+02f, 7.5583e+02f, 1.0689e+03f, 1.5117e+03f,
543 2.1378e+03f, 3.0233e+03f, 4.2756e+03f, 6.0467e+03f, 8.5513e+03f,
544 1.2093e+04f, 1.7103e+04f, 2.4187e+04f, 3.4205e+04f, 4.8373e+04f,
545 6.8410e+04f, 9.6747e+04f, 1.3682e+05f };
546 const float sqrt_energy_gains::gain_5x3_l[34] = { 1.0000e+00f,
547 1.2247e+00f, 1.3229e+00f, 1.5411e+00f, 1.7139e+00f, 1.9605e+00f,
548 2.2044e+00f, 2.5047e+00f, 2.8277e+00f, 3.2049e+00f, 3.6238e+00f,
549 4.1033e+00f, 4.6423e+00f, 5.2548e+00f, 5.9462e+00f, 6.7299e+00f,
550 7.6159e+00f, 8.6193e+00f, 9.7544e+00f, 1.1039e+01f, 1.2493e+01f,
551 1.4139e+01f, 1.6001e+01f, 1.8108e+01f, 2.0493e+01f, 2.3192e+01f,
552 2.6246e+01f, 2.9702e+01f, 3.3614e+01f, 3.8041e+01f, 4.3051e+01f,
553 4.8721e+01f, 5.5138e+01f, 6.2399e+01f };
554 const float sqrt_energy_gains::gain_5x3_h[34] = { 1.0458e+00f,
555 1.3975e+00f, 1.4389e+00f, 1.7287e+00f, 1.8880e+00f, 2.1841e+00f,
556 2.4392e+00f, 2.7830e+00f, 3.1341e+00f, 3.5576e+00f, 4.0188e+00f,
557 4.5532e+00f, 5.1494e+00f, 5.8301e+00f, 6.5963e+00f, 7.4663e+00f,
558 8.4489e+00f, 9.5623e+00f, 1.0821e+01f, 1.2247e+01f, 1.3860e+01f,
559 1.5685e+01f, 1.7751e+01f, 2.0089e+01f, 2.2735e+01f, 2.5729e+01f,
560 2.9117e+01f, 3.2952e+01f, 3.7292e+01f, 4.2203e+01f, 4.7761e+01f,
561 5.4051e+01f, 6.1170e+01f, 6.9226e+01f };
562
564 //static
566 {
567 public:
568 static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
569 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
570 static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
571 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
572
573 private:
574 static const float gain_9x7_l[34];
575 static const float gain_9x7_h[34];
576 static const float gain_5x3_l[34];
577 static const float gain_5x3_h[34];
578 };
579
581 const float bibo_gains::gain_9x7_l[34] = { 1.0000e+00f, 1.3803e+00f,
582 1.3328e+00f, 1.3067e+00f, 1.3028e+00f, 1.3001e+00f, 1.2993e+00f,
583 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
584 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
585 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
586 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
587 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
588 1.2992e+00f, 1.2992e+00f };
589 const float bibo_gains::gain_9x7_h[34] = { 1.2976e+00f, 1.3126e+00f,
590 1.2757e+00f, 1.2352e+00f, 1.2312e+00f, 1.2285e+00f, 1.2280e+00f,
591 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
592 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
593 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
594 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
595 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
596 1.2278e+00f, 1.2278e+00f };
597 const float bibo_gains::gain_5x3_l[34] = { 1.0000e+00f, 1.5000e+00f,
598 1.6250e+00f, 1.6875e+00f, 1.6963e+00f, 1.7067e+00f, 1.7116e+00f,
599 1.7129e+00f, 1.7141e+00f, 1.7145e+00f, 1.7151e+00f, 1.7152e+00f,
600 1.7155e+00f, 1.7155e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
601 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
602 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
603 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
604 1.7156e+00f, 1.7156e+00f };
605 const float bibo_gains::gain_5x3_h[34] = { 2.0000e+00f, 2.5000e+00f,
606 2.7500e+00f, 2.8047e+00f, 2.8198e+00f, 2.8410e+00f, 2.8558e+00f,
607 2.8601e+00f, 2.8628e+00f, 2.8656e+00f, 2.8662e+00f, 2.8667e+00f,
608 2.8669e+00f, 2.8670e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
609 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
610 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
611 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
612 2.8671e+00f, 2.8671e+00f };
613
615 //static
617 {
618 public:
628
629 public:
630 static colour_format get_format(const point& component_subsampling)
631 {
632 if (component_subsampling.x == 2 && component_subsampling.y == 2)
634 else if (component_subsampling.x == 2 && component_subsampling.y == 1)
636 else if (component_subsampling.x == 1 && component_subsampling.y == 1)
638 else
640 }
641
642 public:
643 static const float* get_weights(ui32 format, ui32 comp_type)
644 {
645 if (comp_type == comp_type::OJPH_COMP_Y)
646 return y;
647 else if (comp_type == comp_type::OJPH_COMP_CB)
648 {
649 if (format == VW_COLOUR_FORMAT_420) return cb420;
650 else if (format == VW_COLOUR_FORMAT_422) return cb422;
651 else if (format == VW_COLOUR_FORMAT_444) return cb444;
652 else {
653 assert(0);
654 return y;
655 }
656 }
657 else if (comp_type == comp_type::OJPH_COMP_CR)
658 {
659 if (format == VW_COLOUR_FORMAT_420) return cr420;
660 else if (format == VW_COLOUR_FORMAT_422) return cr422;
661 else if (format == VW_COLOUR_FORMAT_444) return cr444;
662 else {
663 assert(0);
664 return y;
665 }
666 }
667 else {
668 assert(0);
669 return y;
670 }
671 }
672
673 static const float* get_no_weights()
674 { return no_weights; }
675
676 static float get_weight(const float *v, ui32 decomposition_level,
677 ui32 subband_idx)
678
679 {
680 if (subband_idx == 0)
681 return v[18];
682 else {
683 assert(subband_idx >= 1 && subband_idx <= 3);
684 assert(decomposition_level > 0);
685 decomposition_level = ojph_min(decomposition_level, 6);
686 ui32 index = (decomposition_level - 1) * 3 + (3 - subband_idx);
687 return v[index];
688 }
689 }
690
692 static float get_gain(ui32 comp_type)
693 {
694 if (comp_type == comp_type::OJPH_COMP_Y)
695 return 1.0f;
696 else if (comp_type == comp_type::OJPH_COMP_CB)
697 return 1.8051f / 1.7321f;
698 else if (comp_type == comp_type::OJPH_COMP_CR)
699 return 1.5734f / 1.7321f;
700 else {
701 assert(0);
702 return 0.0f;
703 }
704 }
705
707 static float get_delta_ref(float qfactor, ui32 bit_depth,
708 float& power)
709 {
710 // returns delta_ref & power to be used with visual weights
711 constexpr float t0 = 65.0f;
712 constexpr float t1 = 97.0f;
713 constexpr float alpha_t0 = 0.04f, alpha_t1 = 0.10f;
714 constexpr float m_t0 = 2.0f * (1.0f - t0 / 100.0f);
715 constexpr float m_t1 = 2.0f * (1.0f - t1 / 100.0f);
716
717 float m_q;
718 if (qfactor < 50.0f)
719 m_q = 50.0f / qfactor;
720 else
721 m_q = 2.0f * (1.0f - qfactor / 100.0f);
722
723 float alpha_q;
724 if (qfactor <= t0)
725 {
726 power = 1.0f;
727 alpha_q = alpha_t0;
728 }
729 else if (qfactor < t1)
730 {
731 power = std::log(m_q) - std::log(m_t1);
732 power /= std::log(m_t0) - std::log(m_t1);
733 alpha_q = alpha_t1 * std::pow(alpha_t0 / alpha_t1, power);
734 }
735 else
736 {
737 power = 0.0f;
738 alpha_q = alpha_t1;
739 }
740 const float eps = std::sqrt(0.5f) * std::ldexp(1.0f, -(int)bit_depth);
741 return alpha_q * m_q + eps;
742 }
743
744 private:
745 static const float cb420[19];
746 static const float cr420[19];
747 static const float cb422[19];
748 static const float cr422[19];
749 static const float cb444[19];
750 static const float cr444[19];
751 static const float y[19];
752 static const float no_weights[19];
753 };
754
756 const float visual_weights::cb420[19] = {
757 0.2724f, 0.5128f, 0.5128f, // level 1
758 0.6692f, 0.9382f, 0.9382f, // level 2
759 1.0888f, 1.3046f, 1.3046f, // level 3
760 1.4156f, 1.5594f, 1.5594f, // level 4
761 2.0f, 2.0f, 2.0f, // level 5
762 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
763 const float visual_weights::cr420[19] = {
764 0.5196f, 0.8260f, 0.8260f, // level 1
765 1.0080f, 1.2928f, 1.2928f, // level 2
766 1.4440f, 1.6508f, 1.6508f, // level 3
767 1.7538f, 1.8848f, 1.8848f, // level 4
768 2.0f, 2.0f, 2.0f, // level 5
769 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
770 const float visual_weights::cb422[19] = {
771 0.1220f, 0.1220f, 0.3626f, // level 1
772 0.3626f, 0.3626f, 0.6634f, // level 2
773 0.6634f, 0.6634f, 0.9225f, // level 3
774 0.9225f, 0.9225f, 1.1027f, // level 4
775 1.1027f, 1.1027f, 1.4142f, // level 5
776 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
777 const float visual_weights::cr422[19] = {
778 0.2595f, 0.2595f, 0.5841f, // level 1
779 0.5841f, 0.5841f, 0.9141f, // level 2
780 0.9141f, 0.9141f, 1.1673f, // level 3
781 1.1673f, 1.1673f, 1.3328f, // level 4
782 1.3328f, 1.3328f, 1.4142f, // level 5
783 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
784 const float visual_weights::cb444[19] = {
785 0.0263f, 0.0863f, 0.0863f, // level 1
786 0.1362f, 0.2564f, 0.2564f, // level 2
787 0.3346f, 0.4691f, 0.4691f, // level 3
788 0.5444f, 0.6523f, 0.6523f, // level 4
789 0.7078f, 0.7797f, 0.7797f, // level 5
790 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
791 const float visual_weights::cr444[19] = {
792 0.0773f, 0.1835f, 0.1835f, // level 1
793 0.2598f, 0.4130f, 0.4130f, // level 2
794 0.5040f, 0.6464f, 0.6464f, // level 3
795 0.7220f, 0.8254f, 0.8254f, // level 4
796 0.8769f, 0.9424f, 0.9424f, // level 5
797 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
798 const float visual_weights::y[19] = {
799 0.0901f, 0.2758f, 0.2758f, // level 1
800 0.7018f, 0.8378f, 0.8378f, // level 2
801 1.0f, 1.0f, 1.0f, // level 3
802 1.0f, 1.0f, 1.0f, // level 4
803 1.0f, 1.0f, 1.0f, // level 5
804 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
805 const float visual_weights::no_weights[19] = {
806 1.0f, 1.0f, 1.0f, // level 1
807 1.0f, 1.0f, 1.0f, // level 2
808 1.0f, 1.0f, 1.0f, // level 3
809 1.0f, 1.0f, 1.0f, // level 4
810 1.0f, 1.0f, 1.0f, // level 5
811 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
812
813
815 //
816 //
817 //
818 //
819 //
821
824 {
825 //marker size excluding header
826 Lsiz = (ui16)(38 + 3 * Csiz);
827
828 ui8 buf1;
829 ui16 buf2;
830 ui32 buf4;
831 bool result = true;
832
833 buf2 = JP2K_MARKER::SIZ;
834 buf2 = swap_bytes_if_le(buf2);
835 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
836 buf2 = swap_bytes_if_le(Lsiz);
837 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
838 buf2 = swap_bytes_if_le(Rsiz);
839 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
840 buf4 = swap_bytes_if_le(Xsiz);
841 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
842 buf4 = swap_bytes_if_le(Ysiz);
843 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
844 buf4 = swap_bytes_if_le(XOsiz);
845 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
846 buf4 = swap_bytes_if_le(YOsiz);
847 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
848 buf4 = swap_bytes_if_le(XTsiz);
849 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
850 buf4 = swap_bytes_if_le(YTsiz);
851 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
852 buf4 = swap_bytes_if_le(XTOsiz);
853 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
854 buf4 = swap_bytes_if_le(YTOsiz);
855 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
856 buf2 = swap_bytes_if_le(Csiz);
857 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
858 for (int c = 0; c < Csiz; ++c)
859 {
860 buf1 = cptr[c].SSiz;
861 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
862 buf1 = cptr[c].XRsiz;
863 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
864 buf1 = cptr[c].YRsiz;
865 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
866 }
867
868 return result;
869 }
870
873 {
874 if (file->read(&Lsiz, 2) != 2)
875 OJPH_ERROR(0x00050041, "error reading SIZ marker");
876 Lsiz = swap_bytes_if_le(Lsiz);
877 int num_comps = (Lsiz - 38) / 3;
878 if (Lsiz != 38 + 3 * num_comps)
879 OJPH_ERROR(0x00050042, "error in SIZ marker length");
880 if (file->read(&Rsiz, 2) != 2)
881 OJPH_ERROR(0x00050043, "error reading SIZ marker");
882 Rsiz = swap_bytes_if_le(Rsiz);
883 if ((Rsiz & 0x4000) == 0)
884 OJPH_ERROR(0x00050044,
885 "Rsiz bit 14 is not set (this is not a JPH file)");
886 if ((Rsiz & 0x8000) != 0 && (Rsiz & 0xD5F) != 0)
887 OJPH_WARN(0x00050001, "Rsiz in SIZ has unimplemented fields");
888 if (file->read(&Xsiz, 4) != 4)
889 OJPH_ERROR(0x00050045, "error reading SIZ marker");
890 Xsiz = swap_bytes_if_le(Xsiz);
891 if (file->read(&Ysiz, 4) != 4)
892 OJPH_ERROR(0x00050046, "error reading SIZ marker");
893 Ysiz = swap_bytes_if_le(Ysiz);
894 ui32 t_XOsiz, t_YOsiz;
895 if (file->read(&t_XOsiz, 4) != 4)
896 OJPH_ERROR(0x00050047, "error reading SIZ marker");
897 if (file->read(&t_YOsiz, 4) != 4)
898 OJPH_ERROR(0x00050048, "error reading SIZ marker");
900 swap_bytes_if_le(t_XOsiz),
901 swap_bytes_if_le(t_YOsiz)));
902 ui32 t_XTsiz, t_YTsiz;
903 if (file->read(&t_XTsiz, 4) != 4)
904 OJPH_ERROR(0x00050049, "error reading SIZ marker");
905 if (file->read(&t_YTsiz, 4) != 4)
906 OJPH_ERROR(0x0005004A, "error reading SIZ marker");
908 swap_bytes_if_le(t_XTsiz),
909 swap_bytes_if_le(t_YTsiz)));
910 ui32 t_XTOsiz, t_YTOsiz;
911 if (file->read(&t_XTOsiz, 4) != 4)
912 OJPH_ERROR(0x0005004B, "error reading SIZ marker");
913 if (file->read(&t_YTOsiz, 4) != 4)
914 OJPH_ERROR(0x0005004C, "error reading SIZ marker");
916 swap_bytes_if_le(t_XTOsiz),
917 swap_bytes_if_le(t_YTOsiz)));
918 if (file->read(&Csiz, 2) != 2)
919 OJPH_ERROR(0x0005004D, "error reading SIZ marker");
920 Csiz = swap_bytes_if_le(Csiz);
921 if (Csiz != num_comps)
922 OJPH_ERROR(0x0005004E, "Csiz does not match the SIZ marker size");
923 if (Csiz == 0)
924 OJPH_ERROR(0x0005004F, "Wrong Csiz value of 0 in SIZ marker segment");
926 for (int c = 0; c < Csiz; ++c)
927 {
928 if (file->read(&cptr[c].SSiz, 1) != 1)
929 OJPH_ERROR(0x00050051, "error reading SIZ marker");
930 if (file->read(&cptr[c].XRsiz, 1) != 1)
931 OJPH_ERROR(0x00050052, "error reading SIZ marker");
932 if (file->read(&cptr[c].YRsiz, 1) != 1)
933 OJPH_ERROR(0x00050053, "error reading SIZ marker");
934 if ((cptr[c].SSiz & 0x7F) > 37)
935 OJPH_ERROR(0x00050054, "Wrong SIZ-SSiz value of %d", cptr[c].SSiz);
936 if (cptr[c].XRsiz == 0)
937 OJPH_ERROR(0x00050055, "Wrong SIZ-XRsiz value of %d", cptr[c].XRsiz);
938 if (cptr[c].YRsiz == 0)
939 OJPH_ERROR(0x00050056, "Wrong SIZ-YRsiz value of %d", cptr[c].YRsiz);
940 }
941
942 ws_kern_support_needed = (Rsiz & 0x20) != 0;
943 dfs_support_needed = (Rsiz & 0x80) != 0;
944
946 }
947
950 {
951 assert(comp_num < get_num_components());
952
953 point factor(1u << skipped_resolutions, 1u << skipped_resolutions);
954 const param_cod* cdp = cod->get_coc(comp_num);
955 if (dfs && cdp && cdp->is_dfs_defined()) {
956 const param_dfs* d = dfs->get_dfs(cdp->get_dfs_index());
958 }
959 factor.x *= (ui32)cptr[comp_num].XRsiz;
960 factor.y *= (ui32)cptr[comp_num].YRsiz;
961 return factor;
962 }
963
966 {
967 assert(comp_num < get_num_components());
968
969 point factor = get_recon_downsampling(comp_num);
970 point r;
971 r.x = ojph_div_ceil(Xsiz, factor.x) - ojph_div_ceil(XOsiz, factor.x);
972 r.y = ojph_div_ceil(Ysiz, factor.y) - ojph_div_ceil(YOsiz, factor.y);
973 return r;
974 }
975
976
978 //
979 //
980 //
981 //
982 //
984
987 {
988 //marker size excluding header
989 Lcap = 8;
990
991 ui16 buf2;
992 ui32 buf4;
993 bool result = true;
994
995 buf2 = JP2K_MARKER::CAP;
996 buf2 = swap_bytes_if_le(buf2);
997 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
998 buf2 = swap_bytes_if_le(Lcap);
999 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1000 buf4 = swap_bytes_if_le(Pcap);
1001 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
1002
1003 buf2 = swap_bytes_if_le(Ccap[0]);
1004 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1005
1006 return result;
1007 }
1008
1011 {
1012 if (file->read(&Lcap, 2) != 2)
1013 OJPH_ERROR(0x00050061, "error reading CAP marker");
1014 Lcap = swap_bytes_if_le(Lcap);
1015 if (file->read(&Pcap, 4) != 4)
1016 OJPH_ERROR(0x00050062, "error reading CAP marker");
1017 Pcap = swap_bytes_if_le(Pcap);
1018 ui32 count = population_count(Pcap);
1019 if (Pcap & 0xFFFDFFFF)
1020 OJPH_ERROR(0x00050063,
1021 "error Pcap in CAP has options that are not supported");
1022 if ((Pcap & 0x00020000) == 0)
1023 OJPH_ERROR(0x00050064,
1024 "error Pcap should have its 15th MSB set, Pcap^15. "
1025 " This is not a JPH file");
1026 for (ui32 i = 0; i < count; ++i)
1027 if (file->read(Ccap+i, 2) != 2)
1028 OJPH_ERROR(0x00050065, "error reading CAP marker");
1029 if (Lcap != 6 + 2 * count)
1030 OJPH_ERROR(0x00050066, "error in CAP marker length");
1031 }
1032
1034 //
1035 //
1036 //
1037 //
1038 //
1040
1043 {
1044 if (SPcod.wavelet_trans <= 1)
1046 else {
1047 assert(atk != NULL);
1048 return atk->is_reversible();
1049 }
1050 }
1051
1054 {
1055 assert(type == COD_MAIN);
1056
1057 //marker size excluding header
1058 Lcod = 12;
1059 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1060
1061 ui8 buf1;
1062 ui16 buf2;
1063 bool result = true;
1064
1065 buf2 = JP2K_MARKER::COD;
1066 buf2 = swap_bytes_if_le(buf2);
1067 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1068 buf2 = swap_bytes_if_le(Lcod);
1069 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1070 buf1 = Scod;
1071 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1072 buf1 = SGCod.prog_order;
1073 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1074 buf2 = swap_bytes_if_le(SGCod.num_layers);
1075 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1076 buf1 = SGCod.mc_trans;
1077 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1078 buf1 = SPcod.num_decomp;
1079 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1080 buf1 = SPcod.block_width;
1081 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1082 buf1 = SPcod.block_height;
1083 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1084 buf1 = SPcod.block_style;
1085 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1086 buf1 = SPcod.wavelet_trans;
1087 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1088 if (Scod & 1)
1089 for (int i = 0; i <= SPcod.num_decomp; ++i)
1090 {
1091 buf1 = SPcod.precinct_size[i];
1092 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1093 }
1094
1095 return result;
1096 }
1097
1100 {
1101 assert(type == COD_MAIN);
1102 bool result = true;
1103 param_cod *p = this->next;
1104 while (p)
1105 {
1106 if (p->comp_idx < num_comps)
1107 result &= p->internal_write_coc(file, num_comps);
1108 p = p->next;
1109 }
1110 return result;
1111 }
1112
1115 {
1116 assert(type == COC_MAIN);
1117
1118 //marker size excluding header
1119 Lcod = num_comps < 257 ? 9 : 10;
1120 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1121
1122 ui8 buf1;
1123 ui16 buf2;
1124 bool result = true;
1125
1126 buf2 = JP2K_MARKER::COC;
1127 buf2 = swap_bytes_if_le(buf2);
1128 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1129 buf2 = swap_bytes_if_le(Lcod);
1130 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1131 if (num_comps < 257)
1132 {
1133 buf1 = (ui8)comp_idx;
1134 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1135 }
1136 else
1137 {
1138 buf2 = swap_bytes_if_le(comp_idx);
1139 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1140 }
1141 buf1 = Scod;
1142 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1143 buf1 = SPcod.num_decomp;
1144 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1145 buf1 = SPcod.block_width;
1146 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1147 buf1 = SPcod.block_height;
1148 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1149 buf1 = SPcod.block_style;
1150 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1151 buf1 = SPcod.wavelet_trans;
1152 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1153 if (Scod & 1)
1154 for (int i = 0; i <= SPcod.num_decomp; ++i)
1155 {
1156 buf1 = SPcod.precinct_size[i];
1157 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1158 }
1159
1160 return result;
1161 }
1162
1165 {
1166 assert(type == COD_MAIN);
1167
1168 if (file->read(&Lcod, 2) != 2)
1169 OJPH_ERROR(0x00050071, "error reading COD segment");
1170 Lcod = swap_bytes_if_le(Lcod);
1171 if (file->read(&Scod, 1) != 1)
1172 OJPH_ERROR(0x00050072, "error reading COD segment");
1173 if (file->read(&SGCod.prog_order, 1) != 1)
1174 OJPH_ERROR(0x00050073, "error reading COD segment");
1175 if (file->read(&SGCod.num_layers, 2) != 2)
1176 { OJPH_ERROR(0x00050074, "error reading COD segment"); }
1177 else
1178 SGCod.num_layers = swap_bytes_if_le(SGCod.num_layers);
1179 if (file->read(&SGCod.mc_trans, 1) != 1)
1180 OJPH_ERROR(0x00050075, "error reading COD segment");
1181 if (file->read(&SPcod.num_decomp, 1) != 1)
1182 OJPH_ERROR(0x00050076, "error reading COD segment");
1183 if (file->read(&SPcod.block_width, 1) != 1)
1184 OJPH_ERROR(0x00050077, "error reading COD segment");
1185 if (file->read(&SPcod.block_height, 1) != 1)
1186 OJPH_ERROR(0x00050078, "error reading COD segment");
1187 if (file->read(&SPcod.block_style, 1) != 1)
1188 OJPH_ERROR(0x00050079, "error reading COD segment");
1189 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1190 OJPH_ERROR(0x0005007A, "error reading COD segment");
1191
1192 if (get_num_decompositions() > 32
1193 || SPcod.block_width > 8
1194 || SPcod.block_height > 8
1196 || (SPcod.block_style & 0x40) != 0x40
1197 || (SPcod.block_style & 0xB7) != 0x00)
1198 OJPH_ERROR(0x0005007D, "wrong settings in a COD-SPcod parameter");
1199 if ((SPcod.block_style & 0x40) != 0x40
1200 || (SPcod.block_style & 0xB7) != 0x00)
1201 OJPH_ERROR(0x0005007E, "unsupported settings in a COD-SPcod parameter");
1202
1203 ui8 num_decompositions = get_num_decompositions();
1204 if (Scod & 1) {
1205 for (int i = 0; i <= num_decompositions; ++i) {
1206 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1207 OJPH_ERROR(0x0005007B, "error reading COD segment");
1208 if (i)
1209 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1210 (SPcod.precinct_size[i] >> 4) == 0)
1211 OJPH_ERROR(0x0005007F,
1212 "Precinct width or height for resolutions other than the"
1213 " coarsest must be larger than 1; here, they are %d and %d,"
1214 " respectively.",
1215 1 << (SPcod.precinct_size[i] & 0x0F),
1216 1 << (SPcod.precinct_size[i] >> 4));
1217 }
1218 }
1219 if (Lcod != 12 + ((Scod & 1) ? 1 + SPcod.num_decomp : 0))
1220 OJPH_ERROR(0x0005007C, "error in COD segment length");
1221 }
1222
1224 void param_cod::read_coc(infile_base* file, ui32 num_comps,
1226 {
1227 assert(type == COC_MAIN);
1228 assert(top_cod != NULL);
1229
1230 this->SGCod = top_cod->SGCod;
1231 this->top_cod = top_cod;
1232 if (file->read(&Lcod, 2) != 2)
1233 OJPH_ERROR(0x00050121, "error reading COC segment");
1234 Lcod = swap_bytes_if_le(Lcod);
1235 if (num_comps < 257) {
1236 ui8 t;
1237 if (file->read(&t, 1) != 1)
1238 OJPH_ERROR(0x00050122, "error reading COC segment");
1239 comp_idx = t;
1240 }
1241 else {
1242 if (file->read(&comp_idx, 2) != 2)
1243 OJPH_ERROR(0x00050123, "error reading COC segment");
1244 comp_idx = swap_bytes_if_le(comp_idx);
1245 }
1246 if (file->read(&Scod, 1) != 1)
1247 OJPH_ERROR(0x00050124, "error reading COC segment");
1248 if (Scod & 0xF8)
1249 OJPH_WARN(0x00050011,
1250 "Unsupported options in Scoc field of the COC segment");
1251 if (file->read(&SPcod.num_decomp, 1) != 1)
1252 OJPH_ERROR(0x00050125, "error reading COC segment");
1253 if (file->read(&SPcod.block_width, 1) != 1)
1254 OJPH_ERROR(0x00050126, "error reading COC segment");
1255 if (file->read(&SPcod.block_height, 1) != 1)
1256 OJPH_ERROR(0x00050127, "error reading COC segment");
1257 if (file->read(&SPcod.block_style, 1) != 1)
1258 OJPH_ERROR(0x00050128, "error reading COC segment");
1259 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1260 OJPH_ERROR(0x00050129, "error reading COC segment");
1261
1262 if (get_num_decompositions() > 32
1263 || SPcod.block_width > 8
1264 || SPcod.block_height > 8
1266 || (SPcod.block_style & 0x40) != 0x40
1267 || (SPcod.block_style & 0xB7) != 0x00)
1268 OJPH_ERROR(0x0005012C, "wrong settings in a COC-SPcoc parameter");
1269 if ((SPcod.block_style & 0x40) != 0x40
1270 || (SPcod.block_style & 0xB7) != 0x00)
1271 OJPH_ERROR(0x0005012D, "unsupported settings in a COC-SPcoc parameter");
1272
1273 ui8 num_decompositions = get_num_decompositions();
1274 if (Scod & 1) {
1275 for (int i = 0; i <= num_decompositions; ++i) {
1276 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1277 OJPH_ERROR(0x0005012A, "error reading COC segment");
1278 if (i)
1279 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1280 (SPcod.precinct_size[i] >> 4) == 0)
1281 OJPH_ERROR(0x0005012E,
1282 "Precinct width or height for resolutions other than the"
1283 " coarsest must be larger than 1; here, they are %d and %d,"
1284 " respectively.",
1285 1 << (SPcod.precinct_size[i] & 0x0F),
1286 1 << (SPcod.precinct_size[i] >> 4));
1287 }
1288 }
1289 ui32 t = 9;
1290 t += num_comps < 257 ? 0 : 1;
1291 t += (Scod & 1) ? 1 + num_decompositions : 0;
1292 if (Lcod != t)
1293 OJPH_ERROR(0x0005012B, "error in COC segment length");
1294 }
1295
1298 {
1299 assert(type == COD_MAIN);
1300 this->atk = atk->get_atk(SPcod.wavelet_trans);
1301 if (this->atk == NULL)
1302 OJPH_ERROR(0x00050131, "A COD segment employs the DWT kernel "
1303 "atk = %d, but a corresponding ATK segment cannot be found.",
1305 param_cod *p = next;
1306 while (p)
1307 {
1308 p->atk = atk->get_atk(p->SPcod.wavelet_trans);
1309 if (p->atk == NULL)
1310 OJPH_ERROR(0x00050132, "A COC segment employs the DWT kernel "
1311 "atk = %d, but a corresponding ATK segment cannot be found",
1313 p = p->next;
1314 }
1315 }
1316
1319 {
1320 assert(this->type == COD_MAIN || this->top_cod->type == COD_MAIN);
1321 const param_cod *p, *q;
1322 if (this->type == COD_MAIN)
1323 q = p = this;
1324 else
1325 q = p = this->top_cod;
1326 while (p && p->comp_idx != comp_idx)
1327 p = p->next;
1328 return p ? p : q;
1329 }
1330
1333 {
1334 // cast object to constant
1335 const param_cod* const_p = const_cast<const param_cod*>(this);
1336 // call using the constant object, then cast to non-const
1337 return const_cast<param_cod*>(const_p->get_coc(comp_idx));
1338 }
1339
1342 {
1343 assert(type == COD_MAIN);
1344 param_cod *p = this;
1345 while (p->next != NULL)
1346 p = p->next;
1347 if (avail)
1348 {
1349 p->next = avail;
1350 avail = avail->next;
1351 p->next->init(this, (ui16)comp_idx);
1352 }
1353 else
1354 p->next = new param_cod(this, (ui16)comp_idx);
1355 return p->next;
1356 }
1357
1360 {
1361 assert(type == COD_MAIN);
1363 if (p == this)
1365 return p;
1366 }
1367
1369 //
1370 //
1371 //
1372 //
1373 //
1375
1377 void param_qcd::check_validity(const param_siz& siz, const param_cod& cod)
1378 {
1379 assert(this->type == QCD_MAIN);
1380
1381 ui32 num_comps = siz.get_num_components();
1383
1384 // initialize QCD based on the first component that is (a) associated with
1385 // COD and (b) does not have a COC, or the first component othewise.
1386 ui32 qcd_comp = 0;
1387 for (ui32 c = 0; c < num_comps; ++c)
1388 {
1389 if (cod.get_coc(c) == &cod && get_qcc(c) == this)
1390 {
1391 qcd_comp = c;
1392 break;
1393 }
1394 }
1395
1396 // check if only the top QCD has qfactor set, if so, check if any
1397 // of the first component has COC and qfactor set properly
1398 if (this->qfactor != QFACTOR_UNSET)
1399 {
1400 if (num_comps < 3) // one or two components
1401 {
1402 for (ui32 i = 0; i < num_comps; ++i)
1403 {
1404 param_qcd* q = get_qcc(i);
1405 if (q == this)
1406 {
1407 q = add_qcc_object(i);
1408 set_qfactor(i, comp_type::OJPH_COMP_Y, this->qfactor);
1409 }
1410 }
1411 }
1412 else if (num_comps >= 3)
1413 {
1414 for (ui32 i = 0; i < num_comps; ++i) {
1415 param_qcd* q = get_qcc(i);
1416 if (q == this)
1417 {
1418 q = add_qcc_object(i);
1419 ui8 ci = (ui8)(i < 3u ? i : 0u);
1421 set_qfactor(i, t, this->qfactor);
1422 }
1423 }
1424 }
1425 }
1426
1427 this->make_quant_steps(qcd_comp, cod, siz);
1428
1429 // initialize every QCC, creating one for every component that (a) cannot
1430 // use QCD and (b) does not already have a QCC
1431 // NOTE: Qfactor always creates a QCC and QCD cannot be reused
1432 for (ui32 c = 0; c < num_comps; ++c)
1433 {
1434 param_qcd *qcc = this->get_qcc(c);
1435 const param_cod *coc = cod.get_coc(c);
1436
1437 // check if a QCC exists for the component
1438 if (qcc == this)
1439 {
1440 // if none exists, do not create one if QCD can be reused
1441 if (!this->is_qcc_needed(c, *coc, siz))
1442 continue;
1443
1444 qcc = this->add_qcc_object(c);
1445 qcc->set_delta(this->base_delta);
1446 }
1447
1448 qcc->make_quant_steps(c, *coc, siz);
1449 }
1450 }
1451
1453 void param_qcd::make_quant_steps(ui32 comp_num, const param_cod &cod,
1454 const param_siz &siz)
1455 {
1456 if (this->is_init)
1457 OJPH_ERROR(0x00040001, "Quantization step sizes already initialized.");
1458
1459 this->is_init = true;
1460
1461 this->num_decomps = cod.get_num_decompositions();
1462 this->bit_depth = siz.get_bit_depth(comp_num);
1463 this->is_signed = siz.is_signed(comp_num);
1465 this->wavelet_kern = cod.get_wavelet_kern();
1466 this->sampling = siz.get_downsampling(comp_num);
1467 this->num_subbands = 1 + 3 * this->num_decomps;
1468
1470 this->set_rev_quant(this->num_decomps, this->bit_depth,
1471 comp_num < 3 ? this->is_color_trans : false);
1472 else if (this->wavelet_kern == param_cod::DWT_IRV97)
1473 {
1474 if (this->base_delta == -1.0f)
1475 {
1476 ui32 t = ojph_min(16, bit_depth);
1477 this->base_delta = 1.0f / (float)(1 << t);
1478 }
1479 else if (qfactor != QFACTOR_UNSET)
1480 OJPH_WARN(0x00040002, "qstep for component %d is ignored, because "
1481 "qfactor is set.", comp_num);
1482
1483 this->set_irrev_quant(this->num_decomps);
1484 }
1485 }
1486
1488 bool param_qcd::is_qcc_needed(ui32 comp_num, const param_cod &cod,
1489 const param_siz &siz)
1490 {
1491 if (! this->is_init)
1492 OJPH_ERROR(0x00040001, "Quantization step sizes not initialized.");
1493
1494 return this->num_decomps != cod.get_num_decompositions() ||
1495 this->bit_depth != siz.get_bit_depth(comp_num) ||
1496 this->is_signed != siz.is_signed(comp_num) ||
1498 this->wavelet_kern != cod.get_wavelet_kern();
1499 }
1500
1503 assert(this->type == QCD_MAIN);
1504
1505 if (qfactor < 1.0f || qfactor > 100.0f)
1506 OJPH_ERROR(0x00050181, "Qfactor must be between 1 and 100, "
1507 "but was set to %i.", qfactor);
1508
1509 this->qfactor = qfactor;
1510 }
1511
1514 bool is_employing_color_transform)
1515 {
1516 ui32 B = bit_depth;
1517 B += is_employing_color_transform ? 1 : 0; //1 bit for RCT
1518 int s = 0;
1519 double bibo_l = bibo_gains::get_bibo_gain_l(num_decomps, true);
1520 ui32 X = (ui32) ceil(log(bibo_l * bibo_l) / M_LN2);
1521 SPqcd.u8[s++] = (ui8)(B + X);
1522 ui32 max_B_plus_X = (ui32)(B + X);
1523 for (ui32 d = num_decomps; d > 0; --d)
1524 {
1525 double bibo_l = bibo_gains::get_bibo_gain_l(d, true);
1526 double bibo_h = bibo_gains::get_bibo_gain_h(d - 1, true);
1527 X = (ui32) ceil(log(bibo_h * bibo_l) / M_LN2);
1528 SPqcd.u8[s++] = (ui8)(B + X);
1529 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1530 SPqcd.u8[s++] = (ui8)(B + X);
1531 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1532 X = (ui32) ceil(log(bibo_h * bibo_h) / M_LN2);
1533 SPqcd.u8[s++] = (ui8)(B + X);
1534 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1535 }
1536
1537 if (max_B_plus_X > 38)
1538 OJPH_ERROR(0x00050151, "The specified combination of bit_depth, "
1539 "colour transform, and type of wavelet transform requires more than "
1540 "38 bits; it requires %d bits. This is beyond what is allowed in "
1541 "the JPEG2000 image coding format.", max_B_plus_X);
1542
1543 int guard_bits = ojph_max(1, (si32)max_B_plus_X - 31);
1544 Sqcd = (ui8)(guard_bits << 5);
1545 s = 0;
1546 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1547 s++;
1548 for (ui32 d = num_decomps; d > 0; --d)
1549 {
1550 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1551 s++;
1552 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1553 s++;
1554 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1555 s++;
1556 }
1557 }
1558
1561 {
1562 int guard_bits = 1;
1563 Sqcd = (ui8)((guard_bits<<5)|0x2); //one guard bit, scalar quantization
1564
1565 float g_c = 1.0f;
1566 float delta_ref = base_delta;
1567 float power = 1.0f;
1568 const float* weights = visual_weights::get_no_weights();
1569
1570 if (qfactor != QFACTOR_UNSET)
1571 {
1575 OJPH_ERROR(0x00050161, "Qfactor can only be used on components "
1576 "with 4:4:4, 4:2:2 or 4:2:0 sampling");
1577 if (this->ctype == comp_type::OJPH_COMP_Y &&
1578 this->sampling.x != 1 && this->sampling.y != 1)
1579 OJPH_ERROR(0x00050162, "Qfactor can only be used for a Y or "
1580 "luminance component when it is not downsampled.");
1581
1582 // calculate component gain
1583 g_c = visual_weights::get_gain(this->ctype);
1584
1585 // calculate delta_ref & power
1586 delta_ref = visual_weights::get_delta_ref(qfactor, bit_depth, power);
1587
1588 // find visual weight
1589 weights = visual_weights::get_weights(format, this->ctype);
1590 }
1591
1592 // LL band
1593 ui32 b = 0;
1594 float w_b;
1595 float gain_l = sqrt_energy_gains::get_gain_l(num_decomps, false);
1596 w_b = visual_weights::get_weight(weights, num_decomps, b);
1597 w_b = std::pow(w_b, power);
1598 encode_SPqcd(b++, delta_ref / (gain_l * gain_l * g_c * w_b));
1599
1600 // LL, HL, LH, HH, HL, LH, HH...
1601 for (ui32 d = num_decomps; d > 0; --d)
1602 {
1603 // compute square root of the enery gain factor W_g
1604 float gain_l = sqrt_energy_gains::get_gain_l(d, false);
1605 float gain_h = sqrt_energy_gains::get_gain_h(d - 1, false);
1606
1607 w_b = visual_weights::get_weight(weights, d, 1);
1608 w_b = std::pow(w_b, power);
1609 encode_SPqcd(b++, delta_ref / (gain_h * gain_l * g_c * w_b));
1610 w_b = visual_weights::get_weight(weights, d, 2);
1611 w_b = std::pow(w_b, power);
1612 encode_SPqcd(b++, delta_ref / (gain_l * gain_h * g_c * w_b));
1613 w_b = visual_weights::get_weight(weights, d, 3);
1614 w_b = std::pow(w_b, power);
1615 encode_SPqcd(b++, delta_ref / (gain_h * gain_h * g_c * w_b));
1616 }
1617 }
1618
1620 void param_qcd::encode_SPqcd(ui32 subband_index, float delta)
1621 {
1622 int exp = 0, mantissa;
1623 while (delta < 1.0f)
1624 { exp++; delta *= 2.0f; }
1625 mantissa = (int)round(delta * (float)(1<<11)) - (1<<11);
1626 // with rounding, there is a risk that the mantissa becomes
1627 // equal to 1<<11
1628 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1629 SPqcd.u16[subband_index] = (ui16)((exp << 11) | mantissa);
1630 }
1631
1634 {
1635 ui32 B = 0;
1636
1637 const param_qcd *p = this;
1638 while (p)
1639 {
1640 //this can be written better, but it is only executed once
1641 // this assumes a bi-directional wavelet (conventional DWT)
1642 ui32 num_decomps = (p->num_subbands - 1) / 3;
1643
1644 int irrev = p->Sqcd & 0x1F;
1645 if (irrev == 0) //reversible
1646 for (ui32 i = 0; i < p->num_subbands; ++i) {
1647 ui32 t = p->decode_SPqcd(p->SPqcd.u8[i]);
1648 t += p->get_num_guard_bits() - 1u;
1649 B = ojph_max(B, t);
1650 }
1651 else if (irrev == 2) //scalar expounded
1652 for (ui32 i = 0; i < p->num_subbands; ++i)
1653 {
1654 ui32 nb = num_decomps - (i ? (i - 1) / 3 : 0); //decompsition level
1655 ui32 t = (p->SPqcd.u16[i] >> 11) + p->get_num_guard_bits() - nb;
1656 B = ojph_max(B, t);
1657 }
1658 else
1659 assert(0);
1660
1661 p = p->next;
1662 }
1663
1664 return B;
1665 }
1666
1669 ui32 num_decompositions, ui32 comp_num,
1670 ui32 resolution, ui32 subband) const
1671 {
1672 float arr[] = { 1.0f, 2.0f, 2.0f, 4.0f };
1673 if ((Sqcd & 0x1F) != 2)
1674 OJPH_ERROR(0x00050101, "There is something wrong in the configuration "
1675 "of the codestream; for component %d, the codestream defines an "
1676 "irreversible transform, for which the codestream provides a "
1677 "reversible (no quantization) step sizes in Sqcd/Sqcc.", comp_num);
1678
1679 ui32 idx;
1680 if (dfs != NULL && dfs->exists())
1681 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1682 else
1683 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1684 if (idx >= num_subbands) {
1685 OJPH_INFO(0x00050102, "Trying to access quantization step size for "
1686 "subband %d when the QCD/QCC marker segment specifies "
1687 "quantization step sizes for %d subbands only. To continue "
1688 "decoding, we are using the step size for subband %d, which can "
1689 "produce incorrect results",
1690 idx + 1, num_subbands, num_subbands - 1);
1691 idx = num_subbands - 1;
1692 }
1693 int eps = SPqcd.u16[idx] >> 11;
1694 float mantissa;
1695 mantissa = (float)((SPqcd.u16[idx] & 0x7FF) | 0x800) * arr[subband];
1696 mantissa /= (float)(1 << 11);
1697 mantissa /= (float)(1u << eps);
1698 return mantissa;
1699 }
1700
1703 {
1704 ui32 comp_idx = cod->get_comp_idx();
1705 ui32 precision = 0;
1706 const param_cod *main =
1708 if (main->is_employing_color_transform() && comp_idx < 3)
1709 {
1710 for (ui32 i = 0; i < 3; ++i) {
1711 const param_qcd* p = this->get_qcc(i);
1712 precision = ojph_max(precision, p->get_largest_Kmax());
1713 }
1714 }
1715 else {
1716 precision = get_largest_Kmax();
1717 }
1718 // ``precision'' now holds the largest K_max, which excludes the sign
1719 // bit.
1720 // + 1 for the sign bit
1721 // + 1 because my block decoder/encoder does not supports up to 30
1722 // bits (not 31), so we bump it by one more bit.
1723 return precision + 1 + 1;
1724 }
1725
1728 {
1729 return (Sqcd >> 5);
1730 }
1731
1733 ui32 param_qcd::get_Kmax(const param_dfs* dfs, ui32 num_decompositions,
1734 ui32 resolution, ui32 subband) const
1735 {
1736 ui32 idx;
1737 if (dfs != NULL && dfs->exists())
1738 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1739 else
1740 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1741 if (idx >= num_subbands) {
1742 OJPH_INFO(0x00050111, "Trying to access quantization step size for "
1743 "subband %d when the QCD/QCC marker segment specifies "
1744 "quantization step sizes for %d subbands only. To continue "
1745 "decoding, we are using the step size for subband %d, which can "
1746 "produce incorrect results",
1747 idx + 1, num_subbands, num_subbands - 1);
1748 idx = num_subbands - 1;
1749 }
1750
1751 int irrev = Sqcd & 0x1F;
1752 ui32 num_bits = 0;
1753 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1754 {
1755 num_bits = decode_SPqcd(SPqcd.u8[idx]);
1756 num_bits = num_bits == 0 ? 0 : num_bits - 1;
1757 }
1758 else if (irrev == 1)
1759 assert(0);
1760 else if (irrev == 2) //scalar expounded
1761 num_bits = (SPqcd.u16[idx] >> 11) - 1;
1762 else
1763 assert(0);
1764
1765 return num_bits + get_num_guard_bits();
1766 }
1767
1770 {
1771 int irrev = Sqcd & 0x1F;
1772 ui32 num_bits = 0;
1773 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1774 {
1775 for (ui32 i = 0; i < num_subbands; ++i) {
1776 ui32 t = decode_SPqcd(SPqcd.u8[i]);
1777 num_bits = ojph_max(num_bits, t == 0 ? 0 : t - 1);
1778 }
1779 }
1780 else if (irrev == 1)
1781 assert(0);
1782 else if (irrev == 2) //scalar expounded
1783 {
1784 for (ui32 i = 0; i < num_subbands; ++i) {
1785 ui32 t = (SPqcd.u16[i] >> 11) - 1;
1786 num_bits = ojph_max(num_bits, t);
1787 }
1788 }
1789 else
1790 assert(0);
1791
1792 return num_bits + get_num_guard_bits();
1793 }
1794
1797 {
1798 int irrev = Sqcd & 0x1F;
1799
1800 //marker size excluding header
1801 Lqcd = 3;
1802 if (irrev == 0)
1803 Lqcd = (ui16)(Lqcd + num_subbands);
1804 else if (irrev == 2)
1805 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1806 else
1807 assert(0);
1808
1809 ui8 buf1;
1810 ui16 buf2;
1811 bool result = true;
1812
1813 buf2 = JP2K_MARKER::QCD;
1814 buf2 = swap_bytes_if_le(buf2);
1815 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1816 buf2 = swap_bytes_if_le(Lqcd);
1817 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1818 buf1 = Sqcd;
1819 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1820
1821 if (irrev == 0)
1822 for (ui32 i = 0; i < num_subbands; ++i)
1823 {
1824 buf1 = SPqcd.u8[i];
1825 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1826 }
1827 else if (irrev == 2)
1828 for (ui32 i = 0; i < num_subbands; ++i)
1829 {
1830 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1831 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1832 }
1833 else
1834 assert(0);
1835
1836 return result;
1837 }
1838
1841 {
1842 assert(type == QCD_MAIN);
1843 bool result = true;
1844 param_qcd *p = this->next;
1845 while (p)
1846 {
1847 if (p->enabled)
1848 result &= p->internal_write_qcc(file, num_comps);
1849 p = p->next;
1850 }
1851 return result;
1852 }
1853
1856 {
1857 int irrev = Sqcd & 0x1F;
1858
1859 //marker size excluding header
1860 Lqcd = (ui16)(4 + (num_comps < 257 ? 0 : 1));
1861 if (irrev == 0)
1862 Lqcd = (ui16)(Lqcd + num_subbands);
1863 else if (irrev == 2)
1864 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1865 else
1866 assert(0);
1867
1868 ui8 buf1;
1869 ui16 buf2;
1870 bool result = true;
1871
1872 buf2 = JP2K_MARKER::QCC;
1873 buf2 = swap_bytes_if_le(buf2);
1874 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1875 buf2 = swap_bytes_if_le(Lqcd);
1876 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1877 if (num_comps < 257)
1878 {
1879 buf1 = (ui8)comp_idx;
1880 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1881 }
1882 else
1883 {
1884 buf2 = swap_bytes_if_le(comp_idx);
1885 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1886 }
1887 buf1 = Sqcd;
1888 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1889 if (irrev == 0)
1890 for (ui32 i = 0; i < num_subbands; ++i)
1891 {
1892 buf1 = SPqcd.u8[i];
1893 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1894 }
1895 else if (irrev == 2)
1896 for (ui32 i = 0; i < num_subbands; ++i)
1897 {
1898 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1899 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1900 }
1901 else
1902 assert(0);
1903
1904 return result;
1905 }
1906
1909 {
1910 assert(type == QCD_MAIN && comp_idx == OJPH_QCD_DEFAULT);
1911 param_qcd *p = this->next;
1912 while (p)
1913 {
1914 assert(p->type == QCC_MAIN);
1915 p->enabled = p->comp_idx < num_comps;
1916 p = p->next;
1917 }
1918 }
1919
1922 {
1923 if (file->read(&Lqcd, 2) != 2)
1924 OJPH_ERROR(0x00050081, "error reading QCD marker");
1925 Lqcd = swap_bytes_if_le(Lqcd);
1926 if (file->read(&Sqcd, 1) != 1)
1927 OJPH_ERROR(0x00050082, "error reading QCD marker");
1928 if ((Sqcd & 0x1F) == 0)
1929 {
1930 num_subbands = (Lqcd - 3);
1931 if (num_subbands == 0)
1932 OJPH_ERROR(0x0005008A, "QCD marker segment that specifies no "
1933 "quantization informtion");
1934 if (num_subbands > 97 || Lqcd != 3 + num_subbands)
1935 OJPH_ERROR(0x00050083, "wrong Lqcd value of %d in QCD marker", Lqcd);
1936 for (ui32 i = 0; i < num_subbands; ++i)
1937 if (file->read(&SPqcd.u8[i], 1) != 1)
1938 OJPH_ERROR(0x00050084, "error reading QCD marker");
1939 }
1940 else if ((Sqcd & 0x1F) == 1)
1941 {
1942 num_subbands = 0;
1943 OJPH_ERROR(0x00050089,
1944 "Scalar derived quantization is not supported yet in QCD marker");
1945 if (Lqcd != 5)
1946 OJPH_ERROR(0x00050085, "wrong Lqcd value in QCD marker");
1947 }
1948 else if ((Sqcd & 0x1F) == 2)
1949 {
1950 num_subbands = (Lqcd - 3) / 2;
1951 if (num_subbands == 0)
1952 OJPH_ERROR(0x0005008B, "QCD marker segment that specifies no "
1953 "quantization informtion");
1954 if (num_subbands > 97 || Lqcd != 3 + 2 * num_subbands)
1955 OJPH_ERROR(0x00050086, "wrong Lqcd value of %d in QCD marker", Lqcd);
1956 for (ui32 i = 0; i < num_subbands; ++i)
1957 {
1958 if (file->read(&SPqcd.u16[i], 2) != 2)
1959 OJPH_ERROR(0x00050087, "error reading QCD marker");
1960 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
1961 }
1962 }
1963 else
1964 OJPH_ERROR(0x00050088, "wrong Sqcd value in QCD marker");
1965 }
1966
1968 void param_qcd::read_qcc(infile_base *file, ui32 num_comps)
1969 {
1970 if (file->read(&Lqcd, 2) != 2)
1971 OJPH_ERROR(0x000500A1, "error reading QCC marker");
1972 Lqcd = swap_bytes_if_le(Lqcd);
1973 if (num_comps < 257)
1974 {
1975 ui8 v;
1976 if (file->read(&v, 1) != 1)
1977 OJPH_ERROR(0x000500A2, "error reading QCC marker");
1978 comp_idx = v;
1979 }
1980 else
1981 {
1982 if (file->read(&comp_idx, 2) != 2)
1983 OJPH_ERROR(0x000500A3, "error reading QCC marker");
1984 comp_idx = swap_bytes_if_le(comp_idx);
1985 }
1986 if (file->read(&Sqcd, 1) != 1)
1987 OJPH_ERROR(0x000500A4, "error reading QCC marker");
1988 ui32 offset = num_comps < 257 ? 4 : 5;
1989 if ((Sqcd & 0x1F) == 0)
1990 {
1991 num_subbands = (Lqcd - offset);
1992 if (num_subbands == 0)
1993 OJPH_ERROR(0x000500AC, "QCC marker segment that specifies no "
1994 "quantization informtion");
1995 if (num_subbands > 97 || Lqcd != offset + num_subbands)
1996 OJPH_ERROR(0x000500A5, "wrong Lqcd value of %d in QCC marker", Lqcd);
1997 for (ui32 i = 0; i < num_subbands; ++i)
1998 if (file->read(&SPqcd.u8[i], 1) != 1)
1999 OJPH_ERROR(0x000500A6, "error reading QCC marker");
2000 }
2001 else if ((Sqcd & 0x1F) == 1)
2002 {
2003 num_subbands = 0;
2004 OJPH_ERROR(0x000500AB,
2005 "Scalar derived quantization is not supported yet in QCC marker");
2006 if (Lqcd != offset)
2007 OJPH_ERROR(0x000500A7, "wrong Lqcc value in QCC marker");
2008 }
2009 else if ((Sqcd & 0x1F) == 2)
2010 {
2011 num_subbands = (Lqcd - offset) / 2;
2012 if (num_subbands == 0)
2013 OJPH_ERROR(0x000500AD, "QCC marker segment that specifies no "
2014 "quantization informtion");
2015 if (num_subbands > 97 || Lqcd != offset + 2 * num_subbands)
2016 OJPH_ERROR(0x000500A8, "wrong Lqcc value of %d in QCC marker", Lqcd);
2017 for (ui32 i = 0; i < num_subbands; ++i)
2018 {
2019 if (file->read(&SPqcd.u16[i], 2) != 2)
2020 OJPH_ERROR(0x000500A9, "error reading QCC marker");
2021 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
2022 }
2023 }
2024 else
2025 OJPH_ERROR(0x000500AA, "wrong Sqcc value in QCC marker");
2026 }
2027
2030 {
2031 assert(type == QCD_MAIN);
2033 if (p == NULL)
2035 p->set_delta(delta);
2036 }
2037
2040 {
2041 assert(this->type == QCD_MAIN);
2042
2043 if (qfactor < 1.0f || qfactor > 100.0f)
2044 OJPH_ERROR(0x00050191, "Qfactor must be between 1 and 100, "
2045 "but was set to %i.", qfactor);
2046
2048 if (p == this)
2050
2051 p->qfactor = qfactor;
2052 p->ctype = ctype;
2053 }
2054
2057 {
2058 // cast object to constant
2059 const param_qcd* const_p = const_cast<const param_qcd*>(this);
2060 // call using the constant object, then cast to non-const
2061 return const_cast<param_qcd*>(const_p->get_qcc(comp_idx));
2062 }
2063
2066 {
2067 assert(this->type == QCD_MAIN || this->top_qcd->type == QCD_MAIN);
2068 const param_qcd *p, *q;
2069 if (this->type == QCD_MAIN)
2070 q = p = this;
2071 else
2072 q = p = this->top_qcd;
2073 while (p && p->comp_idx != comp_idx)
2074 p = p->next;
2075 return p ? p : q;
2076 }
2077
2080 {
2081 assert(type == QCD_MAIN);
2082 param_qcd *p = this;
2083 while (p->next != NULL)
2084 p = p->next;
2085 if (avail)
2086 {
2087 p->next = avail;
2088 avail = avail->next;
2089 p->next->init(this, (ui16)comp_idx);
2090 }
2091 else
2092 p->next = new param_qcd(this, (ui16)comp_idx);
2093 return p->next;
2094 }
2095
2097 //
2098 //
2099 //
2100 //
2101 //
2103
2106 {
2107 double d = 1.0 / (double)((1ull << 32) - 1);
2108 fd_min = (float)((double)d_min * d);
2109 fd_max = (float)((double)d_max * d);
2110 delta = (fd_max - fd_min) / (float)(num_points - 1);
2111 inv_delta = (float)(num_points - 1) / (fd_max - fd_min);
2112 multiplier = (float)(1ull << get_bit_depth());
2113 float divider = 1 / multiplier;
2114 if (bytes_per_point == 1) {
2115 ui8* sp = (ui8*)marker_points;
2116 float* dp = dec_points;
2117 for (ui32 i = 0; i < num_points; ++i)
2118 *dp++ = *sp++ * divider;
2119 dec_points[-1] = dec_points[0];
2121 }
2122 else if (bytes_per_point == 2) {
2123 ui16* sp = (ui16*)marker_points;
2124 float* dp = dec_points;
2125 for (ui32 i = 0; i < num_points; ++i)
2126 *dp++ = *sp++ * divider;
2127 dec_points[-1] = dec_points[0];
2129 }
2130 else if (bytes_per_point == 4) {
2131 ui32* sp = (ui32*)marker_points;
2132 float* dp = dec_points;
2133 for (ui32 i = 0; i < num_points; ++i)
2134 *dp++ = (float)*sp++ * divider;
2135 dec_points[-1] = dec_points[0];
2137 }
2138 else
2139 assert(0);
2140 }
2141
2144 {
2145 double d = 1.0 / (double)((1ull << 32) - 1);
2146 fd_min = (float)((double)d_min * d);
2147 fd_max = (float)((double)d_max * d);
2148
2149 // create lookup table for encoding
2150 float mul = (float)(1ull << pt_val);
2151 float div = 1.0f / mul;
2152 if (bytes_per_point == 1)
2153 {
2154 ui8* p = (ui8*)marker_points;
2155 enc_points[-1] = enc_points[0] = ft_min = (float)p[0] * div;
2156 ft_max = (float)p[num_points - 1] * div;
2158 delta = (ft_max - ft_min) / (float)(enc_num_points - 1);
2159 inv_delta = (float)(enc_num_points - 1) / (ft_max - ft_min);
2160
2161 ui32 k = 0;
2162 float y_k = (float)p[k] * div, y_kp1 = (float)p[k + 1] * div;
2163 float dt = (fd_max - fd_min) / (float)(num_points - 1);
2164 float d_k = fd_min, d_kp1 = fd_min + dt;
2165 for (ui32 i = 1; i < enc_num_points - 1; ++i)
2166 {
2167 float z = ft_min + (float)i * delta;
2168 while (k + 1 < num_points - 1 && z >= y_kp1)
2169 {
2170 ++k;
2171 d_k = d_kp1;
2172 d_kp1 = fd_min + (float)(k + 1) * dt;
2173 y_k = y_kp1;
2174 y_kp1 = (float)p[k + 1] * div;
2175 }
2176 enc_points[i] = d_k + (z - y_k) * dt / (y_kp1 - y_k);
2177 }
2178 }
2179 else if (bytes_per_point == 2) {
2180 ui16* p = (ui16*)marker_points;
2181 enc_points[-1] = enc_points[0] = ft_min = (float)p[0] * div;
2182 ft_max = (float)p[num_points - 1] * div;
2184 delta = (ft_max - ft_min) / (float)(enc_num_points - 1);
2185 inv_delta = (float)(enc_num_points - 1) / (ft_max - ft_min);
2186
2187 ui32 k = 0;
2188 float y_k = (float)p[k] * div, y_kp1 = (float)p[k + 1] * div;
2189 float dt = (fd_max - fd_min) / (float)(num_points - 1);
2190 float d_k = fd_min, d_kp1 = fd_min + dt;
2191 for (ui32 i = 1; i < enc_num_points - 1; ++i)
2192 {
2193 float z = ft_min + (float)i * delta;
2194 while (k + 1 < num_points - 1 && z >= y_kp1)
2195 {
2196 ++k;
2197 d_k = d_kp1;
2198 d_kp1 = fd_min + (float)(k + 1) * dt;
2199 y_k = y_kp1;
2200 y_kp1 = (float)p[k + 1] * div;
2201 }
2202 enc_points[i] = d_k + (z - y_k) * dt / (y_kp1 - y_k);
2203 }
2204 }
2205 else if (bytes_per_point == 4) {
2206 ui32* p = (ui32*)marker_points;
2207 enc_points[-1] = enc_points[0] = ft_min = (float)p[0] * div;
2208 ft_max = (float)p[num_points - 1] * div;
2210 delta = (ft_max - ft_min) / (float)(enc_num_points - 1);
2211 inv_delta = (float)(enc_num_points - 1) / (ft_max - ft_min);
2212
2213 ui32 k = 0;
2214 float y_k = (float)p[k] * div, y_kp1 = (float)p[k + 1] * div;
2215 float dt = (fd_max - fd_min) / (float)(num_points - 1);
2216 float d_k = fd_min, d_kp1 = fd_min + dt;
2217 for (ui32 i = 1; i < enc_num_points - 1; ++i)
2218 {
2219 float z = ft_min + (float)i * delta;
2220 while (k + 1 < num_points - 1 && z >= y_kp1)
2221 {
2222 ++k;
2223 d_k = d_kp1;
2224 d_kp1 = fd_min + (float)(k + 1) * dt;
2225 y_k = y_kp1;
2226 y_kp1 = (float)p[k + 1] * div;
2227 }
2228 enc_points[i] = d_k + (z - y_k) * dt / (y_kp1 - y_k);;
2229 }
2230 }
2231 }
2232
2235 const param_cod& cod) const
2236 {
2237 ui32 num_comps = siz.get_num_components();
2238 for (ui32 c = 0; c < num_comps; ++c)
2239 {
2240 const nlt_rec* rec = get_nlt_rec(c);
2241 if (rec == NULL)
2242 continue;
2243 ui8 type = rec->get_type();
2244 // the LUT style nonlinearities are implemented for the irreversible
2245 // (9/7) wavelet only
2246 if ((type == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2247 type == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT) &&
2248 cod.get_coc(c)->is_reversible())
2249 return (int)c;
2250 }
2251 return -1;
2252 }
2253
2256 {
2257 if (is_any_enabled() == false)
2258 return;
2259
2260 // the reversible wavelet cannot be used with a LUT style nonlinearity,
2261 // because applying that nonlinearity would need the samples of the
2262 // component to be transformed in a way this library cannot invert;
2263 // refusing it here is better than writing a codestream whose nonlinearity
2264 // a decoder cannot undo
2265 int comp = find_unsupported_nlt(siz, cod);
2266 if (comp >= 0)
2267 OJPH_ERROR(0x000501B1, "The LUT style nonlinearities (type 2, LUT "
2268 "style, and type 4, binary complement followed by a LUT) are "
2269 "supported with the irreversible (9/7) wavelet only; component %d of "
2270 "this codestream is coded with the reversible (5/3) wavelet. Use the "
2271 "irreversible wavelet for that component, use the binary complement "
2272 "nonlinearity (type 3), or do not use a nonlinearity with it.",
2273 comp);
2274
2275 if (this->enabled && this->rec.Tnlt == nonlinearity::OJPH_NLT_UNDEFINED)
2276 this->enabled = false;
2277
2278 if (this->enabled &&
2279 this->rec.Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
2280 {
2281 bool all_same = true;
2282 ui32 num_comps = siz.get_num_components();
2283
2284 // first stage; find out if all components captured by the default
2285 // entry (ALL_COMPS) has the same bit_depth/signedness,
2286 // while doing this, set the BDnlt for components not captured by the
2287 // default entry (ALL_COMPS)
2288 ui32 bit_depth = 0; // unknown yet
2289 bool is_signed = false; // unknown yet
2290 for (ui32 c = 0; c < num_comps; ++c)
2291 { // captured by ALL_COMPS
2292 param_nlt* p = get_nlt_object(c);
2293 if (p == NULL || !p->enabled)
2294 {
2295 if (bit_depth != 0)
2296 {
2297 // we have seen an undefined component previously
2298 all_same = all_same && (bit_depth == siz.get_bit_depth(c));
2299 all_same = all_same && (is_signed == siz.is_signed(c));
2300 }
2301 else
2302 {
2303 // this is the first component which has not type 3 nlt definition
2304 bit_depth = siz.get_bit_depth(c);
2305 is_signed = siz.is_signed(c);
2306 }
2307 }
2308 else
2309 { // can be type 0 or type 3
2310 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2311 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2312 }
2313 }
2314
2315 if (all_same && bit_depth != 0)
2316 { // all the same, and some components are captured by ALL_COMPS
2317 this->rec.BDnlt = (ui8)(bit_depth - 1);
2318 this->rec.BDnlt = (ui8)(this->rec.BDnlt | (is_signed ? 0x80 : 0));
2319 }
2320 else if (!all_same)
2321 { // have different settings or no component is captured by ALL_COMPS
2322 this->enabled = false;
2323 for (ui32 c = 0; c < num_comps; ++c)
2324 {
2325 param_nlt* p = get_nlt_object(c);
2326 if (p == NULL || !p->enabled)
2327 { // captured by ALL_COMPS
2328 if (p == NULL)
2329 p = add_object(c);
2330 p->enabled = true;
2331 p->rec.Tnlt = nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
2332 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2333 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80:0));
2334 }
2335 }
2336 }
2337 }
2338 else {
2339 // fill NLT segment markers with correct information
2340 ui32 num_comps = siz.get_num_components();
2341 for (ui32 c = 0; c < num_comps; ++c)
2342 {
2343 param_nlt* p = get_nlt_object(c);
2344 if (p != NULL && p->enabled)
2345 { // can be type 0 or type 3
2346 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2347 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2348 }
2349 }
2350 }
2351
2353
2354 if (is_any_enabled() == true)
2356 }
2357
2360 {
2361 if (nl_type != ojph::param_nlt::OJPH_NLT_NO_NLT &&
2363 OJPH_ERROR(0x00050171, "Nonliearities other than type 0 "
2364 "(No Nonlinearity) or type 3 (Binary Binary Complement to Sign "
2365 "Magnitude Conversion) are not supported in this function call");
2366 param_nlt* p = get_nlt_object(comp_num);
2367 if (p == NULL)
2368 p = add_object(comp_num);
2369 p->Lnlt = 6;
2370 p->rec.Tnlt = nl_type;
2371 p->enabled = true;
2372 }
2373
2376 ui8 decoded_bit_depth,
2377 bool decoded_signedness,
2378 ui32 d_min, ui32 d_max, ui8 pt_val,
2379 ui16 num_points, void* points,
2380 ui8 nl_type)
2381 {
2384 OJPH_ERROR(0x000501A1, "Nonliearities other than type 1 "
2385 "(LUT Nonlinearity) or type 4 (Binary Binary Complement to Sign "
2386 "Magnitude Conversion followed by LUT Nonlinearity) are not "
2387 "supported in this function call");
2388 if (pt_val == 0 || pt_val > 32)
2389 OJPH_ERROR(0x000501A2, "pt_val must be larger than 0 and "
2390 "smaller than or equal to 32; you provided, %d", pt_val);
2391 if (decoded_bit_depth == 0 || decoded_bit_depth > 38)
2392 OJPH_ERROR(0x000501A3, "decoded_bit_depth must be larger than 0 and "
2393 "smaller than or equal to 38; you provided, %d", decoded_bit_depth);
2394 if (d_min >= d_max)
2395 OJPH_ERROR(0x000501A4, "d_max must be larger than d_min; you "
2396 "provided %d and %d", d_min, d_max);
2397 if (num_points < 2 || num_points > 8192)
2398 OJPH_ERROR(0x000501A5, "The number of points must be larger or equal "
2399 "to 2 and smaller or equal to 8192 -- the code will convert this "
2400 "number to a number in the range 1 to 8191 for the NLT marker "
2401 "segement; you provided %d", num_points);
2402
2403 param_nlt* p = get_nlt_object(comp_num);
2404 if (p == NULL)
2405 p = add_object(comp_num);
2406
2407 p->Lnlt = (ui16)(17u + (ui32)num_points * (ui32)p->rec.get_bpp(pt_val));
2408 p->rec.BDnlt =
2409 (ui8)((decoded_bit_depth - 1) | (decoded_signedness ? 0x80 : 0));
2410 p->rec.Tnlt = nl_type;
2411
2412 p->rec.d_min = d_min;
2413 p->rec.d_max = d_max;
2414 p->rec.pt_val = pt_val;
2415 p->rec.num_points = num_points;
2416 p->rec.bytes_per_point = p->rec.get_bpp(pt_val);
2417
2418 // Check that the LUT has increasing entries or has almost flat segments
2419 ui32 v_min = 0, v_max = 0;
2420 ui32 smallest_gap = UINT_MAX;
2421 if (p->rec.bytes_per_point == 1)
2422 {
2423 ui8* p = (ui8*)points;
2424 for (int k = 0; k < num_points - 1; ++k)
2425 {
2426 if (p[k+1] > p[k])
2427 smallest_gap = ojph_min(smallest_gap, (ui32)(p[k+1] - p[k]));
2428 else
2429 OJPH_ERROR(0x000501A6, "The LUT must have increasing sequence "
2430 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2431 "%d and %d.", k, k, p[k+1], p[k]);
2432 }
2433 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2434 }
2435 else if (p->rec.bytes_per_point == 2)
2436 {
2437 ui16* p = (ui16*)points;
2438 for (int k = 0; k < num_points - 1; ++k)
2439 {
2440 if (p[k+1] > p[k])
2441 smallest_gap = ojph_min(smallest_gap, (ui32)(p[k+1] - p[k]));
2442 else
2443 OJPH_ERROR(0x000501A7, "The LUT must have increasing sequence "
2444 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2445 "%d and %d.", k, k, p[k+1], p[k]);
2446 }
2447 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2448 }
2449 else if (p->rec.bytes_per_point == 4)
2450 {
2451 ui32* p = (ui32*)points;
2452 for (int k = 0; k < num_points - 1; ++k)
2453 {
2454 if (p[k+1] > p[k])
2455 smallest_gap = ojph_min(smallest_gap, p[k+1] - p[k]);
2456 else
2457 OJPH_ERROR(0x000501A8, "The LUT must have increasing sequence "
2458 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2459 "%d and %d.", k, k, p[k+1], p[k]);
2460 }
2461 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2462 }
2463 else
2464 assert(0);
2465
2466 // find ceil of the ratio to a power of 2
2467 ui32 ienc_pnts;
2468 float enc_pnts = std::ceil((float)(v_max-v_min) / (float)(smallest_gap));
2469 if (enc_pnts > 8192.0f)
2470 {
2471 ienc_pnts = 8192;
2472 OJPH_WARN(0x000501A1, "Encoding with LUT is performed with an "
2473 "encoding LUT, derived from the LUT you provided; however, "
2474 "because the provided LUT has almost flat segment or segments, "
2475 "these are hard to invert. We are limiting the encoding "
2476 "LUT to 8192 entries, which means that some segment of the "
2477 "LUT table might be ignored during encoding.")
2478 }
2479 else {
2480 ienc_pnts = (ui32)enc_pnts;
2481 ienc_pnts = 32 - count_leading_zeros(ienc_pnts);
2482 ienc_pnts = 1u << ienc_pnts;
2483 }
2484
2485 ui32 len = p->rec.cal_store_size_for_encoding(ienc_pnts);
2486 if (len > p->rec.store_size)
2487 {
2488 if (p->rec.points_store)
2489 delete[] (ui8*)p->rec.points_store;
2490 p->rec.store_size = 0;
2491 p->rec.points_store = new (std::nothrow) ui8[len];
2492 if (p->rec.points_store == NULL)
2493 OJPH_ERROR(0x000501A9, "Failed to allocated memory");
2494 p->rec.store_size = len;
2495 }
2497 memcpy(p->rec.marker_points, points, num_points * p->rec.bytes_per_point);
2499
2500 p->enabled = true;
2501 }
2502
2504 bool
2506 bool& is_signed, ui8& nl_type) const
2507 {
2508 // top level must be ALL_COMPS; cannot call this functions from
2509 // non-top nlt
2510 assert(Cnlt == special_comp_num::ALL_COMPS);
2511 const param_nlt* p = get_nlt_object(comp_num);
2512 p = (p && p->enabled) ? p : this;
2513 if (p->enabled)
2514 {
2515 bit_depth = (ui8)((p->rec.BDnlt & 0x7F) + 1);
2516 bit_depth = bit_depth <= 38 ? bit_depth : 38;
2517 is_signed = (p->rec.BDnlt & 0x80) == 0x80;
2518 nl_type = (nonlinearity)p->rec.Tnlt;
2519 return true;
2520 }
2521 return false;
2522 }
2523
2526 {
2527 if (is_any_enabled() == false)
2528 return true;
2529
2530 ui8 buf1;
2531 ui16 buf2;
2532 ui32 buf4;
2533 bool result = true;
2534 const param_nlt* p = this;
2535 while (p)
2536 {
2537 if (p->enabled)
2538 {
2539 buf2 = JP2K_MARKER::NLT;
2540 buf2 = swap_bytes_if_le(buf2);
2541 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2542 buf2 = swap_bytes_if_le(p->Lnlt);
2543 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2544 buf2 = swap_bytes_if_le(p->Cnlt);
2545 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2546 result &= file->write(&p->rec.BDnlt, 1) == 1;
2547 result &= file->write(&p->rec.Tnlt, 1) == 1;
2548 if (p->rec.Tnlt == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2549 p->rec.Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2550 {
2551 buf2 = (ui16)(p->rec.num_points - 1);
2552 buf2 = swap_bytes_if_le(buf2);
2553 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2554 buf4 = swap_bytes_if_le(p->rec.d_min);
2555 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2556 buf4 = swap_bytes_if_le(p->rec.d_max);
2557 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2558 // pt_val is a single byte in the marker segment; it must not be
2559 // written through the address of the 32 bit member, which would
2560 // write its most significant (and usually zero) byte on a
2561 // big-endian machine
2562 buf1 = (ui8)p->rec.pt_val;
2563 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
2564
2565 ui32 len = p->rec.bytes_per_point * p->rec.num_points;
2566 if (p->rec.bytes_per_point == 1)
2567 result &= file->write(p->rec.marker_points, len) == len;
2568 else if (p->rec.bytes_per_point == 2)
2569 {
2570 char* sp = (char*)p->rec.marker_points;
2571 for (ui32 i = 0; i < p->rec.num_points; ++i, sp += 2)
2572 {
2573 memcpy(&buf2, sp, 2); // not to violate strict aliasing
2574 buf2 = swap_bytes_if_le(buf2);
2575 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2576 }
2577 }
2578 else
2579 {
2580 char* sp = (char*)p->rec.marker_points;
2581 for (ui32 i = 0; i < p->rec.num_points; ++i, sp += 4)
2582 {
2583 memcpy(&buf4, sp, 4); // not to violate strict aliasing
2584 buf4 = swap_bytes_if_le(buf4);
2585 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2586 }
2587 }
2588 }
2589 }
2590 p = p->next;
2591 }
2592 return result;
2593 }
2594
2597 {
2598 ui16 buf2_len;
2599 ui16 buf2_comp;
2600 ui8 buf1_BDnlt;
2601 ui8 buf1_Tnlt;
2602 bool result = true;
2603
2604 result &= file->read(&buf2_len, sizeof(ui16)) == sizeof(ui16);
2605 result &= file->read(&buf2_comp, sizeof(ui16)) == sizeof(ui16);
2606 result &= file->read(&buf1_BDnlt, sizeof(ui8)) == sizeof(ui8);
2607 result &= file->read(&buf1_Tnlt, sizeof(ui8)) == sizeof(ui8);
2608
2609 if (buf1_Tnlt != nonlinearity::OJPH_NLT_NO_NLT &&
2610 buf1_Tnlt != nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT &&
2611 buf1_Tnlt != nonlinearity::OJPH_NLT_LUT_STYLE_NLT &&
2612 buf1_Tnlt != nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2613 OJPH_ERROR(0x00050141, "Unsupported nonlinearity type in an "
2614 "NLT marker segment, with a value of", buf1_Tnlt);
2615
2616 ui16 length = swap_bytes_if_le(buf2_len);
2617 if (buf1_Tnlt == nonlinearity::OJPH_NLT_NO_NLT ||
2618 buf1_Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
2619 {
2620 if (length != 6)
2621 OJPH_ERROR(0x00050142, "Somethins is wrong with this NLT "
2622 "marker segment -- it has an incorrect length of %d",
2623 length);
2624 }
2625
2626 ui16 comp = swap_bytes_if_le(buf2_comp);
2627 if (comp > 16383 && comp != special_comp_num::ALL_COMPS)
2628 OJPH_ERROR(0x00050143, "Something is wrong with this NLT "
2629 "marker segment -- it has an incorrect component index of %d",
2630 comp);
2631
2632 param_nlt* p = get_nlt_object(comp);
2633 if (p == NULL)
2634 p = add_object(comp);
2635 p->enabled = true;
2636 p->Cnlt = comp;
2637 p->rec.BDnlt = buf1_BDnlt;
2638 if ((buf1_BDnlt & 0x7F) + 1 > 38)
2639 OJPH_ERROR(0x00050144, "The NLT marker segment has an invalid bit "
2640 "depth of %d", (buf1_BDnlt & 0x7F) + 1);
2641 p->rec.Tnlt = buf1_Tnlt;
2642
2643 if (buf1_Tnlt == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2644 buf1_Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2645 {
2646 ui16 buf2_num_points;
2647 ui32 buf4_d_min, buf4_d_max;
2648 ui8 buf_pt_val;
2649
2650 result &= file->read(&buf2_num_points, sizeof(ui16)) == sizeof(ui16);
2651 result &= file->read(&buf4_d_min, sizeof(ui32)) == sizeof(ui32);
2652 result &= file->read(&buf4_d_max, sizeof(ui32)) == sizeof(ui32);
2653 result &= file->read(&buf_pt_val, sizeof(ui8)) == sizeof(ui8);
2654
2655 buf2_num_points = swap_bytes_if_le(buf2_num_points);
2656 buf4_d_min = swap_bytes_if_le(buf4_d_min);
2657 buf4_d_max = swap_bytes_if_le(buf4_d_max);
2658
2659 if (buf2_num_points < 1 || buf2_num_points > 8191)
2660 OJPH_ERROR(0x00050145, "The NLT marker segment has an invalid "
2661 "number of points field", buf2_num_points);
2662 if (buf4_d_min >= buf4_d_max)
2663 OJPH_ERROR(0x00050146, "In an NLT marker segment, Dmin must smaller "
2664 "than Dmax; here we have %d and %d", buf4_d_min, buf4_d_max);
2665 if (buf_pt_val == 0 || buf_pt_val > 32)
2666 OJPH_ERROR(0x00050147, "In an NLT marker segment, the value of "
2667 "pt_val must be larger than 0 and smaller or equal to 32; "
2668 "here, we have %d", buf_pt_val);
2669
2670 p->rec.num_points = buf2_num_points + 1;
2671 p->rec.d_min = buf4_d_min;
2672 p->rec.d_max = buf4_d_max;
2673 p->rec.pt_val = buf_pt_val;
2674 p->rec.bytes_per_point = p->rec.get_bpp(buf_pt_val);
2675
2676 // read the points
2678 if (p->rec.store_size < len)
2679 {
2680 if (p->rec.points_store)
2681 delete[] (ui8*)p->rec.points_store;
2682 p->rec.store_size = 0;
2683 p->rec.points_store = new (std::nothrow) ui8[len];
2684 if (p->rec.points_store == NULL)
2685 OJPH_ERROR(0x00050148, "Failed to allocated memory");
2686 p->rec.store_size = len;
2687 }
2689
2690 if (p->rec.bytes_per_point == 1)
2691 result &= file->read(p->rec.marker_points, len) == len;
2692 else if (p->rec.bytes_per_point == 2)
2693 {
2694 ui16 buf2;
2695 char* dp = (char*)p->rec.marker_points;
2696 for (ui32 i = 0; i < p->rec.num_points; ++i, dp += 2)
2697 {
2698 result &= file->read(&buf2, sizeof(ui16)) == sizeof(ui16);
2699 buf2 = swap_bytes_if_le(buf2);
2700 memcpy(dp, &buf2, 2); // not to violate strict aliasing
2701 }
2702 }
2703 else
2704 {
2705 ui32 buf4;
2706 char* dp = (char*)p->rec.marker_points;
2707 for (ui32 i = 0; i < p->rec.num_points; ++i, dp += 4)
2708 {
2709 result &= file->read(&buf4, sizeof(ui32)) == sizeof(ui32);
2710 buf4 = swap_bytes_if_le(buf4);
2711 memcpy(dp, &buf4, 4); // not to violate strict aliasing
2712 }
2713 }
2715 }
2716
2717 return result;
2718 }
2719
2721 const nlt_rec* param_nlt::get_nlt_rec(ui32 comp_num) const
2722 {
2723 assert(Cnlt == special_comp_num::ALL_COMPS);
2724 const param_nlt* p = get_nlt_object(comp_num);
2725 if (p && p->enabled)
2726 return &p->rec;
2727 else if (this->enabled)
2728 return &this->rec;
2729 else
2730 return NULL;
2731 }
2732
2735 {
2736 // cast object to constant
2737 const param_nlt* const_p = const_cast<const param_nlt*>(this);
2738 // call using the constant object, then cast to non-const
2739 return const_cast<param_nlt*>(const_p->get_nlt_object(comp_num));
2740 }
2741
2744 {
2745 // top level must be ALL_COMPS; cannot call this functions from
2746 // non-top nlt
2747 assert(Cnlt == special_comp_num::ALL_COMPS);
2748
2749 const param_nlt* p = this;
2750 while (p && p->Cnlt != comp_num)
2751 p = p->next;
2752 return p;
2753 }
2754
2757 {
2758 assert(comp_num != special_comp_num::ALL_COMPS);
2759 assert(Cnlt == special_comp_num::ALL_COMPS); // top level
2760 param_nlt* p = this;
2761 while (p->next != NULL) {
2762 assert(p->Cnlt != comp_num);
2763 p = p->next;
2764 }
2765 if (avail)
2766 {
2767 p->next = avail;
2768 avail = avail->next;
2769 p->next->init();
2770 }
2771 else
2772 p->next = new param_nlt;
2773 p = p->next;
2774 p->Cnlt = (ui16)comp_num;
2775 return p;
2776 }
2777
2780 {
2781 // check if any field is enabled
2782 const param_nlt* p = this;
2783 while (p && p->enabled == false)
2784 p = p->next;
2785 return (p != NULL);
2786 }
2787
2790 {
2791 param_nlt* p = this->next;
2792 while (p) {
2793 if (p->enabled == true && p->Cnlt >= num_comps) {
2794 p->enabled = false;
2795 OJPH_INFO(0x00050161, "The NLT marker segment for the "
2796 "non-existing component %d has been removed.", p->Cnlt);
2797 }
2798 p = p->next;
2799 }
2800 }
2801
2802
2804 //
2805 //
2806 //
2807 //
2808 //
2810
2812 bool param_sot::write(outfile_base *file, ui32 payload_len)
2813 {
2814 ui16 buf2;
2815 ui32 buf4;
2816 bool result = true;
2817
2818 this->Psot = payload_len + 14; //inc. SOT marker, field & SOD
2819
2820 buf2 = JP2K_MARKER::SOT;
2821 buf2 = swap_bytes_if_le(buf2);
2822 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2823 buf2 = swap_bytes_if_le(Lsot);
2824 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2825 buf2 = swap_bytes_if_le(Isot);
2826 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2827 buf4 = swap_bytes_if_le(Psot);
2828 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2829 result &= file->write(&TPsot, 1) == 1;
2830 result &= file->write(&TNsot, 1) == 1;
2831
2832 return result;
2833 }
2834
2836 bool param_sot::write(outfile_base *file, ui32 payload_len,
2837 ui8 TPsot, ui8 TNsot)
2838 {
2839 ui32 buf4;
2840 ui16 buf2;
2841 bool result = true;
2842
2843 buf2 = JP2K_MARKER::SOT;
2844 buf2 = swap_bytes_if_le(buf2);
2845 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2846 buf2 = swap_bytes_if_le(Lsot);
2847 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2848 buf2 = swap_bytes_if_le(Isot);
2849 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2850 buf4 = swap_bytes_if_le(payload_len + 14);
2851 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2852 result &= file->write(&TPsot, 1) == 1;
2853 result &= file->write(&TNsot, 1) == 1;
2854
2855 return result;
2856 }
2857
2859 bool param_sot::read(infile_base *file, bool resilient)
2860 {
2861 if (resilient)
2862 {
2863 if (file->read(&Lsot, 2) != 2)
2864 {
2865 OJPH_INFO(0x00050091, "error reading SOT marker");
2866 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2867 return false;
2868 }
2869 Lsot = swap_bytes_if_le(Lsot);
2870 if (Lsot != 10)
2871 {
2872 OJPH_INFO(0x00050092, "error in SOT length");
2873 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2874 return false;
2875 }
2876 if (file->read(&Isot, 2) != 2)
2877 {
2878 OJPH_INFO(0x00050093, "error reading tile index");
2879 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2880 return false;
2881 }
2882 Isot = swap_bytes_if_le(Isot);
2883 if (Isot == 0xFFFF)
2884 {
2885 OJPH_INFO(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2886 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2887 return false;
2888 }
2889 if (file->read(&Psot, 4) != 4)
2890 {
2891 OJPH_INFO(0x00050095, "error reading SOT marker");
2892 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2893 return false;
2894 }
2895 Psot = swap_bytes_if_le(Psot);
2896 if (file->read(&TPsot, 1) != 1)
2897 {
2898 OJPH_INFO(0x00050096, "error reading SOT marker");
2899 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2900 return false;
2901 }
2902 if (file->read(&TNsot, 1) != 1)
2903 {
2904 OJPH_INFO(0x00050097, "error reading SOT marker");
2905 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
2906 return false;
2907 }
2908 }
2909 else
2910 {
2911 if (file->read(&Lsot, 2) != 2)
2912 OJPH_ERROR(0x00050091, "error reading SOT marker");
2913 Lsot = swap_bytes_if_le(Lsot);
2914 if (Lsot != 10)
2915 OJPH_ERROR(0x00050092, "error in SOT length");
2916 if (file->read(&Isot, 2) != 2)
2917 OJPH_ERROR(0x00050093, "error reading SOT tile index");
2918 Isot = swap_bytes_if_le(Isot);
2919 if (Isot == 0xFFFF)
2920 OJPH_ERROR(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
2921 if (file->read(&Psot, 4) != 4)
2922 OJPH_ERROR(0x00050095, "error reading SOT marker");
2923 Psot = swap_bytes_if_le(Psot);
2924 if (file->read(&TPsot, 1) != 1)
2925 OJPH_ERROR(0x00050096, "error reading SOT marker");
2926 if (file->read(&TNsot, 1) != 1)
2927 OJPH_ERROR(0x00050097, "error reading SOT marker");
2928 }
2929 return true;
2930 }
2931
2933 //
2934 //
2935 //
2936 //
2937 //
2939
2942 {
2944 OJPH_ERROR(0x000500B1, "Trying to store %d tileparts in TLM markers, "
2945 "but at most %d can be indexed; a codestream can carry "
2946 "%d TLM marker segments of %d entries each.",
2949 this->num_pairs = num_pairs;
2950 pairs = store;
2951 }
2952
2955 {
2956 assert(next_pair_index < num_pairs);
2957 pairs[next_pair_index].Ttlm = Ttlm;
2958 pairs[next_pair_index].Ptlm = Ptlm + 14;
2960 }
2961
2964 {
2965 assert(next_pair_index == num_pairs);
2966 ui16 buf2;
2967 ui32 buf4;
2968 bool result = true;
2969
2970 ui32 written = 0;
2971 ui32 z = 0;
2972 do
2973 {
2974 ui32 left = num_pairs - written;
2975 ui32 count = left < MAX_PAIRS_PER_SEG ? left : MAX_PAIRS_PER_SEG;
2976 ui8 Ztlm = (ui8)z;
2977 ui8 Stlm = 0x60; // 2-byte Ttlm, 4-byte Ptlm
2978
2979 buf2 = JP2K_MARKER::TLM;
2980 buf2 = swap_bytes_if_le(buf2);
2981 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2982 buf2 = swap_bytes_if_le((ui16)(4 + 6 * count));
2983 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2984 result &= file->write(&Ztlm, 1) == 1;
2985 result &= file->write(&Stlm, 1) == 1;
2986 for (ui32 i = written; i < written + count; ++i)
2987 {
2988 buf2 = swap_bytes_if_le(pairs[i].Ttlm);
2989 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2990 buf4 = swap_bytes_if_le(pairs[i].Ptlm);
2991 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2992 }
2993 written += count;
2994 ++z;
2995 } while (written < num_pairs);
2996 return result;
2997 }
2998
3000 //
3001 //
3002 //
3003 //
3004 //
3006
3008 const param_dfs* param_dfs::get_dfs(int index) const
3009 {
3010 const param_dfs* p = this;
3011 while (p && p->Sdfs != index)
3012 p = p->next;
3013 return p;
3014 }
3015
3018 {
3019 decomp_level = ojph_min(decomp_level, Ids);
3020 ui32 d = decomp_level - 1; // decomp_level starts from 1
3021 ui32 idx = d >> 2; // complete bytes
3022 ui32 bits = d & 0x3; // bit within the bytes
3023 ui32 val = (Ddfs[idx] >> (6 - 2 * bits)) & 0x3;
3024 return (dfs_dwt_type)val;
3025 }
3026
3029 ui32 subband) const
3030 {
3031 assert((resolution == 0 && subband == 0) ||
3032 (resolution > 0 && subband > 0 && subband < 4));
3033
3034 ui32 ns[4] = { 0, 3, 1, 1 };
3035
3036 ui32 idx = 0;
3037 if (resolution > 0)
3038 {
3039 idx = 0;
3040 ui32 i = 1;
3041 for (; i < resolution; ++i)
3042 idx += ns[get_dwt_type(num_decompositions - i + 1)];
3043 dfs_dwt_type t = get_dwt_type(num_decompositions - i + 1);
3044 idx += subband;
3045 if (t == VERT_DWT && subband == 2)
3046 --idx;
3047 }
3048
3049 return idx;
3050 }
3051
3053 point param_dfs::get_res_downsamp(ui32 skipped_resolutions) const
3054 {
3055 point factor(1, 1);
3056 ui32 decomp_level = 1;
3057 while (skipped_resolutions > 0)
3058 {
3059 param_dfs::dfs_dwt_type type = get_dwt_type(decomp_level);
3060 if (type == BIDIR_DWT)
3061 { factor.x *= 2; factor.y *= 2; }
3062 else if (type == HORZ_DWT)
3063 factor.x *= 2;
3064 else if (type == VERT_DWT)
3065 factor.y *= 2;
3066
3067 ++decomp_level;
3068 --skipped_resolutions;
3069 }
3070 return factor;
3071 }
3072
3075 {
3076 if (Ldfs != 0) { // this param_dfs is used
3077 param_dfs* p = this;
3078 while (p->next != NULL)
3079 p = p->next;
3080 if (avail)
3081 {
3082 p->next = avail;
3083 avail = avail->next;
3084 p->next->init();
3085 }
3086 else
3087 p->next = new param_dfs;
3088 p = p->next;
3089 return p->read(file);
3090 }
3091
3092 if (file->read(&Ldfs, 2) != 2)
3093 OJPH_ERROR(0x000500D1, "error reading DFS-Ldfs parameter");
3094 Ldfs = swap_bytes_if_le(Ldfs);
3095 if (file->read(&Sdfs, 2) != 2)
3096 OJPH_ERROR(0x000500D2, "error reading DFS-Sdfs parameter");
3097 Sdfs = swap_bytes_if_le(Sdfs);
3098 if (Sdfs > 15)
3099 OJPH_ERROR(0x000500D3, "The DFS-Sdfs parameter is %d, which is "
3100 "larger than the permissible 15", Sdfs);
3101 ui8 t, l_Ids = 0;
3102 if (file->read(&l_Ids, 1) != 1)
3103 OJPH_ERROR(0x000500D4, "error reading DFS-Ids parameter");
3104 if (l_Ids == 0)
3105 OJPH_ERROR(0x000500D8,
3106 "The value of the Ids member in the DFS marker segment cannot be 0");
3107 constexpr int max_Ddfs = sizeof(Ddfs) * 4;
3108 if (l_Ids > max_Ddfs)
3109 OJPH_INFO(0x000500D5, "The DFS-Ids parameter is %d; while this is "
3110 "valid, the number is unnessarily large -- you do not need more "
3111 "than %d. Please contact me regarding this issue.",
3112 l_Ids, max_Ddfs);
3113 Ids = l_Ids < max_Ddfs ? l_Ids : max_Ddfs;
3114 for (int i = 0; i < Ids; i += 4)
3115 if (file->read(&Ddfs[i / 4], 1) != 1)
3116 OJPH_ERROR(0x000500D6, "error reading DFS-Ddfs parameters");
3117 for (int i = Ids; i < l_Ids; i += 4)
3118 if (file->read(&t, 1) != 1)
3119 OJPH_ERROR(0x000500D7, "error reading DFS-Ddfs parameters");
3120 return true;
3121 }
3122
3124 //
3125 //
3126 //
3127 //
3128 //
3130
3133 {
3134 assert(top_atk == NULL);
3135
3136 if (Latk == 0)
3137 {
3138 // This atk object is not used, initialize it to either 0 (irv97)
3139 // or 1 (rev53), and use it. If index is not 0 nor 1, then index
3140 // must have been read from file previously, otherwise it is an
3141 // error.
3142 if (index == 0) { this->init_irv97(); return this; }
3143 else if (index == 1) { this->init_rev53(); return this; }
3144 }
3145
3146 param_atk* p = this;
3147 while (p && p->get_index() != index)
3148 p = p->next;
3149
3150 if (p == NULL && (index == 0 || index == 1))
3151 {
3152 // The index was not found, add an atk object only if the index is
3153 // either 0 or 1
3154 p = add_object();
3155 if (index == 0)
3156 p->init_irv97();
3157 else if (index == 1)
3158 p->init_rev53();
3159 }
3160
3161 return p;
3162 }
3163
3165 bool param_atk::read_coefficient(infile_base *file, float &K, si32& bytes)
3166 {
3167 int coeff_type = get_coeff_type();
3168 if (coeff_type == 0) { // 8bit
3169 ui8 v;
3170 if (file->read(&v, 1) != 1) return false;
3171 bytes -= 1;
3172 K = v;
3173 }
3174 else if (coeff_type == 1) { // 16bit
3175 ui16 v;
3176 if (file->read(&v, 2) != 2) return false;
3177 bytes -= 2;
3178 K = swap_bytes_if_le(v);
3179 }
3180 else if (coeff_type == 2) { // float
3181 ui32 i;
3182 if (file->read(&i, sizeof(ui32)) != sizeof(ui32)) return false;
3183 bytes -= 4;
3184 i = swap_bytes_if_le(i);
3185 float f;
3186 memcpy(&f, &i, sizeof(float));
3187 K = f;
3188 }
3189 else if (coeff_type == 3) { // double
3190 ui64 i;
3191 if (file->read(&i, sizeof(ui64)) != sizeof(ui64)) return false;
3192 bytes -= 8;
3193 i = swap_bytes_if_le(i);
3194 double d;
3195 memcpy(&d, &i, sizeof(double));
3196 K = (float)d;
3197 }
3198 else if (coeff_type == 4) { // 128 bit float
3199 ui64 v, v1;
3200 if (file->read(&v, 8) != 8) return false;
3201 bytes -= 8;
3202 if (file->read(&v1, 8) != 8) return false; // v1 not needed
3203 bytes -= 8;
3204 v = swap_bytes_if_le(v);
3205
3206 // convert the MSB of 128b float to 32b float
3207 // 32b float has 1 sign bit, 8 exponent (offset 127), 23 mantissa
3208 // 128b float has 1 sign bit, 15 exponent (offset 16383), 112 mantissa
3209 si32 e = (si32)((v >> 48) & 0x7FFF); // exponent
3210 e -= 16383;
3211 e += 127;
3212 e = e & 0xFF; // removes MSBs if negative
3213 e <<= 23; // move bits to their location
3214 ui32 i = 0;
3215 i |= ((ui32)(v >> 32) & 0x80000000); // copy sign bit
3216 i |= (ui32)e; // copy exponent
3217 i |= (ui32)((v >> 25) & 0x007FFFFF); // copy 23 mantissa
3218 float f;
3219 memcpy(&f, &i, sizeof(float));
3220 K = f;
3221 }
3222 return true;
3223 }
3224
3225
3228 {
3229 int coeff_type = get_coeff_type();
3230 if (coeff_type == 0) {
3231 si8 v;
3232 if (file->read(&v, 1) != 1) return false;
3233 bytes -= 1;
3234 K = v;
3235 }
3236 else if (coeff_type == 1) {
3237 si16 v;
3238 if (file->read(&v, 2) != 2) return false;
3239 bytes -= 2;
3240 K = (si16)swap_bytes_if_le((ui16)v);
3241 }
3242 else
3243 return false;
3244 return true;
3245 }
3246
3249 {
3250 if (Latk != 0) // this param_atk is used
3251 return add_object()->read(file);
3252
3253 if (file->read(&Latk, 2) != 2)
3254 OJPH_ERROR(0x000500E1, "error reading ATK-Latk parameter");
3255 Latk = swap_bytes_if_le(Latk);
3256 si32 bytes = Latk - 2;
3257 ojph::ui16 temp_Satk;
3258 if (file->read(&temp_Satk, 2) != 2)
3259 OJPH_ERROR(0x000500E2, "error reading ATK-Satk parameter");
3260 bytes -= 2;
3261 temp_Satk = swap_bytes_if_le(temp_Satk);
3262 int tmp_idx = temp_Satk & 0xFF;
3263 if ((top_atk && top_atk->get_atk(tmp_idx) != NULL)
3264 || tmp_idx == 0 || tmp_idx == 1)
3265 OJPH_ERROR(0x000500F3, "ATK-Satk parameter sets ATK marker index to "
3266 "the illegal value of %d. ATK-Satk should be in (2-255) and, I "
3267 "believe, must not be repeated; otherwise, it would be unclear "
3268 "what marker segment must be employed when an index is repeated.",
3269 tmp_idx);
3270 Satk = temp_Satk;
3271 if (is_m_init0() == false) // only even-indexed is supported
3272 OJPH_ERROR(0x000500E3, "ATK-Satk parameter sets m_init to 1, "
3273 "requiring odd-indexed subsequence in first reconstruction step, "
3274 "which is not supported yet.");
3275 if (is_whole_sample() == false) // ARB filter not supported
3276 OJPH_ERROR(0x000500E4, "ATK-Satk parameter specified ARB filter, "
3277 "which is not supported yet.");
3278 if (is_reversible() && get_coeff_type() >= 2) // reversible & float
3279 OJPH_ERROR(0x000500E5, "ATK-Satk parameter does not make sense. "
3280 "It employs floats with reversible filtering.");
3281 if (is_using_ws_extension() == false) // only sym. ext is supported
3282 OJPH_ERROR(0x000500E6, "ATK-Satk parameter requires constant "
3283 "boundary extension, which is not supported yet.");
3284 if (is_reversible() == false)
3285 if (read_coefficient(file, Katk, bytes) == false)
3286 OJPH_ERROR(0x000500E7, "error reading ATK-Katk parameter");
3287 if (file->read(&Natk, 1) != 1)
3288 OJPH_ERROR(0x000500E8, "error reading ATK-Natk parameter");
3289 bytes -= 1;
3290 if (Natk > max_steps) {
3291 if (d != d_store) // was this allocated -- very unlikely
3292 delete[] d;
3293 d = new lifting_step[Natk];
3294 max_steps = Natk;
3295 }
3296
3297 if (is_reversible())
3298 {
3299 for (int s = 0; s < Natk; ++s)
3300 {
3301 if (file->read(&d[s].rev.Eatk, 1) != 1)
3302 OJPH_ERROR(0x000500E9, "error reading ATK-Eatk parameter");
3303 bytes -= 1;
3304 if (file->read(&d[s].rev.Batk, 2) != 2)
3305 OJPH_ERROR(0x000500EA, "error reading ATK-Batk parameter");
3306 bytes -= 2;
3307 d[s].rev.Batk = (si16)swap_bytes_if_le((ui16)d[s].rev.Batk);
3308 ui8 LCatk;
3309 if (file->read(&LCatk, 1) != 1)
3310 OJPH_ERROR(0x000500EB, "error reading ATK-LCatk parameter");
3311 bytes -= 1;
3312 if (LCatk == 0)
3313 OJPH_ERROR(0x000500EC, "Encountered a ATK-LCatk value of zero; "
3314 "something is wrong.");
3315 if (LCatk > 1)
3316 OJPH_ERROR(0x000500ED, "ATK-LCatk value greater than 1; "
3317 "that is, a multitap filter is not supported");
3318 if (read_coefficient(file, d[s].rev.Aatk, bytes) == false)
3319 OJPH_ERROR(0x000500EE, "Error reding ATK-Aatk parameter");
3320 }
3321 }
3322 else
3323 {
3324 for (int s = 0; s < Natk; ++s)
3325 {
3326 ui8 LCatk;
3327 if (file->read(&LCatk, 1) != 1)
3328 OJPH_ERROR(0x000500EF, "error reading ATK-LCatk parameter");
3329 bytes -= 1;
3330 if (LCatk == 0)
3331 OJPH_ERROR(0x000500F0, "Encountered a ATK-LCatk value of zero; "
3332 "something is wrong.");
3333 if (LCatk > 1)
3334 OJPH_ERROR(0x000500F1, "ATK-LCatk value greater than 1; "
3335 "that is, a multitap filter is not supported.");
3336 if (read_coefficient(file, d[s].irv.Aatk, bytes) == false)
3337 OJPH_ERROR(0x000500F2, "Error reding ATK-Aatk parameter");
3338 }
3339 }
3340 if (bytes != 0)
3341 OJPH_ERROR(0x000500F3, "The length of an ATK marker segment "
3342 "(ATK-Latk) is not correct");
3343
3344 return true;
3345 }
3346
3349 {
3350 Satk = 0x4a00; // illegal because ATK = 0
3351 Katk = (float)1.230174104914001;
3352 Natk = 4;
3353 // next is (A-4) in T.801 second line
3354 Latk = (ui16)(5 + Natk + sizeof(float) * (1 + Natk));
3355 d[0].irv.Aatk = (float)0.443506852043971;
3356 d[1].irv.Aatk = (float)0.882911075530934;
3357 d[2].irv.Aatk = (float)-0.052980118572961;
3358 d[3].irv.Aatk = (float)-1.586134342059924;
3359 }
3360
3363 {
3364 Satk = 0x5801; // illegal because ATK = 1
3365 Natk = 2;
3366 // next is (A-4) in T.801 fourth line
3367 Latk = (ui16)(5 + 2 * Natk + sizeof(ui8) * (Natk + Natk));
3368 d[0].rev.Aatk = 1;
3369 d[0].rev.Batk = 2;
3370 d[0].rev.Eatk = 2;
3371 d[1].rev.Aatk = -1;
3372 d[1].rev.Batk = 1;
3373 d[1].rev.Eatk = 1;
3374 }
3375
3378 {
3379 assert(top_atk == NULL);
3380 param_atk *p = this;
3381 while (p->next != NULL)
3382 p = p->next;
3383 if (avail)
3384 {
3385 p->next = avail;
3386 avail = avail->next;
3387 }
3388 else
3389 p->next = new param_atk;
3390 p = p->next;
3391 p->init(this);
3392 return p;
3393 }
3394
3395 } // !local namespace
3396} // !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 float get_delta_ref(float qfactor, ui32 bit_depth, float &power)
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)
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
@ OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT
bool get_nonlinear_transform(ui32 comp_num, ui8 &decoded_bit_depth, bool &decoded_signedness, ui8 &nl_type) const
local::param_nlt * state
void set_nonlinear_transform(ui32 comp_num, ui8 nl_type)
void set_qfactor(float qfactor)
Sets Qfactor.
void set_irrev_quant(float delta)
Set the irreversible quantization base delta.
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
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
const char OJPH_PO_STRING_RLCP[]
const char OJPH_PO_STRING_RPCL[]
const char OJPH_PO_STRING_CPRL[]
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,...)
ui32 cal_store_size_for_encoding(ui32 enc_num_points)
static ui8 get_bpp(ui32 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)
void set_reversible(bool reversible)
bool is_employing_color_transform() const
void employ_color_transform(ui8 val)
bool get_block_vertical_causality() const
void read(infile_base *file)
size get_log_precinct_size(ui32 res_num) const
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)
size get_precinct_size(ui32 res_num) const
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)
ojph::param_nlt::nonlinearity nonlinearity
void check_validity(param_siz &siz, const param_cod &cod)
const param_nlt * get_nlt_object(ui32 comp_num) const
bool read(infile_base *file)
int find_unsupported_nlt(const param_siz &siz, const param_cod &cod) const
void set_nonlinear_transform(ui32 comp_num, ui8 nl_type)
const nlt_rec * get_nlt_rec(ui32 comp_num) const
bool get_nonlinear_transform(ui32 comp_num, ui8 &decoded_bit_depth, bool &decoded_signedness, ui8 &nl_type) 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)
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)
void set_qfactor(float qfactor)
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
ui32 get_recon_height(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_comp_info(ui32 comp_num, const point &downsampling, ui32 bit_depth, bool is_signed)
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)
void set_image_extent(point dims)
ui32 get_recon_width(ui32 comp_num) const
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)
point(ui32 x=0, ui32 y=0)
Definition ojph_base.h:59
size(ui32 w=0, ui32 h=0)
Definition ojph_base.h:49