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
42#include "ojph_mem.h"
43#include "ojph_params.h"
45#include "ojph_tile.h"
46#include "ojph_tile_comp.h"
47
49
50namespace ojph {
51
52 namespace local
53 {
54
56 void tile::pre_alloc(codestream *codestream, const rect& tile_rect,
57 const rect& recon_tile_rect, ui32& num_tileparts)
58 {
60
61 //allocate tiles_comp
62 const param_siz *szp = codestream->get_siz();
65 allocator->pre_alloc_obj<rect>(num_comps); //for comp_rects
66 allocator->pre_alloc_obj<rect>(num_comps); //for recon_comp_rects
67 allocator->pre_alloc_obj<ui32>(num_comps); //for line_offsets
68 allocator->pre_alloc_obj<ui32>(num_comps); //for num_bits
69 allocator->pre_alloc_obj<bool>(num_comps); //for is_signed
70 allocator->pre_alloc_obj<bool>(num_comps); //for reversible
71 allocator->pre_alloc_obj<ui8>(num_comps); //for nlt_type3
72 allocator->pre_alloc_obj<ui32>(num_comps); //for cur_line
73
74 {
78 num_tileparts = 1; //for num_rc_bytes
79 else if (t == OJPH_TILEPART_COMPONENTS)
80 num_tileparts = num_comps;
81 else if (t == OJPH_TILEPART_RESOLUTIONS)
82 {
83 ui32 max_decs = 0;
84 for (ui32 c = 0; c < num_comps; ++c) {
86 max_decs = ojph_max(max_decs, s);
87 }
88 num_tileparts = 1 + max_decs;
89 }
91 {
92 num_tileparts = 0;
93 for (ui32 c = 0; c < num_comps; ++c) {
95 num_tileparts += s + 1;
96 }
97 }
98 if (num_tileparts > 255)
99 OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
100 "cannot have more than 255 tile parts.", num_tileparts);
101 }
102
103 ui32 tx0 = tile_rect.org.x;
104 ui32 ty0 = tile_rect.org.y;
105 ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
106 ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
107 ui32 recon_tx0 = recon_tile_rect.org.x;
108 ui32 recon_ty0 = recon_tile_rect.org.y;
109 ui32 recon_tx1 = recon_tile_rect.org.x + recon_tile_rect.siz.w;
110 ui32 recon_ty1 = recon_tile_rect.org.y + recon_tile_rect.siz.h;
111
112 ui32 width = 0;
113 for (ui32 i = 0; i < num_comps; ++i)
114 {
115 point downsamp = szp->get_downsampling(i);
116
117 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
118 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
119 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
120 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
121 ui32 recon_tcx0 = ojph_div_ceil(recon_tx0, downsamp.x);
122 ui32 recon_tcy0 = ojph_div_ceil(recon_ty0, downsamp.y);
123 ui32 recon_tcx1 = ojph_div_ceil(recon_tx1, downsamp.x);
124 ui32 recon_tcy1 = ojph_div_ceil(recon_ty1, downsamp.y);
125
126 rect comp_rect;
127 comp_rect.org.x = tcx0;
128 comp_rect.org.y = tcy0;
129 comp_rect.siz.w = tcx1 - tcx0;
130 comp_rect.siz.h = tcy1 - tcy0;
131
132 rect recon_comp_rect;
133 recon_comp_rect.org.x = recon_tcx0;
134 recon_comp_rect.org.y = recon_tcy0;
135 recon_comp_rect.siz.w = recon_tcx1 - recon_tcx0;
136 recon_comp_rect.siz.h = recon_tcy1 - recon_tcy0;
137
138 tile_comp::pre_alloc(codestream, i, comp_rect, recon_comp_rect);
139 width = ojph_max(width, recon_comp_rect.siz.w);
140 }
141
142 //allocate lines
143 const param_cod* cdp = codestream->get_cod();
145 {
146 bool reversible[3];
147 for (ui32 i = 0; i < 3; ++i)
149 if (reversible[0] != reversible[1] || reversible[1] != reversible[2])
150 OJPH_ERROR(0x000300A2, "When the colour transform is employed. "
151 "all colour components must undergo either reversible or "
152 "irreversible wavelet transform; if not, then it is not clear "
153 "what colour transform should be used (reversible or "
154 "irreversible). Here we found that the first three colour "
155 "components uses %s, %s, and %s transforms, respectively.",
156 reversible[0] ? "reversible" : "irreversible",
157 reversible[1] ? "reversible" : "irreversible",
158 reversible[2] ? "reversible" : "irreversible");
159
160 allocator->pre_alloc_obj<line_buf>(3);
161 if (reversible[0])
162 for (int i = 0; i < 3; ++i)
163 allocator->pre_alloc_data<si32>(width, 0);
164 else
165 for (int i = 0; i < 3; ++i)
166 allocator->pre_alloc_data<float>(width, 0);
167 }
168 }
169
172 ui32 tile_idx, ui32& offset,
173 ui32 &num_tileparts)
174 {
175 //this->parent = codestream;
177
178 sot.init(0, (ui16)tile_idx, 0, 1);
180
181 //allocate tiles_comp
182 const param_siz *szp = codestream->get_siz();
183 const param_nlt *nlp = codestream->get_nlt();
184
185 this->num_bytes = 0;
192 num_bits = allocator->post_alloc_obj<ui32>(num_comps);
193 is_signed = allocator->post_alloc_obj<bool>(num_comps);
194 reversible = allocator->post_alloc_obj<bool>(num_comps);
195 nlt_type3 = allocator->post_alloc_obj<ui8>(num_comps);
196 cur_line = allocator->post_alloc_obj<ui32>(num_comps);
197
201 {
205 num_tileparts = 1; //for num_rc_bytes
206 else if (t == OJPH_TILEPART_COMPONENTS)
207 num_tileparts = num_comps;
208 else if (t == OJPH_TILEPART_RESOLUTIONS)
209 {
210 ui32 max_decs = 0;
211 for (ui32 c = 0; c < num_comps; ++c) {
213 max_decs = ojph_max(max_decs, s);
214 }
215 num_tileparts = 1 + max_decs;
216 }
218 {
219 num_tileparts = 0;
220 for (ui32 c = 0; c < num_comps; ++c) {
222 num_tileparts += s + 1;
223 }
224 }
225 if (num_tileparts > 255)
226 OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
227 "cannot have more than 255 tile parts.", num_tileparts);
228 }
229
230 this->resilient = codestream->is_resilient();
231 this->tile_rect = tile_rect;
232
233 ui32 tx0 = tile_rect.org.x;
234 ui32 ty0 = tile_rect.org.y;
235 ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
236 ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
237
238 ui32 width = 0;
239 for (ui32 i = 0; i < num_comps; ++i)
240 {
241 ui8 bd; bool is; // used for nlt_type3
242
243 point downsamp = szp->get_downsampling(i);
244 point recon_downsamp = szp->get_recon_downsampling(i);
245
246 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
247 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
248 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
249 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
250 ui32 recon_tcx0 = ojph_div_ceil(tx0, recon_downsamp.x);
251 ui32 recon_tcy0 = ojph_div_ceil(ty0, recon_downsamp.y);
252 ui32 recon_tcx1 = ojph_div_ceil(tx1, recon_downsamp.x);
253 ui32 recon_tcy1 = ojph_div_ceil(ty1, recon_downsamp.y);
254
255 line_offsets[i] =
256 recon_tcx0 - ojph_div_ceil(tx0 - offset, recon_downsamp.x);
257 comp_rects[i].org.x = tcx0;
258 comp_rects[i].org.y = tcy0;
259 comp_rects[i].siz.w = tcx1 - tcx0;
260 comp_rects[i].siz.h = tcy1 - tcy0;
261 recon_comp_rects[i].org.x = recon_tcx0;
262 recon_comp_rects[i].org.y = recon_tcy0;
263 recon_comp_rects[i].siz.w = recon_tcx1 - recon_tcx0;
264 recon_comp_rects[i].siz.h = recon_tcy1 - recon_tcy0;
265
266 comps[i].finalize_alloc(codestream, this, i, comp_rects[i],
268 width = ojph_max(width, recon_comp_rects[i].siz.w);
269
270 num_bits[i] = szp->get_bit_depth(i);
271 is_signed[i] = szp->is_signed(i);
272 bool result = nlp->get_nonlinear_transform(i, bd, is, nlt_type3[i]);
273 if (result == true && (bd != num_bits[i] || is != is_signed[i]))
274 OJPH_ERROR(0x000300A1, "Mismatch between Ssiz (bit_depth = %d, "
275 "is_signed = %s) from SIZ marker segment, and BDnlt "
276 "(bit_depth = %d, is_signed = %s) from NLT marker segment, "
277 "for component %d", i, num_bits[i],
278 is_signed[i] ? "True" : "False", bd, is ? "True" : "False");
279 cur_line[i] = 0;
281 }
282
283 offset += tile_rect.siz.w;
284
285 //allocate lines
286 const param_cod* cdp = codestream->get_cod();
288 if (this->employ_color_transform)
289 {
290 num_lines = 3;
291 lines = allocator->post_alloc_obj<line_buf>(num_lines);
292 if (reversible[0])
293 for (int i = 0; i < 3; ++i)
294 lines[i].wrap(
295 allocator->post_alloc_data<si32>(width, 0), width, 0);
296 else
297 for (int i = 0; i < 3; ++i)
298 lines[i].wrap(
299 allocator->post_alloc_data<float>(width, 0), width, 0);
300 }
301 else
302 {
303 lines = NULL;
304 num_lines = 0;
305 }
306 next_tile_part = 0;
307 }
308
310 bool tile::push(line_buf *line, ui32 comp_num)
311 {
312 constexpr ui8 type3 =
314
315 assert(comp_num < num_comps);
316 if (cur_line[comp_num] >= comp_rects[comp_num].siz.h)
317 return false;
318 cur_line[comp_num]++;
319
320 //converts to signed representation
321 //employs color transform if there is a need
322 if (!employ_color_transform || comp_num >= 3)
323 {
324 assert(comp_num < num_comps);
325 ui32 comp_width = comp_rects[comp_num].siz.w;
326 line_buf *tc = comps[comp_num].get_line();
327 if (reversible[comp_num])
328 {
329 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
330 if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
331 rev_convert_nlt_type3(line, line_offsets[comp_num],
332 tc, 0, shift + 1, comp_width);
333 else {
334 shift = is_signed[comp_num] ? 0 : -shift;
335 rev_convert(line, line_offsets[comp_num], tc, 0,
336 shift, comp_width);
337 }
338 }
339 else
340 {
341 if (nlt_type3[comp_num] == type3)
343 tc, num_bits[comp_num], is_signed[comp_num], comp_width);
344 else
345 irv_convert_to_float(line, line_offsets[comp_num],
346 tc, num_bits[comp_num], is_signed[comp_num], comp_width);
347 }
348 comps[comp_num].push_line();
349 }
350 else
351 {
352 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
353 ui32 comp_width = comp_rects[comp_num].siz.w;
354 if (reversible[comp_num])
355 {
356 if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
357 rev_convert_nlt_type3(line, line_offsets[comp_num],
358 lines + comp_num, 0, shift + 1, comp_width);
359 else {
360 shift = is_signed[comp_num] ? 0 : -shift;
361 rev_convert(line, line_offsets[comp_num], lines + comp_num, 0,
362 shift, comp_width);
363 }
364
365 if (comp_num == 2)
366 { // reversible color transform
367 rct_forward(lines + 0, lines + 1, lines + 2,
368 comps[0].get_line(),
369 comps[1].get_line(),
370 comps[2].get_line(), comp_width);
371 comps[0].push_line();
372 comps[1].push_line();
373 comps[2].push_line();
374 }
375 }
376 else
377 {
378 if (nlt_type3[comp_num] == type3)
380 lines + comp_num, num_bits[comp_num], is_signed[comp_num],
381 comp_width);
382 else
383 irv_convert_to_float(line, line_offsets[comp_num],
384 lines + comp_num, num_bits[comp_num], is_signed[comp_num],
385 comp_width);
386 if (comp_num == 2)
387 { // irreversible color transform
388 ict_forward(lines[0].f32, lines[1].f32, lines[2].f32,
389 comps[0].get_line()->f32,
390 comps[1].get_line()->f32,
391 comps[2].get_line()->f32, comp_width);
392 comps[0].push_line();
393 comps[1].push_line();
394 comps[2].push_line();
395 }
396 }
397 }
398
399 return true;
400 }
401
403 bool tile::pull(line_buf* tgt_line, ui32 comp_num)
404 {
405 constexpr ui8 type3 =
407
408 assert(comp_num < num_comps);
409 if (cur_line[comp_num] >= recon_comp_rects[comp_num].siz.h)
410 return false;
411
412 cur_line[comp_num]++;
413
415 {
416 line_buf *src_line = comps[comp_num].pull_line();
417 ui32 comp_width = recon_comp_rects[comp_num].siz.w;
418 if (reversible[comp_num])
419 {
420 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
421 if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
422 rev_convert_nlt_type3(src_line, 0, tgt_line,
423 line_offsets[comp_num], shift + 1, comp_width);
424 else {
425 shift = is_signed[comp_num] ? 0 : shift;
426 rev_convert(src_line, 0, tgt_line,
427 line_offsets[comp_num], shift, comp_width);
428 }
429 }
430 else
431 {
432 if (nlt_type3[comp_num] == type3)
433 irv_convert_to_integer_nlt_type3(src_line, tgt_line,
434 line_offsets[comp_num], num_bits[comp_num],
435 is_signed[comp_num], comp_width);
436 else
437 irv_convert_to_integer(src_line, tgt_line,
438 line_offsets[comp_num], num_bits[comp_num],
439 is_signed[comp_num], comp_width);
440 }
441 }
442 else
443 {
444 assert(num_comps >= 3);
445 ui32 comp_width = recon_comp_rects[comp_num].siz.w;
446 if (comp_num == 0)
447 {
448 if (reversible[comp_num])
449 rct_backward(comps[0].pull_line(), comps[1].pull_line(),
450 comps[2].pull_line(), lines + 0, lines + 1,
451 lines + 2, comp_width);
452 else
453 ict_backward(comps[0].pull_line()->f32, comps[1].pull_line()->f32,
454 comps[2].pull_line()->f32, lines[0].f32, lines[1].f32,
455 lines[2].f32, comp_width);
456 }
457 if (reversible[comp_num])
458 {
459 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
460 line_buf* src_line;
461 if (comp_num < 3)
462 src_line = lines + comp_num;
463 else
464 src_line = comps[comp_num].pull_line();
465 if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
466 rev_convert_nlt_type3(src_line, 0, tgt_line,
467 line_offsets[comp_num], shift + 1, comp_width);
468 else {
469 shift = is_signed[comp_num] ? 0 : shift;
470 rev_convert(src_line, 0, tgt_line,
471 line_offsets[comp_num], shift, comp_width);
472 }
473 }
474 else
475 {
476 line_buf* lbp;
477 if (comp_num < 3)
478 lbp = lines + comp_num;
479 else
480 lbp = comps[comp_num].pull_line();
481 if (nlt_type3[comp_num] == type3)
483 line_offsets[comp_num], num_bits[comp_num],
484 is_signed[comp_num], comp_width);
485 else
486 irv_convert_to_integer(lbp, tgt_line,
487 line_offsets[comp_num], num_bits[comp_num],
488 is_signed[comp_num], comp_width);
489 }
490 }
491
492 return true;
493 }
494
495
498 {
499 this->num_bytes = 0;
500 //prepare precinct headers
501 for (ui32 c = 0; c < num_comps; ++c)
502 num_bytes += comps[c].prepare_precincts();
503 }
504
507 {
509 tlm->set_next_pair(sot.get_tile_index(), this->num_bytes);
510 }
512 {
514 ui32 max_decs = 0;
515 for (ui32 c = 0; c < num_comps; ++c)
516 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
517 for (ui32 r = 0; r <= max_decs; ++r)
518 {
519 ui32 bytes = 0;
520 for (ui32 c = 0; c < num_comps; ++c)
521 bytes += comps[c].get_num_bytes(r);
522 tlm->set_next_pair(sot.get_tile_index(), bytes);
523 }
524 }
526 {
528 {
529 ui32 max_decs = 0;
530 for (ui32 c = 0; c < num_comps; ++c)
531 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
532 for (ui32 r = 0; r <= max_decs; ++r)
533 for (ui32 c = 0; c < num_comps; ++c)
534 if (r <= comps[c].get_num_decompositions())
536 comps[c].get_num_bytes(r));
537 }
538 else if (prog_order == OJPH_PO_CPRL)
539 for (ui32 c = 0; c < num_comps; ++c)
541 else
542 assert(0); // should not be here
543 }
544 else
545 {
547 ui32 max_decs = 0;
548 for (ui32 c = 0; c < num_comps; ++c)
549 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
550 for (ui32 r = 0; r <= max_decs; ++r)
551 for (ui32 c = 0; c < num_comps; ++c)
552 if (r <= comps[c].get_num_decompositions())
554 comps[c].get_num_bytes(r));
555 }
556 }
557
558
561 {
562 ui32 max_decompositions = 0;
563 for (ui32 c = 0; c < num_comps; ++c)
564 max_decompositions = ojph_max(max_decompositions,
565 comps[c].get_num_decompositions());
566
568 {
569 //write tile header
570 if (!sot.write(file, this->num_bytes))
571 OJPH_ERROR(0x00030081, "Error writing to file");
572
573 //write start of data
575 if (!file->write(&t, 2))
576 OJPH_ERROR(0x00030082, "Error writing to file");
577 }
578
579
580 //sequence the writing of precincts according to progression order
582 {
584 {
585 for (ui32 r = 0; r <= max_decompositions; ++r)
586 for (ui32 c = 0; c < num_comps; ++c)
587 comps[c].write_precincts(r, file);
588 }
590 {
591 for (ui32 r = 0; r <= max_decompositions; ++r)
592 {
593 ui32 bytes = 0;
594 for (ui32 c = 0; c < num_comps; ++c)
595 bytes += comps[c].get_num_bytes(r);
596
597 //write tile header
598 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
599 OJPH_ERROR(0x00030083, "Error writing to file");
600
601 //write start of data
603 if (!file->write(&t, 2))
604 OJPH_ERROR(0x00030084, "Error writing to file");
605
606 //write precincts
607 for (ui32 c = 0; c < num_comps; ++c)
608 comps[c].write_precincts(r, file);
609 }
610 }
611 else
612 {
613 ui32 num_tileparts = num_comps * (max_decompositions + 1);
614 for (ui32 r = 0; r <= max_decompositions; ++r)
615 for (ui32 c = 0; c < num_comps; ++c)
616 if (r <= comps[c].get_num_decompositions()) {
617 //write tile header
618 if (!sot.write(file, comps[c].get_num_bytes(r),
619 (ui8)(c + r * num_comps), (ui8)num_tileparts))
620 OJPH_ERROR(0x00030085, "Error writing to file");
621 //write start of data
623 if (!file->write(&t, 2))
624 OJPH_ERROR(0x00030086, "Error writing to file");
625 comps[c].write_precincts(r, file);
626 }
627 }
628 }
629 else if (prog_order == OJPH_PO_RPCL)
630 {
631 for (ui32 r = 0; r <= max_decompositions; ++r)
632 {
634 {
635 ui32 bytes = 0;
636 for (ui32 c = 0; c < num_comps; ++c)
637 bytes += comps[c].get_num_bytes(r);
638 //write tile header
639 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
640 OJPH_ERROR(0x00030087, "Error writing to file");
641
642 //write start of data
644 if (!file->write(&t, 2))
645 OJPH_ERROR(0x00030088, "Error writing to file");
646 }
647 while (true)
648 {
649 bool found = false;
650 ui32 comp_num = 0;
651 point smallest(INT_MAX, INT_MAX), cur;
652 for (ui32 c = 0; c < num_comps; ++c)
653 {
654 if (!comps[c].get_top_left_precinct(r, cur))
655 continue;
656 else
657 found = true;
658
659 if (cur.y < smallest.y)
660 { smallest = cur; comp_num = c; }
661 else if (cur.y == smallest.y && cur.x < smallest.x)
662 { smallest = cur; comp_num = c; }
663 }
664 if (found == true)
665 comps[comp_num].write_one_precinct(r, file);
666 else
667 break;
668 }
669 }
670 }
671 else if (prog_order == OJPH_PO_PCRL)
672 {
673 while (true)
674 {
675 bool found = false;
676 ui32 comp_num = 0;
677 ui32 res_num = 0;
678 point smallest(INT_MAX, INT_MAX), cur;
679 for (ui32 c = 0; c < num_comps; ++c)
680 {
681 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
682 {
683 if (!comps[c].get_top_left_precinct(r, cur))
684 continue;
685 else
686 found = true;
687
688 if (cur.y < smallest.y)
689 { smallest = cur; comp_num = c; res_num = r; }
690 else if (cur.y == smallest.y && cur.x < smallest.x)
691 { smallest = cur; comp_num = c; res_num = r; }
692 else if (cur.y == smallest.y && cur.x == smallest.x &&
693 c < comp_num)
694 { smallest = cur; comp_num = c; res_num = r; }
695 else if (cur.y == smallest.y && cur.x == smallest.x &&
696 c == comp_num && r < res_num)
697 { smallest = cur; comp_num = c; res_num = r; }
698 }
699 }
700 if (found == true)
701 comps[comp_num].write_one_precinct(res_num, file);
702 else
703 break;
704 }
705 }
706 else if (prog_order == OJPH_PO_CPRL)
707 {
708 for (ui32 c = 0; c < num_comps; ++c)
709 {
711 {
712 ui32 bytes = comps[c].get_num_bytes();
713 //write tile header
714 if (!sot.write(file, bytes, (ui8)c, (ui8)num_comps))
715 OJPH_ERROR(0x0003008A, "Error writing to file");
716
717 //write start of data
719 if (!file->write(&t, 2))
720 OJPH_ERROR(0x0003008B, "Error writing to file");
721 }
722
723 while (true)
724 {
725 bool found = false;
726 ui32 res_num = 0;
727 point smallest(INT_MAX, INT_MAX), cur;
728 for (ui32 r = 0; r <= max_decompositions; ++r)
729 {
730 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
731 continue;
732 else
733 found = true;
734
735 if (cur.y < smallest.y)
736 { smallest = cur; res_num = r; }
737 else if (cur.y == smallest.y && cur.x < smallest.x)
738 { smallest = cur; res_num = r; }
739 }
740 if (found == true)
741 comps[c].write_one_precinct(res_num, file);
742 else
743 break;
744 }
745 }
746 }
747 else
748 assert(0);
749
750 }
751
754 const ui64& tile_start_location)
755 {
757 {
758 if (resilient)
759 OJPH_INFO(0x00030091, "wrong tile part index")
760 else
761 OJPH_ERROR(0x00030091, "wrong tile part index")
762 }
764
765 //tile_end_location used on failure
766 ui64 tile_end_location = tile_start_location + sot.get_payload_length();
767
768 ui32 data_left = sot.get_payload_length(); //bytes left to parse
769 data_left -= (ui32)((ui64)file->tell() - tile_start_location);
770
771 if (data_left == 0)
772 return;
773
774 ui32 max_decompositions = 0;
775 for (ui32 c = 0; c < num_comps; ++c)
776 max_decompositions = ojph_max(max_decompositions,
777 comps[c].get_num_decompositions());
778
779 try
780 {
781 //sequence the reading of precincts according to progression order
783 {
784 max_decompositions -= skipped_res_for_read;
785 for (ui32 r = 0; r <= max_decompositions; ++r)
786 for (ui32 c = 0; c < num_comps; ++c)
787 if (data_left > 0)
788 comps[c].parse_precincts(r, data_left, file);
789 }
790 else if (prog_order == OJPH_PO_RPCL)
791 {
792 max_decompositions -= skipped_res_for_read;
793 for (ui32 r = 0; r <= max_decompositions; ++r)
794 {
795 while (true)
796 {
797 bool found = false;
798 ui32 comp_num = 0;
799 point smallest(INT_MAX, INT_MAX), cur;
800 for (ui32 c = 0; c < num_comps; ++c)
801 {
802 if (!comps[c].get_top_left_precinct(r, cur))
803 continue;
804 else
805 found = true;
806
807 if (cur.y < smallest.y)
808 { smallest = cur; comp_num = c; }
809 else if (cur.y == smallest.y && cur.x < smallest.x)
810 { smallest = cur; comp_num = c; }
811 }
812 if (found == true && data_left > 0)
813 comps[comp_num].parse_one_precinct(r, data_left, file);
814 else
815 break;
816 }
817 }
818 }
819 else if (prog_order == OJPH_PO_PCRL)
820 {
821 while (true)
822 {
823 bool found = false;
824 ui32 comp_num = 0;
825 ui32 res_num = 0;
826 point smallest(INT_MAX, INT_MAX), cur;
827 for (ui32 c = 0; c < num_comps; ++c)
828 {
829 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
830 {
831 if (!comps[c].get_top_left_precinct(r, cur))
832 continue;
833 else
834 found = true;
835
836 if (cur.y < smallest.y)
837 { smallest = cur; comp_num = c; res_num = r; }
838 else if (cur.y == smallest.y && cur.x < smallest.x)
839 { smallest = cur; comp_num = c; res_num = r; }
840 else if (cur.y == smallest.y && cur.x == smallest.x &&
841 c < comp_num)
842 { smallest = cur; comp_num = c; res_num = r; }
843 else if (cur.y == smallest.y && cur.x == smallest.x &&
844 c == comp_num && r < res_num)
845 { smallest = cur; comp_num = c; res_num = r; }
846 }
847 }
848 if (found == true && data_left > 0)
849 comps[comp_num].parse_one_precinct(res_num, data_left, file);
850 else
851 break;
852 }
853 }
854 else if (prog_order == OJPH_PO_CPRL)
855 {
856 for (ui32 c = 0; c < num_comps; ++c)
857 {
858 while (true)
859 {
860 bool found = false;
861 ui32 res_num = 0;
862 point smallest(INT_MAX, INT_MAX), cur;
863 for (ui32 r = 0; r <= max_decompositions; ++r)
864 {
865 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
866 continue;
867 else
868 found = true;
869
870 if (cur.y < smallest.y)
871 { smallest = cur; res_num = r; }
872 else if (cur.y == smallest.y && cur.x < smallest.x)
873 { smallest = cur; res_num = r; }
874 }
875 if (found == true && data_left > 0)
876 comps[c].parse_one_precinct(res_num, data_left, file);
877 else
878 break;
879 }
880 }
881 }
882 else
883 assert(0);
884
885 }
886 catch (const char *error)
887 {
888 if (resilient)
889 OJPH_INFO(0x00030092, "%s", error)
890 else
891 OJPH_ERROR(0x00030092, "%s", error)
892 }
893 file->seek((si64)tile_end_location, infile_base::OJPH_SEEK_SET);
894 }
895
896 }
897}
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:56
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)
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: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
virtual size_t write(const void *ptr, size_t size)=0
int get_progression_order() const
@ OJPH_NLT_BINARY_COMPLEMENT_NLT
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(* ict_forward)(const float *r, const float *g, const float *b, float *y, float *cb, float *cr, ui32 repeat)
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(* 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)
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)
static ui16 swap_byte(ui16 t)
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(* 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(* 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)
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
bool get_nonlinear_transform(ui32 comp_num, ui8 &bit_depth, bool &is_signed, ui8 &nl_type) 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