OpenJPH
Open-source implementation of JPEG2000 Part-15
Loading...
Searching...
No Matches
ojph_tile.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_tile.cpp
34// Author: Aous Naman
35// Date: 28 August 2019
36//***************************************************************************/
37
38
39#include <climits>
40#include <cmath>
41#include <exception>
42
43#include "ojph_mem.h"
44#include "ojph_params.h"
46#include "ojph_tile.h"
47#include "ojph_tile_comp.h"
48
50
51namespace ojph {
52
53 namespace local
54 {
55
58 const rect& recon_tile_rect, ui32& num_tileparts)
59 {
61
62 //allocate tiles_comp
63 const param_siz *szp = codestream->get_siz();
66 allocator->pre_alloc_obj<rect>(num_comps); //for comp_rects
67 allocator->pre_alloc_obj<rect>(num_comps); //for recon_comp_rects
68 allocator->pre_alloc_obj<ui32>(num_comps); //for line_offsets
69 allocator->pre_alloc_obj<ui32>(num_comps); //for num_bits
70 allocator->pre_alloc_obj<bool>(num_comps); //for is_signed
71 allocator->pre_alloc_obj<bool>(num_comps); //for reversible
72 allocator->pre_alloc_obj<const nlt_rec*>(num_comps);
73 allocator->pre_alloc_obj<ui32>(num_comps); //for cur_line
74
75 {
79 num_tileparts = 1; //for num_rc_bytes
80 else if (t == OJPH_TILEPART_COMPONENTS)
81 num_tileparts = num_comps;
82 else if (t == OJPH_TILEPART_RESOLUTIONS)
83 {
84 ui32 max_decs = 0;
85 for (ui32 c = 0; c < num_comps; ++c) {
87 max_decs = ojph_max(max_decs, s);
88 }
89 num_tileparts = 1 + max_decs;
90 }
92 {
93 num_tileparts = 0;
94 for (ui32 c = 0; c < num_comps; ++c) {
96 num_tileparts += s + 1;
97 }
98 }
99 if (num_tileparts > 255)
100 OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
101 "cannot have more than 255 tile parts.", num_tileparts);
102 }
103
104 ui32 tx0 = tile_rect.org.x;
105 ui32 ty0 = tile_rect.org.y;
106 ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
107 ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
108 ui32 recon_tx0 = recon_tile_rect.org.x;
109 ui32 recon_ty0 = recon_tile_rect.org.y;
110 ui32 recon_tx1 = recon_tile_rect.org.x + recon_tile_rect.siz.w;
111 ui32 recon_ty1 = recon_tile_rect.org.y + recon_tile_rect.siz.h;
112
113 ui32 width = 0;
114 rect colour_comp_rect[3];
115 for (ui32 i = 0; i < num_comps; ++i)
116 {
117 point downsamp = szp->get_downsampling(i);
118
119 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
120 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
121 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
122 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
123 ui32 recon_tcx0 = ojph_div_ceil(recon_tx0, downsamp.x);
124 ui32 recon_tcy0 = ojph_div_ceil(recon_ty0, downsamp.y);
125 ui32 recon_tcx1 = ojph_div_ceil(recon_tx1, downsamp.x);
126 ui32 recon_tcy1 = ojph_div_ceil(recon_ty1, downsamp.y);
127
128 rect comp_rect;
129 comp_rect.org.x = tcx0;
130 comp_rect.org.y = tcy0;
131 comp_rect.siz.w = tcx1 - tcx0;
132 comp_rect.siz.h = tcy1 - tcy0;
133
134 if (i < 3)
135 colour_comp_rect[i] = comp_rect;
136
137 rect recon_comp_rect;
138 recon_comp_rect.org.x = recon_tcx0;
139 recon_comp_rect.org.y = recon_tcy0;
140 recon_comp_rect.siz.w = recon_tcx1 - recon_tcx0;
141 recon_comp_rect.siz.h = recon_tcy1 - recon_tcy0;
142
143 tile_comp::pre_alloc(codestream, i, comp_rect, recon_comp_rect);
144 width = ojph_max(width, recon_comp_rect.siz.w);
145 }
146
147 //allocate lines
148 const param_cod* cdp = codestream->get_cod();
150 {
151 bool reversible[3];
152 for (ui32 i = 0; i < 3; ++i)
154 if (reversible[0] != reversible[1] || reversible[1] != reversible[2])
155 OJPH_ERROR(0x000300A2, "When the colour transform is employed, "
156 "all colour components must undergo either reversible or "
157 "irreversible wavelet transform; if not, then it is not clear "
158 "what colour transform should be used (reversible or "
159 "irreversible). Here we found that the first three colour "
160 "components uses %s, %s, and %s transforms, respectively.",
161 reversible[0] ? "reversible" : "irreversible",
162 reversible[1] ? "reversible" : "irreversible",
163 reversible[2] ? "reversible" : "irreversible");
164
165 if (colour_comp_rect[0] != colour_comp_rect[1] ||
166 colour_comp_rect[1] != colour_comp_rect[2])
167 OJPH_ERROR(0x000300A3, "When the colour transform is employed, "
168 "the first three colour components must have the same rectangle; "
169 "i.e., the same origin on the canvas and the same width and "
170 "height. The first three components have the following "
171 "origin-size (x,y)-(w,h) values. Component 0 (%d,%d)-(%d,%d), "
172 "Component 1 (%d,%d)-(%d,%d), Component 2 (%d,%d)-(%d,%d)",
173 colour_comp_rect[0].org.x, colour_comp_rect[0].org.y,
174 colour_comp_rect[0].siz.w, colour_comp_rect[0].siz.h,
175 colour_comp_rect[1].org.x, colour_comp_rect[1].org.y,
176 colour_comp_rect[1].siz.w, colour_comp_rect[1].siz.h,
177 colour_comp_rect[2].org.x, colour_comp_rect[2].org.y,
178 colour_comp_rect[2].siz.w, colour_comp_rect[2].siz.h);
179
180 allocator->pre_alloc_obj<line_buf>(3);
181 if (reversible[0])
182 for (int i = 0; i < 3; ++i)
183 allocator->pre_alloc_data<si32>(width, 0);
184 else
185 for (int i = 0; i < 3; ++i)
186 allocator->pre_alloc_data<float>(width, 0);
187 }
188 }
189
192 ui32 tile_idx, ui32& offset,
193 ui32 &num_tileparts)
194 {
195 constexpr ui8 type3 =
197
198 //this->parent = codestream;
200
201 sot.init(0, (ui16)tile_idx, 0, 1);
203
204 //allocate tiles_comp
205 const param_siz *szp = codestream->get_siz();
206 const param_nlt *nlp = codestream->get_nlt();
207
208 this->num_bytes = 0;
215 num_bits = allocator->post_alloc_obj<ui32>(num_comps);
216 is_signed = allocator->post_alloc_obj<bool>(num_comps);
217 reversible = allocator->post_alloc_obj<bool>(num_comps);
218 nlt_ptr = allocator->post_alloc_obj<const nlt_rec*>(num_comps);
219 cur_line = allocator->post_alloc_obj<ui32>(num_comps);
220
224 {
228 num_tileparts = 1; //for num_rc_bytes
229 else if (t == OJPH_TILEPART_COMPONENTS)
230 num_tileparts = num_comps;
231 else if (t == OJPH_TILEPART_RESOLUTIONS)
232 {
233 ui32 max_decs = 0;
234 for (ui32 c = 0; c < num_comps; ++c) {
236 max_decs = ojph_max(max_decs, s);
237 }
238 num_tileparts = 1 + max_decs;
239 }
241 {
242 num_tileparts = 0;
243 for (ui32 c = 0; c < num_comps; ++c) {
245 num_tileparts += s + 1;
246 }
247 }
248 if (num_tileparts > 255)
249 OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
250 "cannot have more than 255 tile parts.", num_tileparts);
251 }
252
254 this->tile_rect = tile_rect;
255
256 ui32 tx0 = tile_rect.org.x;
257 ui32 ty0 = tile_rect.org.y;
258 ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
259 ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
260
261 ui32 width = 0;
262 for (ui32 i = 0; i < num_comps; ++i)
263 {
264 point downsamp = szp->get_downsampling(i);
265 point recon_downsamp = szp->get_recon_downsampling(i);
266
267 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
268 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
269 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
270 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
271 ui32 recon_tcx0 = ojph_div_ceil(tx0, recon_downsamp.x);
272 ui32 recon_tcy0 = ojph_div_ceil(ty0, recon_downsamp.y);
273 ui32 recon_tcx1 = ojph_div_ceil(tx1, recon_downsamp.x);
274 ui32 recon_tcy1 = ojph_div_ceil(ty1, recon_downsamp.y);
275
276 line_offsets[i] =
277 recon_tcx0 - ojph_div_ceil(tx0 - offset, recon_downsamp.x);
278 comp_rects[i].org.x = tcx0;
279 comp_rects[i].org.y = tcy0;
280 comp_rects[i].siz.w = tcx1 - tcx0;
281 comp_rects[i].siz.h = tcy1 - tcy0;
282 recon_comp_rects[i].org.x = recon_tcx0;
283 recon_comp_rects[i].org.y = recon_tcy0;
284 recon_comp_rects[i].siz.w = recon_tcx1 - recon_tcx0;
285 recon_comp_rects[i].siz.h = recon_tcy1 - recon_tcy0;
286
289 width = ojph_max(width, recon_comp_rects[i].siz.w);
290
291 num_bits[i] = szp->get_bit_depth(i);
292 is_signed[i] = szp->is_signed(i);
293 nlt_ptr[i] = nlp->get_nlt_rec(i);
294
295 if (nlt_ptr[i])
296 {
297 ui8 bd = nlt_ptr[i]->get_bit_depth();
298 ui8 nlt_type = nlt_ptr[i]->get_type();
299 bool is = nlt_ptr[i]->is_signed();
300 if (nlt_type == type3 && (bd != num_bits[i] || is != is_signed[i]))
301 OJPH_ERROR(0x000300A1, "Mismatch between Ssiz (bit_depth = %d, "
302 "is_signed = %s) from SIZ marker segment, and BDnlt "
303 "(bit_depth = %d, is_signed = %s) from NLT marker segment, "
304 "for component %d", num_bits[i],
305 is_signed[i] ? "True" : "False", bd, is ? "True" : "False", i);
306 }
307 cur_line[i] = 0;
309 }
310
311 offset += tile_rect.siz.w;
312
313 //allocate lines
314 const param_cod* cdp = codestream->get_cod();
316 if (this->employ_color_transform)
317 {
318 num_lines = 3;
319 lines = allocator->post_alloc_obj<line_buf>(num_lines);
320 if (reversible[0])
321 for (int i = 0; i < 3; ++i)
322 lines[i].wrap(
323 allocator->post_alloc_data<si32>(width, 0), width, 0);
324 else
325 for (int i = 0; i < 3; ++i)
326 lines[i].wrap(
327 allocator->post_alloc_data<float>(width, 0), width, 0);
328 }
329 else
330 {
331 lines = NULL;
332 num_lines = 0;
333 }
334 next_tile_part = 0;
335 }
336
338 bool tile::push(line_buf *line, ui32 comp_num)
339 {
340 constexpr ui8 type2 =
342 constexpr ui8 type3 =
344 constexpr ui8 type4 =
346
347 assert(comp_num < num_comps);
348 if (cur_line[comp_num] >= comp_rects[comp_num].siz.h)
349 return false;
350 cur_line[comp_num]++;
351
352 //converts to signed representation
353 //employs color transform if there is a need
354 if (!employ_color_transform || comp_num >= 3)
355 {
356 assert(comp_num < num_comps);
357 ui32 comp_width = comp_rects[comp_num].siz.w;
358 line_buf *tc = comps[comp_num].get_line();
359 if (reversible[comp_num])
360 {
361 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
362 if (nlt_ptr[comp_num] == NULL) {
363 shift = is_signed[comp_num] ? 0 : -shift;
364 rev_convert(line, line_offsets[comp_num], tc, 0,
365 shift, comp_width);
366 }
367 else if (is_signed[comp_num] &&
368 nlt_ptr[comp_num]->get_type() == type3)
369 rev_convert_nlt_type3(line, line_offsets[comp_num],
370 tc, 0, shift + 1, comp_width);
371 else if (nlt_ptr[comp_num]->get_type() == type2 ||
372 nlt_ptr[comp_num]->get_type() == type4)
373 rev_encode_nlt(line, line_offsets[comp_num], tc,
374 num_bits[comp_num], is_signed[comp_num], comp_width,
375 nlt_ptr[comp_num]);
376 }
377 else
378 {
379 if (nlt_ptr[comp_num] == NULL)
380 irv_convert_to_float(line, line_offsets[comp_num],
381 tc, num_bits[comp_num], is_signed[comp_num], comp_width);
382 else if (nlt_ptr[comp_num]->get_type() == type3)
384 tc, num_bits[comp_num], is_signed[comp_num], comp_width);
385 else if (nlt_ptr[comp_num]->get_type() == type2 ||
386 nlt_ptr[comp_num]->get_type() == type4)
388 tc, num_bits[comp_num], is_signed[comp_num], comp_width,
389 nlt_ptr[comp_num]);
390 }
391 comps[comp_num].push_line();
392 }
393 else
394 {
395 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
396 ui32 comp_width = comp_rects[comp_num].siz.w;
397 if (reversible[comp_num])
398 {
399 if (nlt_ptr[comp_num] == NULL) {
400 shift = is_signed[comp_num] ? 0 : -shift;
401 rev_convert(line, line_offsets[comp_num], lines + comp_num, 0,
402 shift, comp_width);
403 }
404 else if (is_signed[comp_num] &&
405 nlt_ptr[comp_num]->get_type() == type3)
406 rev_convert_nlt_type3(line, line_offsets[comp_num],
407 lines + comp_num, 0, shift + 1, comp_width);
408 else if (nlt_ptr[comp_num]->get_type() == type2 ||
409 nlt_ptr[comp_num]->get_type() == type4)
410 rev_encode_nlt(line, line_offsets[comp_num],
411 lines + comp_num, num_bits[comp_num],
412 is_signed[comp_num], comp_width, nlt_ptr[comp_num]);
413
414 if (comp_num == 2)
415 { // reversible color transform
416 rct_forward(lines + 0, lines + 1, lines + 2,
417 comps[0].get_line(),
418 comps[1].get_line(),
419 comps[2].get_line(), comp_width);
420 comps[0].push_line();
421 comps[1].push_line();
422 comps[2].push_line();
423 }
424 }
425 else
426 {
427 if (nlt_ptr[comp_num] == NULL)
428 irv_convert_to_float(line, line_offsets[comp_num],
429 lines + comp_num, num_bits[comp_num], is_signed[comp_num],
430 comp_width);
431 else if (nlt_ptr[comp_num]->get_type() == type3)
433 lines + comp_num, num_bits[comp_num], is_signed[comp_num],
434 comp_width);
435 else if (nlt_ptr[comp_num]->get_type() == type2 ||
436 nlt_ptr[comp_num]->get_type() == type4)
438 lines + comp_num, num_bits[comp_num], is_signed[comp_num],
439 comp_width, nlt_ptr[comp_num]);
440 if (comp_num == 2)
441 { // irreversible color transform
442 ict_forward(lines[0].f32, lines[1].f32, lines[2].f32,
443 comps[0].get_line()->f32,
444 comps[1].get_line()->f32,
445 comps[2].get_line()->f32, comp_width);
446 comps[0].push_line();
447 comps[1].push_line();
448 comps[2].push_line();
449 }
450 }
451 }
452
453 return true;
454 }
455
457 bool tile::pull(line_buf* tgt_line, ui32 comp_num)
458 {
459 constexpr ui8 type2 =
461 constexpr ui8 type3 =
463 constexpr ui8 type4 =
465
466 assert(comp_num < num_comps);
467 if (cur_line[comp_num] >= recon_comp_rects[comp_num].siz.h)
468 return false;
469
470 cur_line[comp_num]++;
471
472 ui32 comp_width = recon_comp_rects[comp_num].siz.w;
473 if (comp_width == 0)
474 return true; // nothing to pull, but not an error
475
477 {
478 line_buf *src_line = comps[comp_num].pull_line();
479 if (reversible[comp_num])
480 {
481 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
482 if (nlt_ptr[comp_num] == NULL) {
483 shift = is_signed[comp_num] ? 0 : shift;
484 rev_convert(src_line, 0, tgt_line,
485 line_offsets[comp_num], shift, comp_width);
486 }
487 else if (is_signed[comp_num] &&
488 nlt_ptr[comp_num]->get_type() == type3)
489 rev_convert_nlt_type3(src_line, 0, tgt_line,
490 line_offsets[comp_num], shift + 1, comp_width);
491 else if (nlt_ptr[comp_num]->get_type() == type2 ||
492 nlt_ptr[comp_num]->get_type() == type4)
493 rev_decode_nlt(src_line, 0, tgt_line,
494 line_offsets[comp_num], num_bits[comp_num],
495 is_signed[comp_num], comp_width, nlt_ptr[comp_num]);
496 }
497 else
498 {
499 if (nlt_ptr[comp_num] == NULL)
500 irv_convert_to_integer(src_line, tgt_line,
501 line_offsets[comp_num], num_bits[comp_num],
502 is_signed[comp_num], comp_width);
503 else if (nlt_ptr[comp_num]->get_type() == type3)
504 irv_convert_to_integer_nlt_type3(src_line, tgt_line,
505 line_offsets[comp_num], num_bits[comp_num],
506 is_signed[comp_num], comp_width);
507 else if (nlt_ptr[comp_num]->get_type() == type2 ||
508 nlt_ptr[comp_num]->get_type() == type4)
509 irv_convert_to_integer_nlt(src_line, tgt_line,
510 line_offsets[comp_num], num_bits[comp_num],
511 is_signed[comp_num], comp_width, nlt_ptr[comp_num]);
512 }
513 }
514 else
515 {
516 assert(num_comps >= 3);
517 if (comp_num == 0)
518 {
519 if (reversible[comp_num])
520 rct_backward(comps[0].pull_line(), comps[1].pull_line(),
521 comps[2].pull_line(), lines + 0, lines + 1,
522 lines + 2, comp_width);
523 else
524 ict_backward(comps[0].pull_line()->f32, comps[1].pull_line()->f32,
525 comps[2].pull_line()->f32, lines[0].f32, lines[1].f32,
526 lines[2].f32, comp_width);
527 }
528 if (reversible[comp_num])
529 {
530 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
531 line_buf* src_line;
532 if (comp_num < 3)
533 src_line = lines + comp_num;
534 else
535 src_line = comps[comp_num].pull_line();
536 if (nlt_ptr[comp_num] == NULL) {
537 shift = is_signed[comp_num] ? 0 : shift;
538 rev_convert(src_line, 0, tgt_line,
539 line_offsets[comp_num], shift, comp_width);
540 }
541 else if (is_signed[comp_num] &&
542 nlt_ptr[comp_num]->get_type() == type3)
543 rev_convert_nlt_type3(src_line, 0, tgt_line,
544 line_offsets[comp_num], shift + 1, comp_width);
545 else if (nlt_ptr[comp_num]->get_type() == type2 ||
546 nlt_ptr[comp_num]->get_type() == type4)
547 rev_decode_nlt(src_line, 0, tgt_line,
548 line_offsets[comp_num], num_bits[comp_num],
549 is_signed[comp_num], comp_width, nlt_ptr[comp_num]);
550 }
551 else
552 {
553 line_buf* lbp;
554 if (comp_num < 3)
555 lbp = lines + comp_num;
556 else
557 lbp = comps[comp_num].pull_line();
558 if (nlt_ptr[comp_num] == NULL)
559 irv_convert_to_integer(lbp, tgt_line,
560 line_offsets[comp_num], num_bits[comp_num],
561 is_signed[comp_num], comp_width);
562 else if (nlt_ptr[comp_num]->get_type() == type3)
564 line_offsets[comp_num], num_bits[comp_num],
565 is_signed[comp_num], comp_width);
566 else if (nlt_ptr[comp_num]->get_type() == type2 ||
567 nlt_ptr[comp_num]->get_type() == type4)
568 irv_convert_to_integer_nlt(lbp, tgt_line,
569 line_offsets[comp_num], num_bits[comp_num], is_signed[comp_num],
570 comp_width, nlt_ptr[comp_num]);
571 }
572 }
573
574 return true;
575 }
576
577
580 {
581 this->num_bytes = 0;
582 //prepare precinct headers
583 for (ui32 c = 0; c < num_comps; ++c)
584 num_bytes += comps[c].prepare_precincts();
585 }
586
589 {
591 tlm->set_next_pair(sot.get_tile_index(), this->num_bytes);
592 }
594 {
596 ui32 max_decs = 0;
597 for (ui32 c = 0; c < num_comps; ++c)
598 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
599 for (ui32 r = 0; r <= max_decs; ++r)
600 {
601 ui32 bytes = 0;
602 for (ui32 c = 0; c < num_comps; ++c)
603 bytes += comps[c].get_num_bytes(r);
604 tlm->set_next_pair(sot.get_tile_index(), bytes);
605 }
606 }
608 {
610 {
611 ui32 max_decs = 0;
612 for (ui32 c = 0; c < num_comps; ++c)
613 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
614 for (ui32 r = 0; r <= max_decs; ++r)
615 for (ui32 c = 0; c < num_comps; ++c)
616 if (r <= comps[c].get_num_decompositions())
618 comps[c].get_num_bytes(r));
619 }
620 else if (prog_order == OJPH_PO_CPRL)
621 for (ui32 c = 0; c < num_comps; ++c)
623 else
624 assert(0); // should not be here
625 }
626 else
627 {
629 ui32 max_decs = 0;
630 for (ui32 c = 0; c < num_comps; ++c)
631 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
632 for (ui32 r = 0; r <= max_decs; ++r)
633 for (ui32 c = 0; c < num_comps; ++c)
634 if (r <= comps[c].get_num_decompositions())
636 comps[c].get_num_bytes(r));
637 }
638 }
639
640
643 {
644 ui32 max_decompositions = 0;
645 for (ui32 c = 0; c < num_comps; ++c)
646 max_decompositions = ojph_max(max_decompositions,
647 comps[c].get_num_decompositions());
648
650 {
651 //write tile header
652 if (!sot.write(file, this->num_bytes))
653 OJPH_ERROR(0x00030081, "Error writing to file");
654
655 //write start of data
656 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOD);
657 if (!file->write(&t, 2))
658 OJPH_ERROR(0x00030082, "Error writing to file");
659 }
660
661
662 //sequence the writing of precincts according to progression order
664 {
666 {
667 for (ui32 r = 0; r <= max_decompositions; ++r)
668 for (ui32 c = 0; c < num_comps; ++c)
669 comps[c].write_precincts(r, file);
670 }
672 {
673 for (ui32 r = 0; r <= max_decompositions; ++r)
674 {
675 ui32 bytes = 0;
676 for (ui32 c = 0; c < num_comps; ++c)
677 bytes += comps[c].get_num_bytes(r);
678
679 //write tile header
680 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
681 OJPH_ERROR(0x00030083, "Error writing to file");
682
683 //write start of data
684 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOD);
685 if (!file->write(&t, 2))
686 OJPH_ERROR(0x00030084, "Error writing to file");
687
688 //write precincts
689 for (ui32 c = 0; c < num_comps; ++c)
690 comps[c].write_precincts(r, file);
691 }
692 }
693 else
694 {
695 ui32 num_tileparts = num_comps * (max_decompositions + 1);
696 for (ui32 r = 0; r <= max_decompositions; ++r)
697 for (ui32 c = 0; c < num_comps; ++c)
698 if (r <= comps[c].get_num_decompositions()) {
699 //write tile header
700 if (!sot.write(file, comps[c].get_num_bytes(r),
701 (ui8)(c + r * num_comps), (ui8)num_tileparts))
702 OJPH_ERROR(0x00030085, "Error writing to file");
703 //write start of data
704 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOD);
705 if (!file->write(&t, 2))
706 OJPH_ERROR(0x00030086, "Error writing to file");
707 comps[c].write_precincts(r, file);
708 }
709 }
710 }
711 else if (prog_order == OJPH_PO_RPCL)
712 {
713 for (ui32 r = 0; r <= max_decompositions; ++r)
714 {
716 {
717 ui32 bytes = 0;
718 for (ui32 c = 0; c < num_comps; ++c)
719 bytes += comps[c].get_num_bytes(r);
720 //write tile header
721 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
722 OJPH_ERROR(0x00030087, "Error writing to file");
723
724 //write start of data
725 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOD);
726 if (!file->write(&t, 2))
727 OJPH_ERROR(0x00030088, "Error writing to file");
728 }
729 while (true)
730 {
731 bool found = false;
732 ui32 comp_num = 0;
733 point smallest(INT_MAX, INT_MAX), cur;
734 for (ui32 c = 0; c < num_comps; ++c)
735 {
736 if (!comps[c].get_top_left_precinct(r, cur))
737 continue;
738 else
739 found = true;
740
741 if (cur.y < smallest.y)
742 { smallest = cur; comp_num = c; }
743 else if (cur.y == smallest.y && cur.x < smallest.x)
744 { smallest = cur; comp_num = c; }
745 }
746 if (found == true)
747 comps[comp_num].write_one_precinct(r, file);
748 else
749 break;
750 }
751 }
752 }
753 else if (prog_order == OJPH_PO_PCRL)
754 {
755 while (true)
756 {
757 bool found = false;
758 ui32 comp_num = 0;
759 ui32 res_num = 0;
760 point smallest(INT_MAX, INT_MAX), cur;
761 for (ui32 c = 0; c < num_comps; ++c)
762 {
763 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
764 {
765 if (!comps[c].get_top_left_precinct(r, cur))
766 continue;
767 else
768 found = true;
769
770 if (cur.y < smallest.y)
771 { smallest = cur; comp_num = c; res_num = r; }
772 else if (cur.y == smallest.y && cur.x < smallest.x)
773 { smallest = cur; comp_num = c; res_num = r; }
774 else if (cur.y == smallest.y && cur.x == smallest.x &&
775 c < comp_num)
776 { smallest = cur; comp_num = c; res_num = r; }
777 else if (cur.y == smallest.y && cur.x == smallest.x &&
778 c == comp_num && r < res_num)
779 { smallest = cur; comp_num = c; res_num = r; }
780 }
781 }
782 if (found == true)
783 comps[comp_num].write_one_precinct(res_num, file);
784 else
785 break;
786 }
787 }
788 else if (prog_order == OJPH_PO_CPRL)
789 {
790 for (ui32 c = 0; c < num_comps; ++c)
791 {
793 {
794 ui32 bytes = comps[c].get_num_bytes();
795 //write tile header
796 if (!sot.write(file, bytes, (ui8)c, (ui8)num_comps))
797 OJPH_ERROR(0x0003008A, "Error writing to file");
798
799 //write start of data
800 ui16 t = swap_bytes_if_le((ui16)JP2K_MARKER::SOD);
801 if (!file->write(&t, 2))
802 OJPH_ERROR(0x0003008B, "Error writing to file");
803 }
804
805 while (true)
806 {
807 bool found = false;
808 ui32 res_num = 0;
809 point smallest(INT_MAX, INT_MAX), cur;
810 for (ui32 r = 0; r <= max_decompositions; ++r)
811 {
812 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
813 continue;
814 else
815 found = true;
816
817 if (cur.y < smallest.y)
818 { smallest = cur; res_num = r; }
819 else if (cur.y == smallest.y && cur.x < smallest.x)
820 { smallest = cur; res_num = r; }
821 }
822 if (found == true)
823 comps[c].write_one_precinct(res_num, file);
824 else
825 break;
826 }
827 }
828 }
829 else
830 assert(0);
831
832 }
833
836 const ui64& tile_start_location)
837 {
839 {
840 if (resilient)
841 OJPH_INFO(0x00030091, "wrong tile part index")
842 else
843 OJPH_ERROR(0x00030091, "wrong tile part index")
844 }
846
847 //tile_end_location used on failure
848 ui64 tile_end_location = tile_start_location + sot.get_payload_length();
849
850 ui32 data_left = sot.get_payload_length(); //bytes left to parse
851 data_left -= (ui32)((ui64)file->tell() - tile_start_location);
852
853 if (data_left == 0)
854 return;
855
856 ui32 max_decompositions = 0;
857 for (ui32 c = 0; c < num_comps; ++c)
858 max_decompositions = ojph_max(max_decompositions,
859 comps[c].get_num_decompositions());
860
861 try
862 {
863 //sequence the reading of precincts according to progression order
865 {
866 max_decompositions -= skipped_res_for_read;
867 for (ui32 r = 0; r <= max_decompositions; ++r)
868 for (ui32 c = 0; c < num_comps; ++c)
869 if (data_left > 0)
870 comps[c].parse_precincts(r, data_left, file);
871 }
872 else if (prog_order == OJPH_PO_RPCL)
873 {
874 max_decompositions -= skipped_res_for_read;
875 for (ui32 r = 0; r <= max_decompositions; ++r)
876 {
877 while (true)
878 {
879 bool found = false;
880 ui32 comp_num = 0;
881 point smallest(INT_MAX, INT_MAX), cur;
882 for (ui32 c = 0; c < num_comps; ++c)
883 {
884 if (!comps[c].get_top_left_precinct(r, cur))
885 continue;
886 else
887 found = true;
888
889 if (cur.y < smallest.y)
890 { smallest = cur; comp_num = c; }
891 else if (cur.y == smallest.y && cur.x < smallest.x)
892 { smallest = cur; comp_num = c; }
893 }
894 if (found == true && data_left > 0)
895 comps[comp_num].parse_one_precinct(r, data_left, file);
896 else
897 break;
898 }
899 }
900 }
901 else if (prog_order == OJPH_PO_PCRL)
902 {
903 while (true)
904 {
905 bool found = false;
906 ui32 comp_num = 0;
907 ui32 res_num = 0;
908 point smallest(INT_MAX, INT_MAX), cur;
909 for (ui32 c = 0; c < num_comps; ++c)
910 {
911 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
912 {
913 if (!comps[c].get_top_left_precinct(r, cur))
914 continue;
915 else
916 found = true;
917
918 if (cur.y < smallest.y)
919 { smallest = cur; comp_num = c; res_num = r; }
920 else if (cur.y == smallest.y && cur.x < smallest.x)
921 { smallest = cur; comp_num = c; res_num = r; }
922 else if (cur.y == smallest.y && cur.x == smallest.x &&
923 c < comp_num)
924 { smallest = cur; comp_num = c; res_num = r; }
925 else if (cur.y == smallest.y && cur.x == smallest.x &&
926 c == comp_num && r < res_num)
927 { smallest = cur; comp_num = c; res_num = r; }
928 }
929 }
930 if (found == true && data_left > 0)
931 comps[comp_num].parse_one_precinct(res_num, data_left, file);
932 else
933 break;
934 }
935 }
936 else if (prog_order == OJPH_PO_CPRL)
937 {
938 for (ui32 c = 0; c < num_comps; ++c)
939 {
940 while (true)
941 {
942 bool found = false;
943 ui32 res_num = 0;
944 point smallest(INT_MAX, INT_MAX), cur;
945 for (ui32 r = 0; r <= max_decompositions; ++r)
946 {
947 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
948 continue;
949 else
950 found = true;
951
952 if (cur.y < smallest.y)
953 { smallest = cur; res_num = r; }
954 else if (cur.y == smallest.y && cur.x < smallest.x)
955 { smallest = cur; res_num = r; }
956 }
957 if (found == true && data_left > 0)
958 comps[c].parse_one_precinct(res_num, data_left, file);
959 else
960 break;
961 }
962 }
963 }
964 else
965 assert(0);
966
967 }
968 catch (const char *error)
969 {
970 if (resilient)
971 OJPH_INFO(0x00030092, "%s", error)
972 else
973 OJPH_ERROR(0x00030092, "%s", error)
974 }
975 // The decode path is meant to throw const char* only, but a nested
976 // OJPH_ERROR throws std::runtime_error and the allocators can throw
977 // std::bad_alloc. These two handlers make sure such throws are also
978 // subject to the resilience setting, instead of unwinding past
979 // parse_tile_header. In the non-resilient case the throw is passed on
980 // unchanged, because it has already been reported at its origin.
981 catch (const std::exception& error)
982 {
983 if (resilient)
984 OJPH_INFO(0x00030093, "%s", error.what())
985 else
986 throw;
987 }
988 catch (...)
989 {
990 if (resilient)
991 OJPH_INFO(0x00030094, "unknown error while parsing a tile header")
992 else
993 throw;
994 }
995 file->seek((si64)tile_end_location, infile_base::OJPH_SEEK_SET);
996 }
997
998 }
999}
virtual si64 tell()=0
const param_cod * get_coc(ui32 comp_num)
mem_fixed_allocator * get_allocator()
void write_one_precinct(ui32 res_num, outfile_base *file)
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, const rect &recon_comp_rect)
void parse_one_precinct(ui32 res_num, ui32 &data_left, infile_base *file)
void write_precincts(ui32 res_num, outfile_base *file)
void parse_precincts(ui32 res_num, ui32 &data_left, infile_base *file)
bool pull(line_buf *, ui32 comp_num)
line_buf * lines
Definition ojph_tile.h:83
void finalize_alloc(codestream *codestream, const rect &tile_rect, ui32 tile_idx, ui32 &offset, ui32 &num_tileparts)
static void pre_alloc(codestream *codestream, const rect &tile_rect, const rect &recon_tile_rect, ui32 &num_tileparts)
Definition ojph_tile.cpp:57
tile_comp * comps
Definition ojph_tile.h:81
void fill_tlm(param_tlm *tlm)
rect * recon_comp_rects
Definition ojph_tile.h:86
void flush(outfile_base *file)
ui32 skipped_res_for_read
Definition ojph_tile.h:88
param_sot sot
Definition ojph_tile.h:97
bool push(line_buf *line, ui32 comp_num)
const nlt_rec ** nlt_ptr
Definition ojph_tile.h:93
bool employ_color_transform
Definition ojph_tile.h:84
void parse_tile_header(const param_sot &sot, infile_base *file, const ui64 &tile_start_location)
ui32 * line_offsets
Definition ojph_tile.h:87
void pre_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:72
void pre_alloc_obj(size_t num_ele)
Definition ojph_mem.h:78
T * post_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:112
T * post_alloc_obj(size_t num_ele)
Definition ojph_mem.h:119
virtual size_t write(const void *ptr, size_t size)=0
int get_progression_order() const
@ OJPH_NLT_BINARY_COMPLEMENT_NLT
@ OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT
void(*) ict_forward(const float *r, const float *g, const float *b, float *y, float *cb, float *cr, ui32 repeat)
void(*) rev_decode_nlt(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, const ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void(*) irv_convert_to_float_nlt_type3(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width)
void(*) irv_convert_to_integer_nlt_type3(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width)
void(*) rev_convert_nlt_type3(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, const ui32 dst_line_offset, si64 shift, ui32 width)
void(*) irv_convert_to_float_nlt(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void(*) rct_forward(const line_buf *r, const line_buf *g, const line_buf *b, line_buf *y, line_buf *cb, line_buf *cr, ui32 repeat)
void(*) irv_convert_to_integer_nlt(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void(*) irv_convert_to_integer(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width)
void(*) rev_convert(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, const ui32 dst_line_offset, si64 shift, ui32 width)
void(*) rev_encode_nlt(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void(*) irv_convert_to_float(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width)
void(*) ict_backward(const float *y, const float *cb, const float *cr, float *r, float *g, float *b, ui32 repeat)
void(*) rct_backward(const line_buf *r, const line_buf *g, const line_buf *b, line_buf *y, line_buf *cb, line_buf *cr, ui32 repeat)
int64_t si64
Definition ojph_defs.h:57
uint64_t ui64
Definition ojph_defs.h:56
uint16_t ui16
Definition ojph_defs.h:52
@ OJPH_TILEPART_RESOLUTIONS
@ OJPH_TILEPART_NO_DIVISIONS
@ OJPH_TILEPART_COMPONENTS
int32_t si32
Definition ojph_defs.h:55
message_error error
uint32_t ui32
Definition ojph_defs.h:54
uint8_t ui8
Definition ojph_defs.h:50
#define ojph_max(a, b)
Definition ojph_defs.h:73
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
#define OJPH_INFO(t,...)
MACROs to insert file and line number for info, warning, and error.
#define OJPH_ERROR(t,...)
bool is_employing_color_transform() const
const nlt_rec * get_nlt_rec(ui32 comp_num) const
ui32 get_bit_depth(ui32 comp_num) const
bool is_signed(ui32 comp_num) const
point get_recon_downsampling(ui32 comp_num) const
point get_downsampling(ui32 comp_num) const
void init(ui32 payload_length=0, ui16 tile_idx=0, ui8 tile_part_index=0, ui8 num_tile_parts=0)
bool write(outfile_base *file, ui32 payload_len)
void set_next_pair(ui16 Ttlm, ui32 Ptlm)
point org
Definition ojph_base.h:66