OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
ojph_resolution.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_resolution.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
39#include <climits>
40#include <cmath>
41#include <new>
42
43#include "ojph_mem.h"
44#include "ojph_params.h"
46#include "ojph_resolution.h"
47#include "ojph_tile_comp.h"
48#include "ojph_tile.h"
49#include "ojph_subband.h"
50#include "ojph_precinct.h"
51
52#include "../transform/ojph_transform.h"
53
54namespace ojph {
55
56 namespace local
57 {
60 const rect& recon_res_rect,
61 ui32 comp_num, ui32 res_num)
62 {
64 const param_cod* cdp = codestream->get_cod(comp_num);
68
69 const param_atk* atk = cdp->access_atk();
71 if (cdp->is_dfs_defined()) {
72 const param_dfs* dfs = codestream->access_dfs();
73 if (dfs == NULL) {
74 OJPH_ERROR(0x00070001, "There is a problem with codestream "
75 "marker segments. COD/COC specifies the use of a DFS marker "
76 "but there are no DFS markers within the main codestream "
77 "headers");
78 }
79 else {
80 ui16 dfs_idx = cdp->get_dfs_index();
81 dfs = dfs->get_dfs(dfs_idx);
82 if (dfs == NULL) {
83 OJPH_ERROR(0x00070002, "There is a problem with codestream "
84 "marker segments. COD/COC specifies the use of a DFS marker "
85 "with index %d, but there are no such marker within the "
86 "main codestream headers", dfs_idx);
87 }
88 ui32 num_decomps = cdp->get_num_decompositions();
89 ds = dfs->get_dwt_type(num_decomps - res_num + 1);
90 }
91 }
92
94 if (res_num > 0)
95 {
96 if (ds == param_dfs::BIDIR_DWT)
98 else if (ds == param_dfs::HORZ_DWT)
100 else if (ds == param_dfs::VERT_DWT)
102 }
103
104 //allocate resolution/subbands
105 ui32 trx0 = res_rect.org.x;
106 ui32 try0 = res_rect.org.y;
107 ui32 trx1 = res_rect.org.x + res_rect.siz.w;
108 ui32 try1 = res_rect.org.y + res_rect.siz.h;
109 allocator->pre_alloc_obj<subband>(4);
110 if (res_num > 0)
111 {
112 if (ds == param_dfs::BIDIR_DWT)
113 {
114 for (ui32 i = 0; i < 4; ++i)
115 {
116 ui32 tbx0 = (trx0 - (i & 1) + 1) >> 1;
117 ui32 tbx1 = (trx1 - (i & 1) + 1) >> 1;
118 ui32 tby0 = (try0 - (i >> 1) + 1) >> 1;
119 ui32 tby1 = (try1 - (i >> 1) + 1) >> 1;
120
121 rect re;
122 re.org.x = tbx0;
123 re.org.y = tby0;
124 re.siz.w = tbx1 - tbx0;
125 re.siz.h = tby1 - tby0;
126 if (i == 0) {
127 allocator->pre_alloc_obj<resolution>(1);
129 skipped_res_for_recon ? recon_res_rect : re,
130 comp_num, res_num - 1);
131 }
132 else
135 }
136 }
137 else if (ds == param_dfs::VERT_DWT)
138 {
139 ui32 tby0, tby1;
140 rect re = res_rect;
141 tby0 = (try0 + 1) >> 1;
142 tby1 = (try1 + 1) >> 1;
143 re.org.y = tby0;
144 re.siz.h = tby1 - tby0;
145 allocator->pre_alloc_obj<resolution>(1);
147 skipped_res_for_recon ? recon_res_rect : re,
148 comp_num, res_num - 1);
149
150 tby0 = try0 >> 1;
151 tby1 = try1 >> 1;
152 re.org.y = tby0;
153 re.siz.h = tby1 - tby0;
156 }
157 else if (ds == param_dfs::HORZ_DWT)
158 {
159 ui32 tbx0, tbx1;
160 rect re = res_rect;
161 tbx0 = (trx0 + 1) >> 1;
162 tbx1 = (trx1 + 1) >> 1;
163 re.org.x = tbx0;
164 re.siz.w = tbx1 - tbx0;
165 allocator->pre_alloc_obj<resolution>(1);
167 skipped_res_for_recon ? recon_res_rect : re,
168 comp_num, res_num - 1);
169
170 tbx0 = trx0 >> 1;
171 tbx1 = trx1 >> 1;
172 re.org.x = tbx0;
173 re.siz.w = tbx1 - tbx0;
176 }
177 else
178 {
179 assert(ds == param_dfs::NO_DWT);
180 allocator->pre_alloc_obj<resolution>(1);
182 skipped_res_for_recon ? recon_res_rect : res_rect,
183 comp_num, res_num - 1);
184 }
185 }
186 else
189
190 //prealloc precincts
193 if (trx0 != trx1 && try0 != try1)
194 {
195 num_precincts.w = (trx1 + (1 << log_PP.w) - 1) >> log_PP.w;
196 num_precincts.w -= trx0 >> log_PP.w;
197 num_precincts.h = (try1 + (1 << log_PP.h) - 1) >> log_PP.h;
198 num_precincts.h -= try0 >> log_PP.h;
199 allocator->pre_alloc_obj<precinct>((size_t)num_precincts.area());
200 }
201
202 const param_siz* szp = codestream->get_siz();
203 ui32 precision = cdp->propose_precision(szp, comp_num);
204
205 //allocate lines
206 if (skipped_res_for_recon == false)
207 {
209 allocator->pre_alloc_obj<line_buf>(num_steps + 2);
210 allocator->pre_alloc_obj<lifting_buf>(num_steps + 2);
211
212 ui32 width = res_rect.siz.w + 1;
213 if (precision <= 32) {
214 for (ui32 i = 0; i < num_steps; ++i)
215 allocator->pre_alloc_data<si32>(width, 1);
216 allocator->pre_alloc_data<si32>(width, 1);
217 allocator->pre_alloc_data<si32>(width, 1);
218 }
219 else
220 {
221 for (ui32 i = 0; i < num_steps; ++i)
222 allocator->pre_alloc_data<si64>(width, 1);
223 allocator->pre_alloc_data<si64>(width, 1);
224 allocator->pre_alloc_data<si64>(width, 1);
225 }
226 }
227 }
228
231 const rect& res_rect,
232 const rect& recon_res_rect,
233 ui32 comp_num, ui32 res_num,
234 point comp_downsamp, point res_downsamp,
235 tile_comp* parent_tile_comp,
236 resolution* parent_res)
237 {
240 const param_cod* cdp = codestream->get_cod(comp_num);
241 ui32 t, num_decomps = cdp->get_num_decompositions();
242 t = num_decomps - codestream->get_skipped_res_for_recon();
244 t = num_decomps - codestream->get_skipped_res_for_read();
246
247 this->comp_downsamp = comp_downsamp;
248 this->parent_comp = parent_tile_comp;
249 this->parent_res = parent_res;
250 this->res_rect = res_rect;
251 this->comp_num = comp_num;
252 this->res_num = res_num;
253 this->num_bytes = 0;
254 this->atk = cdp->access_atk();
256 if (cdp->is_dfs_defined()) {
257 const param_dfs* dfs = codestream->access_dfs();
258 if (dfs == NULL) {
259 OJPH_ERROR(0x00070011, "There is a problem with codestream "
260 "marker segments. COD/COC specifies the use of a DFS marker "
261 "but there are no DFS markers within the main codestream "
262 "headers");
263 }
264 else {
265 ui16 dfs_idx = cdp->get_dfs_index();
266 dfs = dfs->get_dfs(dfs_idx);
267 if (dfs == NULL) {
268 OJPH_ERROR(0x00070012, "There is a problem with codestream "
269 "marker segments. COD/COC specifies the use of a DFS marker "
270 "with index %d, but there are no such marker within the "
271 "main codestream headers", dfs_idx);
272 }
273 ui32 num_decomps = cdp->get_num_decompositions();
274 ds = dfs->get_dwt_type(num_decomps - res_num + 1);
275 }
276 }
277
278 transform_flags = 0;
279 if (res_num > 0)
280 {
281 if (ds == param_dfs::BIDIR_DWT)
283 else if (ds == param_dfs::HORZ_DWT)
285 else if (ds == param_dfs::VERT_DWT)
287 }
288
289 //allocate resolution/subbands
290 ui32 trx0 = res_rect.org.x;
291 ui32 try0 = res_rect.org.y;
292 ui32 trx1 = res_rect.org.x + res_rect.siz.w;
293 ui32 try1 = res_rect.org.y + res_rect.siz.h;
294 bands = allocator->post_alloc_obj<subband>(4);
295 for (int i = 0; i < 4; ++i)
296 new (bands + i) subband;
297 if (res_num > 0)
298 {
299 if (ds == param_dfs::BIDIR_DWT)
300 {
301 for (ui32 i = 0; i < 4; ++i)
302 {
303 ui32 tbx0 = (trx0 - (i & 1) + 1) >> 1;
304 ui32 tbx1 = (trx1 - (i & 1) + 1) >> 1;
305 ui32 tby0 = (try0 - (i >> 1) + 1) >> 1;
306 ui32 tby1 = (try1 - (i >> 1) + 1) >> 1;
307
308 rect re;
309 re.org.x = tbx0;
310 re.org.y = tby0;
311 re.siz.w = tbx1 - tbx0;
312 re.siz.h = tby1 - tby0;
313 if (i == 0) {
314 point next_res_downsamp;
315 next_res_downsamp.x = res_downsamp.x * 2;
316 next_res_downsamp.y = res_downsamp.y * 2;
317
318 child_res = allocator->post_alloc_obj<resolution>(1);
320 skipped_res_for_recon ? recon_res_rect : re, comp_num,
321 res_num - 1, comp_downsamp, next_res_downsamp,
322 parent_tile_comp, this);
323 }
324 else
325 bands[i].finalize_alloc(codestream, re, this, res_num, i);
326 }
327 }
328 else if (ds == param_dfs::VERT_DWT)
329 {
330 ui32 tby0, tby1;
331 rect re = res_rect;
332 tby0 = (try0 + 1) >> 1;
333 tby1 = (try1 + 1) >> 1;
334 re.org.y = tby0;
335 re.siz.h = tby1 - tby0;
336
337 point next_res_downsamp;
338 next_res_downsamp.x = res_downsamp.x;
339 next_res_downsamp.y = res_downsamp.y * 2;
340 child_res = allocator->post_alloc_obj<resolution>(1);
342 skipped_res_for_recon ? recon_res_rect : re, comp_num,
343 res_num - 1, comp_downsamp, next_res_downsamp,
344 parent_tile_comp, this);
345
346 tby0 = try0 >> 1;
347 tby1 = try1 >> 1;
348 re.org.y = tby0;
349 re.siz.h = tby1 - tby0;
350 bands[2].finalize_alloc(codestream, re, this, res_num, 2);
351 }
352 else if (ds == param_dfs::HORZ_DWT)
353 {
354 ui32 tbx0, tbx1;
355 rect re = res_rect;
356 tbx0 = (trx0 + 1) >> 1;
357 tbx1 = (trx1 + 1) >> 1;
358 re.org.x = tbx0;
359 re.siz.w = tbx1 - tbx0;
360
361 point next_res_downsamp;
362 next_res_downsamp.x = res_downsamp.x * 2;
363 next_res_downsamp.y = res_downsamp.y;
364 child_res = allocator->post_alloc_obj<resolution>(1);
366 skipped_res_for_recon ? recon_res_rect : re, comp_num,
367 res_num - 1, comp_downsamp, next_res_downsamp,
368 parent_tile_comp, this);
369
370 tbx0 = trx0 >> 1;
371 tbx1 = trx1 >> 1;
372 re.org.x = tbx0;
373 re.siz.w = tbx1 - tbx0;
374 bands[1].finalize_alloc(codestream, re, this, res_num, 1);
375 }
376 else
377 {
378 assert(ds == param_dfs::NO_DWT);
379 child_res = allocator->post_alloc_obj<resolution>(1);
381 skipped_res_for_recon ? recon_res_rect : res_rect, comp_num,
382 res_num - 1, comp_downsamp, res_downsamp, parent_tile_comp, this);
383 }
384 }
385 else {
386 child_res = NULL;
388 }
389
390 //finalize precincts
393 precincts = NULL;
394 if (trx0 != trx1 && try0 != try1)
395 {
396 num_precincts.w = (trx1 + (1 << log_PP.w) - 1) >> log_PP.w;
397 num_precincts.w -= trx0 >> log_PP.w;
398 num_precincts.h = (try1 + (1 << log_PP.h) - 1) >> log_PP.h;
399 num_precincts.h -= try0 >> log_PP.h;
400 precincts =
401 allocator->post_alloc_obj<precinct>((size_t)num_precincts.area());
402 ui64 num = num_precincts.area();
403 for (ui64 i = 0; i < num; ++i)
404 precincts[i] = precinct();
405 }
406 // precincts will be initialized in full shortly
407
408 ui32 x_lower_bound = (trx0 >> log_PP.w) << log_PP.w;
409 ui32 y_lower_bound = (try0 >> log_PP.h) << log_PP.h;
410
411 precinct* pp = precincts;
412 point tile_top_left = parent_tile_comp->get_tile()->get_tile_rect().org;
413 for (ui32 y = 0; y < num_precincts.h; ++y)
414 {
415 ui32 ppy0 = y_lower_bound + (y << log_PP.h);
416 for (ui32 x = 0; x < num_precincts.w; ++x, ++pp)
417 {
418 ui32 ppx0 = x_lower_bound + (x << log_PP.w);
419 point t(res_downsamp.x * ppx0, res_downsamp.y * ppy0);
420 t.x = t.x > tile_top_left.x ? t.x : tile_top_left.x;
421 t.y = t.y > tile_top_left.y ? t.y : tile_top_left.y;
422 pp->img_point = t;
423 pp->bands = bands;
424 pp->may_use_sop = cdp->packets_may_use_sop();
425 pp->uses_eph = cdp->packets_use_eph();
427 pp->coded = NULL;
428 }
429 }
430 for (int i = 0; i < 4; ++i)
431 if (bands[i].exists())
433
434 // determine how to divide scratch into multiple levels of
435 // tag trees
436 size log_cb = cdp->get_log_block_dims();
437 log_PP.w -= (transform_flags & HORZ_TRX) ? 1 : 0;
438 log_PP.h -= (transform_flags & VERT_TRX) ? 1 : 0;
439 size ratio;
440 ratio.w = log_PP.w - ojph_min(log_cb.w, log_PP.w);
441 ratio.h = log_PP.h - ojph_min(log_cb.h, log_PP.h);
442 max_num_levels = ojph_max(ratio.w, ratio.h);
443 ui32 val = 1u << (max_num_levels << 1);
444 tag_tree_size = (int)((val * 4 + 2) / 3);
446 level_index[0] = 0;
447 for (ui32 i = 1; i <= max_num_levels; ++i, val >>= 2)
448 level_index[i] = level_index[i - 1] + val;
449 cur_precinct_loc = point(0, 0);
450
451 const param_siz* szp = codestream->get_siz();
452 ui32 precision = cdp->propose_precision(szp, comp_num);
453
454 //allocate lines
455 if (skipped_res_for_recon == false)
456 {
457 this->atk = cdp->access_atk();
458 this->reversible = atk->is_reversible();
459 this->num_steps = atk->get_num_steps();
460 // create line buffers and lifting_bufs
461 lines = allocator->post_alloc_obj<line_buf>(num_steps + 2);
462 ssp = allocator->post_alloc_obj<lifting_buf>(num_steps + 2);
463 sig = ssp + num_steps;
464 aug = ssp + num_steps + 1;
465
466 // initiate lifting_bufs
467 for (ui32 i = 0; i < num_steps; ++i) {
468 new (ssp + i) lifting_buf;
469 ssp[i].line = lines + i;
470 };
471 new (sig) lifting_buf;
472 sig->line = lines + num_steps;
473 new (aug) lifting_buf;
474 aug->line = lines + num_steps + 1;
475
476 // initiate storage of line_buf
477 ui32 width = res_rect.siz.w + 1;
478 if (precision <= 32)
479 {
480 for (ui32 i = 0; i < num_steps; ++i)
481 ssp[i].line->wrap(
482 allocator->post_alloc_data<si32>(width, 1), width, 1);
483 sig->line->wrap(allocator->post_alloc_data<si32>(width, 1), width, 1);
484 aug->line->wrap(allocator->post_alloc_data<si32>(width, 1), width, 1);
485 }
486 else
487 {
488 for (ui32 i = 0; i < num_steps; ++i)
489 ssp[i].line->wrap(
490 allocator->post_alloc_data<si64>(width, 1), width, 1);
491 sig->line->wrap(allocator->post_alloc_data<si64>(width, 1), width, 1);
492 aug->line->wrap(allocator->post_alloc_data<si64>(width, 1), width, 1);
493 }
494
495 cur_line = 0;
497 vert_even = (res_rect.org.y & 1) == 0;
498 horz_even = (res_rect.org.x & 1) == 0;
499 }
500 }
501
504 {
505 if (vert_even)
506 {
507 ++cur_line;
508 sig->active = true;
509 return sig->line;
510 }
511 else
512 {
513 ++cur_line;
514 aug->active = true;
515 return aug->line;
516 }
517 }
518
521 {
522 if (res_num == 0)
523 {
524 assert(child_res == NULL);
526 bands[0].push_line();
527 return;
528 }
529
530 ui32 width = res_rect.siz.w;
531 if (width == 0)
532 return;
533 if (reversible)
534 {
535 if (res_rect.siz.h > 1)
536 {
537 if (!vert_even && cur_line < res_rect.siz.h) {
539 return;
540 }
541
542 do
543 {
544 //vertical transform
545 for (ui32 i = 0; i < num_steps; ++i)
546 {
547 if (aug->active && (sig->active || ssp[i].active))
548 {
549 line_buf* dp = aug->line;
550 line_buf* sp1 = sig->active ? sig->line : ssp[i].line;
551 line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line;
552 const lifting_step* s = atk->get_step(num_steps - i - 1);
553 rev_vert_step(s, sp1, sp2, dp, width, false);
554 }
555 lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t;
556 }
557
558 if (aug->active) {
560 bands[3].get_line(), aug->line, width, horz_even);
561 bands[2].push_line();
562 bands[3].push_line();
563 aug->active = false;
565 }
566 if (sig->active) {
568 bands[1].get_line(), sig->line, width, horz_even);
569 bands[1].push_line();
571 sig->active = false;
573 };
575 } while (cur_line >= res_rect.siz.h && rows_to_produce > 0);
576 }
577 else
578 {
579 if (vert_even) {
580 // horizontal transform
582 bands[1].get_line(), sig->line, width, horz_even);
583 bands[1].push_line();
585 }
586 else
587 {
588 // vertical transform
589 si32* sp = aug->line->i32;
590 for (ui32 i = width; i > 0; --i)
591 *sp++ <<= 1;
592 // horizontal transform
594 bands[3].get_line(), aug->line, width, horz_even);
595 bands[2].push_line();
596 bands[3].push_line();
597 }
598 }
599 }
600 else
601 {
602 if (res_rect.siz.h > 1)
603 {
604 if (!vert_even && cur_line < res_rect.siz.h) {
606 return;
607 }
608
609 do
610 {
611 //vertical transform
612 for (ui32 i = 0; i < num_steps; ++i)
613 {
614 if (aug->active && (sig->active || ssp[i].active))
615 {
616 line_buf* dp = aug->line;
617 line_buf* sp1 = sig->active ? sig->line : ssp[i].line;
618 line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line;
619 const lifting_step* s = atk->get_step(num_steps - i - 1);
620 irv_vert_step(s, sp1, sp2, dp, width, false);
621 }
622 lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t;
623 }
624
625 if (aug->active) {
626 const float K = atk->get_K();
627 irv_vert_times_K(K, aug->line, width);
628
630 bands[3].get_line(), aug->line, width, horz_even);
631 bands[2].push_line();
632 bands[3].push_line();
633 aug->active = false;
635 }
636 if (sig->active) {
637 const float K_inv = 1.0f / atk->get_K();
638 irv_vert_times_K(K_inv, sig->line, width);
639
641 bands[1].get_line(), sig->line, width, horz_even);
642 bands[1].push_line();
644 sig->active = false;
646 };
648 } while (cur_line >= res_rect.siz.h && rows_to_produce > 0);
649 }
650 else
651 {
652 if (vert_even) {
653 // horizontal transform
655 bands[1].get_line(), sig->line, width, horz_even);
656 bands[1].push_line();
658 }
659 else
660 {
661 // vertical transform
662 float* sp = aug->line->f32;
663 for (ui32 i = width; i > 0; --i)
664 *sp++ *= 2.0f;
665 // horizontal transform
667 bands[3].get_line(), aug->line, width, horz_even);
668 bands[2].push_line();
669 bands[3].push_line();
670 }
671 }
672 }
673 }
674
677 {
678 if (res_num == 0)
679 {
680 assert(child_res == NULL);
681 return bands[0].pull_line();
682 }
683
684 if (skipped_res_for_recon == true)
685 return child_res->pull_line();
686
687 ui32 width = res_rect.siz.w;
688 if (width == 0)
689 return NULL;
690
692 {
693 if (reversible)
694 {
695 if (res_rect.siz.h > 1)
696 {
697 if (sig->active) {
698 sig->active = false;
699 return sig->line;
700 };
701 for (;;)
702 {
703 //horizontal transform
704 if (cur_line < res_rect.siz.h)
705 {
706 if (vert_even) { // even
709 bands[1].pull_line(), width, horz_even);
710 else
711 memcpy(aug->line->p, child_res->pull_line()->p,
712 (size_t)width
714 aug->active = true;
716 ++cur_line;
717 continue;
718 }
719 else {
722 bands[3].pull_line(), width, horz_even);
723 else
724 memcpy(sig->line->p, bands[2].pull_line()->p,
725 (size_t)width
727 sig->active = true;
729 ++cur_line;
730 }
731 }
732
733 //vertical transform
734 for (ui32 i = 0; i < num_steps; ++i)
735 {
736 if (aug->active && (sig->active || ssp[i].active))
737 {
738 line_buf* dp = aug->line;
739 line_buf* sp1 = sig->active ? sig->line : ssp[i].line;
740 line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line;
741 const lifting_step* s = atk->get_step(i);
742 rev_vert_step(s, sp1, sp2, dp, width, true);
743 }
744 lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t;
745 }
746
747 if (aug->active) {
748 aug->active = false;
749 return aug->line;
750 }
751 if (sig->active) {
752 sig->active = false;
753 return sig->line;
754 };
755 }
756 }
757 else
758 {
759 if (vert_even) {
762 bands[1].pull_line(), width, horz_even);
763 else
764 memcpy(aug->line->p, child_res->pull_line()->p,
765 (size_t)width
767 }
768 else
769 {
772 bands[3].pull_line(), width, horz_even);
773 else
774 memcpy(aug->line->p, bands[2].pull_line()->p,
775 (size_t)width
778 {
779 si32* sp = aug->line->i32;
780 for (ui32 i = width; i > 0; --i)
781 *sp++ >>= 1;
782 }
783 else
784 {
785 assert(aug->line->flags & line_buf::LFT_64BIT);
786 si64* sp = aug->line->i64;
787 for (ui32 i = width; i > 0; --i)
788 *sp++ >>= 1;
789 }
790 }
791 return aug->line;
792 }
793 }
794 else
795 {
796 if (res_rect.siz.h > 1)
797 {
798 if (sig->active) {
799 sig->active = false;
800 return sig->line;
801 };
802 for (;;)
803 {
804 //horizontal transform
805 if (cur_line < res_rect.siz.h)
806 {
807 if (vert_even) { // even
810 bands[1].pull_line(), width, horz_even);
811 else
812 memcpy(aug->line->f32, child_res->pull_line()->f32,
813 width * sizeof(float));
814 aug->active = true;
816 ++cur_line;
817
818 const float K = atk->get_K();
819 irv_vert_times_K(K, aug->line, width);
820
821 continue;
822 }
823 else {
826 bands[3].pull_line(), width, horz_even);
827 else
828 memcpy(sig->line->f32, bands[2].pull_line()->f32,
829 width * sizeof(float));
830 sig->active = true;
832 ++cur_line;
833
834 const float K_inv = 1.0f / atk->get_K();
835 irv_vert_times_K(K_inv, sig->line, width);
836 }
837 }
838
839 //vertical transform
840 for (ui32 i = 0; i < num_steps; ++i)
841 {
842 if (aug->active && (sig->active || ssp[i].active))
843 {
844 line_buf* dp = aug->line;
845 line_buf* sp1 = sig->active ? sig->line : ssp[i].line;
846 line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line;
847 const lifting_step* s = atk->get_step(i);
848 irv_vert_step(s, sp1, sp2, dp, width, true);
849 }
850 lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t;
851 }
852
853 if (aug->active) {
854 aug->active = false;
855 return aug->line;
856 }
857 if (sig->active) {
858 sig->active = false;
859 return sig->line;
860 };
861 }
862 }
863 else
864 {
865 if (vert_even) {
868 bands[1].pull_line(), width, horz_even);
869 else
870 memcpy(aug->line->f32, child_res->pull_line()->f32,
871 width * sizeof(float));
872 }
873 else
874 {
877 bands[3].pull_line(), width, horz_even);
878 else
879 memcpy(aug->line->f32, bands[2].pull_line()->f32,
880 width * sizeof(float));
881 float* sp = aug->line->f32;
882 for (ui32 i = width; i > 0; --i)
883 *sp++ *= 0.5f;
884 }
885 return aug->line;
886 }
887 }
888 }
889 else
890 {
891 if (reversible)
892 {
895 bands[1].pull_line(), width, horz_even);
896 else
897 memcpy(aug->line->p, child_res->pull_line()->p,
898 (size_t)width * (aug->line->flags & line_buf::LFT_SIZE_MASK));
899 return aug->line;
900 }
901 else
902 {
905 bands[1].pull_line(), width, horz_even);
906 else
907 memcpy(aug->line->f32, child_res->pull_line()->f32,
908 width * sizeof(float));
909 return aug->line;
910 }
911 }
912 }
913
916 {
917 ui32 lower_resolutions_bytes = 0;
918 if (res_num != 0)
919 lower_resolutions_bytes = child_res->prepare_precinct();
920
921 this->num_bytes = 0;
922 si32 repeat = (si32)num_precincts.area();
923 for (si32 i = 0; i < repeat; ++i)
926 return this->num_bytes + lower_resolutions_bytes;
927 }
928
931 {
932 precinct* p = precincts;
933 for (si32 i = 0; i < (si32)num_precincts.area(); ++i)
934 p[i].write(file);
935 }
936
939 {
941 if (idx < num_precincts.area())
942 {
943 top_left = precincts[idx].img_point;
944 return true;
945 }
946 return false;
947 }
948
951 {
953 assert(idx < num_precincts.area());
954 precincts[idx].write(file);
955
957 {
960 }
961 }
962
965 {
966 precinct* p = precincts;
968 for (ui32 i = idx; i < num_precincts.area(); ++i)
969 {
970 if (data_left == 0)
971 break;
972 p[i].parse(tag_tree_size, level_index, elastic, data_left, file,
975 {
978 }
979 }
980 }
981
984 {
986 assert(idx < num_precincts.area());
987
988 if (data_left == 0)
989 return;
990 precinct* p = precincts + idx;
991 p->parse(tag_tree_size, level_index, elastic, data_left, file,
994 {
997 }
998 }
999
1002 {
1003 if (this->res_num == resolution_num)
1004 return get_num_bytes();
1005 else {
1006 if (child_res)
1007 return child_res->get_num_bytes(resolution_num);
1008 else
1009 return 0;
1010 }
1011
1012 }
1013 }
1014}
float * f32
Definition ojph_mem.h:174
void wrap(T *buffer, size_t num_ele, ui32 pre_size)
mem_elastic_allocator * get_elastic_alloc()
mem_fixed_allocator * get_allocator()
const param_dfs * access_dfs()
bool get_top_left_precinct(point &top_left)
void parse_one_precinct(ui32 &data_left, infile_base *file)
mem_elastic_allocator * elastic
void write_precincts(outfile_base *file)
static void pre_alloc(codestream *codestream, const rect &res_rect, const rect &recon_res_rect, ui32 comp_num, ui32 res_num)
void finalize_alloc(codestream *codestream, const rect &res_rect, const rect &recon_res_rect, ui32 comp_num, ui32 res_num, point comp_downsamp, point res_downsamp, tile_comp *parent_tile_comp, resolution *parent_res)
void parse_all_precincts(ui32 &data_left, infile_base *file)
void write_one_precinct(outfile_base *file)
static void pre_alloc(codestream *codestream, const rect &band_rect, ui32 comp_num, ui32 res_num, ui32 transform_flags)
void exchange_buf(line_buf *l)
line_buf * get_line()
void get_cb_indices(const size &num_precincts, precinct *precincts)
void finalize_alloc(codestream *codestream, const rect &band_rect, resolution *res, ui32 res_num, ui32 subband_num)
rect get_tile_rect()
Definition ojph_tile.h:75
void pre_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:66
void pre_alloc_obj(size_t num_ele)
Definition ojph_mem.h:72
T * post_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:89
T * post_alloc_obj(size_t num_ele)
Definition ojph_mem.h:96
void(* rev_horz_ana)(const param_atk *atk, const line_buf *ldst, const line_buf *hdst, const line_buf *src, ui32 width, bool even)
void(* irv_vert_times_K)(float K, const line_buf *aug, ui32 repeat)
void(* irv_vert_step)(const lifting_step *s, const line_buf *sig, const line_buf *other, const line_buf *aug, ui32 repeat, bool synthesis)
void(* rev_horz_syn)(const param_atk *atk, const line_buf *dst, const line_buf *lsrc, const line_buf *hsrc, ui32 width, bool even)
void(* irv_horz_ana)(const param_atk *atk, const line_buf *ldst, const line_buf *hdst, const line_buf *src, ui32 width, bool even)
void(* rev_vert_step)(const lifting_step *s, const line_buf *sig, const line_buf *other, const line_buf *aug, ui32 repeat, bool synthesis)
void(* irv_horz_syn)(const param_atk *atk, const line_buf *dst, const line_buf *lsrc, const line_buf *hsrc, ui32 width, bool even)
int64_t si64
Definition ojph_defs.h:57
uint64_t ui64
Definition ojph_defs.h:56
uint16_t ui16
Definition ojph_defs.h:52
int32_t si32
Definition ojph_defs.h:55
uint32_t ui32
Definition ojph_defs.h:54
#define ojph_max(a, b)
Definition ojph_defs.h:73
#define ojph_min(a, b)
Definition ojph_defs.h:76
#define OJPH_ERROR(t,...)
line_buf * line
Definition ojph_mem.h:183
const lifting_step * get_step(ui32 s) const
const param_atk * access_atk() const
size get_log_precinct_size(ui32 res_num) const
ui32 propose_precision(const param_siz *siz, ui32 comp_num) const
dfs_dwt_type get_dwt_type(ui32 decomp_level) const
const param_dfs * get_dfs(int index) const
void write(outfile_base *file)
void parse(int tag_tree_size, ui32 *lev_idx, mem_elastic_allocator *elastic, ui32 &data_left, infile_base *file, bool skipped)
point org
Definition ojph_base.h:66
ui64 area() const
Definition ojph_base.h:53