OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
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 res_num)
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();
67 size log_cb = cdp->get_log_block_dims();
68 size log_PP = cdp->get_log_precinct_size(res_num);
69
72
73 size nominal(1 << xcb_prime, 1 << ycb_prime);
74
79
81 num_blocks.w = (tbx1 + (1 << xcb_prime) - 1) >> xcb_prime;
83 num_blocks.h = (tby1 + (1 << ycb_prime) - 1) >> ycb_prime;
85
87 //allocate codeblock headers
89
90 for (ui32 i = 0; i < num_blocks.w; ++i)
92
93 //allocate lines
94 allocator->pre_alloc_obj<line_buf>(1);
95 //allocate line_buf
96 ui32 width = band_rect.siz.w + 1;
97 allocator->pre_alloc_data<si32>(width, 1);
98 }
99
102 const rect &band_rect,
103 resolution* res, ui32 res_num,
105 {
108
109 this->res_num = res_num;
110 this->band_num = subband_num;
111 this->band_rect = band_rect;
112 this->parent = res;
113
114 const param_cod* cdp = codestream->get_cod();
115 this->reversible = cdp->is_reversible();
116 size log_cb = cdp->get_log_block_dims();
117 log_PP = cdp->get_log_precinct_size(res_num);
118
119 xcb_prime = ojph_min(log_cb.w, log_PP.w - (res_num?1:0));
120 ycb_prime = ojph_min(log_cb.h, log_PP.h - (res_num?1:0));
121
122 size nominal(1 << xcb_prime, 1 << ycb_prime);
123
124 cur_cb_row = 0;
125 cur_line = 0;
126 cur_cb_height = 0;
128 this->K_max = qcd->get_Kmax(this->res_num, band_num);
129 if (!reversible)
130 {
131 float d = qcd->irrev_get_delta(res_num, subband_num);
132 d /= (float)(1u << (31 - this->K_max));
133 delta = d;
134 delta_inv = (1.0f/d);
135 }
136
137 this->empty = ((band_rect.siz.w == 0) || (band_rect.siz.h == 0));
138 if (this->empty)
139 return;
140
145
146 num_blocks = size();
147 num_blocks.w = (tbx1 + (1 << xcb_prime) - 1) >> xcb_prime;
149 num_blocks.h = (tby1 + (1 << ycb_prime) - 1) >> ycb_prime;
151
153 //allocate codeblock headers
156 memset(coded_cbs, 0, sizeof(coded_cb_header) * (size_t)num_blocks.area());
157 for (int i = (int)num_blocks.area(); i > 0; --i, ++cp)
158 cp->Kmax = K_max;
159
162
163 size cb_size;
164 cb_size.h = ojph_min(tby1, y_lower_bound + nominal.h) - tby0;
165 cur_cb_height = (si32)cb_size.h;
166 int line_offset = 0;
167 for (ui32 i = 0; i < num_blocks.w; ++i)
168 {
170 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
171 cb_size.w = cbx1 - cbx0;
172 blocks[i].finalize_alloc(codestream, this, nominal, cb_size,
173 coded_cbs + i, K_max, line_offset);
174 line_offset += cb_size.w;
175 }
176
177 //allocate lines
178 lines = allocator->post_alloc_obj<line_buf>(1);
179 //allocate line_buf
180 ui32 width = band_rect.siz.w + 1;
181 lines->wrap(allocator->post_alloc_data<si32>(width,1),width,1);
182 }
183
185 void subband::get_cb_indices(const size& num_precincts,
186 precinct *precincts)
187 {
188 if (empty)
189 return;
190
191 rect res_rect = parent->get_rect();
192 ui32 trx0 = res_rect.org.x;
193 ui32 try0 = res_rect.org.y;
194 ui32 trx1 = res_rect.org.x + res_rect.siz.w;
195 ui32 try1 = res_rect.org.y + res_rect.siz.h;
196
197 ui32 pc_lft = (res_rect.org.x >> log_PP.w) << log_PP.w;
198 ui32 pc_top = (res_rect.org.y >> log_PP.h) << log_PP.h;
199
200 ui32 pcx0, pcx1, pcy0, pcy1, shift = (band_num != 0 ? 1 : 0);
201 ui32 yb, xb, coly = 0, colx = 0;
202 for (ui32 y = 0; y < num_precincts.h; ++y)
203 {
204 pcy0 = ojph_max(try0, pc_top + (y << log_PP.h));
205 pcy1 = ojph_min(try1, pc_top + ((y + 1) << log_PP.h));
206 pcy0 = (pcy0 - (band_num >> 1) + (1<<shift) - 1) >> shift;
207 pcy1 = (pcy1 - (band_num >> 1) + (1<<shift) - 1) >> shift;
208
209 precinct *p = precincts + y * num_precincts.w;
210 yb = ((pcy1 + (1<<ycb_prime) - 1) >> ycb_prime);
211 yb -= (pcy0 >> ycb_prime);
212 colx = 0;
213
214 for (ui32 x = 0; x < num_precincts.w; ++x, ++p)
215 {
216 pcx0 = ojph_max(trx0, pc_lft + (x << log_PP.w));
217 pcx1 = ojph_min(trx1, pc_lft + ((x + 1) << log_PP.w));
218 pcx0 = (pcx0 - (band_num & 1) + (1<<shift) - 1) >> shift;
219 pcx1 = (pcx1 - (band_num & 1) + (1<<shift) - 1) >> shift;
220
221 rect *bp = p->cb_idxs + band_num;
222 xb = ((pcx1 + (1<<xcb_prime) - 1) >> xcb_prime);
223 xb -= (pcx0 >> xcb_prime);
224
225 bp->org.x = colx;
226 bp->org.y = coly;
227 bp->siz.w = xb;
228 bp->siz.h = yb;
229
230 colx += xb;
231 }
232 coly += yb;
233 }
235 }
236
239 {
240 if (empty)
241 return;
242
243 assert(l->pre_size == lines[0].pre_size && l->size == lines[0].size);
244 si32* t = lines[0].i32;
245 lines[0].i32 = l->i32;
246 l->i32 = t;
247 }
248
251 {
252 if (empty)
253 return;
254
255 //push to codeblocks
256 for (ui32 i = 0; i < num_blocks.w; ++i)
257 blocks[i].push(lines + 0);
258 if (++cur_line >= cur_cb_height)
259 {
260 for (ui32 i = 0; i < num_blocks.w; ++i)
261 blocks[i].encode(elastic);
262
263 if (++cur_cb_row < num_blocks.h)
264 {
265 cur_line = 0;
266
271 size nominal(1 << xcb_prime, 1 << ycb_prime);
272
277
278 size cb_size;
279 cb_size.h = cby1 - ojph_max(tby0, cby0);
280 cur_cb_height = (int)cb_size.h;
281 for (ui32 i = 0; i < num_blocks.w; ++i)
282 {
284 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
285 cb_size.w = cbx1 - cbx0;
286 blocks[i].recreate(cb_size,
288 }
289 }
290 }
291 }
292
295 {
296 if (empty)
297 return lines;
298
299 //pull from codeblocks
300 if (--cur_line <= 0)
301 {
302 if (cur_cb_row < num_blocks.h)
303 {
308 size nominal(1 << xcb_prime, 1 << ycb_prime);
309
314
315 size cb_size;
316 cb_size.h = cby1 - cby0;
317 cur_line = cur_cb_height = (int)cb_size.h;
318 for (ui32 i = 0; i < num_blocks.w; ++i)
319 {
321 ui32 cbx1 = ojph_min(tbx1, x_lower_bound + (i + 1) * nominal.w);
322 cb_size.w = cbx1 - cbx0;
323 blocks[i].recreate(cb_size,
325 blocks[i].decode();
326 }
327 ++cur_cb_row;
328 }
329 }
330
331 assert(cur_line >= 0);
332
333 //pull from codeblocks
334 for (ui32 i = 0; i < num_blocks.w; ++i)
335 blocks[i].pull_line(lines + 0);
336
337 return lines;
338 }
339
340 }
341}
static void pre_alloc(codestream *codestream, 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()
mem_fixed_allocator * get_allocator()
void exchange_buf(line_buf *l)
coded_cb_header * coded_cbs
void get_cb_indices(const size &num_precincts, precinct *precincts)
mem_elastic_allocator * elastic
static void pre_alloc(codestream *codestream, const rect &band_rect, ui32 res_num)
resolution * parent
void finalize_alloc(codestream *codestream, const rect &band_rect, resolution *res, ui32 res_num, ui32 subband_num)
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
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
void wrap(T *buffer, size_t num_ele, ui32 pre_size)
ui32 get_Kmax(ui32 resolution, ui32 subband) const
float irrev_get_delta(ui32 resolution, ui32 subband) const
point org
Definition ojph_base.h:66
ui64 area() const
Definition ojph_base.h:53