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