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_irrev_quant(float delta, size_t num_weights,
420 const float weights[])
421 {
422 state->set_delta(delta, num_weights, weights);
423 }
424
426 void param_qcd::set_qfactor(float qfactor) {
427 state->set_qfactor(qfactor);
428 }
429
431 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta)
432 {
433 state->set_delta(comp_idx, delta);
434 }
435
437 void param_qcd::set_irrev_quant(ui32 comp_idx, float delta,
438 size_t num_weights, const float weights[])
439 {
440 state->set_delta(comp_idx, delta, num_weights, weights);
441 }
442
444 void param_qcd::set_qfactor(ui32 comp_idx, comp_type ctype, float qfactor)
445 {
446 state->set_qfactor(comp_idx, ctype, qfactor);
447 }
448
450 //
451 //
452 //
453 //
454 //
456
459 {
460 state->set_nonlinear_transform(comp_num, nl_type);
461 }
462
465 ui8 decoded_bit_depth,
466 bool decoded_signedness,
467 ui32 d_min, ui32 d_max, ui8 pt_val,
468 ui16 num_points, void* points,
469 ui8 nl_type,
470 bool approx_encoding_nlt,
471 ui32 num_enc_points)
472 {
473 state->set_nonlinear_transform(comp_num, decoded_bit_depth,
474 decoded_signedness, d_min, d_max, pt_val, num_points, points, nl_type,
475 approx_encoding_nlt, num_enc_points);
476 }
477
480 ui8& decoded_bit_depth,
481 bool& decoded_signedness,
482 ui8& nl_type) const
483 {
484 return state->get_nonlinear_transform(comp_num, decoded_bit_depth,
485 decoded_signedness, nl_type);
486 }
487
489 //
490 //
491 //
492 //
493 //
495
497 void comment_exchange::set_string(const char* str)
498 {
499 size_t t = strlen(str);
500 if (len > 65531)
501 OJPH_ERROR(0x000500C1,
502 "COM marker string length cannot be larger than 65531");
503 this->data = str;
504 this->len = (ui16)t;
505 this->Rcom = 1;
506 }
507
510 {
511 if (len > 65531)
512 OJPH_ERROR(0x000500C2,
513 "COM marker string length cannot be larger than 65531");
514 this->data = data;
515 this->len = len;
516 this->Rcom = 0;
517 }
518
520 //
521 //
522 // LOCAL
523 //
524 //
526
527 namespace local {
528
530 //static
532 {
533 public:
534 static float get_gain_l(ui32 num_decomp, bool reversible)
535 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
536 static float get_gain_h(ui32 num_decomp, bool reversible)
537 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
538
539 private:
540 static const float gain_9x7_l[34];
541 static const float gain_9x7_h[34];
542 static const float gain_5x3_l[34];
543 static const float gain_5x3_h[34];
544 };
545
547 const float sqrt_energy_gains::gain_9x7_l[34] = { 1.0000e+00f,
548 1.4021e+00f, 2.0304e+00f, 2.9012e+00f, 4.1153e+00f, 5.8245e+00f,
549 8.2388e+00f, 1.1652e+01f, 1.6479e+01f, 2.3304e+01f, 3.2957e+01f,
550 4.6609e+01f, 6.5915e+01f, 9.3217e+01f, 1.3183e+02f, 1.8643e+02f,
551 2.6366e+02f, 3.7287e+02f, 5.2732e+02f, 7.4574e+02f, 1.0546e+03f,
552 1.4915e+03f, 2.1093e+03f, 2.9830e+03f, 4.2185e+03f, 5.9659e+03f,
553 8.4371e+03f, 1.1932e+04f, 1.6874e+04f, 2.3864e+04f, 3.3748e+04f,
554 4.7727e+04f, 6.7496e+04f, 9.5454e+04f };
555 const float sqrt_energy_gains::gain_9x7_h[34] = { 1.4425e+00f,
556 1.9669e+00f, 2.8839e+00f, 4.1475e+00f, 5.8946e+00f, 8.3472e+00f,
557 1.1809e+01f, 1.6701e+01f, 2.3620e+01f, 3.3403e+01f, 4.7240e+01f,
558 6.6807e+01f, 9.4479e+01f, 1.3361e+02f, 1.8896e+02f, 2.6723e+02f,
559 3.7792e+02f, 5.3446e+02f, 7.5583e+02f, 1.0689e+03f, 1.5117e+03f,
560 2.1378e+03f, 3.0233e+03f, 4.2756e+03f, 6.0467e+03f, 8.5513e+03f,
561 1.2093e+04f, 1.7103e+04f, 2.4187e+04f, 3.4205e+04f, 4.8373e+04f,
562 6.8410e+04f, 9.6747e+04f, 1.3682e+05f };
563 const float sqrt_energy_gains::gain_5x3_l[34] = { 1.0000e+00f,
564 1.2247e+00f, 1.3229e+00f, 1.5411e+00f, 1.7139e+00f, 1.9605e+00f,
565 2.2044e+00f, 2.5047e+00f, 2.8277e+00f, 3.2049e+00f, 3.6238e+00f,
566 4.1033e+00f, 4.6423e+00f, 5.2548e+00f, 5.9462e+00f, 6.7299e+00f,
567 7.6159e+00f, 8.6193e+00f, 9.7544e+00f, 1.1039e+01f, 1.2493e+01f,
568 1.4139e+01f, 1.6001e+01f, 1.8108e+01f, 2.0493e+01f, 2.3192e+01f,
569 2.6246e+01f, 2.9702e+01f, 3.3614e+01f, 3.8041e+01f, 4.3051e+01f,
570 4.8721e+01f, 5.5138e+01f, 6.2399e+01f };
571 const float sqrt_energy_gains::gain_5x3_h[34] = { 1.0458e+00f,
572 1.3975e+00f, 1.4389e+00f, 1.7287e+00f, 1.8880e+00f, 2.1841e+00f,
573 2.4392e+00f, 2.7830e+00f, 3.1341e+00f, 3.5576e+00f, 4.0188e+00f,
574 4.5532e+00f, 5.1494e+00f, 5.8301e+00f, 6.5963e+00f, 7.4663e+00f,
575 8.4489e+00f, 9.5623e+00f, 1.0821e+01f, 1.2247e+01f, 1.3860e+01f,
576 1.5685e+01f, 1.7751e+01f, 2.0089e+01f, 2.2735e+01f, 2.5729e+01f,
577 2.9117e+01f, 3.2952e+01f, 3.7292e+01f, 4.2203e+01f, 4.7761e+01f,
578 5.4051e+01f, 6.1170e+01f, 6.9226e+01f };
579
581 //static
583 {
584 public:
585 static float get_bibo_gain_l(ui32 num_decomp, bool reversible)
586 { return reversible ? gain_5x3_l[num_decomp] : gain_9x7_l[num_decomp]; }
587 static float get_bibo_gain_h(ui32 num_decomp, bool reversible)
588 { return reversible ? gain_5x3_h[num_decomp] : gain_9x7_h[num_decomp]; }
589
590 private:
591 static const float gain_9x7_l[34];
592 static const float gain_9x7_h[34];
593 static const float gain_5x3_l[34];
594 static const float gain_5x3_h[34];
595 };
596
598 const float bibo_gains::gain_9x7_l[34] = { 1.0000e+00f, 1.3803e+00f,
599 1.3328e+00f, 1.3067e+00f, 1.3028e+00f, 1.3001e+00f, 1.2993e+00f,
600 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
601 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
602 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
603 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
604 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f, 1.2992e+00f,
605 1.2992e+00f, 1.2992e+00f };
606 const float bibo_gains::gain_9x7_h[34] = { 1.2976e+00f, 1.3126e+00f,
607 1.2757e+00f, 1.2352e+00f, 1.2312e+00f, 1.2285e+00f, 1.2280e+00f,
608 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
609 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
610 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
611 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
612 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f, 1.2278e+00f,
613 1.2278e+00f, 1.2278e+00f };
614 const float bibo_gains::gain_5x3_l[34] = { 1.0000e+00f, 1.5000e+00f,
615 1.6250e+00f, 1.6875e+00f, 1.6963e+00f, 1.7067e+00f, 1.7116e+00f,
616 1.7129e+00f, 1.7141e+00f, 1.7145e+00f, 1.7151e+00f, 1.7152e+00f,
617 1.7155e+00f, 1.7155e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
618 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
619 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
620 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f, 1.7156e+00f,
621 1.7156e+00f, 1.7156e+00f };
622 const float bibo_gains::gain_5x3_h[34] = { 2.0000e+00f, 2.5000e+00f,
623 2.7500e+00f, 2.8047e+00f, 2.8198e+00f, 2.8410e+00f, 2.8558e+00f,
624 2.8601e+00f, 2.8628e+00f, 2.8656e+00f, 2.8662e+00f, 2.8667e+00f,
625 2.8669e+00f, 2.8670e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
626 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
627 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
628 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f, 2.8671e+00f,
629 2.8671e+00f, 2.8671e+00f };
630
632 //static
634 {
635 public:
645
646 public:
647 static colour_format get_format(const point& component_subsampling)
648 {
649 if (component_subsampling.x == 2 && component_subsampling.y == 2)
651 else if (component_subsampling.x == 2 && component_subsampling.y == 1)
653 else if (component_subsampling.x == 1 && component_subsampling.y == 1)
655 else
657 }
658
659 public:
660 static const float* get_weights(ui32 format, ui32 comp_type)
661 {
662 if (comp_type == comp_type::OJPH_COMP_Y)
663 return y;
664 else if (comp_type == comp_type::OJPH_COMP_CB)
665 {
666 if (format == VW_COLOUR_FORMAT_420) return cb420;
667 else if (format == VW_COLOUR_FORMAT_422) return cb422;
668 else if (format == VW_COLOUR_FORMAT_444) return cb444;
669 else {
670 assert(0);
671 return y;
672 }
673 }
674 else if (comp_type == comp_type::OJPH_COMP_CR)
675 {
676 if (format == VW_COLOUR_FORMAT_420) return cr420;
677 else if (format == VW_COLOUR_FORMAT_422) return cr422;
678 else if (format == VW_COLOUR_FORMAT_444) return cr444;
679 else {
680 assert(0);
681 return y;
682 }
683 }
684 else {
685 assert(0);
686 return y;
687 }
688 }
689
690 static const float* get_no_weights()
691 { return no_weights; }
692
693 static float get_weight(const float *v, ui32 decomposition_level,
694 ui32 subband_idx)
695
696 {
697 if (subband_idx == 0)
698 return v[18];
699 else {
700 assert(subband_idx >= 1 && subband_idx <= 3);
701 assert(decomposition_level > 0);
702 decomposition_level = ojph_min(decomposition_level, 6);
703 ui32 index = (decomposition_level - 1) * 3 + (3 - subband_idx);
704 return v[index];
705 }
706 }
707
709 static float get_gain(ui32 comp_type)
710 {
711 if (comp_type == comp_type::OJPH_COMP_Y)
712 return 1.0f;
713 else if (comp_type == comp_type::OJPH_COMP_CB)
714 return 1.8051f / 1.7321f;
715 else if (comp_type == comp_type::OJPH_COMP_CR)
716 return 1.5734f / 1.7321f;
717 else {
718 assert(0);
719 return 0.0f;
720 }
721 }
722
724 static float get_delta_ref(float qfactor, ui32 bit_depth,
725 float& power)
726 {
727 // returns delta_ref & power to be used with visual weights
728 constexpr float t0 = 65.0f;
729 constexpr float t1 = 97.0f;
730 constexpr float alpha_t0 = 0.04f, alpha_t1 = 0.10f;
731 constexpr float m_t0 = 2.0f * (1.0f - t0 / 100.0f);
732 constexpr float m_t1 = 2.0f * (1.0f - t1 / 100.0f);
733
734 float m_q;
735 if (qfactor < 50.0f)
736 m_q = 50.0f / qfactor;
737 else
738 m_q = 2.0f * (1.0f - qfactor / 100.0f);
739
740 float alpha_q;
741 if (qfactor <= t0)
742 {
743 power = 1.0f;
744 alpha_q = alpha_t0;
745 }
746 else if (qfactor < t1)
747 {
748 power = std::log(m_q) - std::log(m_t1);
749 power /= std::log(m_t0) - std::log(m_t1);
750 alpha_q = alpha_t1 * std::pow(alpha_t0 / alpha_t1, power);
751 }
752 else
753 {
754 power = 0.0f;
755 alpha_q = alpha_t1;
756 }
757 const float eps = std::sqrt(0.5f) * std::ldexp(1.0f, -(int)bit_depth);
758 return alpha_q * m_q + eps;
759 }
760
761 private:
762 static const float cb420[19];
763 static const float cr420[19];
764 static const float cb422[19];
765 static const float cr422[19];
766 static const float cb444[19];
767 static const float cr444[19];
768 static const float y[19];
769 static const float no_weights[19];
770 };
771
773 const float visual_weights::cb420[19] = {
774 0.2724f, 0.5128f, 0.5128f, // level 1
775 0.6692f, 0.9382f, 0.9382f, // level 2
776 1.0888f, 1.3046f, 1.3046f, // level 3
777 1.4156f, 1.5594f, 1.5594f, // level 4
778 2.0f, 2.0f, 2.0f, // level 5
779 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
780 const float visual_weights::cr420[19] = {
781 0.5196f, 0.8260f, 0.8260f, // level 1
782 1.0080f, 1.2928f, 1.2928f, // level 2
783 1.4440f, 1.6508f, 1.6508f, // level 3
784 1.7538f, 1.8848f, 1.8848f, // level 4
785 2.0f, 2.0f, 2.0f, // level 5
786 2.0f, 2.0f, 2.0f, 2.0f}; // level 6 + LL
787 const float visual_weights::cb422[19] = {
788 0.1220f, 0.1220f, 0.3626f, // level 1
789 0.3626f, 0.3626f, 0.6634f, // level 2
790 0.6634f, 0.6634f, 0.9225f, // level 3
791 0.9225f, 0.9225f, 1.1027f, // level 4
792 1.1027f, 1.1027f, 1.4142f, // level 5
793 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
794 const float visual_weights::cr422[19] = {
795 0.2595f, 0.2595f, 0.5841f, // level 1
796 0.5841f, 0.5841f, 0.9141f, // level 2
797 0.9141f, 0.9141f, 1.1673f, // level 3
798 1.1673f, 1.1673f, 1.3328f, // level 4
799 1.3328f, 1.3328f, 1.4142f, // level 5
800 1.4142f, 1.4142f, 1.4142f, 1.4142f}; // level 6 + LL
801 const float visual_weights::cb444[19] = {
802 0.0263f, 0.0863f, 0.0863f, // level 1
803 0.1362f, 0.2564f, 0.2564f, // level 2
804 0.3346f, 0.4691f, 0.4691f, // level 3
805 0.5444f, 0.6523f, 0.6523f, // level 4
806 0.7078f, 0.7797f, 0.7797f, // level 5
807 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
808 const float visual_weights::cr444[19] = {
809 0.0773f, 0.1835f, 0.1835f, // level 1
810 0.2598f, 0.4130f, 0.4130f, // level 2
811 0.5040f, 0.6464f, 0.6464f, // level 3
812 0.7220f, 0.8254f, 0.8254f, // level 4
813 0.8769f, 0.9424f, 0.9424f, // level 5
814 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
815 const float visual_weights::y[19] = {
816 0.0901f, 0.2758f, 0.2758f, // level 1
817 0.7018f, 0.8378f, 0.8378f, // level 2
818 1.0f, 1.0f, 1.0f, // level 3
819 1.0f, 1.0f, 1.0f, // level 4
820 1.0f, 1.0f, 1.0f, // level 5
821 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
822 const float visual_weights::no_weights[19] = {
823 1.0f, 1.0f, 1.0f, // level 1
824 1.0f, 1.0f, 1.0f, // level 2
825 1.0f, 1.0f, 1.0f, // level 3
826 1.0f, 1.0f, 1.0f, // level 4
827 1.0f, 1.0f, 1.0f, // level 5
828 1.0f, 1.0f, 1.0f, 1.0f}; // level 6 + LL
829
830
832 //
833 //
834 //
835 //
836 //
838
841 {
842 //marker size excluding header
843 Lsiz = (ui16)(38 + 3 * Csiz);
844
845 ui8 buf1;
846 ui16 buf2;
847 ui32 buf4;
848 bool result = true;
849
850 buf2 = JP2K_MARKER::SIZ;
851 buf2 = swap_bytes_if_le(buf2);
852 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
853 buf2 = swap_bytes_if_le(Lsiz);
854 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
855 buf2 = swap_bytes_if_le(Rsiz);
856 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
857 buf4 = swap_bytes_if_le(Xsiz);
858 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
859 buf4 = swap_bytes_if_le(Ysiz);
860 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
861 buf4 = swap_bytes_if_le(XOsiz);
862 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
863 buf4 = swap_bytes_if_le(YOsiz);
864 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
865 buf4 = swap_bytes_if_le(XTsiz);
866 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
867 buf4 = swap_bytes_if_le(YTsiz);
868 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
869 buf4 = swap_bytes_if_le(XTOsiz);
870 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
871 buf4 = swap_bytes_if_le(YTOsiz);
872 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
873 buf2 = swap_bytes_if_le(Csiz);
874 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
875 for (int c = 0; c < Csiz; ++c)
876 {
877 buf1 = cptr[c].SSiz;
878 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
879 buf1 = cptr[c].XRsiz;
880 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
881 buf1 = cptr[c].YRsiz;
882 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
883 }
884
885 return result;
886 }
887
890 {
891 if (file->read(&Lsiz, 2) != 2)
892 OJPH_ERROR(0x00050041, "error reading SIZ marker");
893 Lsiz = swap_bytes_if_le(Lsiz);
894 int num_comps = (Lsiz - 38) / 3;
895 if (Lsiz != 38 + 3 * num_comps)
896 OJPH_ERROR(0x00050042, "error in SIZ marker length");
897 if (file->read(&Rsiz, 2) != 2)
898 OJPH_ERROR(0x00050043, "error reading SIZ marker");
899 Rsiz = swap_bytes_if_le(Rsiz);
900 if ((Rsiz & 0x4000) == 0)
901 OJPH_ERROR(0x00050044,
902 "Rsiz bit 14 is not set (this is not a JPH file)");
903 if ((Rsiz & 0x8000) != 0 && (Rsiz & 0xD5F) != 0)
904 OJPH_WARN(0x00050001, "Rsiz in SIZ has unimplemented fields");
905 if (file->read(&Xsiz, 4) != 4)
906 OJPH_ERROR(0x00050045, "error reading SIZ marker");
907 Xsiz = swap_bytes_if_le(Xsiz);
908 if (file->read(&Ysiz, 4) != 4)
909 OJPH_ERROR(0x00050046, "error reading SIZ marker");
910 Ysiz = swap_bytes_if_le(Ysiz);
911 ui32 t_XOsiz, t_YOsiz;
912 if (file->read(&t_XOsiz, 4) != 4)
913 OJPH_ERROR(0x00050047, "error reading SIZ marker");
914 if (file->read(&t_YOsiz, 4) != 4)
915 OJPH_ERROR(0x00050048, "error reading SIZ marker");
917 swap_bytes_if_le(t_XOsiz),
918 swap_bytes_if_le(t_YOsiz)));
919 ui32 t_XTsiz, t_YTsiz;
920 if (file->read(&t_XTsiz, 4) != 4)
921 OJPH_ERROR(0x00050049, "error reading SIZ marker");
922 if (file->read(&t_YTsiz, 4) != 4)
923 OJPH_ERROR(0x0005004A, "error reading SIZ marker");
925 swap_bytes_if_le(t_XTsiz),
926 swap_bytes_if_le(t_YTsiz)));
927 ui32 t_XTOsiz, t_YTOsiz;
928 if (file->read(&t_XTOsiz, 4) != 4)
929 OJPH_ERROR(0x0005004B, "error reading SIZ marker");
930 if (file->read(&t_YTOsiz, 4) != 4)
931 OJPH_ERROR(0x0005004C, "error reading SIZ marker");
933 swap_bytes_if_le(t_XTOsiz),
934 swap_bytes_if_le(t_YTOsiz)));
935 if (file->read(&Csiz, 2) != 2)
936 OJPH_ERROR(0x0005004D, "error reading SIZ marker");
937 Csiz = swap_bytes_if_le(Csiz);
938 if (Csiz != num_comps)
939 OJPH_ERROR(0x0005004E, "Csiz does not match the SIZ marker size");
940 if (Csiz == 0)
941 OJPH_ERROR(0x0005004F, "Wrong Csiz value of 0 in SIZ marker segment");
943 for (int c = 0; c < Csiz; ++c)
944 {
945 if (file->read(&cptr[c].SSiz, 1) != 1)
946 OJPH_ERROR(0x00050051, "error reading SIZ marker");
947 if (file->read(&cptr[c].XRsiz, 1) != 1)
948 OJPH_ERROR(0x00050052, "error reading SIZ marker");
949 if (file->read(&cptr[c].YRsiz, 1) != 1)
950 OJPH_ERROR(0x00050053, "error reading SIZ marker");
951 if ((cptr[c].SSiz & 0x7F) > 37)
952 OJPH_ERROR(0x00050054, "Wrong SIZ-SSiz value of %d", cptr[c].SSiz);
953 if (cptr[c].XRsiz == 0)
954 OJPH_ERROR(0x00050055, "Wrong SIZ-XRsiz value of %d", cptr[c].XRsiz);
955 if (cptr[c].YRsiz == 0)
956 OJPH_ERROR(0x00050056, "Wrong SIZ-YRsiz value of %d", cptr[c].YRsiz);
957 }
958
959 ws_kern_support_needed = (Rsiz & 0x20) != 0;
960 dfs_support_needed = (Rsiz & 0x80) != 0;
961
963 }
964
967 {
968 assert(comp_num < get_num_components());
969
970 point factor(1u << skipped_resolutions, 1u << skipped_resolutions);
971 const param_cod* cdp = cod->get_coc(comp_num);
972 if (dfs && cdp && cdp->is_dfs_defined()) {
973 ui16 dfs_idx = cdp->get_dfs_index();
974 const param_dfs* d = dfs->get_dfs(dfs_idx);
975 if (d != NULL)
977 }
978 factor.x *= (ui32)cptr[comp_num].XRsiz;
979 factor.y *= (ui32)cptr[comp_num].YRsiz;
980 return factor;
981 }
982
985 {
986 assert(comp_num < get_num_components());
987
988 point factor = get_recon_downsampling(comp_num);
989 point r;
990 r.x = ojph_div_ceil(Xsiz, factor.x) - ojph_div_ceil(XOsiz, factor.x);
991 r.y = ojph_div_ceil(Ysiz, factor.y) - ojph_div_ceil(YOsiz, factor.y);
992 return r;
993 }
994
995
997 //
998 //
999 //
1000 //
1001 //
1003
1006 {
1007 //marker size excluding header
1008 Lcap = 8;
1009
1010 ui16 buf2;
1011 ui32 buf4;
1012 bool result = true;
1013
1014 buf2 = JP2K_MARKER::CAP;
1015 buf2 = swap_bytes_if_le(buf2);
1016 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1017 buf2 = swap_bytes_if_le(Lcap);
1018 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1019 buf4 = swap_bytes_if_le(Pcap);
1020 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
1021
1022 buf2 = swap_bytes_if_le(Ccap[0]);
1023 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1024
1025 return result;
1026 }
1027
1030 {
1031 if (file->read(&Lcap, 2) != 2)
1032 OJPH_ERROR(0x00050061, "error reading CAP marker");
1033 Lcap = swap_bytes_if_le(Lcap);
1034 if (file->read(&Pcap, 4) != 4)
1035 OJPH_ERROR(0x00050062, "error reading CAP marker");
1036 Pcap = swap_bytes_if_le(Pcap);
1037 ui32 count = population_count(Pcap);
1038 if (Pcap & 0xFFFDFFFF)
1039 OJPH_ERROR(0x00050063,
1040 "error Pcap in CAP has options that are not supported");
1041 if ((Pcap & 0x00020000) == 0)
1042 OJPH_ERROR(0x00050064,
1043 "error Pcap should have its 15th MSB set, Pcap^15. "
1044 " This is not a JPH file");
1045 for (ui32 i = 0; i < count; ++i)
1046 if (file->read(Ccap+i, 2) != 2)
1047 OJPH_ERROR(0x00050065, "error reading CAP marker");
1048 if (Lcap != 6 + 2 * count)
1049 OJPH_ERROR(0x00050066, "error in CAP marker length");
1050 }
1051
1053 //
1054 //
1055 //
1056 //
1057 //
1059
1062 {
1063 if (SPcod.wavelet_trans <= 1)
1065 else {
1066 assert(atk != NULL);
1067 return atk->is_reversible();
1068 }
1069 }
1070
1073 {
1074 assert(type == COD_MAIN);
1075
1076 //marker size excluding header
1077 Lcod = 12;
1078 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1079
1080 ui8 buf1;
1081 ui16 buf2;
1082 bool result = true;
1083
1084 buf2 = JP2K_MARKER::COD;
1085 buf2 = swap_bytes_if_le(buf2);
1086 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1087 buf2 = swap_bytes_if_le(Lcod);
1088 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1089 buf1 = Scod;
1090 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1091 buf1 = SGCod.prog_order;
1092 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1093 buf2 = swap_bytes_if_le(SGCod.num_layers);
1094 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1095 buf1 = SGCod.mc_trans;
1096 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1097 buf1 = SPcod.num_decomp;
1098 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1099 buf1 = SPcod.block_width;
1100 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1101 buf1 = SPcod.block_height;
1102 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1103 buf1 = SPcod.block_style;
1104 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1105 buf1 = SPcod.wavelet_trans;
1106 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1107 if (Scod & 1)
1108 for (int i = 0; i <= SPcod.num_decomp; ++i)
1109 {
1110 buf1 = SPcod.precinct_size[i];
1111 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1112 }
1113
1114 return result;
1115 }
1116
1119 {
1120 assert(type == COD_MAIN);
1121 bool result = true;
1122 param_cod *p = this->next;
1123 while (p)
1124 {
1125 if (p->comp_idx < num_comps)
1126 result &= p->internal_write_coc(file, num_comps);
1127 p = p->next;
1128 }
1129 return result;
1130 }
1131
1134 {
1135 assert(type == COC_MAIN);
1136
1137 //marker size excluding header
1138 Lcod = num_comps < 257 ? 9 : 10;
1139 Lcod = (ui16)(Lcod + (Scod & 1 ? 1 + SPcod.num_decomp : 0));
1140
1141 ui8 buf1;
1142 ui16 buf2;
1143 bool result = true;
1144
1145 buf2 = JP2K_MARKER::COC;
1146 buf2 = swap_bytes_if_le(buf2);
1147 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1148 buf2 = swap_bytes_if_le(Lcod);
1149 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1150 if (num_comps < 257)
1151 {
1152 buf1 = (ui8)comp_idx;
1153 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1154 }
1155 else
1156 {
1157 buf2 = swap_bytes_if_le(comp_idx);
1158 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1159 }
1160 buf1 = Scod;
1161 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1162 buf1 = SPcod.num_decomp;
1163 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1164 buf1 = SPcod.block_width;
1165 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1166 buf1 = SPcod.block_height;
1167 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1168 buf1 = SPcod.block_style;
1169 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1170 buf1 = SPcod.wavelet_trans;
1171 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1172 if (Scod & 1)
1173 for (int i = 0; i <= SPcod.num_decomp; ++i)
1174 {
1175 buf1 = SPcod.precinct_size[i];
1176 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1177 }
1178
1179 return result;
1180 }
1181
1184 {
1185 assert(type == COD_MAIN);
1186
1187 if (file->read(&Lcod, 2) != 2)
1188 OJPH_ERROR(0x00050071, "error reading COD segment");
1189 Lcod = swap_bytes_if_le(Lcod);
1190 if (file->read(&Scod, 1) != 1)
1191 OJPH_ERROR(0x00050072, "error reading COD segment");
1192 if (file->read(&SGCod.prog_order, 1) != 1)
1193 OJPH_ERROR(0x00050073, "error reading COD segment");
1194 if (file->read(&SGCod.num_layers, 2) != 2)
1195 { OJPH_ERROR(0x00050074, "error reading COD segment"); }
1196 else
1197 SGCod.num_layers = swap_bytes_if_le(SGCod.num_layers);
1198 if (file->read(&SGCod.mc_trans, 1) != 1)
1199 OJPH_ERROR(0x00050075, "error reading COD segment");
1200 if (file->read(&SPcod.num_decomp, 1) != 1)
1201 OJPH_ERROR(0x00050076, "error reading COD segment");
1202 if (file->read(&SPcod.block_width, 1) != 1)
1203 OJPH_ERROR(0x00050077, "error reading COD segment");
1204 if (file->read(&SPcod.block_height, 1) != 1)
1205 OJPH_ERROR(0x00050078, "error reading COD segment");
1206 if (file->read(&SPcod.block_style, 1) != 1)
1207 OJPH_ERROR(0x00050079, "error reading COD segment");
1208 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1209 OJPH_ERROR(0x0005007A, "error reading COD segment");
1210
1211 if (get_num_decompositions() > 32
1212 || SPcod.block_width > 8
1213 || SPcod.block_height > 8
1215 || (SPcod.block_style & 0x40) != 0x40
1216 || (SPcod.block_style & 0xB7) != 0x00)
1217 OJPH_ERROR(0x0005007D, "wrong settings in a COD-SPcod parameter");
1218 if ((SPcod.block_style & 0x40) != 0x40
1219 || (SPcod.block_style & 0xB7) != 0x00)
1220 OJPH_ERROR(0x0005007E, "unsupported settings in a COD-SPcod parameter");
1221
1222 ui8 num_decompositions = get_num_decompositions();
1223 if (Scod & 1) {
1224 for (int i = 0; i <= num_decompositions; ++i) {
1225 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1226 OJPH_ERROR(0x0005007B, "error reading COD segment");
1227 if (i)
1228 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1229 (SPcod.precinct_size[i] >> 4) == 0)
1230 OJPH_ERROR(0x0005007F,
1231 "Precinct width or height for resolutions other than the"
1232 " coarsest must be larger than 1; here, they are %d and %d,"
1233 " respectively.",
1234 1 << (SPcod.precinct_size[i] & 0x0F),
1235 1 << (SPcod.precinct_size[i] >> 4));
1236 }
1237 }
1238 if (Lcod != 12 + ((Scod & 1) ? 1 + SPcod.num_decomp : 0))
1239 OJPH_ERROR(0x0005007C, "error in COD segment length");
1240 }
1241
1243 void param_cod::read_coc(infile_base* file, ui32 num_comps,
1245 {
1246 assert(type == COC_MAIN);
1247 assert(top_cod != NULL);
1248
1249 this->SGCod = top_cod->SGCod;
1250 this->top_cod = top_cod;
1251 if (file->read(&Lcod, 2) != 2)
1252 OJPH_ERROR(0x00050121, "error reading COC segment");
1253 Lcod = swap_bytes_if_le(Lcod);
1254 if (num_comps < 257) {
1255 ui8 t;
1256 if (file->read(&t, 1) != 1)
1257 OJPH_ERROR(0x00050122, "error reading COC segment");
1258 comp_idx = t;
1259 }
1260 else {
1261 if (file->read(&comp_idx, 2) != 2)
1262 OJPH_ERROR(0x00050123, "error reading COC segment");
1263 comp_idx = swap_bytes_if_le(comp_idx);
1264 }
1265 if (file->read(&Scod, 1) != 1)
1266 OJPH_ERROR(0x00050124, "error reading COC segment");
1267 if (Scod & 0xF8)
1268 OJPH_WARN(0x00050011,
1269 "Unsupported options in Scoc field of the COC segment");
1270 if (file->read(&SPcod.num_decomp, 1) != 1)
1271 OJPH_ERROR(0x00050125, "error reading COC segment");
1272 if (file->read(&SPcod.block_width, 1) != 1)
1273 OJPH_ERROR(0x00050126, "error reading COC segment");
1274 if (file->read(&SPcod.block_height, 1) != 1)
1275 OJPH_ERROR(0x00050127, "error reading COC segment");
1276 if (file->read(&SPcod.block_style, 1) != 1)
1277 OJPH_ERROR(0x00050128, "error reading COC segment");
1278 if (file->read(&SPcod.wavelet_trans, 1) != 1)
1279 OJPH_ERROR(0x00050129, "error reading COC segment");
1280
1281 if (get_num_decompositions() > 32
1282 || SPcod.block_width > 8
1283 || SPcod.block_height > 8
1285 || (SPcod.block_style & 0x40) != 0x40
1286 || (SPcod.block_style & 0xB7) != 0x00)
1287 OJPH_ERROR(0x0005012C, "wrong settings in a COC-SPcoc parameter");
1288 if ((SPcod.block_style & 0x40) != 0x40
1289 || (SPcod.block_style & 0xB7) != 0x00)
1290 OJPH_ERROR(0x0005012D, "unsupported settings in a COC-SPcoc parameter");
1291
1292 ui8 num_decompositions = get_num_decompositions();
1293 if (Scod & 1) {
1294 for (int i = 0; i <= num_decompositions; ++i) {
1295 if (file->read(&SPcod.precinct_size[i], 1) != 1)
1296 OJPH_ERROR(0x0005012A, "error reading COC segment");
1297 if (i)
1298 if ((SPcod.precinct_size[i] & 0x0F) == 0 ||
1299 (SPcod.precinct_size[i] >> 4) == 0)
1300 OJPH_ERROR(0x0005012E,
1301 "Precinct width or height for resolutions other than the"
1302 " coarsest must be larger than 1; here, they are %d and %d,"
1303 " respectively.",
1304 1 << (SPcod.precinct_size[i] & 0x0F),
1305 1 << (SPcod.precinct_size[i] >> 4));
1306 }
1307 }
1308 ui32 t = 9;
1309 t += num_comps < 257 ? 0 : 1;
1310 t += (Scod & 1) ? 1 + num_decompositions : 0;
1311 if (Lcod != t)
1312 OJPH_ERROR(0x0005012B, "error in COC segment length");
1313 }
1314
1317 {
1318 assert(type == COD_MAIN);
1319 this->atk = atk->get_atk(SPcod.wavelet_trans);
1320 if (this->atk == NULL)
1321 OJPH_ERROR(0x00050131, "A COD segment employs the DWT kernel "
1322 "atk = %d, but a corresponding ATK segment cannot be found.",
1324 param_cod *p = next;
1325 while (p)
1326 {
1327 p->atk = atk->get_atk(p->SPcod.wavelet_trans);
1328 if (p->atk == NULL)
1329 OJPH_ERROR(0x00050132, "A COC segment employs the DWT kernel "
1330 "atk = %d, but a corresponding ATK segment cannot be found",
1332 p = p->next;
1333 }
1334 }
1335
1338 {
1339 assert(this->type == COD_MAIN || this->top_cod->type == COD_MAIN);
1340 const param_cod *p, *q;
1341 if (this->type == COD_MAIN)
1342 q = p = this;
1343 else
1344 q = p = this->top_cod;
1345 while (p && p->comp_idx != comp_idx)
1346 p = p->next;
1347 return p ? p : q;
1348 }
1349
1352 {
1353 // cast object to constant
1354 const param_cod* const_p = const_cast<const param_cod*>(this);
1355 // call using the constant object, then cast to non-const
1356 return const_cast<param_cod*>(const_p->get_coc(comp_idx));
1357 }
1358
1361 {
1362 assert(type == COD_MAIN);
1363 param_cod *p = this;
1364 while (p->next != NULL)
1365 p = p->next;
1366 if (avail)
1367 {
1368 p->next = avail;
1369 avail = avail->next;
1370 p->next->init(this, (ui16)comp_idx);
1371 }
1372 else
1373 p->next = new param_cod(this, (ui16)comp_idx);
1374 return p->next;
1375 }
1376
1379 {
1380 assert(type == COD_MAIN);
1382 if (p == this)
1384 return p;
1385 }
1386
1388 //
1389 //
1390 //
1391 //
1392 //
1394
1396 void param_qcd::check_validity(const param_siz& siz, const param_cod& cod)
1397 {
1398 assert(this->type == QCD_MAIN);
1399
1400 ui32 num_comps = siz.get_num_components();
1402
1403 // initialize QCD based on the first component that is (a) associated with
1404 // COD and (b) does not have a COC, or the first component othewise.
1405 ui32 qcd_comp = 0;
1406 for (ui32 c = 0; c < num_comps; ++c)
1407 {
1408 if (cod.get_coc(c) == &cod && get_qcc(c) == this)
1409 {
1410 qcd_comp = c;
1411 break;
1412 }
1413 }
1414
1415 // check if only the top QCD has qfactor set, if so, check if any
1416 // of the first component has COC and qfactor set properly
1417 if (this->qfactor != QFACTOR_UNSET)
1418 {
1419 if (num_comps < 3) // one or two components
1420 {
1421 for (ui32 i = 0; i < num_comps; ++i)
1422 {
1423 param_qcd* q = get_qcc(i);
1424 if (q == this)
1425 {
1426 q = add_qcc_object(i);
1427 set_qfactor(i, comp_type::OJPH_COMP_Y, this->qfactor);
1428 }
1429 }
1430 }
1431 else if (num_comps >= 3)
1432 {
1433 for (ui32 i = 0; i < num_comps; ++i) {
1434 param_qcd* q = get_qcc(i);
1435 if (q == this)
1436 {
1437 q = add_qcc_object(i);
1438 ui8 ci = (ui8)(i < 3u ? i : 0u);
1440 set_qfactor(i, t, this->qfactor);
1441 }
1442 }
1443 }
1444 }
1445
1446 this->make_quant_steps(qcd_comp, cod, siz);
1447
1448 // initialize every QCC, creating one for every component that (a) cannot
1449 // use QCD and (b) does not already have a QCC
1450 // NOTE: Qfactor always creates a QCC and QCD cannot be reused
1451 for (ui32 c = 0; c < num_comps; ++c)
1452 {
1453 param_qcd *qcc = this->get_qcc(c);
1454 const param_cod *coc = cod.get_coc(c);
1455
1456 // check if a QCC exists for the component
1457 if (qcc == this)
1458 {
1459 // if none exists, do not create one if QCD can be reused
1460 if (!this->is_qcc_needed(c, *coc, siz))
1461 continue;
1462
1463 qcc = this->add_qcc_object(c);
1464 qcc->set_delta(this->base_delta);
1465 }
1466
1467 qcc->make_quant_steps(c, *coc, siz);
1468 }
1469 }
1470
1472 void param_qcd::make_quant_steps(ui32 comp_num, const param_cod &cod,
1473 const param_siz &siz)
1474 {
1475 if (this->is_init)
1476 OJPH_ERROR(0x000501C1, "Quantization step sizes already initialized.");
1477
1478 this->is_init = true;
1479
1480 this->num_decomps = cod.get_num_decompositions();
1481 this->bit_depth = siz.get_bit_depth(comp_num);
1482 this->is_signed = siz.is_signed(comp_num);
1484 this->wavelet_kern = cod.get_wavelet_kern();
1485 this->sampling = siz.get_downsampling(comp_num);
1486 this->num_subbands = 1 + 3 * this->num_decomps;
1487
1488 if (this->num_weights != 0)
1489 {
1491 OJPH_ERROR(0x000501C2, "Quantization weights for component %d can "
1492 "only be used with the irreversible transform.", comp_num);
1493 if (this->qfactor != QFACTOR_UNSET)
1494 OJPH_ERROR(0x000501C3, "Quantization weights for component %d "
1495 "cannot be used together with qfactor.", comp_num);
1496 if (this->num_weights != this->num_subbands)
1497 OJPH_ERROR(0x000501C4, "Component %d has %d quantization weights, "
1498 "but %d are needed for %d decomposition levels.", comp_num,
1499 this->num_weights, this->num_subbands, this->num_decomps);
1500 }
1501
1503 this->set_rev_quant(this->num_decomps, this->bit_depth,
1504 comp_num < 3 ? this->is_color_trans : false);
1505 else if (this->wavelet_kern == param_cod::DWT_IRV97)
1506 {
1507 if (this->base_delta == -1.0f)
1508 {
1509 ui32 t = ojph_min(16, bit_depth);
1510 this->base_delta = 1.0f / (float)(1 << t);
1511 }
1512 else if (qfactor != QFACTOR_UNSET)
1513 OJPH_WARN(0x000501C5, "qstep for component %d is ignored, because "
1514 "qfactor is set.", comp_num);
1515
1516 this->set_irrev_quant(this->num_decomps);
1517 }
1518 }
1519
1521 bool param_qcd::is_qcc_needed(ui32 comp_num, const param_cod &cod,
1522 const param_siz &siz)
1523 {
1524 if (! this->is_init)
1525 OJPH_ERROR(0x000501D1, "Quantization step sizes not initialized.");
1526
1527 return this->num_decomps != cod.get_num_decompositions() ||
1528 this->bit_depth != siz.get_bit_depth(comp_num) ||
1529 this->is_signed != siz.is_signed(comp_num) ||
1531 this->wavelet_kern != cod.get_wavelet_kern();
1532 }
1533
1536 assert(this->type == QCD_MAIN);
1537
1538 if (qfactor < 1.0f || qfactor > 100.0f)
1539 OJPH_ERROR(0x00050181, "Qfactor must be between 1 and 100, "
1540 "but was set to %i.", qfactor);
1541
1542 this->qfactor = qfactor;
1543 }
1544
1547 bool is_employing_color_transform)
1548 {
1549 ui32 B = bit_depth;
1550 B += is_employing_color_transform ? 1 : 0; //1 bit for RCT
1551 int s = 0;
1552 double bibo_l = bibo_gains::get_bibo_gain_l(num_decomps, true);
1553 ui32 X = (ui32) ceil(log(bibo_l * bibo_l) / M_LN2);
1554 SPqcd.u8[s++] = (ui8)(B + X);
1555 ui32 max_B_plus_X = (ui32)(B + X);
1556 for (ui32 d = num_decomps; d > 0; --d)
1557 {
1558 double bibo_l = bibo_gains::get_bibo_gain_l(d, true);
1559 double bibo_h = bibo_gains::get_bibo_gain_h(d - 1, true);
1560 X = (ui32) ceil(log(bibo_h * bibo_l) / M_LN2);
1561 SPqcd.u8[s++] = (ui8)(B + X);
1562 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1563 SPqcd.u8[s++] = (ui8)(B + X);
1564 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1565 X = (ui32) ceil(log(bibo_h * bibo_h) / M_LN2);
1566 SPqcd.u8[s++] = (ui8)(B + X);
1567 max_B_plus_X = ojph_max(max_B_plus_X, B + X);
1568 }
1569
1570 if (max_B_plus_X > 38)
1571 OJPH_ERROR(0x00050151, "The specified combination of bit_depth, "
1572 "colour transform, and type of wavelet transform requires more than "
1573 "38 bits; it requires %d bits. This is beyond what is allowed in "
1574 "the JPEG2000 image coding format.", max_B_plus_X);
1575
1576 int guard_bits = ojph_max(1, (si32)max_B_plus_X - 31);
1577 Sqcd = (ui8)(guard_bits << 5);
1578 s = 0;
1579 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1580 s++;
1581 for (ui32 d = num_decomps; d > 0; --d)
1582 {
1583 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1584 s++;
1585 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1586 s++;
1587 SPqcd.u8[s] = encode_SPqcd((ui8)(SPqcd.u8[s] - guard_bits));
1588 s++;
1589 }
1590 }
1591
1594 {
1595 int guard_bits = 1;
1596 Sqcd = (ui8)((guard_bits<<5)|0x2); //one guard bit, scalar quantization
1597
1598 float g_c = 1.0f;
1599 float delta_ref = base_delta;
1600 float power = 1.0f;
1601 const float* weights = visual_weights::get_no_weights();
1602
1603 if (qfactor != QFACTOR_UNSET)
1604 {
1608 OJPH_ERROR(0x00050161, "Qfactor can only be used on components "
1609 "with 4:4:4, 4:2:2 or 4:2:0 sampling");
1610 if (this->ctype == comp_type::OJPH_COMP_Y &&
1611 this->sampling.x != 1 && this->sampling.y != 1)
1612 OJPH_ERROR(0x00050162, "Qfactor can only be used for a Y or "
1613 "luminance component when it is not downsampled.");
1614
1615 // calculate component gain
1616 g_c = visual_weights::get_gain(this->ctype);
1617
1618 // calculate delta_ref & power
1619 delta_ref = visual_weights::get_delta_ref(qfactor, bit_depth, power);
1620
1621 // find visual weight
1622 weights = visual_weights::get_weights(format, this->ctype);
1623 }
1624
1625 // returns sqrt(w_b), the square root of the weight, for a decomposition
1626 // level and subband (0:LL, 1:HL, 2:LH, 3:HH); coefficients are ordered
1627 // {LH1, HL1, HH1, ..., LLN}
1628 auto get_sqrt_weight = [&](ui32 d, ui32 sb) -> float
1629 {
1630 if (num_weights == 0)
1631 return visual_weights::get_weight(weights, d, sb);
1632 if (sb == 0)
1633 return this->weights[num_weights - 1];
1634 static const ui32 pos[4] = { 0, 1, 0, 2 };
1635 return this->weights[(d - 1) * 3 + pos[sb]];
1636 };
1637
1638 // LL band
1639 ui32 b = 0;
1640 float w_b;
1641 float gain_l = sqrt_energy_gains::get_gain_l(num_decomps, false);
1642 w_b = get_sqrt_weight(num_decomps, b);
1643 w_b = std::pow(w_b, power);
1644 encode_SPqcd(b++, delta_ref / (gain_l * gain_l * g_c * w_b));
1645
1646 // LL, HL, LH, HH, HL, LH, HH...
1647 for (ui32 d = num_decomps; d > 0; --d)
1648 {
1649 // compute square root of the enery gain factor W_g
1650 float gain_l = sqrt_energy_gains::get_gain_l(d, false);
1651 float gain_h = sqrt_energy_gains::get_gain_h(d - 1, false);
1652
1653 w_b = get_sqrt_weight(d, 1);
1654 w_b = std::pow(w_b, power);
1655 encode_SPqcd(b++, delta_ref / (gain_h * gain_l * g_c * w_b));
1656 w_b = get_sqrt_weight(d, 2);
1657 w_b = std::pow(w_b, power);
1658 encode_SPqcd(b++, delta_ref / (gain_l * gain_h * g_c * w_b));
1659 w_b = get_sqrt_weight(d, 3);
1660 w_b = std::pow(w_b, power);
1661 encode_SPqcd(b++, delta_ref / (gain_h * gain_h * g_c * w_b));
1662 }
1663 }
1664
1666 void param_qcd::encode_SPqcd(ui32 subband_index, float delta)
1667 {
1668 int exp = 0, mantissa;
1669 while (delta < 1.0f)
1670 { exp++; delta *= 2.0f; }
1671 mantissa = (int)round(delta * (float)(1<<11)) - (1<<11);
1672 // with rounding, there is a risk that the mantissa becomes
1673 // equal to 1<<11
1674 mantissa = mantissa < (1<<11) ? mantissa : 0x7FF;
1675 SPqcd.u16[subband_index] = (ui16)((exp << 11) | mantissa);
1676 }
1677
1680 {
1681 ui32 B = 0;
1682
1683 const param_qcd *p = this;
1684 while (p)
1685 {
1686 //this can be written better, but it is only executed once
1687 // this assumes a bi-directional wavelet (conventional DWT)
1688 ui32 num_decomps = (p->num_subbands - 1) / 3;
1689
1690 int irrev = p->Sqcd & 0x1F;
1691 if (irrev == 0) //reversible
1692 for (ui32 i = 0; i < p->num_subbands; ++i) {
1693 ui32 t = p->decode_SPqcd(p->SPqcd.u8[i]);
1694 t += p->get_num_guard_bits() - 1u;
1695 B = ojph_max(B, t);
1696 }
1697 else if (irrev == 2) //scalar expounded
1698 for (ui32 i = 0; i < p->num_subbands; ++i)
1699 {
1700 ui32 nb = num_decomps - (i ? (i - 1) / 3 : 0); //decompsition level
1701 ui32 t = (p->SPqcd.u16[i] >> 11) + p->get_num_guard_bits() - nb;
1702 B = ojph_max(B, t);
1703 }
1704 else
1705 assert(0);
1706
1707 p = p->next;
1708 }
1709
1710 return B;
1711 }
1712
1715 ui32 num_decompositions, ui32 comp_num,
1716 ui32 resolution, ui32 subband) const
1717 {
1718 float arr[] = { 1.0f, 2.0f, 2.0f, 4.0f };
1719 if ((Sqcd & 0x1F) != 2)
1720 OJPH_ERROR(0x00050101, "There is something wrong in the configuration "
1721 "of the codestream; for component %d, the codestream defines an "
1722 "irreversible transform, for which the codestream provides a "
1723 "reversible (no quantization) step sizes in Sqcd/Sqcc.", comp_num);
1724
1725 ui32 idx;
1726 if (dfs != NULL && dfs->exists())
1727 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1728 else
1729 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1730 if (idx >= num_subbands) {
1731 OJPH_INFO(0x00050102, "Trying to access quantization step size for "
1732 "subband %d when the QCD/QCC marker segment specifies "
1733 "quantization step sizes for %d subbands only. To continue "
1734 "decoding, we are using the step size for subband %d, which can "
1735 "produce incorrect results",
1736 idx + 1, num_subbands, num_subbands - 1);
1737 idx = num_subbands - 1;
1738 }
1739 int eps = SPqcd.u16[idx] >> 11;
1740 float mantissa;
1741 mantissa = (float)((SPqcd.u16[idx] & 0x7FF) | 0x800) * arr[subband];
1742 mantissa /= (float)(1 << 11);
1743 mantissa /= (float)(1u << eps);
1744 return mantissa;
1745 }
1746
1749 {
1750 ui32 comp_idx = cod->get_comp_idx();
1751 ui32 precision = 0;
1752 const param_cod *main =
1754 if (main->is_employing_color_transform() && comp_idx < 3)
1755 {
1756 for (ui32 i = 0; i < 3; ++i) {
1757 const param_qcd* p = this->get_qcc(i);
1758 precision = ojph_max(precision, p->get_largest_Kmax());
1759 }
1760 }
1761 else {
1762 precision = get_largest_Kmax();
1763 }
1764 // ``precision'' now holds the largest K_max, which excludes the sign
1765 // bit.
1766 // + 1 for the sign bit
1767 // + 1 because my block decoder/encoder does not supports up to 30
1768 // bits (not 31), so we bump it by one more bit.
1769 return precision + 1 + 1;
1770 }
1771
1774 {
1775 return (Sqcd >> 5);
1776 }
1777
1779 ui32 param_qcd::get_Kmax(const param_dfs* dfs, ui32 num_decompositions,
1780 ui32 resolution, ui32 subband) const
1781 {
1782 ui32 idx;
1783 if (dfs != NULL && dfs->exists())
1784 idx = dfs->get_subband_idx(num_decompositions, resolution, subband);
1785 else
1786 idx = resolution ? (resolution - 1) * 3 + subband : 0;
1787 if (idx >= num_subbands) {
1788 OJPH_INFO(0x00050111, "Trying to access quantization step size for "
1789 "subband %d when the QCD/QCC marker segment specifies "
1790 "quantization step sizes for %d subbands only. To continue "
1791 "decoding, we are using the step size for subband %d, which can "
1792 "produce incorrect results",
1793 idx + 1, num_subbands, num_subbands - 1);
1794 idx = num_subbands - 1;
1795 }
1796
1797 int irrev = Sqcd & 0x1F;
1798 ui32 num_bits = 0;
1799 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1800 {
1801 num_bits = decode_SPqcd(SPqcd.u8[idx]);
1802 num_bits = num_bits == 0 ? 0 : num_bits - 1;
1803 }
1804 else if (irrev == 1)
1805 assert(0);
1806 else if (irrev == 2) //scalar expounded
1807 num_bits = (SPqcd.u16[idx] >> 11) - 1;
1808 else
1809 assert(0);
1810
1811 return num_bits + get_num_guard_bits();
1812 }
1813
1816 {
1817 int irrev = Sqcd & 0x1F;
1818 ui32 num_bits = 0;
1819 if (irrev == 0) // reversible; this is (10.22) from the J2K book
1820 {
1821 for (ui32 i = 0; i < num_subbands; ++i) {
1822 ui32 t = decode_SPqcd(SPqcd.u8[i]);
1823 num_bits = ojph_max(num_bits, t == 0 ? 0 : t - 1);
1824 }
1825 }
1826 else if (irrev == 1)
1827 assert(0);
1828 else if (irrev == 2) //scalar expounded
1829 {
1830 for (ui32 i = 0; i < num_subbands; ++i) {
1831 ui32 t = (SPqcd.u16[i] >> 11) - 1;
1832 num_bits = ojph_max(num_bits, t);
1833 }
1834 }
1835 else
1836 assert(0);
1837
1838 return num_bits + get_num_guard_bits();
1839 }
1840
1843 {
1844 int irrev = Sqcd & 0x1F;
1845
1846 //marker size excluding header
1847 Lqcd = 3;
1848 if (irrev == 0)
1849 Lqcd = (ui16)(Lqcd + num_subbands);
1850 else if (irrev == 2)
1851 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1852 else
1853 assert(0);
1854
1855 ui8 buf1;
1856 ui16 buf2;
1857 bool result = true;
1858
1859 buf2 = JP2K_MARKER::QCD;
1860 buf2 = swap_bytes_if_le(buf2);
1861 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1862 buf2 = swap_bytes_if_le(Lqcd);
1863 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1864 buf1 = Sqcd;
1865 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1866
1867 if (irrev == 0)
1868 for (ui32 i = 0; i < num_subbands; ++i)
1869 {
1870 buf1 = SPqcd.u8[i];
1871 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1872 }
1873 else if (irrev == 2)
1874 for (ui32 i = 0; i < num_subbands; ++i)
1875 {
1876 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1877 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1878 }
1879 else
1880 assert(0);
1881
1882 return result;
1883 }
1884
1887 {
1888 assert(type == QCD_MAIN);
1889 bool result = true;
1890 param_qcd *p = this->next;
1891 while (p)
1892 {
1893 if (p->enabled)
1894 result &= p->internal_write_qcc(file, num_comps);
1895 p = p->next;
1896 }
1897 return result;
1898 }
1899
1902 {
1903 int irrev = Sqcd & 0x1F;
1904
1905 //marker size excluding header
1906 Lqcd = (ui16)(4 + (num_comps < 257 ? 0 : 1));
1907 if (irrev == 0)
1908 Lqcd = (ui16)(Lqcd + num_subbands);
1909 else if (irrev == 2)
1910 Lqcd = (ui16)(Lqcd + 2 * num_subbands);
1911 else
1912 assert(0);
1913
1914 ui8 buf1;
1915 ui16 buf2;
1916 bool result = true;
1917
1918 buf2 = JP2K_MARKER::QCC;
1919 buf2 = swap_bytes_if_le(buf2);
1920 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1921 buf2 = swap_bytes_if_le(Lqcd);
1922 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1923 if (num_comps < 257)
1924 {
1925 buf1 = (ui8)comp_idx;
1926 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1927 }
1928 else
1929 {
1930 buf2 = swap_bytes_if_le(comp_idx);
1931 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1932 }
1933 buf1 = Sqcd;
1934 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1935 if (irrev == 0)
1936 for (ui32 i = 0; i < num_subbands; ++i)
1937 {
1938 buf1 = SPqcd.u8[i];
1939 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
1940 }
1941 else if (irrev == 2)
1942 for (ui32 i = 0; i < num_subbands; ++i)
1943 {
1944 buf2 = swap_bytes_if_le(SPqcd.u16[i]);
1945 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
1946 }
1947 else
1948 assert(0);
1949
1950 return result;
1951 }
1952
1955 {
1956 assert(type == QCD_MAIN && comp_idx == OJPH_QCD_DEFAULT);
1957 param_qcd *p = this->next;
1958 while (p)
1959 {
1960 assert(p->type == QCC_MAIN);
1961 p->enabled = p->comp_idx < num_comps;
1962 p = p->next;
1963 }
1964 }
1965
1968 {
1969 if (file->read(&Lqcd, 2) != 2)
1970 OJPH_ERROR(0x00050081, "error reading QCD marker");
1971 Lqcd = swap_bytes_if_le(Lqcd);
1972 if (file->read(&Sqcd, 1) != 1)
1973 OJPH_ERROR(0x00050082, "error reading QCD marker");
1974 if ((Sqcd & 0x1F) == 0)
1975 {
1976 num_subbands = (Lqcd - 3);
1977 if (num_subbands == 0)
1978 OJPH_ERROR(0x0005008A, "QCD marker segment that specifies no "
1979 "quantization informtion");
1981 OJPH_ERROR(0x00050083, "wrong Lqcd value of %d in QCD marker", Lqcd);
1982 for (ui32 i = 0; i < num_subbands; ++i)
1983 if (file->read(&SPqcd.u8[i], 1) != 1)
1984 OJPH_ERROR(0x00050084, "error reading QCD marker");
1985 }
1986 else if ((Sqcd & 0x1F) == 1)
1987 {
1988 num_subbands = 0;
1989 OJPH_ERROR(0x00050089,
1990 "Scalar derived quantization is not supported yet in QCD marker");
1991 if (Lqcd != 5)
1992 OJPH_ERROR(0x00050085, "wrong Lqcd value in QCD marker");
1993 }
1994 else if ((Sqcd & 0x1F) == 2)
1995 {
1996 num_subbands = (Lqcd - 3) / 2;
1997 if (num_subbands == 0)
1998 OJPH_ERROR(0x0005008B, "QCD marker segment that specifies no "
1999 "quantization informtion");
2000 if (num_subbands > MAX_SUBBAND_COUNT || Lqcd != 3 + 2 * num_subbands)
2001 OJPH_ERROR(0x00050086, "wrong Lqcd value of %d in QCD marker", Lqcd);
2002 for (ui32 i = 0; i < num_subbands; ++i)
2003 {
2004 if (file->read(&SPqcd.u16[i], 2) != 2)
2005 OJPH_ERROR(0x00050087, "error reading QCD marker");
2006 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
2007 }
2008 }
2009 else
2010 OJPH_ERROR(0x00050088, "wrong Sqcd value in QCD marker");
2011 }
2012
2014 void param_qcd::read_qcc(infile_base *file, ui32 num_comps)
2015 {
2016 if (file->read(&Lqcd, 2) != 2)
2017 OJPH_ERROR(0x000500A1, "error reading QCC marker");
2018 Lqcd = swap_bytes_if_le(Lqcd);
2019 if (num_comps < 257)
2020 {
2021 ui8 v;
2022 if (file->read(&v, 1) != 1)
2023 OJPH_ERROR(0x000500A2, "error reading QCC marker");
2024 comp_idx = v;
2025 }
2026 else
2027 {
2028 if (file->read(&comp_idx, 2) != 2)
2029 OJPH_ERROR(0x000500A3, "error reading QCC marker");
2030 comp_idx = swap_bytes_if_le(comp_idx);
2031 }
2032 if (file->read(&Sqcd, 1) != 1)
2033 OJPH_ERROR(0x000500A4, "error reading QCC marker");
2034 ui32 offset = num_comps < 257 ? 4 : 5;
2035 if ((Sqcd & 0x1F) == 0)
2036 {
2037 num_subbands = (Lqcd - offset);
2038 if (num_subbands == 0)
2039 OJPH_ERROR(0x000500AC, "QCC marker segment that specifies no "
2040 "quantization informtion");
2041 if (num_subbands > MAX_SUBBAND_COUNT || Lqcd != offset + num_subbands)
2042 OJPH_ERROR(0x000500A5, "wrong Lqcd value of %d in QCC marker", Lqcd);
2043 for (ui32 i = 0; i < num_subbands; ++i)
2044 if (file->read(&SPqcd.u8[i], 1) != 1)
2045 OJPH_ERROR(0x000500A6, "error reading QCC marker");
2046 }
2047 else if ((Sqcd & 0x1F) == 1)
2048 {
2049 num_subbands = 0;
2050 OJPH_ERROR(0x000500AB,
2051 "Scalar derived quantization is not supported yet in QCC marker");
2052 if (Lqcd != offset)
2053 OJPH_ERROR(0x000500A7, "wrong Lqcc value in QCC marker");
2054 }
2055 else if ((Sqcd & 0x1F) == 2)
2056 {
2057 num_subbands = (Lqcd - offset) / 2;
2058 if (num_subbands == 0)
2059 OJPH_ERROR(0x000500AD, "QCC marker segment that specifies no "
2060 "quantization informtion");
2061 if (num_subbands>MAX_SUBBAND_COUNT || Lqcd != offset + 2*num_subbands)
2062 OJPH_ERROR(0x000500A8, "wrong Lqcc value of %d in QCC marker", Lqcd);
2063 for (ui32 i = 0; i < num_subbands; ++i)
2064 {
2065 if (file->read(&SPqcd.u16[i], 2) != 2)
2066 OJPH_ERROR(0x000500A9, "error reading QCC marker");
2067 SPqcd.u16[i] = swap_bytes_if_le(SPqcd.u16[i]);
2068 }
2069 }
2070 else
2071 OJPH_ERROR(0x000500AA, "wrong Sqcc value in QCC marker");
2072 }
2073
2076 {
2077 assert(type == QCD_MAIN);
2079 if (p == this)
2081 p->set_delta(delta);
2082 }
2083
2085 void param_qcd::set_weights(size_t num_weights, const float *weights)
2086 {
2087 if (weights == NULL || num_weights==0 || num_weights > MAX_SUBBAND_COUNT)
2088 OJPH_ERROR(0x000501A1, "The number of quantization weights must be "
2089 "between 1 and %d, but %zu were provided.",
2091 for (size_t i = 0; i < num_weights; ++i)
2092 if (!(weights[i] > 0.0f))
2093 OJPH_ERROR(0x000501A2, "Quantization weights must be positive.");
2094 memcpy(this->weights, weights, num_weights * sizeof(float));
2095 this->num_weights = (ui32)num_weights;
2096 }
2097
2100 size_t num_weights, const float *weights)
2101 {
2102 assert(type == QCD_MAIN);
2104 if (p == this)
2106 p->set_delta(delta);
2108 }
2109
2112 {
2113 assert(this->type == QCD_MAIN);
2114
2115 if (qfactor < 1.0f || qfactor > 100.0f)
2116 OJPH_ERROR(0x00050191, "Qfactor must be between 1 and 100, "
2117 "but was set to %i.", qfactor);
2118
2120 if (p == this)
2122
2123 p->qfactor = qfactor;
2124 p->ctype = ctype;
2125 }
2126
2129 {
2130 // cast object to constant
2131 const param_qcd* const_p = const_cast<const param_qcd*>(this);
2132 // call using the constant object, then cast to non-const
2133 return const_cast<param_qcd*>(const_p->get_qcc(comp_idx));
2134 }
2135
2138 {
2139 assert(this->type == QCD_MAIN || this->top_qcd->type == QCD_MAIN);
2140 const param_qcd *p, *q;
2141 if (this->type == QCD_MAIN)
2142 q = p = this;
2143 else
2144 q = p = this->top_qcd;
2145 while (p && p->comp_idx != comp_idx)
2146 p = p->next;
2147 return p ? p : q;
2148 }
2149
2152 {
2153 assert(type == QCD_MAIN);
2154 param_qcd *p = this;
2155 while (p->next != NULL)
2156 p = p->next;
2157 if (avail)
2158 {
2159 p->next = avail;
2160 avail = avail->next;
2161 p->next->init(this, (ui16)comp_idx);
2162 }
2163 else
2164 p->next = new param_qcd(this, (ui16)comp_idx);
2165 return p->next;
2166 }
2167
2169 //
2170 //
2171 //
2172 //
2173 //
2175
2178 {
2179 double d = 1.0 / (double)((1ull << 32) - 1);
2180 fd_min = (float)((double)d_min * d);
2181 fd_max = (float)((double)d_max * d);
2182 delta = (fd_max - fd_min) / (float)(num_points - 1);
2183 inv_delta = (float)(num_points - 1) / (fd_max - fd_min);
2184 multiplier = (float)(1ull << get_bit_depth());
2185 float divider = (float)(1.0 / (double)(1ull << get_bit_depth()));
2186 if (bytes_per_point == 1) {
2187 ui8* sp = (ui8*)marker_points;
2188 float* dp = dec_points;
2189 for (ui32 i = 0; i < num_points; ++i)
2190 *dp++ = *sp++ * divider;
2191 dec_points[-1] = dec_points[0];
2193 }
2194 else if (bytes_per_point == 2) {
2195 ui16* sp = (ui16*)marker_points;
2196 float* dp = dec_points;
2197 for (ui32 i = 0; i < num_points; ++i)
2198 *dp++ = *sp++ * divider;
2199 dec_points[-1] = dec_points[0];
2201 }
2202 else if (bytes_per_point == 4) {
2203 ui32* sp = (ui32*)marker_points;
2204 float* dp = dec_points;
2205 for (ui32 i = 0; i < num_points; ++i)
2206 *dp++ = (float)*sp++ * divider;
2207 dec_points[-1] = dec_points[0];
2209 }
2210 else
2211 assert(0);
2212 }
2213
2215 template<typename T>
2216 static inline void
2217 prepare_for_encoding_approx_for_type(const void* marker_points, float div,
2218 float& ft_min, float& ft_max, float& delta, float& inv_delta,
2219 float fd_min, float fd_max, ui32 num_points, ui32 enc_num_points,
2220 float* approx_enc_points)
2221 {
2222 const T* p = (const T*)marker_points;
2223 ft_min = (float)p[0] * div;
2224 ft_max = (float)p[num_points - 1] * div;
2225 delta = (ft_max - ft_min) / (float)(enc_num_points - 1);
2226 inv_delta = (float)(enc_num_points - 1) / (ft_max - ft_min);
2227
2228 ui32 k = 0;
2229 float y_k = (float)p[k] * div, y_kp1 = (float)p[k + 1] * div;
2230 float dt = (fd_max - fd_min) / (float)(num_points - 1);
2231 float d_k = fd_min, d_kp1 = fd_min + dt;
2232 for (ui32 i = 1; i < enc_num_points - 1; ++i)
2233 {
2234 float z = ft_min + (float)i * delta;
2235 while (k + 1 < num_points - 1 && z >= y_kp1)
2236 {
2237 ++k;
2238 d_k = d_kp1;
2239 d_kp1 = fd_min + (float)(k + 1) * dt;
2240 y_k = y_kp1;
2241 y_kp1 = (float)p[k + 1] * div;
2242 }
2243 approx_enc_points[i] = d_k + (z - y_k) * dt / (y_kp1 - y_k);
2244 }
2245 }
2246
2249 {
2250 double d = 1.0 / (double)((1ull << 32) - 1);
2251 fd_min = (float)((double)d_min * d);
2252 fd_max = (float)((double)d_max * d);
2253
2254 // enc_points holds positions in the domain of the LUT, whose first
2255 // and last entries are fd_min and fd_max, not LUT values
2262
2263 // create lookup table for encoding
2264 float mul = (float)((1ull << pt_val) - 1);
2265 float div = 1.0f / mul;
2266 if (bytes_per_point == 1)
2271 else if (bytes_per_point == 2)
2276 else if (bytes_per_point == 4)
2281
2282 multiplier = (float)(1.0 / (double)(1ull << get_bit_depth()));
2283 }
2284
2287 {
2288 double d = 1.0 / (double)((1ull << 32) - 1);
2289 fd_min = (float)((double)d_min * d);
2290 fd_max = (float)((double)d_max * d);
2291
2292 float mul = (float)((1ull << pt_val) - 1);
2293 float div = 1.0f / mul;
2294
2295 // convert decoder lookup table to floats
2296 if (bytes_per_point == 1) {
2297 const ui8* p = (const ui8*)marker_points;
2298 for (ui32 i = 0; i < num_points; ++i)
2299 precise_dec_lut[i] = (float)p[i] * div;
2302 }
2303 else if (bytes_per_point == 2) {
2304 const ui16* p = (const ui16*)marker_points;
2305 for (ui32 i = 0; i < num_points; ++i)
2306 precise_dec_lut[i] = (float)p[i] * div;
2309 }
2310 else if (bytes_per_point == 4) {
2311 const ui32* p = (const ui32*)marker_points;
2312 for (ui32 i = 0; i < num_points; ++i)
2313 precise_dec_lut[i] = (float)p[i] * div;
2316 }
2321 delta = (fd_max - fd_min) / (float)(num_points - 1);
2322 inv_delta = (float)(enc_num_points - 1) / (ft_max - ft_min);
2323
2324 multiplier = (float)(1.0 / (double)(1ull << get_bit_depth()));
2325
2326 // find index into decoder lookup table
2327 float td = (ft_max - ft_min) / (float)(enc_num_points - 1);
2329 ui16 k = 0, old_k = 0;
2330 for (ui32 i = 0; i < enc_num_points; ++i)
2331 {
2332 float z = ft_min + (float)i * td;
2333 while (k < num_points - 1 && z >= precise_dec_lut[k + 1])
2334 ++k;
2337 old_k = k;
2338 }
2339 }
2340
2349
2352 const param_cod& cod) const
2353 {
2354 ui32 num_comps = siz.get_num_components();
2355 for (ui32 c = 0; c < num_comps; ++c)
2356 {
2357 const nlt_rec* rec = get_nlt_rec(c);
2358 if (rec == NULL)
2359 continue;
2360 ui8 type = rec->get_type();
2361 // the LUT style nonlinearities are implemented for the irreversible
2362 // (9/7) wavelet only
2363 if ((type == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2364 type == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT) &&
2365 cod.get_coc(c)->is_reversible())
2366 return (int)c;
2367 }
2368 return -1;
2369 }
2370
2373 {
2374 if (is_any_enabled() == false)
2375 return;
2376
2377 // the reversible wavelet cannot be used with a LUT style nonlinearity,
2378 // because applying that nonlinearity would need the samples of the
2379 // component to be transformed in a way this library cannot invert;
2380 // refusing it here is better than writing a codestream whose nonlinearity
2381 // a decoder cannot undo
2382 int comp = find_unsupported_nlt(siz, cod);
2383 if (comp >= 0)
2384 OJPH_ERROR(0x000501B1, "The LUT style nonlinearities (type 2, LUT "
2385 "style, and type 4, binary complement followed by a LUT) are "
2386 "supported with the irreversible (9/7) wavelet only; component %d of "
2387 "this codestream is coded with the reversible (5/3) wavelet. Use the "
2388 "irreversible wavelet for that component, use the binary complement "
2389 "nonlinearity (type 3), or do not use a nonlinearity with it.",
2390 comp);
2391
2392 if (this->enabled && this->rec.Tnlt == nonlinearity::OJPH_NLT_UNDEFINED)
2393 this->enabled = false;
2394
2395 if (this->enabled &&
2396 this->rec.Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
2397 {
2398 bool all_same = true;
2399 ui32 num_comps = siz.get_num_components();
2400
2401 // first stage; find out if all components captured by the default
2402 // entry (ALL_COMPS) has the same bit_depth/signedness,
2403 // while doing this, set the BDnlt for components not captured by the
2404 // default entry (ALL_COMPS)
2405 ui32 bit_depth = 0; // unknown yet
2406 bool is_signed = false; // unknown yet
2407 for (ui32 c = 0; c < num_comps; ++c)
2408 { // captured by ALL_COMPS
2409 param_nlt* p = get_nlt_object(c);
2410 if (p == NULL || !p->enabled)
2411 {
2412 if (bit_depth != 0)
2413 {
2414 // we have seen an undefined component previously
2415 all_same = all_same && (bit_depth == siz.get_bit_depth(c));
2416 all_same = all_same && (is_signed == siz.is_signed(c));
2417 }
2418 else
2419 {
2420 // this is the first component which has not type 3 nlt definition
2421 bit_depth = siz.get_bit_depth(c);
2422 is_signed = siz.is_signed(c);
2423 }
2424 }
2425 else
2426 { // can be type 0 or type 3
2427 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2428 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2429 }
2430 }
2431
2432 if (all_same && bit_depth != 0)
2433 { // all the same, and some components are captured by ALL_COMPS
2434 this->rec.BDnlt = (ui8)(bit_depth - 1);
2435 this->rec.BDnlt = (ui8)(this->rec.BDnlt | (is_signed ? 0x80 : 0));
2436 }
2437 else if (!all_same)
2438 { // have different settings or no component is captured by ALL_COMPS
2439 this->enabled = false;
2440 for (ui32 c = 0; c < num_comps; ++c)
2441 {
2442 param_nlt* p = get_nlt_object(c);
2443 if (p == NULL || !p->enabled)
2444 { // captured by ALL_COMPS
2445 if (p == NULL)
2446 p = add_object(c);
2447 p->enabled = true;
2448 p->rec.Tnlt = nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
2449 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2450 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80:0));
2451 }
2452 }
2453 }
2454 }
2455 else {
2456 // fill NLT segment markers with correct information
2457 ui32 num_comps = siz.get_num_components();
2458 for (ui32 c = 0; c < num_comps; ++c)
2459 {
2460 param_nlt* p = get_nlt_object(c);
2461 if (p != NULL && p->enabled)
2462 { // can be type 0 or type 3
2463 p->rec.BDnlt = (ui8)(siz.get_bit_depth(c) - 1);
2464 p->rec.BDnlt = (ui8)(p->rec.BDnlt | (siz.is_signed(c) ? 0x80 : 0));
2465 }
2466 }
2467 }
2468
2470
2471 if (is_any_enabled() == true)
2473 }
2474
2477 {
2478 if (nl_type != ojph::param_nlt::OJPH_NLT_NO_NLT &&
2480 OJPH_ERROR(0x00050171, "Nonliearities other than type 0 "
2481 "(No Nonlinearity) or type 3 (Binary Binary Complement to Sign "
2482 "Magnitude Conversion) are not supported in this function call");
2483 param_nlt* p = get_nlt_object(comp_num);
2484 if (p == NULL)
2485 p = add_object(comp_num);
2486 p->Lnlt = 6;
2487 p->rec.Tnlt = nl_type;
2488 p->enabled = true;
2489 }
2490
2493 ui8 decoded_bit_depth,
2494 bool decoded_signedness,
2495 ui32 d_min, ui32 d_max, ui8 pt_val,
2496 ui16 num_points, void* points,
2497 ui8 nl_type,
2498 bool approx_encoding_nlt,
2499 ui32 num_enc_points)
2500 {
2503 OJPH_ERROR(0x000501A1, "Nonliearities other than type 1 "
2504 "(LUT Nonlinearity) or type 4 (Binary Binary Complement to Sign "
2505 "Magnitude Conversion followed by LUT Nonlinearity) are not "
2506 "supported in this function call");
2507 if (pt_val == 0 || pt_val > 32)
2508 OJPH_ERROR(0x000501A2, "pt_val must be larger than 0 and "
2509 "smaller than or equal to 32; you provided, %d", pt_val);
2510 if (decoded_bit_depth == 0 || decoded_bit_depth > 38)
2511 OJPH_ERROR(0x000501A3, "decoded_bit_depth must be larger than 0 and "
2512 "smaller than or equal to 38; you provided, %d", decoded_bit_depth);
2513 if (d_min >= d_max)
2514 OJPH_ERROR(0x000501A4, "d_max must be larger than d_min; you "
2515 "provided %d and %d", d_min, d_max);
2516 if (num_points < 2 || num_points > 8192)
2517 OJPH_ERROR(0x000501A5, "The number of points must be larger or equal "
2518 "to 2 and smaller or equal to 8192 -- the code will convert this "
2519 "number to a number in the range 1 to 8191 for the NLT marker "
2520 "segement; you provided %d", num_points);
2521 if (num_enc_points == 1)
2522 OJPH_ERROR(0x000501AA, "The num_enc_points cannot be 1");
2523
2524 param_nlt* p = get_nlt_object(comp_num);
2525 if (p == NULL)
2526 p = add_object(comp_num);
2527
2528 p->Lnlt = (ui16)(17u + (ui32)num_points * (ui32)p->rec.get_bpp(pt_val));
2529 p->rec.BDnlt =
2530 (ui8)((decoded_bit_depth - 1) | (decoded_signedness ? 0x80 : 0));
2531 p->rec.Tnlt = nl_type;
2532
2533 p->rec.d_min = d_min;
2534 p->rec.d_max = d_max;
2535 p->rec.pt_val = pt_val;
2536 p->rec.num_points = num_points;
2537 p->rec.bytes_per_point = p->rec.get_bpp(pt_val);
2538 p->rec.approx_encoding_nlt = approx_encoding_nlt;
2539
2540 // Check that the LUT has increasing entries or has almost flat segments
2541 ui32 v_min = 0, v_max = 0;
2542 ui32 smallest_gap = UINT_MAX;
2543 if (p->rec.bytes_per_point == 1)
2544 {
2545 ui8* p = (ui8*)points;
2546 for (int k = 0; k < num_points - 1; ++k)
2547 {
2548 if (p[k+1] > p[k])
2549 smallest_gap = ojph_min(smallest_gap, (ui32)(p[k+1] - p[k]));
2550 else
2551 OJPH_ERROR(0x000501A6, "The LUT must have increasing sequence "
2552 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2553 "%d and %d.", k, k, p[k+1], p[k]);
2554 }
2555 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2556 }
2557 else if (p->rec.bytes_per_point == 2)
2558 {
2559 ui16* p = (ui16*)points;
2560 for (int k = 0; k < num_points - 1; ++k)
2561 {
2562 if (p[k+1] > p[k])
2563 smallest_gap = ojph_min(smallest_gap, (ui32)(p[k+1] - p[k]));
2564 else
2565 OJPH_ERROR(0x000501A7, "The LUT must have increasing sequence "
2566 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2567 "%d and %d.", k, k, p[k+1], p[k]);
2568 }
2569 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2570 }
2571 else if (p->rec.bytes_per_point == 4)
2572 {
2573 ui32* p = (ui32*)points;
2574 for (int k = 0; k < num_points - 1; ++k)
2575 {
2576 if (p[k+1] > p[k])
2577 smallest_gap = ojph_min(smallest_gap, p[k+1] - p[k]);
2578 else
2579 OJPH_ERROR(0x000501A8, "The LUT must have increasing sequence "
2580 "of numbers; here we have at LUT[%d+1] <= LUT[%d], with values "
2581 "%d and %d.", k, k, p[k+1], p[k]);
2582 }
2583 v_min = (ui32)p[0]; v_max = (ui32)p[num_points - 1];
2584 }
2585 else
2586 assert(0);
2587
2588 // find ceil of the ratio to a power of 2
2589 ui32 ienc_pnts = num_enc_points;
2590 if (num_enc_points == 0)
2591 {
2592 float enc_pnts =
2593 std::ceil((float)(v_max-v_min) / (float)(smallest_gap));
2594 if (enc_pnts > 8192.0f)
2595 {
2596 ienc_pnts = 8192;
2597 OJPH_WARN(0x000501A1, "Encoding with LUT is performed with an "
2598 "encoding LUT, derived from the LUT you provided; however, "
2599 "because the provided LUT has almost flat segment or segments, "
2600 "these are hard to invert. We are limiting the encoding "
2601 "LUT to 8192 entries, which means that some segment of the "
2602 "LUT table might be ignored during encoding.")
2603 }
2604 else {
2605 ienc_pnts = (ui32)enc_pnts;
2606 ienc_pnts = 32 - count_leading_zeros(ienc_pnts);
2607 ienc_pnts = 1u << ienc_pnts;
2608 ienc_pnts = ojph_max(ienc_pnts, 2);
2609 }
2610 }
2611
2612 ui32 len = p->rec.cal_store_size_for_encoding(ienc_pnts);
2613 if (len > p->rec.store_size)
2614 {
2615 if (p->rec.points_store)
2616 delete[] (ui8*)p->rec.points_store;
2617 p->rec.store_size = 0;
2618 p->rec.points_store = new (std::nothrow) ui8[len];
2619 if (p->rec.points_store == NULL)
2620 OJPH_ERROR(0x000501A9, "Failed to allocated memory");
2621 p->rec.store_size = len;
2622 }
2624 memcpy(p->rec.marker_points, points, num_points * p->rec.bytes_per_point);
2626
2627 p->enabled = true;
2628 }
2629
2631 bool
2633 bool& is_signed, ui8& nl_type) const
2634 {
2635 // top level must be ALL_COMPS; cannot call this functions from
2636 // non-top nlt
2637 assert(Cnlt == special_comp_num::ALL_COMPS);
2638 const param_nlt* p = get_nlt_object(comp_num);
2639 p = (p && p->enabled) ? p : this;
2640 if (p->enabled)
2641 {
2642 bit_depth = (ui8)((p->rec.BDnlt & 0x7F) + 1);
2643 bit_depth = bit_depth <= 38 ? bit_depth : 38;
2644 is_signed = (p->rec.BDnlt & 0x80) == 0x80;
2645 nl_type = (nonlinearity)p->rec.Tnlt;
2646 return true;
2647 }
2648 return false;
2649 }
2650
2653 {
2654 if (is_any_enabled() == false)
2655 return true;
2656
2657 ui8 buf1;
2658 ui16 buf2;
2659 ui32 buf4;
2660 bool result = true;
2661 const param_nlt* p = this;
2662 while (p)
2663 {
2664 if (p->enabled)
2665 {
2666 buf2 = JP2K_MARKER::NLT;
2667 buf2 = swap_bytes_if_le(buf2);
2668 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2669 buf2 = swap_bytes_if_le(p->Lnlt);
2670 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2671 buf2 = swap_bytes_if_le(p->Cnlt);
2672 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2673 result &= file->write(&p->rec.BDnlt, 1) == 1;
2674 result &= file->write(&p->rec.Tnlt, 1) == 1;
2675 if (p->rec.Tnlt == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2676 p->rec.Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2677 {
2678 buf2 = (ui16)(p->rec.num_points - 1);
2679 buf2 = swap_bytes_if_le(buf2);
2680 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2681 buf4 = swap_bytes_if_le(p->rec.d_min);
2682 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2683 buf4 = swap_bytes_if_le(p->rec.d_max);
2684 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2685 // pt_val is a single byte in the marker segment; it must not be
2686 // written through the address of the 32 bit member, which would
2687 // write its most significant (and usually zero) byte on a
2688 // big-endian machine
2689 buf1 = (ui8)p->rec.pt_val;
2690 result &= file->write(&buf1, sizeof(ui8)) == sizeof(ui8);
2691
2692 ui32 len = p->rec.bytes_per_point * p->rec.num_points;
2693 if (p->rec.bytes_per_point == 1)
2694 result &= file->write(p->rec.marker_points, len) == len;
2695 else if (p->rec.bytes_per_point == 2)
2696 {
2697 char* sp = (char*)p->rec.marker_points;
2698 for (ui32 i = 0; i < p->rec.num_points; ++i, sp += 2)
2699 {
2700 memcpy(&buf2, sp, 2); // not to violate strict aliasing
2701 buf2 = swap_bytes_if_le(buf2);
2702 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2703 }
2704 }
2705 else
2706 {
2707 char* sp = (char*)p->rec.marker_points;
2708 for (ui32 i = 0; i < p->rec.num_points; ++i, sp += 4)
2709 {
2710 memcpy(&buf4, sp, 4); // not to violate strict aliasing
2711 buf4 = swap_bytes_if_le(buf4);
2712 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2713 }
2714 }
2715 }
2716 }
2717 p = p->next;
2718 }
2719 return result;
2720 }
2721
2724 {
2725 ui16 buf2_len;
2726 ui16 buf2_comp;
2727 ui8 buf1_BDnlt;
2728 ui8 buf1_Tnlt;
2729 bool result = true;
2730
2731 result &= file->read(&buf2_len, sizeof(ui16)) == sizeof(ui16);
2732 result &= file->read(&buf2_comp, sizeof(ui16)) == sizeof(ui16);
2733 result &= file->read(&buf1_BDnlt, sizeof(ui8)) == sizeof(ui8);
2734 result &= file->read(&buf1_Tnlt, sizeof(ui8)) == sizeof(ui8);
2735 if (result == false)
2736 OJPH_ERROR(0x000501E1, "Error reading NLT marker, Location 1");
2737
2738 if (buf1_Tnlt != nonlinearity::OJPH_NLT_NO_NLT &&
2739 buf1_Tnlt != nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT &&
2740 buf1_Tnlt != nonlinearity::OJPH_NLT_LUT_STYLE_NLT &&
2741 buf1_Tnlt != nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2742 OJPH_ERROR(0x00050141, "Unsupported nonlinearity type in an "
2743 "NLT marker segment, with a value of", buf1_Tnlt);
2744
2745 ui16 length = swap_bytes_if_le(buf2_len);
2746 if (buf1_Tnlt == nonlinearity::OJPH_NLT_NO_NLT ||
2747 buf1_Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT)
2748 {
2749 if (length != 6)
2750 OJPH_ERROR(0x00050142, "Somethins is wrong with this NLT "
2751 "marker segment -- it has an incorrect length of %d",
2752 length);
2753 }
2754
2755 ui16 comp = swap_bytes_if_le(buf2_comp);
2756 if (comp > 16383 && comp != special_comp_num::ALL_COMPS)
2757 OJPH_ERROR(0x00050143, "Something is wrong with this NLT "
2758 "marker segment -- it has an incorrect component index of %d",
2759 comp);
2760
2761 param_nlt* p = get_nlt_object(comp);
2762 if (p == NULL)
2763 p = add_object(comp);
2764 p->enabled = true;
2765 p->Cnlt = comp;
2766 p->rec.BDnlt = buf1_BDnlt;
2767 if ((buf1_BDnlt & 0x7F) + 1 > 38)
2768 OJPH_ERROR(0x00050144, "The NLT marker segment has an invalid bit "
2769 "depth of %d", (buf1_BDnlt & 0x7F) + 1);
2770 p->rec.Tnlt = buf1_Tnlt;
2771
2772 if (buf1_Tnlt == nonlinearity::OJPH_NLT_LUT_STYLE_NLT ||
2773 buf1_Tnlt == nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
2774 {
2775 ui16 buf2_num_points;
2776 ui32 buf4_d_min, buf4_d_max;
2777 ui8 buf_pt_val;
2778
2779 result &= file->read(&buf2_num_points, sizeof(ui16)) == sizeof(ui16);
2780 result &= file->read(&buf4_d_min, sizeof(ui32)) == sizeof(ui32);
2781 result &= file->read(&buf4_d_max, sizeof(ui32)) == sizeof(ui32);
2782 result &= file->read(&buf_pt_val, sizeof(ui8)) == sizeof(ui8);
2783 if (result == false)
2784 OJPH_ERROR(0x000501E2, "Error reading NLT marker, Location 2");
2785
2786 buf2_num_points = swap_bytes_if_le(buf2_num_points);
2787 buf4_d_min = swap_bytes_if_le(buf4_d_min);
2788 buf4_d_max = swap_bytes_if_le(buf4_d_max);
2789
2790 if (buf2_num_points < 1 || buf2_num_points > 8191)
2791 OJPH_ERROR(0x00050145, "The NLT marker segment has an invalid "
2792 "number of points field", buf2_num_points);
2793 if (buf4_d_min >= buf4_d_max)
2794 OJPH_ERROR(0x00050146, "In an NLT marker segment, Dmin must smaller "
2795 "than Dmax; here we have %d and %d", buf4_d_min, buf4_d_max);
2796 if (buf_pt_val == 0 || buf_pt_val > 32)
2797 OJPH_ERROR(0x00050147, "In an NLT marker segment, the value of "
2798 "pt_val must be larger than 0 and smaller or equal to 32; "
2799 "here, we have %d", buf_pt_val);
2800
2801 p->rec.num_points = buf2_num_points + 1;
2802 p->rec.d_min = buf4_d_min;
2803 p->rec.d_max = buf4_d_max;
2804 p->rec.pt_val = buf_pt_val;
2805 p->rec.bytes_per_point = p->rec.get_bpp(buf_pt_val);
2806
2807 // read the points
2809 if (p->rec.store_size < len)
2810 {
2811 if (p->rec.points_store)
2812 delete[] (ui8*)p->rec.points_store;
2813 p->rec.store_size = 0;
2814 p->rec.points_store = new (std::nothrow) ui8[len];
2815 if (p->rec.points_store == NULL)
2816 OJPH_ERROR(0x00050148, "Failed to allocated memory");
2817 p->rec.store_size = len;
2818 }
2820
2821 if (p->rec.bytes_per_point == 1)
2822 result &=
2823 file->read(p->rec.marker_points, p->rec.num_points)
2824 == p->rec.num_points;
2825 else if (p->rec.bytes_per_point == 2)
2826 {
2827 ui16 buf2;
2828 char* dp = (char*)p->rec.marker_points;
2829 for (ui32 i = 0; i < p->rec.num_points; ++i, dp += 2)
2830 {
2831 result &= file->read(&buf2, sizeof(ui16)) == sizeof(ui16);
2832 buf2 = swap_bytes_if_le(buf2);
2833 memcpy(dp, &buf2, 2); // not to violate strict aliasing
2834 }
2835 }
2836 else
2837 {
2838 ui32 buf4;
2839 char* dp = (char*)p->rec.marker_points;
2840 for (ui32 i = 0; i < p->rec.num_points; ++i, dp += 4)
2841 {
2842 result &= file->read(&buf4, sizeof(ui32)) == sizeof(ui32);
2843 buf4 = swap_bytes_if_le(buf4);
2844 memcpy(dp, &buf4, 4); // not to violate strict aliasing
2845 }
2846 }
2848 }
2849
2850 if (result == false)
2851 OJPH_ERROR(0x000501E3, "Error reading NLT marker, Location 3");
2852
2853 return result;
2854 }
2855
2857 const nlt_rec* param_nlt::get_nlt_rec(ui32 comp_num) const
2858 {
2859 assert(Cnlt == special_comp_num::ALL_COMPS);
2860 const param_nlt* p = get_nlt_object(comp_num);
2861 if (p && p->enabled)
2862 return &p->rec;
2863 else if (this->enabled)
2864 return &this->rec;
2865 else
2866 return NULL;
2867 }
2868
2871 {
2872 // cast object to constant
2873 const param_nlt* const_p = const_cast<const param_nlt*>(this);
2874 // call using the constant object, then cast to non-const
2875 return const_cast<param_nlt*>(const_p->get_nlt_object(comp_num));
2876 }
2877
2880 {
2881 // top level must be ALL_COMPS; cannot call this functions from
2882 // non-top nlt
2883 assert(Cnlt == special_comp_num::ALL_COMPS);
2884
2885 const param_nlt* p = this;
2886 while (p && p->Cnlt != comp_num)
2887 p = p->next;
2888 return p;
2889 }
2890
2893 {
2894 assert(comp_num != special_comp_num::ALL_COMPS);
2895 assert(Cnlt == special_comp_num::ALL_COMPS); // top level
2896 param_nlt* p = this;
2897 while (p->next != NULL) {
2898 assert(p->Cnlt != comp_num);
2899 p = p->next;
2900 }
2901 if (avail)
2902 {
2903 p->next = avail;
2904 avail = avail->next;
2905 p->next->init();
2906 }
2907 else
2908 p->next = new param_nlt;
2909 p = p->next;
2910 p->Cnlt = (ui16)comp_num;
2911 return p;
2912 }
2913
2916 {
2917 // check if any field is enabled
2918 const param_nlt* p = this;
2919 while (p && p->enabled == false)
2920 p = p->next;
2921 return (p != NULL);
2922 }
2923
2926 {
2927 param_nlt* p = this->next;
2928 while (p) {
2929 if (p->enabled == true && p->Cnlt >= num_comps) {
2930 p->enabled = false;
2931 OJPH_INFO(0x00050161, "The NLT marker segment for the "
2932 "non-existing component %d has been removed.", p->Cnlt);
2933 }
2934 p = p->next;
2935 }
2936 }
2937
2938
2940 //
2941 //
2942 //
2943 //
2944 //
2946
2948 bool param_sot::write(outfile_base *file, ui32 payload_len)
2949 {
2950 ui16 buf2;
2951 ui32 buf4;
2952 bool result = true;
2953
2954 this->Psot = payload_len + 14; //inc. SOT marker, field & SOD
2955
2956 buf2 = JP2K_MARKER::SOT;
2957 buf2 = swap_bytes_if_le(buf2);
2958 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2959 buf2 = swap_bytes_if_le(Lsot);
2960 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2961 buf2 = swap_bytes_if_le(Isot);
2962 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2963 buf4 = swap_bytes_if_le(Psot);
2964 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2965 result &= file->write(&TPsot, 1) == 1;
2966 result &= file->write(&TNsot, 1) == 1;
2967
2968 return result;
2969 }
2970
2972 bool param_sot::write(outfile_base *file, ui32 payload_len,
2973 ui8 TPsot, ui8 TNsot)
2974 {
2975 ui32 buf4;
2976 ui16 buf2;
2977 bool result = true;
2978
2979 buf2 = JP2K_MARKER::SOT;
2980 buf2 = swap_bytes_if_le(buf2);
2981 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2982 buf2 = swap_bytes_if_le(Lsot);
2983 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2984 buf2 = swap_bytes_if_le(Isot);
2985 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
2986 buf4 = swap_bytes_if_le(payload_len + 14);
2987 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
2988 result &= file->write(&TPsot, 1) == 1;
2989 result &= file->write(&TNsot, 1) == 1;
2990
2991 return result;
2992 }
2993
2995 bool param_sot::read(infile_base *file, bool resilient)
2996 {
2997 if (resilient)
2998 {
2999 if (file->read(&Lsot, 2) != 2)
3000 {
3001 OJPH_INFO(0x00050091, "error reading SOT marker");
3002 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3003 return false;
3004 }
3005 Lsot = swap_bytes_if_le(Lsot);
3006 if (Lsot != 10)
3007 {
3008 OJPH_INFO(0x00050092, "error in SOT length");
3009 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3010 return false;
3011 }
3012 if (file->read(&Isot, 2) != 2)
3013 {
3014 OJPH_INFO(0x00050093, "error reading tile index");
3015 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3016 return false;
3017 }
3018 Isot = swap_bytes_if_le(Isot);
3019 if (Isot == 0xFFFF)
3020 {
3021 OJPH_INFO(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
3022 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3023 return false;
3024 }
3025 if (file->read(&Psot, 4) != 4)
3026 {
3027 OJPH_INFO(0x00050095, "error reading SOT marker");
3028 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3029 return false;
3030 }
3031 Psot = swap_bytes_if_le(Psot);
3032 if (file->read(&TPsot, 1) != 1)
3033 {
3034 OJPH_INFO(0x00050096, "error reading SOT marker");
3035 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3036 return false;
3037 }
3038 if (file->read(&TNsot, 1) != 1)
3039 {
3040 OJPH_INFO(0x00050097, "error reading SOT marker");
3041 Lsot = 0; Isot = 0; Psot = 0; TPsot = 0; TNsot = 0;
3042 return false;
3043 }
3044 }
3045 else
3046 {
3047 if (file->read(&Lsot, 2) != 2)
3048 OJPH_ERROR(0x00050091, "error reading SOT marker");
3049 Lsot = swap_bytes_if_le(Lsot);
3050 if (Lsot != 10)
3051 OJPH_ERROR(0x00050092, "error in SOT length");
3052 if (file->read(&Isot, 2) != 2)
3053 OJPH_ERROR(0x00050093, "error reading SOT tile index");
3054 Isot = swap_bytes_if_le(Isot);
3055 if (Isot == 0xFFFF)
3056 OJPH_ERROR(0x00050094, "tile index in SOT marker cannot be 0xFFFF");
3057 if (file->read(&Psot, 4) != 4)
3058 OJPH_ERROR(0x00050095, "error reading SOT marker");
3059 Psot = swap_bytes_if_le(Psot);
3060 if (file->read(&TPsot, 1) != 1)
3061 OJPH_ERROR(0x00050096, "error reading SOT marker");
3062 if (file->read(&TNsot, 1) != 1)
3063 OJPH_ERROR(0x00050097, "error reading SOT marker");
3064 }
3065 return true;
3066 }
3067
3069 //
3070 //
3071 //
3072 //
3073 //
3075
3078 {
3080 OJPH_ERROR(0x000500B1, "Trying to store %d tileparts in TLM markers, "
3081 "but at most %d can be indexed; a codestream can carry "
3082 "%d TLM marker segments of %d entries each.",
3085 this->num_pairs = num_pairs;
3086 pairs = store;
3087 }
3088
3091 {
3092 assert(next_pair_index < num_pairs);
3093 pairs[next_pair_index].Ttlm = Ttlm;
3094 pairs[next_pair_index].Ptlm = Ptlm + 14;
3096 }
3097
3100 {
3101 assert(next_pair_index == num_pairs);
3102 ui16 buf2;
3103 ui32 buf4;
3104 bool result = true;
3105
3106 ui32 written = 0;
3107 ui32 z = 0;
3108 do
3109 {
3110 ui32 left = num_pairs - written;
3111 ui32 count = left < MAX_PAIRS_PER_SEG ? left : MAX_PAIRS_PER_SEG;
3112 ui8 Ztlm = (ui8)z;
3113 ui8 Stlm = 0x60; // 2-byte Ttlm, 4-byte Ptlm
3114
3115 buf2 = JP2K_MARKER::TLM;
3116 buf2 = swap_bytes_if_le(buf2);
3117 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
3118 buf2 = swap_bytes_if_le((ui16)(4 + 6 * count));
3119 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
3120 result &= file->write(&Ztlm, 1) == 1;
3121 result &= file->write(&Stlm, 1) == 1;
3122 for (ui32 i = written; i < written + count; ++i)
3123 {
3124 buf2 = swap_bytes_if_le(pairs[i].Ttlm);
3125 result &= file->write(&buf2, sizeof(ui16)) == sizeof(ui16);
3126 buf4 = swap_bytes_if_le(pairs[i].Ptlm);
3127 result &= file->write(&buf4, sizeof(ui32)) == sizeof(ui32);
3128 }
3129 written += count;
3130 ++z;
3131 } while (written < num_pairs);
3132 return result;
3133 }
3134
3136 //
3137 //
3138 //
3139 //
3140 //
3142
3144 const param_dfs* param_dfs::get_dfs(int index) const
3145 {
3146 const param_dfs* p = this;
3147 while (p && p->Sdfs != index)
3148 p = p->next;
3149 return p;
3150 }
3151
3154 {
3155 decomp_level = ojph_min(decomp_level, Ids);
3156 ui32 d = decomp_level - 1; // decomp_level starts from 1
3157 ui32 idx = d >> 2; // complete bytes
3158 ui32 bits = d & 0x3; // bit within the bytes
3159 ui32 val = (Ddfs[idx] >> (6 - 2 * bits)) & 0x3;
3160 return (dfs_dwt_type)val;
3161 }
3162
3165 ui32 subband) const
3166 {
3167 assert((resolution == 0 && subband == 0) ||
3168 (resolution > 0 && subband > 0 && subband < 4));
3169
3170 ui32 ns[4] = { 0, 3, 1, 1 };
3171
3172 ui32 idx = 0;
3173 if (resolution > 0)
3174 {
3175 idx = 0;
3176 ui32 i = 1;
3177 for (; i < resolution; ++i)
3178 idx += ns[get_dwt_type(num_decompositions - i + 1)];
3179 dfs_dwt_type t = get_dwt_type(num_decompositions - i + 1);
3180 idx += subband;
3181 if (t == VERT_DWT && subband == 2)
3182 --idx;
3183 }
3184
3185 return idx;
3186 }
3187
3189 point param_dfs::get_res_downsamp(ui32 skipped_resolutions) const
3190 {
3191 point factor(1, 1);
3192 ui32 decomp_level = 1;
3193 while (skipped_resolutions > 0)
3194 {
3195 param_dfs::dfs_dwt_type type = get_dwt_type(decomp_level);
3196 if (type == BIDIR_DWT)
3197 { factor.x *= 2; factor.y *= 2; }
3198 else if (type == HORZ_DWT)
3199 factor.x *= 2;
3200 else if (type == VERT_DWT)
3201 factor.y *= 2;
3202
3203 ++decomp_level;
3204 --skipped_resolutions;
3205 }
3206 return factor;
3207 }
3208
3211 {
3212 if (Ldfs != 0) { // this param_dfs is used
3213 param_dfs* p = this;
3214 while (p->next != NULL)
3215 p = p->next;
3216 if (avail)
3217 {
3218 p->next = avail;
3219 avail = avail->next;
3220 p->next->init();
3221 }
3222 else
3223 p->next = new param_dfs;
3224 p = p->next;
3225 return p->read(file);
3226 }
3227
3228 if (file->read(&Ldfs, 2) != 2)
3229 OJPH_ERROR(0x000500D1, "error reading DFS-Ldfs parameter");
3230 Ldfs = swap_bytes_if_le(Ldfs);
3231 if (file->read(&Sdfs, 2) != 2)
3232 OJPH_ERROR(0x000500D2, "error reading DFS-Sdfs parameter");
3233 Sdfs = swap_bytes_if_le(Sdfs);
3234 if (Sdfs > 15)
3235 OJPH_ERROR(0x000500D3, "The DFS-Sdfs parameter is %d, which is "
3236 "larger than the permissible 15", Sdfs);
3237 ui8 t, l_Ids = 0;
3238 if (file->read(&l_Ids, 1) != 1)
3239 OJPH_ERROR(0x000500D4, "error reading DFS-Ids parameter");
3240 if (l_Ids == 0)
3241 OJPH_ERROR(0x000500D8,
3242 "The value of the Ids member in the DFS marker segment cannot be 0");
3243 constexpr int max_Ddfs = sizeof(Ddfs) * 4;
3244 if (l_Ids > max_Ddfs)
3245 OJPH_INFO(0x000500D5, "The DFS-Ids parameter is %d; while this is "
3246 "valid, the number is unnessarily large -- you do not need more "
3247 "than %d. Please contact me regarding this issue.",
3248 l_Ids, max_Ddfs);
3249 Ids = l_Ids < max_Ddfs ? l_Ids : max_Ddfs;
3250 for (int i = 0; i < Ids; i += 4)
3251 if (file->read(&Ddfs[i / 4], 1) != 1)
3252 OJPH_ERROR(0x000500D6, "error reading DFS-Ddfs parameters");
3253 for (int i = Ids; i < l_Ids; i += 4)
3254 if (file->read(&t, 1) != 1)
3255 OJPH_ERROR(0x000500D7, "error reading DFS-Ddfs parameters");
3256 return true;
3257 }
3258
3260 //
3261 //
3262 //
3263 //
3264 //
3266
3269 {
3270 assert(top_atk == NULL);
3271
3272 if (Latk == 0)
3273 {
3274 // This atk object is not used, initialize it to either 0 (irv97)
3275 // or 1 (rev53), and use it. If index is not 0 nor 1, then index
3276 // must have been read from file previously, otherwise it is an
3277 // error.
3278 if (index == 0) { this->init_irv97(); return this; }
3279 else if (index == 1) { this->init_rev53(); return this; }
3280 }
3281
3282 param_atk* p = this;
3283 while (p && p->get_index() != index)
3284 p = p->next;
3285
3286 if (p == NULL && (index == 0 || index == 1))
3287 {
3288 // The index was not found, add an atk object only if the index is
3289 // either 0 or 1
3290 p = add_object();
3291 if (index == 0)
3292 p->init_irv97();
3293 else if (index == 1)
3294 p->init_rev53();
3295 }
3296
3297 return p;
3298 }
3299
3301 bool param_atk::read_coefficient(infile_base *file, float &K, si32& bytes)
3302 {
3303 int coeff_type = get_coeff_type();
3304 if (coeff_type == 0) { // 8bit
3305 ui8 v;
3306 if (file->read(&v, 1) != 1) return false;
3307 bytes -= 1;
3308 K = v;
3309 }
3310 else if (coeff_type == 1) { // 16bit
3311 ui16 v;
3312 if (file->read(&v, 2) != 2) return false;
3313 bytes -= 2;
3314 K = swap_bytes_if_le(v);
3315 }
3316 else if (coeff_type == 2) { // float
3317 ui32 i;
3318 if (file->read(&i, sizeof(ui32)) != sizeof(ui32)) return false;
3319 bytes -= 4;
3320 i = swap_bytes_if_le(i);
3321 float f;
3322 memcpy(&f, &i, sizeof(float));
3323 K = f;
3324 }
3325 else if (coeff_type == 3) { // double
3326 ui64 i;
3327 if (file->read(&i, sizeof(ui64)) != sizeof(ui64)) return false;
3328 bytes -= 8;
3329 i = swap_bytes_if_le(i);
3330 double d;
3331 memcpy(&d, &i, sizeof(double));
3332 K = (float)d;
3333 }
3334 else if (coeff_type == 4) { // 128 bit float
3335 ui64 v, v1;
3336 if (file->read(&v, 8) != 8) return false;
3337 bytes -= 8;
3338 if (file->read(&v1, 8) != 8) return false; // v1 not needed
3339 bytes -= 8;
3340 v = swap_bytes_if_le(v);
3341
3342 // convert the MSB of 128b float to 32b float
3343 // 32b float has 1 sign bit, 8 exponent (offset 127), 23 mantissa
3344 // 128b float has 1 sign bit, 15 exponent (offset 16383), 112 mantissa
3345 si32 e = (si32)((v >> 48) & 0x7FFF); // exponent
3346 e -= 16383;
3347 e += 127;
3348 e = e & 0xFF; // removes MSBs if negative
3349 e <<= 23; // move bits to their location
3350 ui32 i = 0;
3351 i |= ((ui32)(v >> 32) & 0x80000000); // copy sign bit
3352 i |= (ui32)e; // copy exponent
3353 i |= (ui32)((v >> 25) & 0x007FFFFF); // copy 23 mantissa
3354 float f;
3355 memcpy(&f, &i, sizeof(float));
3356 K = f;
3357 }
3358 return true;
3359 }
3360
3361
3364 {
3365 int coeff_type = get_coeff_type();
3366 if (coeff_type == 0) {
3367 si8 v;
3368 if (file->read(&v, 1) != 1) return false;
3369 bytes -= 1;
3370 K = v;
3371 }
3372 else if (coeff_type == 1) {
3373 si16 v;
3374 if (file->read(&v, 2) != 2) return false;
3375 bytes -= 2;
3376 K = (si16)swap_bytes_if_le((ui16)v);
3377 }
3378 else
3379 return false;
3380 return true;
3381 }
3382
3385 {
3386 if (Latk != 0) // this param_atk is used
3387 return add_object()->read(file);
3388
3389 if (file->read(&Latk, 2) != 2)
3390 OJPH_ERROR(0x000500E1, "error reading ATK-Latk parameter");
3391 Latk = swap_bytes_if_le(Latk);
3392 si32 bytes = Latk - 2;
3393 ojph::ui16 temp_Satk;
3394 if (file->read(&temp_Satk, 2) != 2)
3395 OJPH_ERROR(0x000500E2, "error reading ATK-Satk parameter");
3396 bytes -= 2;
3397 temp_Satk = swap_bytes_if_le(temp_Satk);
3398 int tmp_idx = temp_Satk & 0xFF;
3399 if ((top_atk && top_atk->get_atk(tmp_idx) != NULL)
3400 || tmp_idx == 0 || tmp_idx == 1)
3401 OJPH_ERROR(0x000500F3, "ATK-Satk parameter sets ATK marker index to "
3402 "the illegal value of %d. ATK-Satk should be in (2-255) and, I "
3403 "believe, must not be repeated; otherwise, it would be unclear "
3404 "what marker segment must be employed when an index is repeated.",
3405 tmp_idx);
3406 Satk = temp_Satk;
3407 if (is_m_init0() == false) // only even-indexed is supported
3408 OJPH_ERROR(0x000500E3, "ATK-Satk parameter sets m_init to 1, "
3409 "requiring odd-indexed subsequence in first reconstruction step, "
3410 "which is not supported yet.");
3411 if (is_whole_sample() == false) // ARB filter not supported
3412 OJPH_ERROR(0x000500E4, "ATK-Satk parameter specified ARB filter, "
3413 "which is not supported yet.");
3414 if (is_reversible() && get_coeff_type() >= 2) // reversible & float
3415 OJPH_ERROR(0x000500E5, "ATK-Satk parameter does not make sense. "
3416 "It employs floats with reversible filtering.");
3417 if (is_using_ws_extension() == false) // only sym. ext is supported
3418 OJPH_ERROR(0x000500E6, "ATK-Satk parameter requires constant "
3419 "boundary extension, which is not supported yet.");
3420 if (is_reversible() == false)
3421 if (read_coefficient(file, Katk, bytes) == false)
3422 OJPH_ERROR(0x000500E7, "error reading ATK-Katk parameter");
3423 if (file->read(&Natk, 1) != 1)
3424 OJPH_ERROR(0x000500E8, "error reading ATK-Natk parameter");
3425 bytes -= 1;
3426 if (Natk > max_steps) {
3427 if (d != d_store) // was this allocated -- very unlikely
3428 delete[] d;
3429 d = new lifting_step[Natk];
3430 max_steps = Natk;
3431 }
3432
3433 if (is_reversible())
3434 {
3435 for (int s = 0; s < Natk; ++s)
3436 {
3437 if (file->read(&d[s].rev.Eatk, 1) != 1)
3438 OJPH_ERROR(0x000500E9, "error reading ATK-Eatk parameter");
3439 bytes -= 1;
3440 if (file->read(&d[s].rev.Batk, 2) != 2)
3441 OJPH_ERROR(0x000500EA, "error reading ATK-Batk parameter");
3442 bytes -= 2;
3443 d[s].rev.Batk = (si16)swap_bytes_if_le((ui16)d[s].rev.Batk);
3444 ui8 LCatk;
3445 if (file->read(&LCatk, 1) != 1)
3446 OJPH_ERROR(0x000500EB, "error reading ATK-LCatk parameter");
3447 bytes -= 1;
3448 if (LCatk == 0)
3449 OJPH_ERROR(0x000500EC, "Encountered a ATK-LCatk value of zero; "
3450 "something is wrong.");
3451 if (LCatk > 1)
3452 OJPH_ERROR(0x000500ED, "ATK-LCatk value greater than 1; "
3453 "that is, a multitap filter is not supported");
3454 if (read_coefficient(file, d[s].rev.Aatk, bytes) == false)
3455 OJPH_ERROR(0x000500EE, "Error reding ATK-Aatk parameter");
3456 }
3457 }
3458 else
3459 {
3460 for (int s = 0; s < Natk; ++s)
3461 {
3462 ui8 LCatk;
3463 if (file->read(&LCatk, 1) != 1)
3464 OJPH_ERROR(0x000500EF, "error reading ATK-LCatk parameter");
3465 bytes -= 1;
3466 if (LCatk == 0)
3467 OJPH_ERROR(0x000500F0, "Encountered a ATK-LCatk value of zero; "
3468 "something is wrong.");
3469 if (LCatk > 1)
3470 OJPH_ERROR(0x000500F1, "ATK-LCatk value greater than 1; "
3471 "that is, a multitap filter is not supported.");
3472 if (read_coefficient(file, d[s].irv.Aatk, bytes) == false)
3473 OJPH_ERROR(0x000500F2, "Error reding ATK-Aatk parameter");
3474 }
3475 }
3476 if (bytes != 0)
3477 OJPH_ERROR(0x000500F3, "The length of an ATK marker segment "
3478 "(ATK-Latk) is not correct");
3479
3480 return true;
3481 }
3482
3485 {
3486 Satk = 0x4a00; // illegal because ATK = 0
3487 Katk = (float)1.230174104914001;
3488 Natk = 4;
3489 // next is (A-4) in T.801 second line
3490 Latk = (ui16)(5 + Natk + sizeof(float) * (1 + Natk));
3491 d[0].irv.Aatk = (float)0.443506852043971;
3492 d[1].irv.Aatk = (float)0.882911075530934;
3493 d[2].irv.Aatk = (float)-0.052980118572961;
3494 d[3].irv.Aatk = (float)-1.586134342059924;
3495 }
3496
3499 {
3500 Satk = 0x5801; // illegal because ATK = 1
3501 Natk = 2;
3502 // next is (A-4) in T.801 fourth line
3503 Latk = (ui16)(5 + 2 * Natk + sizeof(ui8) * (Natk + Natk));
3504 d[0].rev.Aatk = 1;
3505 d[0].rev.Batk = 2;
3506 d[0].rev.Eatk = 2;
3507 d[1].rev.Aatk = -1;
3508 d[1].rev.Batk = 1;
3509 d[1].rev.Eatk = 1;
3510 }
3511
3514 {
3515 assert(top_atk == NULL);
3516 param_atk *p = this;
3517 while (p->next != NULL)
3518 p = p->next;
3519 if (avail)
3520 {
3521 p->next = avail;
3522 avail = avail->next;
3523 }
3524 else
3525 p->next = new param_atk;
3526 p = p->next;
3527 p->init(this);
3528 return p;
3529 }
3530
3531 } // !local namespace
3532} // !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
static void prepare_for_encoding_approx_for_type(const void *marker_points, float div, float &ft_min, float &ft_max, float &delta, float &inv_delta, float fd_min, float fd_max, ui32 num_points, ui32 enc_num_points, float *approx_enc_points)
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
void set_weights(size_t num_weights, const float *weights)
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)
static constexpr ui32 MAX_SUBBAND_COUNT
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
float weights[MAX_SUBBAND_COUNT]
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