OpenJPH
Open-source implementation of JPEG2000 Part-15
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
48#include "../transform/ojph_colour.h"
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 nlt_type3
71 allocator->pre_alloc_obj<ui32>(num_comps); //for cur_line
72
74 num_tileparts = 1; //for num_rc_bytes
75 // this code is not ideal, since the number of decompositions can be
76 // different for different components
78 num_tileparts *= num_comps;
80 num_tileparts *= codestream->get_cod()->get_num_decompositions() + 1;
81 if (num_tileparts > 255)
82 OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile cannot "
83 "have more than 255 tile parts.", num_tileparts);
84
85 ui32 tx0 = tile_rect.org.x;
86 ui32 ty0 = tile_rect.org.y;
89 ui32 recon_tx0 = recon_tile_rect.org.x;
90 ui32 recon_ty0 = recon_tile_rect.org.y;
91 ui32 recon_tx1 = recon_tile_rect.org.x + recon_tile_rect.siz.w;
92 ui32 recon_ty1 = recon_tile_rect.org.y + recon_tile_rect.siz.h;
93
94 ui32 width = 0;
95 for (ui32 i = 0; i < num_comps; ++i)
96 {
97 point downsamp = szp->get_downsampling(i);
98
99 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
100 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
101 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
102 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
103 ui32 recon_tcx0 = ojph_div_ceil(recon_tx0, downsamp.x);
104 ui32 recon_tcy0 = ojph_div_ceil(recon_ty0, downsamp.y);
105 ui32 recon_tcx1 = ojph_div_ceil(recon_tx1, downsamp.x);
106 ui32 recon_tcy1 = ojph_div_ceil(recon_ty1, downsamp.y);
107
108 rect comp_rect;
109 comp_rect.org.x = tcx0;
110 comp_rect.org.y = tcy0;
111 comp_rect.siz.w = tcx1 - tcx0;
112 comp_rect.siz.h = tcy1 - tcy0;
113
114 rect recon_comp_rect;
115 recon_comp_rect.org.x = recon_tcx0;
116 recon_comp_rect.org.y = recon_tcy0;
117 recon_comp_rect.siz.w = recon_tcx1 - recon_tcx0;
118 recon_comp_rect.siz.h = recon_tcy1 - recon_tcy0;
119
120 tile_comp::pre_alloc(codestream, i, comp_rect, recon_comp_rect);
121 width = ojph_max(width, recon_comp_rect.siz.w);
122 }
123
124 //allocate lines
126 {
127 allocator->pre_alloc_obj<line_buf>(3);
128 for (int i = 0; i < 3; ++i)
129 allocator->pre_alloc_data<si32>(width, 0);
130 }
131 }
132
135 ui32 tile_idx, ui32& offset,
136 ui32 &num_tileparts)
137 {
138 //this->parent = codestream;
140
141 sot.init(0, (ui16)tile_idx, 0, 1);
143
144 //allocate tiles_comp
145 const param_siz *szp = codestream->get_siz();
146 const param_nlt *nlp = codestream->get_nlt();
147
148 this->num_bytes = 0;
155 num_bits = allocator->post_alloc_obj<ui32>(num_comps);
156 is_signed = allocator->post_alloc_obj<bool>(num_comps);
157 nlt_type3 = allocator->post_alloc_obj<bool>(num_comps);
158 cur_line = allocator->post_alloc_obj<ui32>(num_comps);
159
163 num_tileparts = 1;
164 // this code is not ideal, since the number of decompositions can be
165 // different for different components
167 num_tileparts *= num_comps;
169 num_tileparts *= codestream->get_cod()->get_num_decompositions() + 1;
170
171 this->resilient = codestream->is_resilient();
172 this->tile_rect = tile_rect;
173
174 ui32 tx0 = tile_rect.org.x;
175 ui32 ty0 = tile_rect.org.y;
176 ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
177 ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
178
179 ui32 width = 0;
180 for (ui32 i = 0; i < num_comps; ++i)
181 {
182 ui8 bd; bool is; // used for nlt_type3
183
184 point downsamp = szp->get_downsampling(i);
185 point recon_downsamp = szp->get_recon_downsampling(i);
186
187 ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
188 ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
189 ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
190 ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
191 ui32 recon_tcx0 = ojph_div_ceil(tx0, recon_downsamp.x);
192 ui32 recon_tcy0 = ojph_div_ceil(ty0, recon_downsamp.y);
193 ui32 recon_tcx1 = ojph_div_ceil(tx1, recon_downsamp.x);
194 ui32 recon_tcy1 = ojph_div_ceil(ty1, recon_downsamp.y);
195
196 line_offsets[i] =
197 recon_tcx0 - ojph_div_ceil(tx0 - offset, recon_downsamp.x);
198 comp_rects[i].org.x = tcx0;
199 comp_rects[i].org.y = tcy0;
200 comp_rects[i].siz.w = tcx1 - tcx0;
201 comp_rects[i].siz.h = tcy1 - tcy0;
202 recon_comp_rects[i].org.x = recon_tcx0;
203 recon_comp_rects[i].org.y = recon_tcy0;
204 recon_comp_rects[i].siz.w = recon_tcx1 - recon_tcx0;
205 recon_comp_rects[i].siz.h = recon_tcy1 - recon_tcy0;
206
207 comps[i].finalize_alloc(codestream, this, i, comp_rects[i],
209 width = ojph_max(width, recon_comp_rects[i].siz.w);
210
211 num_bits[i] = szp->get_bit_depth(i);
212 is_signed[i] = szp->is_signed(i);
213 nlt_type3[i] = nlp->get_type3_transformation(i, bd, is);
214 if (nlt_type3[i] == true && (bd != num_bits[i] || is != is_signed[i]))
215 OJPH_ERROR(0x000300A1, "Mismatch between Ssiz (bit_depth = %d, "
216 "is_signed = %s) from SIZ marker segment, and BDnlt "
217 "(bit_depth = %d, is_signed = %s) from NLT marker segment, "
218 "for component %d",i, num_bits[i],
219 is_signed[i] ? "True" : "False", bd, is ? "True" : "False");
220 cur_line[i] = 0;
221 }
222
223 offset += tile_rect.siz.w;
224
225 //allocate lines
226 const param_cod* cdp = codestream->get_cod();
227 this->reversible = cdp->access_atk()->is_reversible();
229 if (this->employ_color_transform)
230 {
231 num_lines = 3;
232 lines = allocator->post_alloc_obj<line_buf>(num_lines);
233 for (int i = 0; i < 3; ++i)
234 lines[i].wrap(allocator->post_alloc_data<si32>(width, 0), width, 0);
235 }
236 else
237 {
238 lines = NULL;
239 num_lines = 0;
240 }
241 next_tile_part = 0;
242 }
243
245 bool tile::push(line_buf *line, ui32 comp_num)
246 {
247 assert(comp_num < num_comps);
248 if (cur_line[comp_num] >= comp_rects[comp_num].siz.h)
249 return false;
250 cur_line[comp_num]++;
251
252 //converts to signed representation
253 //employs color transform if there is a need
254 if (!employ_color_transform || comp_num >= 3)
255 {
256 assert(comp_num < num_comps);
257 ui32 comp_width = comp_rects[comp_num].siz.w;
258 line_buf *tc = comps[comp_num].get_line();
259 if (reversible)
260 {
261 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
262 if (is_signed[comp_num] && nlt_type3[comp_num])
263 rev_convert_nlt_type3(line, line_offsets[comp_num],
264 tc, 0, shift + 1, comp_width);
265 else {
266 shift = is_signed[comp_num] ? 0 : -shift;
267 rev_convert(line, line_offsets[comp_num], tc, 0,
268 shift, comp_width);
269 }
270 }
271 else
272 {
273 float mul = 1.0f / (float)(1<<num_bits[comp_num]);
274 const si32 *sp = line->i32 + line_offsets[comp_num];
275 float *dp = tc->f32;
276 if (is_signed[comp_num])
277 cnvrt_si32_to_float(sp, dp, mul, comp_width);
278 else
279 cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
280 }
281 comps[comp_num].push_line();
282 }
283 else
284 {
285 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
286 ui32 comp_width = comp_rects[comp_num].siz.w;
287 if (reversible)
288 {
289 if (is_signed[comp_num] && nlt_type3[comp_num])
290 rev_convert_nlt_type3(line, line_offsets[comp_num],
291 lines + comp_num, 0, shift + 1, comp_width);
292 else {
293 shift = is_signed[comp_num] ? 0 : -shift;
294 rev_convert(line, line_offsets[comp_num], lines + comp_num, 0,
295 shift, comp_width);
296 }
297
298 if (comp_num == 2)
299 { // reversible color transform
300 rct_forward(lines + 0, lines + 1, lines + 2,
301 comps[0].get_line(),
302 comps[1].get_line(),
303 comps[2].get_line(), comp_width);
304 comps[0].push_line();
305 comps[1].push_line();
306 comps[2].push_line();
307 }
308 }
309 else
310 {
311 float mul = 1.0f / (float)(1<<num_bits[comp_num]);
312 const si32 *sp = line->i32 + line_offsets[comp_num];
313 float *dp = lines[comp_num].f32;
314 if (is_signed[comp_num])
315 cnvrt_si32_to_float(sp, dp, mul, comp_width);
316 else
317 cnvrt_si32_to_float_shftd(sp, dp, mul, comp_width);
318 if (comp_num == 2)
319 { // irreversible color transform
320 ict_forward(lines[0].f32, lines[1].f32, lines[2].f32,
321 comps[0].get_line()->f32,
322 comps[1].get_line()->f32,
323 comps[2].get_line()->f32, comp_width);
324 comps[0].push_line();
325 comps[1].push_line();
326 comps[2].push_line();
327 }
328 }
329 }
330
331 return true;
332 }
333
335 bool tile::pull(line_buf* tgt_line, ui32 comp_num)
336 {
337 assert(comp_num < num_comps);
338 if (cur_line[comp_num] >= recon_comp_rects[comp_num].siz.h)
339 return false;
340
341 cur_line[comp_num]++;
342
344 {
345 line_buf *src_line = comps[comp_num].pull_line();
346 ui32 comp_width = recon_comp_rects[comp_num].siz.w;
347 if (reversible)
348 {
349 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
350 if (is_signed[comp_num] && nlt_type3[comp_num])
351 rev_convert_nlt_type3(src_line, 0, tgt_line,
352 line_offsets[comp_num], shift + 1, comp_width);
353 else {
354 shift = is_signed[comp_num] ? 0 : shift;
355 rev_convert(src_line, 0, tgt_line,
356 line_offsets[comp_num], shift, comp_width);
357 }
358 }
359 else
360 {
361 float mul = (float)(1 << num_bits[comp_num]);
362 const float *sp = src_line->f32;
363 si32 *dp = tgt_line->i32 + line_offsets[comp_num];
364 if (is_signed[comp_num])
365 cnvrt_float_to_si32(sp, dp, mul, comp_width);
366 else
367 cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
368 }
369 }
370 else
371 {
372 assert(num_comps >= 3);
373 ui32 comp_width = recon_comp_rects[comp_num].siz.w;
374 if (comp_num == 0)
375 {
376 if (reversible)
377 rct_backward(comps[0].pull_line(), comps[1].pull_line(),
378 comps[2].pull_line(), lines + 0, lines + 1,
379 lines + 2, comp_width);
380 else
381 ict_backward(comps[0].pull_line()->f32, comps[1].pull_line()->f32,
382 comps[2].pull_line()->f32, lines[0].f32, lines[1].f32,
383 lines[2].f32, comp_width);
384 }
385 if (reversible)
386 {
387 si64 shift = (si64)1 << (num_bits[comp_num] - 1);
388 line_buf* src_line;
389 if (comp_num < 3)
390 src_line = lines + comp_num;
391 else
392 src_line = comps[comp_num].pull_line();
393 if (is_signed[comp_num] && nlt_type3[comp_num])
394 rev_convert_nlt_type3(src_line, 0, tgt_line,
395 line_offsets[comp_num], shift + 1, comp_width);
396 else {
397 shift = is_signed[comp_num] ? 0 : shift;
398 rev_convert(src_line, 0, tgt_line,
399 line_offsets[comp_num], shift, comp_width);
400 }
401 }
402 else
403 {
404 float mul = (float)(1 << num_bits[comp_num]);
405 const float *sp;
406 if (comp_num < 3)
407 sp = lines[comp_num].f32;
408 else
409 sp = comps[comp_num].pull_line()->f32;
410 si32 *dp = tgt_line->i32 + line_offsets[comp_num];
411 if (is_signed[comp_num])
412 cnvrt_float_to_si32(sp, dp, mul, comp_width);
413 else
414 cnvrt_float_to_si32_shftd(sp, dp, mul, comp_width);
415 }
416 }
417
418 return true;
419 }
420
421
424 {
425 this->num_bytes = 0;
426 //prepare precinct headers
427 for (ui32 c = 0; c < num_comps; ++c)
428 num_bytes += comps[c].prepare_precincts();
429 }
430
433 {
435 tlm->set_next_pair(sot.get_tile_index(), this->num_bytes);
436 }
438 {
440 ui32 max_decs = 0;
441 for (ui32 c = 0; c < num_comps; ++c)
442 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
443 for (ui32 r = 0; r <= max_decs; ++r)
444 {
445 ui32 bytes = 0;
446 for (ui32 c = 0; c < num_comps; ++c)
447 bytes += comps[c].get_num_bytes(r);
448 tlm->set_next_pair(sot.get_tile_index(), bytes);
449 }
450 }
452 {
454 {
455 ui32 max_decs = 0;
456 for (ui32 c = 0; c < num_comps; ++c)
457 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
458 for (ui32 r = 0; r <= max_decs; ++r)
459 for (ui32 c = 0; c < num_comps; ++c)
460 if (r <= comps[c].get_num_decompositions())
462 comps[c].get_num_bytes(r));
463 }
464 else if (prog_order == OJPH_PO_CPRL)
465 for (ui32 c = 0; c < num_comps; ++c)
467 else
468 assert(0); // should not be here
469 }
470 else
471 {
473 ui32 max_decs = 0;
474 for (ui32 c = 0; c < num_comps; ++c)
475 max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
476 for (ui32 r = 0; r <= max_decs; ++r)
477 for (ui32 c = 0; c < num_comps; ++c)
478 if (r <= comps[c].get_num_decompositions())
480 comps[c].get_num_bytes(r));
481 }
482 }
483
484
487 {
488 ui32 max_decompositions = 0;
489 for (ui32 c = 0; c < num_comps; ++c)
490 max_decompositions = ojph_max(max_decompositions,
491 comps[c].get_num_decompositions());
492
494 {
495 //write tile header
496 if (!sot.write(file, this->num_bytes))
497 OJPH_ERROR(0x00030081, "Error writing to file");
498
499 //write start of data
501 if (!file->write(&t, 2))
502 OJPH_ERROR(0x00030082, "Error writing to file");
503 }
504
505
506 //sequence the writing of precincts according to progression order
508 {
510 {
511 for (ui32 r = 0; r <= max_decompositions; ++r)
512 for (ui32 c = 0; c < num_comps; ++c)
513 comps[c].write_precincts(r, file);
514 }
516 {
517 for (ui32 r = 0; r <= max_decompositions; ++r)
518 {
519 ui32 bytes = 0;
520 for (ui32 c = 0; c < num_comps; ++c)
521 bytes += comps[c].get_num_bytes(r);
522
523 //write tile header
524 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
525 OJPH_ERROR(0x00030083, "Error writing to file");
526
527 //write start of data
529 if (!file->write(&t, 2))
530 OJPH_ERROR(0x00030084, "Error writing to file");
531
532 //write precincts
533 for (ui32 c = 0; c < num_comps; ++c)
534 comps[c].write_precincts(r, file);
535 }
536 }
537 else
538 {
539 ui32 num_tileparts = num_comps * (max_decompositions + 1);
540 for (ui32 r = 0; r <= max_decompositions; ++r)
541 for (ui32 c = 0; c < num_comps; ++c)
542 if (r <= comps[c].get_num_decompositions()) {
543 //write tile header
544 if (!sot.write(file, comps[c].get_num_bytes(r),
545 (ui8)(c + r * num_comps), (ui8)num_tileparts))
546 OJPH_ERROR(0x00030085, "Error writing to file");
547 //write start of data
549 if (!file->write(&t, 2))
550 OJPH_ERROR(0x00030086, "Error writing to file");
551 comps[c].write_precincts(r, file);
552 }
553 }
554 }
555 else if (prog_order == OJPH_PO_RPCL)
556 {
557 for (ui32 r = 0; r <= max_decompositions; ++r)
558 {
560 {
561 ui32 bytes = 0;
562 for (ui32 c = 0; c < num_comps; ++c)
563 bytes += comps[c].get_num_bytes(r);
564 //write tile header
565 if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
566 OJPH_ERROR(0x00030087, "Error writing to file");
567
568 //write start of data
570 if (!file->write(&t, 2))
571 OJPH_ERROR(0x00030088, "Error writing to file");
572 }
573 while (true)
574 {
575 bool found = false;
576 ui32 comp_num = 0;
577 point smallest(INT_MAX, INT_MAX), cur;
578 for (ui32 c = 0; c < num_comps; ++c)
579 {
580 if (!comps[c].get_top_left_precinct(r, cur))
581 continue;
582 else
583 found = true;
584
585 if (cur.y < smallest.y)
586 { smallest = cur; comp_num = c; }
587 else if (cur.y == smallest.y && cur.x < smallest.x)
588 { smallest = cur; comp_num = c; }
589 }
590 if (found == true)
591 comps[comp_num].write_one_precinct(r, file);
592 else
593 break;
594 }
595 }
596 }
597 else if (prog_order == OJPH_PO_PCRL)
598 {
599 while (true)
600 {
601 bool found = false;
602 ui32 comp_num = 0;
603 ui32 res_num = 0;
604 point smallest(INT_MAX, INT_MAX), cur;
605 for (ui32 c = 0; c < num_comps; ++c)
606 {
607 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
608 {
609 if (!comps[c].get_top_left_precinct(r, cur))
610 continue;
611 else
612 found = true;
613
614 if (cur.y < smallest.y)
615 { smallest = cur; comp_num = c; res_num = r; }
616 else if (cur.y == smallest.y && cur.x < smallest.x)
617 { smallest = cur; comp_num = c; res_num = r; }
618 else if (cur.y == smallest.y && cur.x == smallest.x &&
619 c < comp_num)
620 { smallest = cur; comp_num = c; res_num = r; }
621 else if (cur.y == smallest.y && cur.x == smallest.x &&
622 c == comp_num && r < res_num)
623 { smallest = cur; comp_num = c; res_num = r; }
624 }
625 }
626 if (found == true)
627 comps[comp_num].write_one_precinct(res_num, file);
628 else
629 break;
630 }
631 }
632 else if (prog_order == OJPH_PO_CPRL)
633 {
634 for (ui32 c = 0; c < num_comps; ++c)
635 {
637 {
638 ui32 bytes = comps[c].get_num_bytes();
639 //write tile header
640 if (!sot.write(file, bytes, (ui8)c, (ui8)num_comps))
641 OJPH_ERROR(0x0003008A, "Error writing to file");
642
643 //write start of data
645 if (!file->write(&t, 2))
646 OJPH_ERROR(0x0003008B, "Error writing to file");
647 }
648
649 while (true)
650 {
651 bool found = false;
652 ui32 res_num = 0;
653 point smallest(INT_MAX, INT_MAX), cur;
654 for (ui32 r = 0; r <= max_decompositions; ++r)
655 {
656 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
657 continue;
658 else
659 found = true;
660
661 if (cur.y < smallest.y)
662 { smallest = cur; res_num = r; }
663 else if (cur.y == smallest.y && cur.x < smallest.x)
664 { smallest = cur; res_num = r; }
665 }
666 if (found == true)
667 comps[c].write_one_precinct(res_num, file);
668 else
669 break;
670 }
671 }
672 }
673 else
674 assert(0);
675
676 }
677
680 const ui64& tile_start_location)
681 {
683 {
684 if (resilient)
685 OJPH_INFO(0x00030091, "wrong tile part index")
686 else
687 OJPH_ERROR(0x00030091, "wrong tile part index")
688 }
690
691 //tile_end_location used on failure
692 ui64 tile_end_location = tile_start_location + sot.get_payload_length();
693
694 ui32 data_left = sot.get_payload_length(); //bytes left to parse
695 data_left -= (ui32)((ui64)file->tell() - tile_start_location);
696
697 if (data_left == 0)
698 return;
699
700 ui32 max_decompositions = 0;
701 for (ui32 c = 0; c < num_comps; ++c)
702 max_decompositions = ojph_max(max_decompositions,
703 comps[c].get_num_decompositions());
704
705 try
706 {
707 //sequence the reading of precincts according to progression order
709 {
710 max_decompositions -= skipped_res_for_read;
711 for (ui32 r = 0; r <= max_decompositions; ++r)
712 for (ui32 c = 0; c < num_comps; ++c)
713 if (data_left > 0)
714 comps[c].parse_precincts(r, data_left, file);
715 }
716 else if (prog_order == OJPH_PO_RPCL)
717 {
718 max_decompositions -= skipped_res_for_read;
719 for (ui32 r = 0; r <= max_decompositions; ++r)
720 {
721 while (true)
722 {
723 bool found = false;
724 ui32 comp_num = 0;
725 point smallest(INT_MAX, INT_MAX), cur;
726 for (ui32 c = 0; c < num_comps; ++c)
727 {
728 if (!comps[c].get_top_left_precinct(r, cur))
729 continue;
730 else
731 found = true;
732
733 if (cur.y < smallest.y)
734 { smallest = cur; comp_num = c; }
735 else if (cur.y == smallest.y && cur.x < smallest.x)
736 { smallest = cur; comp_num = c; }
737 }
738 if (found == true && data_left > 0)
739 comps[comp_num].parse_one_precinct(r, data_left, file);
740 else
741 break;
742 }
743 }
744 }
745 else if (prog_order == OJPH_PO_PCRL)
746 {
747 while (true)
748 {
749 bool found = false;
750 ui32 comp_num = 0;
751 ui32 res_num = 0;
752 point smallest(INT_MAX, INT_MAX), cur;
753 for (ui32 c = 0; c < num_comps; ++c)
754 {
755 for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
756 {
757 if (!comps[c].get_top_left_precinct(r, cur))
758 continue;
759 else
760 found = true;
761
762 if (cur.y < smallest.y)
763 { smallest = cur; comp_num = c; res_num = r; }
764 else if (cur.y == smallest.y && cur.x < smallest.x)
765 { smallest = cur; comp_num = c; res_num = r; }
766 else if (cur.y == smallest.y && cur.x == smallest.x &&
767 c < comp_num)
768 { smallest = cur; comp_num = c; res_num = r; }
769 else if (cur.y == smallest.y && cur.x == smallest.x &&
770 c == comp_num && r < res_num)
771 { smallest = cur; comp_num = c; res_num = r; }
772 }
773 }
774 if (found == true && data_left > 0)
775 comps[comp_num].parse_one_precinct(res_num, data_left, file);
776 else
777 break;
778 }
779 }
780 else if (prog_order == OJPH_PO_CPRL)
781 {
782 for (ui32 c = 0; c < num_comps; ++c)
783 {
784 while (true)
785 {
786 bool found = false;
787 ui32 res_num = 0;
788 point smallest(INT_MAX, INT_MAX), cur;
789 for (ui32 r = 0; r <= max_decompositions; ++r)
790 {
791 if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
792 continue;
793 else
794 found = true;
795
796 if (cur.y < smallest.y)
797 { smallest = cur; res_num = r; }
798 else if (cur.y == smallest.y && cur.x < smallest.x)
799 { smallest = cur; res_num = r; }
800 }
801 if (found == true && data_left > 0)
802 comps[c].parse_one_precinct(res_num, data_left, file);
803 else
804 break;
805 }
806 }
807 }
808 else
809 assert(0);
810
811 }
812 catch (const char *error)
813 {
814 if (resilient)
815 OJPH_INFO(0x00030092, "%s", error)
816 else
817 OJPH_ERROR(0x00030092, "%s", error)
818 }
819 file->seek((si64)tile_end_location, infile_base::OJPH_SEEK_SET);
820 }
821
822 }
823}
virtual si64 tell()=0
float * f32
Definition: ojph_mem.h:174
si32 * i32
Definition: ojph_mem.h:172
const param_siz * get_siz()
mem_fixed_allocator * get_allocator()
const param_nlt * get_nlt()
const param_cod * get_cod()
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)
ui32 get_num_bytes() const
void parse_precincts(ui32 res_num, ui32 &data_left, infile_base *file)
bool pull(line_buf *, ui32 comp_num)
Definition: ojph_tile.cpp:335
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)
Definition: ojph_tile.cpp:134
static void pre_alloc(codestream *codestream, const rect &tile_rect, const rect &recon_tile_rect, ui32 &num_tileparts)
Definition: ojph_tile.cpp:56
void prepare_for_flush()
Definition: ojph_tile.cpp:423
tile_comp * comps
Definition: ojph_tile.h:81
void fill_tlm(param_tlm *tlm)
Definition: ojph_tile.cpp:432
rect * recon_comp_rects
Definition: ojph_tile.h:85
bool * nlt_type3
Definition: ojph_tile.h:92
bool * is_signed
Definition: ojph_tile.h:90
void flush(outfile_base *file)
Definition: ojph_tile.cpp:486
ui32 skipped_res_for_read
Definition: ojph_tile.h:87
param_sot sot
Definition: ojph_tile.h:96
bool push(line_buf *line, ui32 comp_num)
Definition: ojph_tile.cpp:245
bool employ_color_transform
Definition: ojph_tile.h:84
rect * comp_rects
Definition: ojph_tile.h:85
void parse_tile_header(const param_sot &sot, infile_base *file, const ui64 &tile_start_location)
Definition: ojph_tile.cpp:679
ui32 * line_offsets
Definition: ojph_tile.h:86
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
void(* cnvrt_float_to_si32)(const float *sp, si32 *dp, float mul, ui32 width)
Definition: ojph_colour.cpp:79
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)
Definition: ojph_colour.cpp:83
void(* cnvrt_si32_to_float_shftd)(const si32 *sp, float *dp, float mul, ui32 width)
Definition: ojph_colour.cpp:67
void(* ict_forward)(const float *r, const float *g, const float *b, float *y, float *cb, float *cr, ui32 repeat)
Definition: ojph_colour.cpp:93
void(* ict_backward)(const float *y, const float *cb, const float *cr, float *r, float *g, float *b, ui32 repeat)
Definition: ojph_colour.cpp:98
void(* cnvrt_float_to_si32_shftd)(const float *sp, si32 *dp, float mul, ui32 width)
Definition: ojph_colour.cpp:75
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)
Definition: ojph_colour.cpp:88
void(* cnvrt_si32_to_float)(const si32 *sp, float *dp, float mul, ui32 width)
Definition: ojph_colour.cpp:71
static ui16 swap_byte(ui16 t)
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)
Definition: ojph_colour.cpp:61
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)
Definition: ojph_colour.cpp:55
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.
Definition: ojph_message.h:283
#define OJPH_ERROR(t,...)
Definition: ojph_message.h:287
bool is_employing_color_transform() const
const param_atk * access_atk() const
ui8 get_num_decompositions() const
bool get_type3_transformation(ui32 comp_num, ui8 &bit_depth, bool &is_signed) 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)
size siz
Definition: ojph_base.h:67
point org
Definition: ojph_base.h:66
ui32 w
Definition: ojph_base.h:50
ui32 h
Definition: ojph_base.h:51