diff --git a/src/core/codestream/ojph_codestream_local.h b/src/core/codestream/ojph_codestream_local.h index 5bfa09d..8e77eb1 100644 --- a/src/core/codestream/ojph_codestream_local.h +++ b/src/core/codestream/ojph_codestream_local.h @@ -82,8 +82,19 @@ namespace ojph { { return &siz; } ojph::param_cod access_cod() //return externally wrapped cod { return ojph::param_cod(&cod); } - const param_cod* get_cod() //return internal code + const param_cod* get_cod() //return internal code { return &cod; } + const param_cod* get_cod(ui32 comp_num) //return internal code + { + if (used_coc_fields == 0) + return &cod; + else { + for (int i = 0; i < used_coc_fields; ++i) + if (coc[i].get_comp_num() == comp_num) + return coc + i; + return &cod; + } + } param_qcd* access_qcd(ui32 comp_num) { if (used_qcc_fields > 0) @@ -92,6 +103,8 @@ namespace ojph { return qcc + v; return &qcd; } + const param_dfs* access_dfs() + { if (dfs.exists()) return &dfs; else return NULL; } mem_fixed_allocator* get_allocator() { return allocator; } mem_elastic_allocator* get_elastic_alloc() { return elastic_alloc; } outfile_base* get_file() { return outfile; } diff --git a/src/core/codestream/ojph_params.cpp b/src/core/codestream/ojph_params.cpp index 3795d4b..ef65265 100644 --- a/src/core/codestream/ojph_params.cpp +++ b/src/core/codestream/ojph_params.cpp @@ -824,12 +824,12 @@ namespace ojph { ui8 t; if (file->read(&t, 1) != 1) OJPH_ERROR(0x00050122, "error reading COC segment"); - comp_idx = t; + comp_num = t; } else { - if (file->read(&comp_idx, 2) != 2) + if (file->read(&comp_num, 2) != 2) OJPH_ERROR(0x00050123, "error reading COC segment"); - comp_idx = swap_byte(comp_idx); + comp_num = swap_byte(comp_num); } if (file->read(&Scod, 1) != 1) OJPH_ERROR(0x00050124, "error reading COC segment"); @@ -1393,8 +1393,6 @@ namespace ojph { ////////////////////////////////////////////////////////////////////////// param_dfs::dfs_dwt_type param_dfs::get_dwt_type(ui32 decomp_level) const { - assert(decomp_level > 0 && decomp_level <= Ids); - decomp_level = ojph_min(decomp_level, Ids); ui32 d = decomp_level - 1; // decomp_level starts from 1 ui32 idx = d >> 2; // complete bytes @@ -1605,7 +1603,7 @@ namespace ojph { if (Natk > max_steps) { if (d != d_store) // was this allocated -- very unlikely delete[] d; - d = new data[Natk]; + d = new lifting_step[Natk]; max_steps = Natk; } diff --git a/src/core/codestream/ojph_params_local.h b/src/core/codestream/ojph_params_local.h index e8e43f8..c08d750 100644 --- a/src/core/codestream/ojph_params_local.h +++ b/src/core/codestream/ojph_params_local.h @@ -515,6 +515,10 @@ namespace ojph { ui16 get_dfs_index() const // cannot be more than 15 { return SPcod.num_decomp & 0xF; } + //////////////////////////////////////// + ui32 get_comp_num() + { assert(type == COC_MAIN); return comp_num; } + private: // Common variables cod_type type; // The type of this cod structure ui16 Lcod; // serves as Lcod and Scod @@ -524,7 +528,7 @@ namespace ojph { private: // COC only variables param_cod* parent; // parent COD structure - ui16 comp_idx; // component index of this COC structure + ui16 comp_num; // component index of this COC structure const param_atk* atk; // useful when SPcod.wavelet_trans > 1 }; @@ -788,16 +792,9 @@ namespace ojph { // // /////////////////////////////////////////////////////////////////////////// - struct param_atk - { - // Limitations: - // Arbitrary filters (ARB) are not supported - // Up to 6 steps are supported -- more than 6 are not supported - // Only one coefficient per step -- first order filter - // Only even-indexed subsequence in first reconstruction step, - // m_init = 0 is supported + // data structures used by param_atk - public: // data structures used by this object + union lifting_step { struct irv_data { // si8 Oatk; // only for arbitrary filter // ui8 LCatk; // number of lifting coefficients in a step @@ -812,10 +809,18 @@ namespace ojph { si16 Aatk; // lifting coefficient }; - union data { - irv_data irv; - rev_data rev; - }; + irv_data irv; + rev_data rev; + }; + + struct param_atk + { + // Limitations: + // Arbitrary filters (ARB) are not supported + // Up to 6 steps are supported -- more than 6 are not supported + // Only one coefficient per step -- first order filter + // Only even-indexed subsequence in first reconstruction step, + // m_init = 0 is supported public: // member functions param_atk() { init(); } @@ -835,7 +840,7 @@ namespace ojph { void init(bool clear_all = true) { if (clear_all) memset(this, 0, sizeof(param_atk)); - d = d_store; max_steps = sizeof(d_store) / sizeof(data); + d = d_store; max_steps = sizeof(d_store) / sizeof(lifting_step); } void init_irv97(); void init_rev53(); @@ -849,16 +854,19 @@ namespace ojph { bool is_m_init0() const { return (Satk & 0x2000) == 0; } bool is_using_ws_extension() const { return (Satk & 0x4000) != 0; } const param_atk* get_atk(int index) const; - const data* get_step(ui32 s) const { assert(s < Natk); return d + s; } + const lifting_step* get_step(ui32 s) const + { assert(s < Natk); return d + s; } + const ui32 get_num_steps() const { return Natk; } + const float get_K() const { return Katk; } private: // member variables ui16 Latk; // structure length ui16 Satk; // carries a variety of information float Katk; // only for irreversible scaling factor K ui8 Natk; // number of lifting steps - data* d; // pointer to data, initialized to d_store + lifting_step* d; // pointer to data, initialized to d_store int max_steps; // maximum number of steps without memory allocation - data d_store[6]; // step coefficient + lifting_step d_store[6]; // lifting step coefficient param_atk* next; // used for chaining if more than one atk segment // exist in the codestream bool alloced_next; // true if next was allocated, not just set to an diff --git a/src/core/codestream/ojph_resolution.cpp b/src/core/codestream/ojph_resolution.cpp index 03d1278..105c57d 100644 --- a/src/core/codestream/ojph_resolution.cpp +++ b/src/core/codestream/ojph_resolution.cpp @@ -98,14 +98,39 @@ namespace ojph { ////////////////////////////////////////////////////////////////////////// void resolution::pre_alloc(codestream* codestream, const rect& res_rect, - const rect& recon_res_rect, ui32 res_num) + const rect& recon_res_rect, + ui32 comp_num, ui32 res_num) { mem_fixed_allocator* allocator = codestream->get_allocator(); - const param_cod* cdp = codestream->get_cod(); - ui32 t = codestream->get_cod()->get_num_decompositions() + const param_cod* cdp = codestream->get_cod(comp_num); + ui32 t = cdp->get_num_decompositions() - codestream->get_skipped_res_for_recon(); bool skipped_res_for_recon = res_num > t; + const param_atk* atk = cdp->access_atk(); + param_dfs::dfs_dwt_type downsampling_style = param_dfs::BIDIR_DWT; + if (cdp->is_dfs_defined()) { + const param_dfs* dfs = codestream->access_dfs(); + if (dfs == NULL) { + OJPH_ERROR(0x00070001, "There is a problem with codestream " + "marker segments. COD/COC specifies the use of a DFS marker " + "but there are no DFS markers within the main codestream " + "headers"); + } + else { + ui16 dfs_idx = cdp->get_dfs_index(); + dfs = dfs->get_dfs(dfs_idx); + if (dfs == NULL) { + OJPH_ERROR(0x00070002, "There is a problem with codestream " + "marker segments. COD/COC specifies the use of a DFS marker " + "with index %d, but there are no such marker within the " + "main codestream headers", dfs_idx); + } + ui32 num_decomps = cdp->get_num_decompositions(); + downsampling_style = dfs->get_dwt_type(num_decomps - res_num + 1); + } + } + //create next resolution if (res_num > 0) { @@ -122,7 +147,8 @@ namespace ojph { next_res_rect.siz.h = try1 - try0; resolution::pre_alloc(codestream, next_res_rect, - skipped_res_for_recon ? recon_res_rect : next_res_rect, res_num - 1); + skipped_res_for_recon ? recon_res_rect : next_res_rect, + comp_num, res_num - 1); } //allocate subbands @@ -145,11 +171,11 @@ namespace ojph { band_rect.org.y = tby0; band_rect.siz.w = tbx1 - tbx0; band_rect.siz.h = tby1 - tby0; - subband::pre_alloc(codestream, band_rect, res_num); + subband::pre_alloc(codestream, band_rect, comp_num, res_num); } } else - subband::pre_alloc(codestream, res_rect, res_num); + subband::pre_alloc(codestream, res_rect, comp_num, res_num); //prealloc precincts size log_PP = cdp->get_log_precinct_size(res_num); @@ -166,13 +192,15 @@ namespace ojph { //allocate lines if (skipped_res_for_recon == false) { - bool reversible = cdp->access_atk()->is_reversible(); - ui32 num_lines = reversible ? 4 : 6; - allocator->pre_alloc_obj(num_lines); + ui32 num_steps = atk->get_num_steps(); + allocator->pre_alloc_obj(num_steps + 2); + allocator->pre_alloc_obj(num_steps + 2); ui32 width = res_rect.siz.w + 1; - for (ui32 i = 0; i < num_lines; ++i) + for (ui32 i = 0; i < num_steps; ++i) allocator->pre_alloc_data(width, 1); + allocator->pre_alloc_data(width, 1); + allocator->pre_alloc_data(width, 1); } } @@ -187,12 +215,12 @@ namespace ojph { { mem_fixed_allocator* allocator = codestream->get_allocator(); elastic = codestream->get_elastic_alloc(); - ui32 t, num_decomps = codestream->get_cod()->get_num_decompositions(); + const param_cod* cdp = codestream->get_cod(comp_num); + ui32 t, num_decomps = cdp->get_num_decompositions(); t = num_decomps - codestream->get_skipped_res_for_recon(); skipped_res_for_recon = res_num > t; t = num_decomps - codestream->get_skipped_res_for_read(); skipped_res_for_read = res_num > t; - const param_cod* cdp = codestream->get_cod(); this->comp_downsamp = comp_downsamp; this->parent_comp = parent_tile_comp; @@ -201,6 +229,31 @@ namespace ojph { this->comp_num = comp_num; this->res_num = res_num; this->num_bytes = 0; + this->atk = cdp->access_atk(); + this->downsampling_style = param_dfs::BIDIR_DWT; + if (cdp->is_dfs_defined()) { + const param_dfs* dfs = codestream->access_dfs(); + if (dfs == NULL) { + OJPH_ERROR(0x00070011, "There is a problem with codestream " + "marker segments. COD/COC specifies the use of a DFS marker " + "but there are no DFS markers within the main codestream " + "headers"); + } + else { + ui16 dfs_idx = cdp->get_dfs_index(); + dfs = dfs->get_dfs(dfs_idx); + if (dfs == NULL) { + OJPH_ERROR(0x00070012, "There is a problem with codestream " + "marker segments. COD/COC specifies the use of a DFS marker " + "with index %d, but there are no such marker within the " + "main codestream headers", dfs_idx); + } + ui32 num_decomps = cdp->get_num_decompositions(); + this->downsampling_style = + dfs->get_dwt_type(num_decomps - res_num + 1); + } + } + //finalize next resolution if (res_num > 0) { @@ -321,13 +374,33 @@ namespace ojph { //allocate lines if (skipped_res_for_recon == false) { - this->reversible = cdp->access_atk()->is_reversible(); - this->num_lines = this->reversible ? 4 : 6; - lines = allocator->post_alloc_obj(num_lines); - + this->atk = cdp->access_atk(); + this->reversible = atk->is_reversible(); + this->num_steps = atk->get_num_steps(); + // create line buffers and lifting_bufs + lines = allocator->post_alloc_obj(num_steps + 2); + ssp = allocator->post_alloc_obj(num_steps + 2); + sig = ssp + num_steps; + aug = ssp + num_steps + 1; + + // initiate lifting_bufs + for (ui32 i = 0; i < num_steps; ++i) { + new (ssp + i) lifting_buf; + ssp[i].line = lines + i; + }; + new (sig) lifting_buf; + sig->line = lines + num_steps; + new (aug) lifting_buf; + aug->line = lines + num_steps + 1; + + // initiate storage of line_buf ui32 width = res_rect.siz.w + 1; - for (ui32 i = 0; i < num_lines; ++i) - lines[i].wrap(allocator->post_alloc_data(width, 1), width, 1); + for (ui32 i = 0; i < num_steps; ++i) + ssp[i].line->wrap( + allocator->post_alloc_data(width, 1), width, 1); + sig->line->wrap(allocator->post_alloc_data(width, 1), width, 1); + aug->line->wrap(allocator->post_alloc_data(width, 1), width, 1); + cur_line = 0; vert_even = (res_rect.org.y & 1) == 0; horz_even = (res_rect.org.x & 1) == 0; @@ -340,271 +413,271 @@ namespace ojph { if (res_num == 0) { assert(num_bands == 1 && child_res == NULL); - bands[0].exchange_buf(lines + 0);//line at location 0 + bands[0].exchange_buf(ssp[0].line);//line at location 0 bands[0].push_line(); return; } - ui32 width = res_rect.siz.w; - if (width == 0) - return; - if (reversible) - { - //vertical transform - assert(num_lines >= 4); - if (vert_even) - { - rev_vert_wvlt_fwd_predict(lines, - cur_line > 1 ? lines + 2 : lines, - lines + 1, width); - rev_vert_wvlt_fwd_update(lines + 1, - cur_line > 2 ? lines + 3 : lines + 1, - lines + 2, width); - - // push to horizontal transform lines[2](L) and lines[1] (H) - if (cur_line >= 1) - { - rev_horz_wvlt_fwd_tx(lines + 1, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - } - if (cur_line >= 2) - { - rev_horz_wvlt_fwd_tx(lines + 2, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - } - - if (cur_line >= res_rect.siz.h - 1) - { //finished, so we need to process any lines left - if (cur_line) - { - if (vert_even) - { - rev_vert_wvlt_fwd_update(lines + 1, lines + 1, - lines, width); - //push lines[0] to L - rev_horz_wvlt_fwd_tx(lines, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - else - { - rev_vert_wvlt_fwd_predict(lines + 1, lines + 1, - lines, width); - rev_vert_wvlt_fwd_update(lines, - cur_line > 1 ? lines + 2 : lines, - lines + 1, width); - - // push to horizontal transform lines[1](L) and line[0] (H) - //line[0] to H - rev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - //line[1] to L - rev_horz_wvlt_fwd_tx(lines + 1, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - } - else - { //only one line - if (vert_even) - { - //push to L - rev_horz_wvlt_fwd_tx(lines, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - else - { - si32* sp = lines[0].i32; - for (ui32 i = width; i > 0; --i) - *sp++ <<= 1; - //push to H - rev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - } - } - } - - rotate_buffers(lines, lines + 1, lines + 2, lines + 3); - - ++cur_line; - vert_even = !vert_even; - } - else - { - //vertical transform - assert(num_lines >= 6); - if (vert_even) - { - irrev_vert_wvlt_step(lines + 0, - cur_line > 1 ? lines + 2 : lines, - lines + 1, 0, width); - irrev_vert_wvlt_step(lines + 1, - cur_line > 2 ? lines + 3 : lines + 1, - lines + 2, 1, width); - irrev_vert_wvlt_step(lines + 2, - cur_line > 3 ? lines + 4 : lines + 2, - lines + 3, 2, width); - irrev_vert_wvlt_step(lines + 3, - cur_line > 4 ? lines + 5 : lines + 3, - lines + 4, 3, width); - - // push to horizontal transform lines[4](L) and lines[3] (H) - if (cur_line >= 3) - { - irrev_vert_wvlt_K(lines + 3, lines + 5, - false, width); - irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - } - if (cur_line >= 4) - { - irrev_vert_wvlt_K(lines + 4, lines + 5, - true, width); - irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - } - - if (cur_line >= res_rect.siz.h - 1) - { //finished, so we need to process any left line - if (cur_line) - { - if (vert_even) - { - irrev_vert_wvlt_step(lines + 1, lines + 1, - lines, 1, width); - irrev_vert_wvlt_step(lines, - cur_line > 1 ? lines + 2 : lines, - lines + 1, 2, width); - irrev_vert_wvlt_step(lines + 1, - cur_line > 2 ? lines + 3 : lines + 1, - lines + 2, 3, width); - irrev_vert_wvlt_step(lines + 1, lines + 1, - lines, 3, width); - //push lines[2] to L, lines[1] to H, and lines[0] to L - if (cur_line >= 2) - { - irrev_vert_wvlt_K(lines + 2, lines + 5, - true, width); - irrev_horz_wvlt_fwd_tx(lines + 5, - child_res->get_line(), bands[1].get_line(), - width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - irrev_vert_wvlt_K(lines + 1, lines + 5, - false, width); - irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - irrev_vert_wvlt_K(lines, lines + 5, - true, width); - irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - else - { - irrev_vert_wvlt_step(lines + 1, lines + 1, - lines, 0, width); - irrev_vert_wvlt_step(lines, - cur_line > 1 ? lines + 2 : lines, - lines + 1, 1, width); - irrev_vert_wvlt_step(lines + 1, - cur_line > 2 ? lines + 3 : lines + 1, - lines + 2, 2, width); - irrev_vert_wvlt_step(lines + 2, - cur_line > 3 ? lines + 4 : lines + 2, - lines + 3, 3, width); - - irrev_vert_wvlt_step(lines + 1, lines + 1, - lines, 2, width); - irrev_vert_wvlt_step(lines, - cur_line > 1 ? lines + 2 : lines, - lines + 1, 3, width); - - //push lines[3] L, lines[2] H, lines[1] L, and lines[0] H - if (cur_line >= 3) - { - irrev_vert_wvlt_K(lines + 3, lines + 5, - true, width); - irrev_horz_wvlt_fwd_tx(lines + 5, - child_res->get_line(), bands[1].get_line(), - width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - if (cur_line >= 2) - irrev_vert_wvlt_K(lines + 2, lines + 5, false, width); - else - irrev_vert_wvlt_K(lines, lines + 5, false, width); - irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - irrev_vert_wvlt_K(lines + 1, lines + 5, - true, width); - irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - irrev_vert_wvlt_K(lines, lines + 5, - false, width); - irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - } - } - else - { //only one line - if (vert_even) - { - //push to L - irrev_horz_wvlt_fwd_tx(lines, child_res->get_line(), - bands[1].get_line(), width, horz_even); - bands[1].push_line(); - child_res->push_line(); - } - else - { - float* sp = lines[0].f32; - for (ui32 i = width; i > 0; --i) - *sp++ *= 2.0f; - //push to H - irrev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), - bands[3].get_line(), width, horz_even); - bands[2].push_line(); - bands[3].push_line(); - } - } - } - - rotate_buffers(lines, lines + 1, lines + 2, lines + 3, lines + 4, - lines + 5); - - ++cur_line; - vert_even = !vert_even; - } + //ui32 width = res_rect.siz.w; + //if (width == 0) + // return; + //if (reversible) + //{ + // //vertical transform + // assert(num_lines >= 4); + // if (vert_even) + // { + // rev_vert_wvlt_fwd_predict(lines, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, width); + // rev_vert_wvlt_fwd_update(lines + 1, + // cur_line > 2 ? lines + 3 : lines + 1, + // lines + 2, width); + + // // push to horizontal transform lines[2](L) and lines[1] (H) + // if (cur_line >= 1) + // { + // rev_horz_wvlt_fwd_tx(lines + 1, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // } + // if (cur_line >= 2) + // { + // rev_horz_wvlt_fwd_tx(lines + 2, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // } + + // if (cur_line >= res_rect.siz.h - 1) + // { //finished, so we need to process any lines left + // if (cur_line) + // { + // if (vert_even) + // { + // rev_vert_wvlt_fwd_update(lines + 1, lines + 1, + // lines, width); + // //push lines[0] to L + // rev_horz_wvlt_fwd_tx(lines, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // else + // { + // rev_vert_wvlt_fwd_predict(lines + 1, lines + 1, + // lines, width); + // rev_vert_wvlt_fwd_update(lines, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, width); + + // // push to horizontal transform lines[1](L) and line[0] (H) + // //line[0] to H + // rev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // //line[1] to L + // rev_horz_wvlt_fwd_tx(lines + 1, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // } + // else + // { //only one line + // if (vert_even) + // { + // //push to L + // rev_horz_wvlt_fwd_tx(lines, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // else + // { + // si32* sp = lines[0].i32; + // for (ui32 i = width; i > 0; --i) + // *sp++ <<= 1; + // //push to H + // rev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // } + // } + // } + + // rotate_buffers(lines, lines + 1, lines + 2, lines + 3); + + // ++cur_line; + // vert_even = !vert_even; + //} + //else + //{ + // //vertical transform + // assert(num_lines >= 6); + // if (vert_even) + // { + // irrev_vert_wvlt_step(lines + 0, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, 0, width); + // irrev_vert_wvlt_step(lines + 1, + // cur_line > 2 ? lines + 3 : lines + 1, + // lines + 2, 1, width); + // irrev_vert_wvlt_step(lines + 2, + // cur_line > 3 ? lines + 4 : lines + 2, + // lines + 3, 2, width); + // irrev_vert_wvlt_step(lines + 3, + // cur_line > 4 ? lines + 5 : lines + 3, + // lines + 4, 3, width); + + // // push to horizontal transform lines[4](L) and lines[3] (H) + // if (cur_line >= 3) + // { + // irrev_vert_wvlt_K(lines + 3, lines + 5, + // false, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // } + // if (cur_line >= 4) + // { + // irrev_vert_wvlt_K(lines + 4, lines + 5, + // true, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // } + + // if (cur_line >= res_rect.siz.h - 1) + // { //finished, so we need to process any left line + // if (cur_line) + // { + // if (vert_even) + // { + // irrev_vert_wvlt_step(lines + 1, lines + 1, + // lines, 1, width); + // irrev_vert_wvlt_step(lines, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, 2, width); + // irrev_vert_wvlt_step(lines + 1, + // cur_line > 2 ? lines + 3 : lines + 1, + // lines + 2, 3, width); + // irrev_vert_wvlt_step(lines + 1, lines + 1, + // lines, 3, width); + // //push lines[2] to L, lines[1] to H, and lines[0] to L + // if (cur_line >= 2) + // { + // irrev_vert_wvlt_K(lines + 2, lines + 5, + // true, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, + // child_res->get_line(), bands[1].get_line(), + // width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // irrev_vert_wvlt_K(lines + 1, lines + 5, + // false, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // irrev_vert_wvlt_K(lines, lines + 5, + // true, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // else + // { + // irrev_vert_wvlt_step(lines + 1, lines + 1, + // lines, 0, width); + // irrev_vert_wvlt_step(lines, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, 1, width); + // irrev_vert_wvlt_step(lines + 1, + // cur_line > 2 ? lines + 3 : lines + 1, + // lines + 2, 2, width); + // irrev_vert_wvlt_step(lines + 2, + // cur_line > 3 ? lines + 4 : lines + 2, + // lines + 3, 3, width); + + // irrev_vert_wvlt_step(lines + 1, lines + 1, + // lines, 2, width); + // irrev_vert_wvlt_step(lines, + // cur_line > 1 ? lines + 2 : lines, + // lines + 1, 3, width); + + // //push lines[3] L, lines[2] H, lines[1] L, and lines[0] H + // if (cur_line >= 3) + // { + // irrev_vert_wvlt_K(lines + 3, lines + 5, + // true, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, + // child_res->get_line(), bands[1].get_line(), + // width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // if (cur_line >= 2) + // irrev_vert_wvlt_K(lines + 2, lines + 5, false, width); + // else + // irrev_vert_wvlt_K(lines, lines + 5, false, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // irrev_vert_wvlt_K(lines + 1, lines + 5, + // true, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // irrev_vert_wvlt_K(lines, lines + 5, + // false, width); + // irrev_horz_wvlt_fwd_tx(lines + 5, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // } + // } + // else + // { //only one line + // if (vert_even) + // { + // //push to L + // irrev_horz_wvlt_fwd_tx(lines, child_res->get_line(), + // bands[1].get_line(), width, horz_even); + // bands[1].push_line(); + // child_res->push_line(); + // } + // else + // { + // float* sp = lines[0].f32; + // for (ui32 i = width; i > 0; --i) + // *sp++ *= 2.0f; + // //push to H + // irrev_horz_wvlt_fwd_tx(lines, bands[2].get_line(), + // bands[3].get_line(), width, horz_even); + // bands[2].push_line(); + // bands[3].push_line(); + // } + // } + // } + + // rotate_buffers(lines, lines + 1, lines + 2, lines + 3, lines + 4, + // lines + 5); + + // ++cur_line; + // vert_even = !vert_even; + //} } ////////////////////////////////////////////////////////////////////////// @@ -621,147 +694,159 @@ namespace ojph { ui32 width = res_rect.siz.w; if (width == 0) - return lines; + return NULL; if (reversible) { - assert(num_lines >= 4); if (res_rect.siz.h > 1) { - do + if (sig->active) { + sig->active = false; + return sig->line; + }; + for (;;) { //horizontal transform if (cur_line < res_rect.siz.h) { - if (vert_even) - rev_horz_wvlt_bwd_tx(lines, + if (vert_even) { // even + rev_horz_syn(atk, aug->line, child_res->pull_line(), bands[1].pull_line(), width, horz_even); - else - rev_horz_wvlt_bwd_tx(lines, + aug->active = true; + vert_even = !vert_even; + ++cur_line; + continue; + } + else { + rev_horz_syn(atk, sig->line, bands[2].pull_line(), bands[3].pull_line(), width, horz_even); + sig->active = true; + vert_even = !vert_even; + ++cur_line; + } } //vertical transform - if (!vert_even) + for (ui32 i = 0; i < num_steps; ++i) { - rev_vert_wvlt_bwd_update( - cur_line > 1 ? lines + 2 : lines, - cur_line < res_rect.siz.h ? lines : lines + 2, - lines + 1, width); - rev_vert_wvlt_bwd_predict( - cur_line > 2 ? lines + 3 : lines + 1, - cur_line < res_rect.siz.h + 1 ? lines + 1 : lines + 3, - lines + 2, width); + if (aug->active && + (sig->active == true || ssp[i].active == true)) + { + line_buf* dp = aug->line; + line_buf* sp1 = sig->active ? sig->line : ssp[i].line; + line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line; + const lifting_step* s = atk->get_step(num_steps - i - 1); + rev_vert_syn_step(s, dp, sp1, sp2, width); + } + lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t; } - vert_even = !vert_even; - rotate_buffers(lines, lines + 1, lines + 2, lines + 3); - ++cur_line; - } while (cur_line < 3); - memcpy(lines[0].i32, lines[3].i32, res_rect.siz.w * sizeof(si32)); - return lines; + if (aug->active) { + aug->active = false; + return aug->line; + } + if (sig->active) { + sig->active = false; + return sig->line; + }; + } } - else if (res_rect.siz.h == 1) + else { if (vert_even) - { - rev_horz_wvlt_bwd_tx(lines, child_res->pull_line(), + rev_horz_syn(atk, aug->line, child_res->pull_line(), bands[1].pull_line(), width, horz_even); - } else { - rev_horz_wvlt_bwd_tx(lines, bands[2].pull_line(), + rev_horz_syn(atk, aug->line, bands[2].pull_line(), bands[3].pull_line(), width, horz_even); - if (width) - { - si32* sp = lines[0].i32; - for (ui32 i = width; i > 0; --i) - *sp++ >>= 1; - } + si32* sp = aug->line->i32; + for (ui32 i = width; i > 0; --i) + *sp++ >>= 1; } - return lines; + return aug->line; } - else - return lines; } else { - assert(num_lines >= 6); if (res_rect.siz.h > 1) { - do + if (sig->active) { + sig->active = false; + return sig->line; + }; + for (;;) { //horizontal transform if (cur_line < res_rect.siz.h) { - if (vert_even) - { - irrev_horz_wvlt_bwd_tx(lines, + if (vert_even) { // even + irv_horz_syn(atk, aug->line, child_res->pull_line(), bands[1].pull_line(), width, horz_even); - irrev_vert_wvlt_K(lines, lines, false, width); + aug->active = true; + vert_even = !vert_even; + ++cur_line; + + const float K = atk->get_K(); + irv_vert_syn_K(K, aug->line, width); + + continue; } - else - { - irrev_horz_wvlt_bwd_tx(lines, + else { + irv_horz_syn(atk, sig->line, bands[2].pull_line(), bands[3].pull_line(), width, horz_even); - irrev_vert_wvlt_K(lines, lines, true, width); + sig->active = true; + vert_even = !vert_even; + ++cur_line; + + const float K_inv = 1.0f / atk->get_K(); + irv_vert_syn_K(K_inv, sig->line, width); } } //vertical transform - if (!vert_even) + for (ui32 i = 0; i < num_steps; ++i) { - irrev_vert_wvlt_step( - cur_line > 1 ? lines + 2 : lines, - cur_line < res_rect.siz.h ? lines : lines + 2, - lines + 1, 7, width); - irrev_vert_wvlt_step( - cur_line > 2 ? lines + 3 : lines + 1, - cur_line < res_rect.siz.h + 1 ? lines + 1 : lines + 3, - lines + 2, 6, width); - irrev_vert_wvlt_step( - cur_line > 3 ? lines + 4 : lines + 2, - cur_line < res_rect.siz.h + 2 ? lines + 2 : lines + 4, - lines + 3, 5, width); - irrev_vert_wvlt_step( - cur_line > 4 ? lines + 5 : lines + 3, - cur_line < res_rect.siz.h + 3 ? lines + 3 : lines + 5, - lines + 4, 4, width); + if (aug->active && + (sig->active == true || ssp[i].active == true)) + { + line_buf* dp = aug->line; + line_buf* sp1 = sig->active ? sig->line : ssp[i].line; + line_buf* sp2 = ssp[i].active ? ssp[i].line : sig->line; + const lifting_step* s = atk->get_step(num_steps - i - 1); + irv_vert_syn_step(s, dp, sp1, sp2, width); + } + lifting_buf t = *aug; *aug = ssp[i]; ssp[i] = *sig; *sig = t; } - vert_even = !vert_even; - rotate_buffers(lines, lines + 1, lines + 2, lines + 3, lines + 4, - lines + 5); - ++cur_line; - } while (cur_line < 5); - memcpy(lines[0].f32, lines[5].f32, res_rect.siz.w * sizeof(float)); - return lines; + if (aug->active) { + aug->active = false; + return aug->line; + } + if (sig->active) { + sig->active = false; + return sig->line; + }; + } } - else if (res_rect.siz.h == 1) + else { if (vert_even) - { - irrev_horz_wvlt_bwd_tx(lines, child_res->pull_line(), + irv_horz_syn(atk, aug->line, child_res->pull_line(), bands[1].pull_line(), width, horz_even); - } else { - irrev_horz_wvlt_bwd_tx(lines, bands[2].pull_line(), + irv_horz_syn(atk, aug->line, bands[2].pull_line(), bands[3].pull_line(), width, horz_even); - if (width) - { - float* sp = lines[0].f32; - for (ui32 i = width; i > 0; --i) - *sp++ *= 0.5f; - } + float *sp = aug->line->f32; + for (ui32 i = width; i > 0; --i) + *sp++ *= 0.5f; } - return lines; + return aug->line; } - else - return lines; } } diff --git a/src/core/codestream/ojph_resolution.h b/src/core/codestream/ojph_resolution.h index e110811..7a7d43d 100644 --- a/src/core/codestream/ojph_resolution.h +++ b/src/core/codestream/ojph_resolution.h @@ -64,14 +64,15 @@ namespace ojph { public: static void pre_alloc(codestream *codestream, const rect& res_rect, - const rect& recon_res_rect, ui32 res_num); + 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, tile_comp *parent_tile_comp, resolution *parent_res); - line_buf* get_line() { return lines + 0; } + line_buf* get_line() { return ssp[0].line; } void push_line(); line_buf* pull_line(); rect get_rect() { return res_rect; } @@ -90,14 +91,16 @@ namespace ojph { private: bool reversible, skipped_res_for_read, skipped_res_for_recon; - ui32 num_lines; + ui32 num_steps; ui32 num_bands, res_num; ui32 comp_num; ui32 num_bytes; // number of bytes in this resolution // used for tilepart length point comp_downsamp; - rect res_rect; - line_buf *lines; + rect res_rect; // resolution rectangle + line_buf* lines; // used to store lines + lifting_buf *ssp; // step state pointer + lifting_buf *aug, *sig; subband *bands; tile_comp *parent_comp; resolution *parent_res, *child_res; @@ -109,6 +112,8 @@ namespace ojph { int tag_tree_size; ui32 level_index[20]; //more than enough point cur_precinct_loc; //used for progressing spatial modes (2, 3, 4) + const param_atk* atk; + param_dfs::dfs_dwt_type downsampling_style; //wavelet machinery ui32 cur_line; bool vert_even, horz_even; diff --git a/src/core/codestream/ojph_subband.cpp b/src/core/codestream/ojph_subband.cpp index 6348e98..dbef3b7 100644 --- a/src/core/codestream/ojph_subband.cpp +++ b/src/core/codestream/ojph_subband.cpp @@ -55,7 +55,7 @@ namespace ojph { ////////////////////////////////////////////////////////////////////////// void subband::pre_alloc(codestream *codestream, const rect &band_rect, - ui32 res_num) + ui32 comp_num, ui32 res_num) { mem_fixed_allocator* allocator = codestream->get_allocator(); @@ -63,7 +63,7 @@ namespace ojph { if (empty) return; - const param_cod* cdp = codestream->get_cod(); + const param_cod* cdp = codestream->get_cod(comp_num); size log_cb = cdp->get_log_block_dims(); size log_PP = cdp->get_log_precinct_size(res_num); @@ -111,7 +111,7 @@ namespace ojph { this->band_rect = band_rect; this->parent = res; - const param_cod* cdp = codestream->get_cod(); + const param_cod* cdp = codestream->get_cod(parent->get_comp_num()); this->reversible = cdp->access_atk()->is_reversible(); size log_cb = cdp->get_log_block_dims(); log_PP = cdp->get_log_precinct_size(res_num); @@ -125,8 +125,7 @@ namespace ojph { cur_line = 0; cur_cb_height = 0; param_qcd* qcd = codestream->access_qcd(parent->get_comp_num()); - const param_cod* cod = codestream->get_cod(); - ui32 num_decomps = cod->get_num_decompositions(); + ui32 num_decomps = cdp->get_num_decompositions(); this->K_max = qcd->get_Kmax(NULL, num_decomps, this->res_num, band_num); if (!reversible) { diff --git a/src/core/codestream/ojph_subband.h b/src/core/codestream/ojph_subband.h index 3bcc6ed..9928c5e 100644 --- a/src/core/codestream/ojph_subband.h +++ b/src/core/codestream/ojph_subband.h @@ -64,7 +64,7 @@ namespace ojph { friend struct precinct; public: static void pre_alloc(codestream *codestream, const rect& band_rect, - ui32 res_num); + ui32 comp_num, ui32 res_num); void finalize_alloc(codestream *codestream, const rect& band_rect, resolution* res, ui32 res_num, ui32 subband_num); diff --git a/src/core/codestream/ojph_tile.cpp b/src/core/codestream/ojph_tile.cpp index b7cb52c..48f8bb5 100644 --- a/src/core/codestream/ojph_tile.cpp +++ b/src/core/codestream/ojph_tile.cpp @@ -116,7 +116,7 @@ namespace ojph { recon_comp_rect.siz.w = recon_tcx1 - recon_tcx0; recon_comp_rect.siz.h = recon_tcy1 - recon_tcy0; - tile_comp::pre_alloc(codestream, comp_rect, recon_comp_rect); + tile_comp::pre_alloc(codestream, i, comp_rect, recon_comp_rect); width = ojph_max(width, recon_comp_rect.siz.w); } diff --git a/src/core/codestream/ojph_tile_comp.cpp b/src/core/codestream/ojph_tile_comp.cpp index a2124e8..69ed0bc 100644 --- a/src/core/codestream/ojph_tile_comp.cpp +++ b/src/core/codestream/ojph_tile_comp.cpp @@ -51,7 +51,8 @@ namespace ojph { { ////////////////////////////////////////////////////////////////////////// - void tile_comp::pre_alloc(codestream *codestream, const rect& comp_rect, + void tile_comp::pre_alloc(codestream *codestream, ui32 comp_num, + const rect& comp_rect, const rect& recon_comp_rect) { mem_fixed_allocator* allocator = codestream->get_allocator(); @@ -60,7 +61,7 @@ namespace ojph { ui32 num_decomps = codestream->access_cod().get_num_decompositions(); allocator->pre_alloc_obj(1); - resolution::pre_alloc(codestream, comp_rect, recon_comp_rect, + resolution::pre_alloc(codestream, comp_rect, recon_comp_rect, comp_num, num_decomps); } @@ -72,7 +73,7 @@ namespace ojph { mem_fixed_allocator* allocator = codestream->get_allocator(); //allocate a resolution - num_decomps = codestream->get_cod()->get_num_decompositions(); + num_decomps = codestream->get_cod(comp_num)->get_num_decompositions(); comp_downsamp = codestream->get_siz()->get_downsampling(comp_num); this->comp_rect = comp_rect; diff --git a/src/core/codestream/ojph_tile_comp.h b/src/core/codestream/ojph_tile_comp.h index d7304d9..def39e5 100644 --- a/src/core/codestream/ojph_tile_comp.h +++ b/src/core/codestream/ojph_tile_comp.h @@ -62,7 +62,8 @@ namespace ojph { class tile_comp { public: - static void pre_alloc(codestream *codestream, const rect& comp_rect, + static void pre_alloc(codestream *codestream, ui32 comp_num, + const rect& comp_rect, const rect& recon_comp_rect); void finalize_alloc(codestream *codestream, tile *parent, ui32 comp_num, const rect& comp_rect, diff --git a/src/core/common/ojph_mem.h b/src/core/common/ojph_mem.h index 712727c..d7497cd 100644 --- a/src/core/common/ojph_mem.h +++ b/src/core/common/ojph_mem.h @@ -134,6 +134,8 @@ namespace ojph { ///////////////////////////////////////////////////////////////////////////// struct line_buf { + line_buf() : size(0), pre_size(0), i32(0) {} + template void pre_alloc(mem_fixed_allocator *p, size_t num_ele, ui32 pre_size) { @@ -157,6 +159,14 @@ namespace ojph { }; }; + ///////////////////////////////////////////////////////////////////////////// + struct lifting_buf + { + lifting_buf() { line = NULL; active = false; } + line_buf *line; + bool active; + }; + ///////////////////////////////////////////////////////////////////////////// struct coded_lists { diff --git a/src/core/transform/ojph_transform.cpp b/src/core/transform/ojph_transform.cpp index b691903..46231d6 100644 --- a/src/core/transform/ojph_transform.cpp +++ b/src/core/transform/ojph_transform.cpp @@ -41,6 +41,8 @@ #include "ojph_mem.h" #include "ojph_transform.h" #include "ojph_transform_local.h" +#include "ojph_params.h" +#include "../codestream/ojph_params_local.h" namespace ojph { struct line_buf; @@ -81,6 +83,24 @@ namespace ojph { (line_buf* dst, line_buf *lsrc, line_buf *hsrc, ui32 width, bool even) = NULL; + + + + + ///////////////////////////////////////////////////////////////////////// + void (*rev_vert_syn_step) + (const lifting_step* s, line_buf* aug, const line_buf* sig, + line_buf* other, ui32 repeat) = NULL; + + ///////////////////////////////////////////////////////////////////////// + void (*rev_horz_syn) + (const param_atk* atk, line_buf* dst, line_buf* lsrc, + line_buf* hsrc, ui32 width, bool even) = NULL; + + + + + ///////////////////////////////////////////////////////////////////////// // Irreversible functions ///////////////////////////////////////////////////////////////////////// @@ -105,6 +125,27 @@ namespace ojph { (line_buf* src, line_buf *ldst, line_buf *hdst, ui32 width, bool even) = NULL; + + + + + ///////////////////////////////////////////////////////////////////////// + void (*irv_vert_syn_step) + (const lifting_step* s, line_buf* aug, const line_buf* sig, + line_buf* other, ui32 repeat) = NULL; + + ///////////////////////////////////////////////////////////////////////// + void (*irv_vert_syn_K)(const float K, line_buf* aug, ui32 repeat) = NULL; + + ///////////////////////////////////////////////////////////////////////// + void (*irv_horz_syn) + (const param_atk* atk, line_buf* dst, line_buf* lsrc, + line_buf* hsrc, ui32 width, bool even) = NULL; + + + + + //////////////////////////////////////////////////////////////////////////// static bool wavelet_transform_functions_initialized = false; @@ -122,11 +163,19 @@ namespace ojph { rev_vert_wvlt_bwd_predict = gen_rev_vert_wvlt_bwd_predict; rev_vert_wvlt_bwd_update = gen_rev_vert_wvlt_bwd_update; rev_horz_wvlt_bwd_tx = gen_rev_horz_wvlt_bwd_tx; + + rev_vert_syn_step = gen_rev_vert_syn_step; + rev_horz_syn = gen_rev_horz_syn; + irrev_vert_wvlt_step = gen_irrev_vert_wvlt_step; irrev_vert_wvlt_K = gen_irrev_vert_wvlt_K; irrev_horz_wvlt_fwd_tx = gen_irrev_horz_wvlt_fwd_tx; irrev_horz_wvlt_bwd_tx = gen_irrev_horz_wvlt_bwd_tx; + irv_vert_syn_step = gen_irv_vert_syn_step; + irv_vert_syn_K = gen_irv_vert_syn_K; + irv_horz_syn = gen_irv_horz_syn; + #ifndef OJPH_DISABLE_INTEL_SIMD int level = get_cpu_ext_level(); @@ -326,6 +375,96 @@ namespace ojph { } + + + + ////////////////////////////////////////////////////////////////////////// + void gen_rev_vert_syn_step(const lifting_step* s, line_buf* aug, + const line_buf* sig, line_buf* other, + ui32 repeat) + { + si32 a = s->rev.Aatk; + si32 b = s->rev.Batk; + ui32 e = s->rev.Eatk; + + si32* dst = aug->i32; + const si32* src1 = sig->i32, * src2 = other->i32; + if (a >= 0) + for (ui32 i = repeat; i > 0; --i) + *dst++ -= (b + a * (*src1++ + *src2++)) >> e; + else + for (ui32 i = repeat; i > 0; --i) + *dst++ += (b - a * (*src1++ + *src2++)) >> e; + } + + ////////////////////////////////////////////////////////////////////////// + void gen_rev_horz_syn(const param_atk *atk, line_buf* dst, line_buf *lsrc, + line_buf *hsrc, ui32 width, bool even) + { + if (width > 1) + { + bool ev = even; + si32* oth = hsrc->i32, * aug = lsrc->i32; + ui32 aug_width = (width + (even ? 1 : 0)) >> 1; // low pass + ui32 oth_width = (width + (even ? 0 : 1)) >> 1; // high pass + ui32 num_steps = atk->get_num_steps(); + for (ui32 j = num_steps; j > 0; --j) + { + // first lifting step + const lifting_step* s = atk->get_step(j - 1); + si32 a = s->rev.Aatk; + si32 b = s->rev.Batk; + ui32 e = s->rev.Eatk; + + // extension + oth[-1] = oth[0]; + oth[oth_width] = oth[oth_width - 1]; + // lifting step + const si32* sp = oth + (ev ? 0 : 1); + si32* dp = aug; + if (a >= 0) + for (ui32 i = aug_width; i > 0; --i, sp++, dp++) + *dp -= (b + a * (sp[-1] + sp[0])) >> e; + else + for (ui32 i = aug_width; i > 0; --i, sp++, dp++) + *dp += (b - a * (sp[-1] + sp[0])) >> e; + + // swap buffers + si32* t = aug; aug = oth; oth = t; + ev = !ev; + ui32 w = aug_width; aug_width = oth_width; oth_width = w; + } + + // combine both lsrc and hsrc into dst + si32* sph = hsrc->i32; + si32* spl = lsrc->i32; + si32* dp = dst->i32; + ui32 w = width; + if (!even) + { + *dp++ = *sph++; --w; + } + for (; w > 1; w -= 2) + { + *dp++ = *spl++; *dp++ = *sph++; + } + if (w) + { + *dp++ = *spl++; --w; + } + } + else { + if (even) + dst->i32[0] = lsrc->i32[0]; + else + dst->i32[0] = hsrc->i32[0] >> 1; + } + } + + + + + ////////////////////////////////////////////////////////////////////////// void gen_irrev_vert_wvlt_step(const line_buf* line_src1, const line_buf* line_src2, @@ -499,6 +638,102 @@ namespace ojph { } } + + + + + ////////////////////////////////////////////////////////////////////////// + void gen_irv_vert_syn_step(const lifting_step* s, line_buf* aug, + const line_buf* sig, line_buf* other, + ui32 repeat) + { + float a = s->irv.Aatk; + + float* dst = aug->f32; + const float* src1 = sig->f32, * src2 = other->f32; + for (ui32 i = repeat; i > 0; --i) + *dst++ -= a * (*src1++ + *src2++); + } + + ////////////////////////////////////////////////////////////////////////// + void gen_irv_vert_syn_K(const float K, line_buf* aug, ui32 repeat) + { + float* dst = aug->f32; + for (ui32 i = repeat; i > 0; --i) + *dst++ *= K; + } + + ////////////////////////////////////////////////////////////////////////// + void gen_irv_horz_syn(const param_atk* atk, line_buf* dst, line_buf* lsrc, + line_buf* hsrc, ui32 width, bool even) + { + if (width > 1) + { + bool ev = even; + float* oth = hsrc->f32, * aug = lsrc->f32; + ui32 aug_width = (width + (even ? 1 : 0)) >> 1; // low pass + ui32 oth_width = (width + (even ? 0 : 1)) >> 1; // high pass + + { + float K = atk->get_K(); + float K_inv = 1.0f / K; + float* dp; + + dp = aug; + for (ui32 i = aug_width; i > 0; --i) + *dp++ *= K; + + dp = oth; + for (ui32 i = oth_width; i > 0; --i) + *dp++ *= K_inv; + } + + ui32 num_steps = atk->get_num_steps(); + for (ui32 j = num_steps; j > 0; --j) + { + // first lifting step + const lifting_step* s = atk->get_step(j - 1); + float a = s->irv.Aatk; + + // extension + oth[-1] = oth[0]; + oth[oth_width] = oth[oth_width - 1]; + // lifting step + const float* sp = oth + (ev ? 0 : 1); + float* dp = aug; + for (ui32 i = aug_width; i > 0; --i, sp++, dp++) + *dp -= a * (sp[-1] + sp[0]); + + // swap buffers + float* t = aug; aug = oth; oth = t; + ev = !ev; + ui32 w = aug_width; aug_width = oth_width; oth_width = w; + } + + // combine both lsrc and hsrc into dst + float* sph = hsrc->f32; + float* spl = lsrc->f32; + float* dp = dst->f32; + ui32 w = width; + if (!even) + { *dp++ = *sph++; --w; } + for (; w > 1; w -= 2) + { *dp++ = *spl++; *dp++ = *sph++; } + if (w) + { *dp++ = *spl++; --w; } + } + else { + if (even) + dst->f32[0] = lsrc->f32[0]; + else + dst->f32[0] = hsrc->f32[0] * 0.5f; + } + } + + + + + #endif // !OJPH_ENABLE_WASM_SIMD } diff --git a/src/core/transform/ojph_transform.h b/src/core/transform/ojph_transform.h index 002235d..77ede96 100644 --- a/src/core/transform/ojph_transform.h +++ b/src/core/transform/ojph_transform.h @@ -44,6 +44,8 @@ namespace ojph { struct line_buf; namespace local { + union lifting_step; + struct param_atk; ////////////////////////////////////////////////////////////////////////// void init_wavelet_transform_functions(); @@ -80,6 +82,24 @@ namespace ojph { extern void (*rev_horz_wvlt_bwd_tx) (line_buf* dst, line_buf *lsrc, line_buf *hsrc, ui32 width, bool even); + + + + + ///////////////////////////////////////////////////////////////////////// + extern void (*rev_vert_syn_step) + (const lifting_step* s, line_buf* aug, const line_buf* sig, + line_buf* other, ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + extern void (*rev_horz_syn) + (const param_atk* atk, line_buf* dst, line_buf* lsrc, + line_buf* hsrc, ui32 width, bool even); + + + + + ///////////////////////////////////////////////////////////////////////// // Irreversible functions ///////////////////////////////////////////////////////////////////////// @@ -102,6 +122,28 @@ namespace ojph { extern void (*irrev_horz_wvlt_bwd_tx) (line_buf* src, line_buf *ldst, line_buf *hdst, ui32 width, bool even); + + + + + ///////////////////////////////////////////////////////////////////////// + extern void (*irv_vert_syn_step) + (const lifting_step* s, line_buf* aug, const line_buf* sig, + line_buf* other, ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + extern void (*irv_vert_syn_K) + (const float K, line_buf* aug, ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + extern void (*irv_horz_syn) + (const param_atk* atk, line_buf* dst, line_buf* lsrc, + line_buf* hsrc, ui32 width, bool even); + + + + + } } diff --git a/src/core/transform/ojph_transform_local.h b/src/core/transform/ojph_transform_local.h index 2bf041c..42cec37 100644 --- a/src/core/transform/ojph_transform_local.h +++ b/src/core/transform/ojph_transform_local.h @@ -44,6 +44,7 @@ namespace ojph { struct line_buf; namespace local { + struct param_atk; ////////////////////////////////////////////////////////////////////////// struct LIFTING_FACTORS @@ -93,6 +94,23 @@ namespace ojph { void gen_rev_horz_wvlt_bwd_tx(line_buf* dst, line_buf *lsrc, line_buf *hsrc, ui32 width, bool even); + + + + + ///////////////////////////////////////////////////////////////////////// + void gen_rev_vert_syn_step(const lifting_step* s, line_buf* aug, + const line_buf* sig, line_buf* other, + ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + void gen_rev_horz_syn(const param_atk *atk, line_buf* dst, line_buf *lsrc, + line_buf *hsrc, ui32 width, bool even); + + + + + ////////////////////////////////////////////////////////////////////////// // Irreversible functions ////////////////////////////////////////////////////////////////////////// @@ -113,6 +131,26 @@ namespace ojph { void gen_irrev_horz_wvlt_bwd_tx(line_buf* src, line_buf *ldst, line_buf *hdst, ui32 width, bool even); + + + + + ///////////////////////////////////////////////////////////////////////// + void gen_irv_vert_syn_step(const lifting_step* s, line_buf* aug, + const line_buf* sig, line_buf* other, + ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + void gen_irv_vert_syn_K(const float K, line_buf* aug, ui32 repeat); + + ///////////////////////////////////////////////////////////////////////// + void gen_irv_horz_syn(const param_atk *atk, line_buf* dst, line_buf *lsrc, + line_buf *hsrc, ui32 width, bool even); + + + + + ////////////////////////////////////////////////////////////////////////// // //