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