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