OpenJPH
Open-source implementation of JPEG2000 Part-15
ojph_subband.cpp
Go to the documentation of this file.
1
2//***************************************************************************/
3// This software is released under the 2-Clause BSD license, included
4// below.
5//
6// Copyright (c) 2019, Aous Naman
7// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
8// Copyright (c) 2019, The University of New South Wales, Australia
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//***************************************************************************/
33// This file is part of the OpenJPH software implementation.
34// File: ojph_subband.cpp
35// Author: Aous Naman
36// Date: 28 August 2019
37//***************************************************************************/
38
39
40#include <climits>
41#include <cmath>
42
43#include "ojph_mem.h"
44#include "ojph_params.h"
46#include "ojph_subband.h"
47#include "ojph_resolution.h"
48#include "ojph_codeblock.h"
49#include "ojph_precinct.h"
50
51namespace ojph {
52
53 namespace local
54 {
55
58 ui32 comp_num, ui32 res_num, ui32 transform_flags)
59 {
61
62 bool empty = ((band_rect.siz.w == 0) || (band_rect.siz.h == 0));
63 if (empty)
64 return;
65
66 const param_cod* cdp = codestream->get_cod(comp_num);
67 size log_cb = cdp->get_log_block_dims();
69
70 ui32 x_off = ((transform_flags & resolution::HORZ_TRX) ? 1 : 0);
71 ui32 y_off = ((transform_flags & resolution::VERT_TRX) ? 1 : 0);
72
73 ui32 xcb_prime = ojph_min(log_cb.w, log_PP.w - x_off);
74 ui32 ycb_prime = ojph_min(log_cb.h, log_PP.h - y_off);
75
76 size nominal(1 << xcb_prime, 1 << ycb_prime);
77
78 ui32 tbx0 = band_rect.org.x;
79 ui32 tby0 = band_rect.org.y;
80 ui32 tbx1 = band_rect.org.x + band_rect.siz.w;
81 ui32 tby1 = band_rect.org.y + band_rect.siz.h;
82
84 num_blocks.w = (tbx1 + (1 << xcb_prime) - 1) >> xcb_prime;
85 num_blocks.w -= tbx0 >> xcb_prime;
86 num_blocks.h = (tby1 + (1 << ycb_prime) - 1) >> ycb_prime;
87 num_blocks.h -= tby0 >> ycb_prime;
88
90 //allocate codeblock headers
91 allocator->pre_alloc_obj<coded_cb_header>((size_t)num_blocks.area());
92
93 for (ui32 i = 0; i < num_blocks.w; ++i)
94 codeblock::pre_alloc(codestream, comp_num, nominal);
95
96 //allocate lines
97 allocator->pre_alloc_obj<line_buf>(1);
98 //allocate line_buf
99 ui32 width = band_rect.siz.w + 1;
100 const param_siz* szp = codestream->get_siz();
101 ui32 precision = cdp->propose_precision(szp, comp_num);
102 if (precision <= 32)
103 allocator->pre_alloc_data<si32>(width, 1);
104 else
105 allocator->pre_alloc_data<si64>(width, 1);
106 }
107
110 const rect &band_rect,
111 resolution* res, ui32 res_num,
112 ui32 subband_num)
113 {
116
117 this->res_num = res_num;
118 this->band_num = subband_num;
119 this->band_rect = band_rect;
120 this->parent = res;
121
123 this->reversible = cdp->access_atk()->is_reversible();
124 size log_cb = cdp->get_log_block_dims();
126
127 ui32 x_off = ((parent->has_horz_transform()) ? 1 : 0);
128 ui32 y_off = ((parent->has_vert_transform()) ? 1 : 0);
129
130 xcb_prime = ojph_min(log_cb.w, log_PP.w - x_off);
131 ycb_prime = ojph_min(log_cb.h, log_PP.h - y_off);
132
133 size nominal(1 << xcb_prime, 1 << ycb_prime);
134
135 cur_cb_row = 0;
136 cur_line = 0;
137 cur_cb_height = 0;
138 const param_dfs* dfs = NULL;
139 if (cdp->is_dfs_defined()) {
140 dfs = codestream->access_dfs();
141 if (dfs != NULL)
142 dfs = dfs->get_dfs(cdp->get_dfs_index());
143 }
144 ui32 comp_num = parent->get_comp_num();
145 param_qcd* qcd = codestream->access_qcd(comp_num);
146 ui32 num_decomps = cdp->get_num_decompositions();
147 this->K_max = qcd->get_Kmax(dfs, num_decomps, this->res_num, band_num);
148 if (!reversible)
149 {
150 float d =
151 qcd->irrev_get_delta(dfs, num_decomps, res_num, subband_num);
152 d /= (float)(1u << (31 - this->K_max));
153 delta = d;
154 delta_inv = (1.0f/d);
155 }
156
157 this->empty = ((band_rect.siz.w == 0) || (band_rect.siz.h == 0));
158 if (this->empty)
159 return;
160
161 ui32 tbx0 = band_rect.org.x;
162 ui32 tby0 = band_rect.org.y;
163 ui32 tbx1 = band_rect.org.x + band_rect.siz.w;
164 ui32 tby1 = band_rect.org.y + band_rect.siz.h;
165
166 num_blocks = size();
167 num_blocks.w = (tbx1 + (1 << xcb_prime) - 1) >> xcb_prime;
168 num_blocks.w -= tbx0 >> xcb_prime;
169 num_blocks.h = (tby1 + (1 << ycb_prime) - 1) >> ycb_prime;
170 num_blocks.h -= tby0 >> ycb_prime;
171
173 //allocate codeblock headers
175 allocator->post_alloc_obj<coded_cb_header>((size_t)num_blocks.area());
176 memset(coded_cbs, 0, sizeof(coded_cb_header) * (size_t)num_blocks.area());
177 for (int i = (int)num_blocks.area(); i > 0; --i, ++cp)
178 cp->Kmax = K_max;
179
180 ui32 x_lower_bound = (tbx0 >> xcb_prime) << xcb_prime;
181 ui32 y_lower_bound = (tby0 >> ycb_prime) << ycb_prime;
182
183 size cb_size;
184 cb_size.h = ojph_min(tby1, y_lower_bound + nominal.h) - tby0;
185 cur_cb_height = (si32)cb_size.h;
186 int line_offset = 0;
187 for (ui32 i = 0; i < num_blocks.w; ++i)
188 {
189 ui32 cbx0 = ojph_max(tbx0, x_lower_bound + i * nominal.w);
190 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
191 cb_size.w = cbx1 - cbx0;
192 blocks[i].finalize_alloc(codestream, this, nominal, cb_size,
193 coded_cbs + i, K_max, line_offset);
194 line_offset += cb_size.w;
195 }
196
197 //allocate lines
198 lines = allocator->post_alloc_obj<line_buf>(1);
199 //allocate line_buf
200 ui32 width = band_rect.siz.w + 1;
201 const param_siz* szp = codestream->get_siz();
202 ui32 precision = cdp->propose_precision(szp, comp_num);
203 if (precision <= 32)
204 lines->wrap(allocator->post_alloc_data<si32>(width, 1), width, 1);
205 else
206 lines->wrap(allocator->post_alloc_data<si64>(width, 1), width, 1);
207 }
208
210 void subband::get_cb_indices(const size& num_precincts,
211 precinct *precincts)
212 {
213 if (empty)
214 return;
215
216 rect res_rect = parent->get_rect();
217 ui32 trx0 = res_rect.org.x;
218 ui32 try0 = res_rect.org.y;
219 ui32 trx1 = res_rect.org.x + res_rect.siz.w;
220 ui32 try1 = res_rect.org.y + res_rect.siz.h;
221
222 ui32 pc_lft = (res_rect.org.x >> log_PP.w) << log_PP.w;
223 ui32 pc_top = (res_rect.org.y >> log_PP.h) << log_PP.h;
224
225 ui32 pcx0, pcx1, pcy0, pcy1;
226 ui32 x_shift = parent->has_horz_transform() ? 1 : 0;
227 ui32 y_shift = parent->has_vert_transform() ? 1 : 0;
228 ui32 yb, xb, coly = 0, colx = 0;
229 for (ui32 y = 0; y < num_precincts.h; ++y)
230 {
231 pcy0 = ojph_max(try0, pc_top + (y << log_PP.h));
232 pcy1 = ojph_min(try1, pc_top + ((y + 1) << log_PP.h));
233 pcy0 = (pcy0 - (band_num >> 1) + (1 << y_shift) - 1) >> y_shift;
234 pcy1 = (pcy1 - (band_num >> 1) + (1 << y_shift) - 1) >> y_shift;
235
236 precinct *p = precincts + y * num_precincts.w;
237 yb = ((pcy1 + (1<<ycb_prime) - 1) >> ycb_prime);
238 yb -= (pcy0 >> ycb_prime);
239 colx = 0;
240
241 for (ui32 x = 0; x < num_precincts.w; ++x, ++p)
242 {
243 pcx0 = ojph_max(trx0, pc_lft + (x << log_PP.w));
244 pcx1 = ojph_min(trx1, pc_lft + ((x + 1) << log_PP.w));
245 pcx0 = (pcx0 - (band_num & 1) + (1 << x_shift) - 1) >> x_shift;
246 pcx1 = (pcx1 - (band_num & 1) + (1 << x_shift) - 1) >> x_shift;
247
248 rect *bp = p->cb_idxs + band_num;
249 xb = ((pcx1 + (1<<xcb_prime) - 1) >> xcb_prime);
250 xb -= (pcx0 >> xcb_prime);
251
252 bp->org.x = colx;
253 bp->org.y = coly;
254 bp->siz.w = xb;
255 bp->siz.h = yb;
256
257 colx += xb;
258 }
259 coly += yb;
260 }
261 assert(colx == num_blocks.w && coly == num_blocks.h);
262 }
263
266 {
267 if (empty)
268 return;
269
270 assert(l->pre_size == lines[0].pre_size && l->size == lines[0].size &&
271 l->flags == lines[0].flags);
272 void* p = lines[0].p;
273 lines[0].p = l->p;
274 l->p = p;
275 }
276
279 {
280 if (empty)
281 return;
282
283 //push to codeblocks
284 for (ui32 i = 0; i < num_blocks.w; ++i)
285 blocks[i].push(lines + 0);
286 if (++cur_line >= cur_cb_height)
287 {
288 for (ui32 i = 0; i < num_blocks.w; ++i)
289 blocks[i].encode(elastic);
290
291 if (++cur_cb_row < num_blocks.h)
292 {
293 cur_line = 0;
294
295 ui32 tbx0 = band_rect.org.x;
296 ui32 tby0 = band_rect.org.y;
297 ui32 tbx1 = band_rect.org.x + band_rect.siz.w;
298 ui32 tby1 = band_rect.org.y + band_rect.siz.h;
299 size nominal(1 << xcb_prime, 1 << ycb_prime);
300
301 ui32 x_lower_bound = (tbx0 >> xcb_prime) << xcb_prime;
302 ui32 y_lower_bound = (tby0 >> ycb_prime) << ycb_prime;
303 ui32 cby0 = y_lower_bound + cur_cb_row * nominal.h;
304 ui32 cby1 = ojph_min(tby1, cby0 + nominal.h);
305
306 size cb_size;
307 cb_size.h = cby1 - ojph_max(tby0, cby0);
308 cur_cb_height = (int)cb_size.h;
309 for (ui32 i = 0; i < num_blocks.w; ++i)
310 {
311 ui32 cbx0 = ojph_max(tbx0, x_lower_bound + i * nominal.w);
312 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
313 cb_size.w = cbx1 - cbx0;
314 blocks[i].recreate(cb_size,
316 }
317 }
318 }
319 }
320
323 {
324 if (empty)
325 return lines;
326
327 //pull from codeblocks
328 if (--cur_line <= 0)
329 {
330 if (cur_cb_row < num_blocks.h)
331 {
332 ui32 tbx0 = band_rect.org.x;
333 ui32 tby0 = band_rect.org.y;
334 ui32 tbx1 = band_rect.org.x + band_rect.siz.w;
335 ui32 tby1 = band_rect.org.y + band_rect.siz.h;
336 size nominal(1 << xcb_prime, 1 << ycb_prime);
337
338 ui32 x_lower_bound = (tbx0 >> xcb_prime) << xcb_prime;
339 ui32 y_lower_bound = (tby0 >> ycb_prime) << ycb_prime;
340 ui32 cby0 = ojph_max(tby0, y_lower_bound + cur_cb_row * nominal.h);
341 ui32 cby1 = ojph_min(tby1, y_lower_bound+(cur_cb_row+1)*nominal.h);
342
343 size cb_size;
344 cb_size.h = cby1 - cby0;
345 cur_line = cur_cb_height = (int)cb_size.h;
346 for (ui32 i = 0; i < num_blocks.w; ++i)
347 {
348 ui32 cbx0 = ojph_max(tbx0, x_lower_bound + i * nominal.w);
349 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
350 cb_size.w = cbx1 - cbx0;
351 blocks[i].recreate(cb_size,
353 blocks[i].decode();
354 }
355 ++cur_cb_row;
356 }
357 }
358
359 assert(cur_line >= 0);
360
361 //pull from codeblocks
362 for (ui32 i = 0; i < num_blocks.w; ++i)
363 blocks[i].pull_line(lines + 0);
364
365 return lines;
366 }
367
368 }
369}
size_t size
Definition: ojph_mem.h:168
void wrap(T *buffer, size_t num_ele, ui32 pre_size)
static void pre_alloc(codestream *codestream, ui32 comp_num, const size &nominal)
void recreate(const size &cb_size, coded_cb_header *coded_cb)
void finalize_alloc(codestream *codestream, subband *parent, const size &nominal, const size &cb_size, coded_cb_header *coded_cb, ui32 K_max, int tbx0)
param_qcd * access_qcd(ui32 comp_num)
mem_elastic_allocator * get_elastic_alloc()
const param_siz * get_siz()
mem_fixed_allocator * get_allocator()
const param_cod * get_cod()
const param_dfs * access_dfs()
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)
coded_cb_header * coded_cbs
Definition: ojph_subband.h:117
void get_cb_indices(const size &num_precincts, precinct *precincts)
mem_elastic_allocator * elastic
Definition: ojph_subband.h:118
resolution * parent
Definition: ojph_subband.h:107
void finalize_alloc(codestream *codestream, const rect &band_rect, resolution *res, ui32 res_num, ui32 subband_num)
line_buf * pull_line()
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
int64_t si64
Definition: ojph_defs.h:57
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
const param_atk * access_atk() const
size get_log_precinct_size(ui32 res_num) const
ui8 get_num_decompositions() const
ui32 propose_precision(const param_siz *siz, ui32 comp_num) const
const param_dfs * get_dfs(int index) const
float irrev_get_delta(const param_dfs *dfs, ui32 num_decompositions, ui32 resolution, ui32 subband) const
ui32 get_Kmax(const param_dfs *dfs, ui32 num_decompositions, ui32 resolution, ui32 subband) const
size siz
Definition: ojph_base.h:67
point org
Definition: ojph_base.h:66
ui64 area() const
Definition: ojph_base.h:53
ui32 w
Definition: ojph_base.h:50
ui32 h
Definition: ojph_base.h:51