Loading...
Searching...
No Matches
ojph_tile.cpp
Go to the documentation of this file.
//***************************************************************************/
// This software is released under the 2-Clause BSD license, included
// below.
//
// Copyright (c) 2019, Aous Naman
// Copyright (c) 2019, Kakadu Software Pty Ltd, Australia
// Copyright (c) 2019, The University of New South Wales, Australia
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************/
// This file is part of the OpenJPH software implementation.
// File: ojph_tile.cpp
// Author: Aous Naman
// Date: 28 August 2019
//***************************************************************************/
#include <climits>
#include <cmath>
#include "ojph_mem.h"
#include "ojph_params.h"
#include "ojph_codestream_local.h"
#include "ojph_tile.h"
#include "ojph_tile_comp.h"
#include "../transform/ojph_colour.h"
namespace ojph {
namespace local
{
void tile::pre_alloc(codestream *codestream, const rect& tile_rect,
const rect& recon_tile_rect, ui32& num_tileparts)
{
mem_fixed_allocator* allocator = codestream->get_allocator();
//allocate tiles_comp
const param_siz *szp = codestream->get_siz();
ui32 num_comps = szp->get_num_components();
allocator->pre_alloc_obj<tile_comp>(num_comps);
allocator->pre_alloc_obj<rect>(num_comps); //for comp_rects
allocator->pre_alloc_obj<rect>(num_comps); //for recon_comp_rects
allocator->pre_alloc_obj<ui32>(num_comps); //for line_offsets
allocator->pre_alloc_obj<ui32>(num_comps); //for num_bits
allocator->pre_alloc_obj<bool>(num_comps); //for is_signed
allocator->pre_alloc_obj<bool>(num_comps); //for reversible
allocator->pre_alloc_obj<ui8>(num_comps); //for nlt_type3
allocator->pre_alloc_obj<ui32>(num_comps); //for cur_line
{
ui32 tilepart_div = codestream->get_tilepart_div();
ui32 t = tilepart_div & OJPH_TILEPART_MASK;
if (t == OJPH_TILEPART_NO_DIVISIONS)
num_tileparts = 1; //for num_rc_bytes
else if (t == OJPH_TILEPART_COMPONENTS)
num_tileparts = num_comps;
else if (t == OJPH_TILEPART_RESOLUTIONS)
{
ui32 max_decs = 0;
for (ui32 c = 0; c < num_comps; ++c) {
ui32 s = codestream->get_coc(c)->get_num_decompositions();
max_decs = ojph_max(max_decs, s);
}
num_tileparts = 1 + max_decs;
}
else if (t == (OJPH_TILEPART_COMPONENTS | OJPH_TILEPART_RESOLUTIONS))
{
num_tileparts = 0;
for (ui32 c = 0; c < num_comps; ++c) {
ui32 s = codestream->get_coc(c)->get_num_decompositions();
num_tileparts += s + 1;
}
}
if (num_tileparts > 255)
OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
"cannot have more than 255 tile parts.", num_tileparts);
}
ui32 tx0 = tile_rect.org.x;
ui32 ty0 = tile_rect.org.y;
ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
ui32 recon_tx0 = recon_tile_rect.org.x;
ui32 recon_ty0 = recon_tile_rect.org.y;
ui32 recon_tx1 = recon_tile_rect.org.x + recon_tile_rect.siz.w;
ui32 recon_ty1 = recon_tile_rect.org.y + recon_tile_rect.siz.h;
ui32 width = 0;
for (ui32 i = 0; i < num_comps; ++i)
{
point downsamp = szp->get_downsampling(i);
ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
ui32 recon_tcx0 = ojph_div_ceil(recon_tx0, downsamp.x);
ui32 recon_tcy0 = ojph_div_ceil(recon_ty0, downsamp.y);
ui32 recon_tcx1 = ojph_div_ceil(recon_tx1, downsamp.x);
ui32 recon_tcy1 = ojph_div_ceil(recon_ty1, downsamp.y);
rect comp_rect;
comp_rect.org.x = tcx0;
comp_rect.org.y = tcy0;
comp_rect.siz.w = tcx1 - tcx0;
comp_rect.siz.h = tcy1 - tcy0;
rect recon_comp_rect;
recon_comp_rect.org.x = recon_tcx0;
recon_comp_rect.org.y = recon_tcy0;
recon_comp_rect.siz.w = recon_tcx1 - recon_tcx0;
recon_comp_rect.siz.h = recon_tcy1 - recon_tcy0;
tile_comp::pre_alloc(codestream, i, comp_rect, recon_comp_rect);
width = ojph_max(width, recon_comp_rect.siz.w);
}
//allocate lines
const param_cod* cdp = codestream->get_cod();
if (cdp->is_employing_color_transform())
{
bool reversible[3];
for (ui32 i = 0; i < 3; ++i)
reversible[i] = codestream->get_coc(i)->is_reversible();
if (reversible[0] != reversible[1] || reversible[1] != reversible[2])
OJPH_ERROR(0x000300A2, "When the colour transform is employed. "
"all colour components must undergo either reversible or "
"irreversible wavelet transform; if not, then it is not clear "
"what colour transform should be used (reversible or "
"irreversible). Here we found that the first three colour "
"components uses %s, %s, and %s transforms, respectively.",
reversible[0] ? "reversible" : "irreversible",
reversible[1] ? "reversible" : "irreversible",
reversible[2] ? "reversible" : "irreversible");
allocator->pre_alloc_obj<line_buf>(3);
if (reversible[0])
for (int i = 0; i < 3; ++i)
allocator->pre_alloc_data<si32>(width, 0);
else
for (int i = 0; i < 3; ++i)
allocator->pre_alloc_data<float>(width, 0);
}
}
void tile::finalize_alloc(codestream *codestream, const rect& tile_rect,
ui32 tile_idx, ui32& offset,
ui32 &num_tileparts)
{
//this->parent = codestream;
mem_fixed_allocator* allocator = codestream->get_allocator();
sot.init(0, (ui16)tile_idx, 0, 1);
prog_order = codestream->access_cod().get_progression_order();
//allocate tiles_comp
const param_siz *szp = codestream->get_siz();
const param_nlt *nlp = codestream->get_nlt();
this->num_bytes = 0;
num_comps = szp->get_num_components();
skipped_res_for_read = codestream->get_skipped_res_for_read();
comps = allocator->post_alloc_obj<tile_comp>(num_comps);
comp_rects = allocator->post_alloc_obj<rect>(num_comps);
recon_comp_rects = allocator->post_alloc_obj<rect>(num_comps);
line_offsets = allocator->post_alloc_obj<ui32>(num_comps);
num_bits = allocator->post_alloc_obj<ui32>(num_comps);
is_signed = allocator->post_alloc_obj<bool>(num_comps);
reversible = allocator->post_alloc_obj<bool>(num_comps);
nlt_type3 = allocator->post_alloc_obj<ui8>(num_comps);
cur_line = allocator->post_alloc_obj<ui32>(num_comps);
profile = codestream->get_profile();
tilepart_div = codestream->get_tilepart_div();
need_tlm = codestream->is_tlm_needed();
{
ui32 tilepart_div = codestream->get_tilepart_div();
ui32 t = tilepart_div & OJPH_TILEPART_MASK;
if (t == OJPH_TILEPART_NO_DIVISIONS)
num_tileparts = 1; //for num_rc_bytes
else if (t == OJPH_TILEPART_COMPONENTS)
num_tileparts = num_comps;
else if (t == OJPH_TILEPART_RESOLUTIONS)
{
ui32 max_decs = 0;
for (ui32 c = 0; c < num_comps; ++c) {
ui32 s = codestream->get_coc(c)->get_num_decompositions();
max_decs = ojph_max(max_decs, s);
}
num_tileparts = 1 + max_decs;
}
else if (t == (OJPH_TILEPART_COMPONENTS | OJPH_TILEPART_RESOLUTIONS))
{
num_tileparts = 0;
for (ui32 c = 0; c < num_comps; ++c) {
ui32 s = codestream->get_coc(c)->get_num_decompositions();
num_tileparts += s + 1;
}
}
if (num_tileparts > 255)
OJPH_ERROR(0x000300D1, "Trying to create %d tileparts; a tile "
"cannot have more than 255 tile parts.", num_tileparts);
}
this->resilient = codestream->is_resilient();
this->tile_rect = tile_rect;
ui32 tx0 = tile_rect.org.x;
ui32 ty0 = tile_rect.org.y;
ui32 tx1 = tile_rect.org.x + tile_rect.siz.w;
ui32 ty1 = tile_rect.org.y + tile_rect.siz.h;
ui32 width = 0;
for (ui32 i = 0; i < num_comps; ++i)
{
ui8 bd; bool is; // used for nlt_type3
point downsamp = szp->get_downsampling(i);
point recon_downsamp = szp->get_recon_downsampling(i);
ui32 tcx0 = ojph_div_ceil(tx0, downsamp.x);
ui32 tcy0 = ojph_div_ceil(ty0, downsamp.y);
ui32 tcx1 = ojph_div_ceil(tx1, downsamp.x);
ui32 tcy1 = ojph_div_ceil(ty1, downsamp.y);
ui32 recon_tcx0 = ojph_div_ceil(tx0, recon_downsamp.x);
ui32 recon_tcy0 = ojph_div_ceil(ty0, recon_downsamp.y);
ui32 recon_tcx1 = ojph_div_ceil(tx1, recon_downsamp.x);
ui32 recon_tcy1 = ojph_div_ceil(ty1, recon_downsamp.y);
line_offsets[i] =
recon_tcx0 - ojph_div_ceil(tx0 - offset, recon_downsamp.x);
comp_rects[i].org.x = tcx0;
comp_rects[i].org.y = tcy0;
comp_rects[i].siz.w = tcx1 - tcx0;
comp_rects[i].siz.h = tcy1 - tcy0;
recon_comp_rects[i].org.x = recon_tcx0;
recon_comp_rects[i].org.y = recon_tcy0;
recon_comp_rects[i].siz.w = recon_tcx1 - recon_tcx0;
recon_comp_rects[i].siz.h = recon_tcy1 - recon_tcy0;
comps[i].finalize_alloc(codestream, this, i, comp_rects[i],
recon_comp_rects[i]);
width = ojph_max(width, recon_comp_rects[i].siz.w);
num_bits[i] = szp->get_bit_depth(i);
is_signed[i] = szp->is_signed(i);
bool result = nlp->get_nonlinear_transform(i, bd, is, nlt_type3[i]);
if (result == true && (bd != num_bits[i] || is != is_signed[i]))
OJPH_ERROR(0x000300A1, "Mismatch between Ssiz (bit_depth = %d, "
"is_signed = %s) from SIZ marker segment, and BDnlt "
"(bit_depth = %d, is_signed = %s) from NLT marker segment, "
"for component %d", i, num_bits[i],
is_signed[i] ? "True" : "False", bd, is ? "True" : "False");
if (result == false)
nlt_type3[i] = param_nlt::nonlinearity::OJPH_NLT_NO_NLT;
cur_line[i] = 0;
reversible[i] = codestream->get_coc(i)->is_reversible();
}
offset += tile_rect.siz.w;
//allocate lines
const param_cod* cdp = codestream->get_cod();
this->employ_color_transform = cdp->is_employing_color_transform();
if (this->employ_color_transform)
{
num_lines = 3;
lines = allocator->post_alloc_obj<line_buf>(num_lines);
if (reversible[0])
for (int i = 0; i < 3; ++i)
lines[i].wrap(
allocator->post_alloc_data<si32>(width, 0), width, 0);
else
for (int i = 0; i < 3; ++i)
lines[i].wrap(
allocator->post_alloc_data<float>(width, 0), width, 0);
}
else
{
lines = NULL;
num_lines = 0;
}
next_tile_part = 0;
}
bool tile::push(line_buf *line, ui32 comp_num)
{
constexpr ui8 type3 =
param_nlt::nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
assert(comp_num < num_comps);
if (cur_line[comp_num] >= comp_rects[comp_num].siz.h)
return false;
cur_line[comp_num]++;
//converts to signed representation
//employs color transform if there is a need
if (!employ_color_transform || comp_num >= 3)
{
assert(comp_num < num_comps);
ui32 comp_width = comp_rects[comp_num].siz.w;
line_buf *tc = comps[comp_num].get_line();
if (reversible[comp_num])
{
si64 shift = (si64)1 << (num_bits[comp_num] - 1);
if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
rev_convert_nlt_type3(line, line_offsets[comp_num],
tc, 0, shift + 1, comp_width);
else {
shift = is_signed[comp_num] ? 0 : -shift;
rev_convert(line, line_offsets[comp_num], tc, 0,
shift, comp_width);
}
}
else
{
if (nlt_type3[comp_num] == type3)
irv_convert_to_float_nlt_type3(line, line_offsets[comp_num],
tc, num_bits[comp_num], is_signed[comp_num], comp_width);
else
irv_convert_to_float(line, line_offsets[comp_num],
tc, num_bits[comp_num], is_signed[comp_num], comp_width);
}
comps[comp_num].push_line();
}
else
{
si64 shift = (si64)1 << (num_bits[comp_num] - 1);
ui32 comp_width = comp_rects[comp_num].siz.w;
if (reversible[comp_num])
{
if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
rev_convert_nlt_type3(line, line_offsets[comp_num],
lines + comp_num, 0, shift + 1, comp_width);
else {
shift = is_signed[comp_num] ? 0 : -shift;
rev_convert(line, line_offsets[comp_num], lines + comp_num, 0,
shift, comp_width);
}
if (comp_num == 2)
{ // reversible color transform
rct_forward(lines + 0, lines + 1, lines + 2,
comps[0].get_line(),
comps[1].get_line(),
comps[2].get_line(), comp_width);
comps[0].push_line();
comps[1].push_line();
comps[2].push_line();
}
}
else
{
if (nlt_type3[comp_num] == type3)
irv_convert_to_float_nlt_type3(line, line_offsets[comp_num],
lines + comp_num, num_bits[comp_num], is_signed[comp_num],
comp_width);
else
irv_convert_to_float(line, line_offsets[comp_num],
lines + comp_num, num_bits[comp_num], is_signed[comp_num],
comp_width);
if (comp_num == 2)
{ // irreversible color transform
ict_forward(lines[0].f32, lines[1].f32, lines[2].f32,
comps[0].get_line()->f32,
comps[1].get_line()->f32,
comps[2].get_line()->f32, comp_width);
comps[0].push_line();
comps[1].push_line();
comps[2].push_line();
}
}
}
return true;
}
bool tile::pull(line_buf* tgt_line, ui32 comp_num)
{
constexpr ui8 type3 =
param_nlt::nonlinearity::OJPH_NLT_BINARY_COMPLEMENT_NLT;
assert(comp_num < num_comps);
if (cur_line[comp_num] >= recon_comp_rects[comp_num].siz.h)
return false;
cur_line[comp_num]++;
ui32 comp_width = recon_comp_rects[comp_num].siz.w;
if (comp_width == 0)
return true; // nothing to pull, but not an error
if (!employ_color_transform || num_comps == 1)
{
line_buf *src_line = comps[comp_num].pull_line();
if (reversible[comp_num])
{
si64 shift = (si64)1 << (num_bits[comp_num] - 1);
if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
rev_convert_nlt_type3(src_line, 0, tgt_line,
line_offsets[comp_num], shift + 1, comp_width);
else {
shift = is_signed[comp_num] ? 0 : shift;
rev_convert(src_line, 0, tgt_line,
line_offsets[comp_num], shift, comp_width);
}
}
else
{
if (nlt_type3[comp_num] == type3)
irv_convert_to_integer_nlt_type3(src_line, tgt_line,
line_offsets[comp_num], num_bits[comp_num],
is_signed[comp_num], comp_width);
else
irv_convert_to_integer(src_line, tgt_line,
line_offsets[comp_num], num_bits[comp_num],
is_signed[comp_num], comp_width);
}
}
else
{
assert(num_comps >= 3);
if (comp_num == 0)
{
if (reversible[comp_num])
rct_backward(comps[0].pull_line(), comps[1].pull_line(),
comps[2].pull_line(), lines + 0, lines + 1,
lines + 2, comp_width);
else
ict_backward(comps[0].pull_line()->f32, comps[1].pull_line()->f32,
comps[2].pull_line()->f32, lines[0].f32, lines[1].f32,
lines[2].f32, comp_width);
}
if (reversible[comp_num])
{
si64 shift = (si64)1 << (num_bits[comp_num] - 1);
line_buf* src_line;
if (comp_num < 3)
src_line = lines + comp_num;
else
src_line = comps[comp_num].pull_line();
if (is_signed[comp_num] && nlt_type3[comp_num] == type3)
rev_convert_nlt_type3(src_line, 0, tgt_line,
line_offsets[comp_num], shift + 1, comp_width);
else {
shift = is_signed[comp_num] ? 0 : shift;
rev_convert(src_line, 0, tgt_line,
line_offsets[comp_num], shift, comp_width);
}
}
else
{
line_buf* lbp;
if (comp_num < 3)
lbp = lines + comp_num;
else
lbp = comps[comp_num].pull_line();
if (nlt_type3[comp_num] == type3)
irv_convert_to_integer_nlt_type3(lbp, tgt_line,
line_offsets[comp_num], num_bits[comp_num],
is_signed[comp_num], comp_width);
else
irv_convert_to_integer(lbp, tgt_line,
line_offsets[comp_num], num_bits[comp_num],
is_signed[comp_num], comp_width);
}
}
return true;
}
void tile::prepare_for_flush()
{
this->num_bytes = 0;
//prepare precinct headers
for (ui32 c = 0; c < num_comps; ++c)
num_bytes += comps[c].prepare_precincts();
}
void tile::fill_tlm(param_tlm *tlm)
{
if (tilepart_div == OJPH_TILEPART_NO_DIVISIONS) {
tlm->set_next_pair(sot.get_tile_index(), this->num_bytes);
}
else if (tilepart_div == OJPH_TILEPART_RESOLUTIONS)
{
assert(prog_order != OJPH_PO_PCRL && prog_order != OJPH_PO_CPRL);
ui32 max_decs = 0;
for (ui32 c = 0; c < num_comps; ++c)
max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
for (ui32 r = 0; r <= max_decs; ++r)
{
ui32 bytes = 0;
for (ui32 c = 0; c < num_comps; ++c)
bytes += comps[c].get_num_bytes(r);
tlm->set_next_pair(sot.get_tile_index(), bytes);
}
}
else if (tilepart_div == OJPH_TILEPART_COMPONENTS)
{
if (prog_order == OJPH_PO_LRCP || prog_order == OJPH_PO_RLCP)
{
ui32 max_decs = 0;
for (ui32 c = 0; c < num_comps; ++c)
max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
for (ui32 r = 0; r <= max_decs; ++r)
for (ui32 c = 0; c < num_comps; ++c)
if (r <= comps[c].get_num_decompositions())
tlm->set_next_pair(sot.get_tile_index(),
comps[c].get_num_bytes(r));
}
else if (prog_order == OJPH_PO_CPRL)
for (ui32 c = 0; c < num_comps; ++c)
tlm->set_next_pair(sot.get_tile_index(), comps[c].get_num_bytes());
else
assert(0); // should not be here
}
else
{
assert(prog_order == OJPH_PO_LRCP || prog_order == OJPH_PO_RLCP);
ui32 max_decs = 0;
for (ui32 c = 0; c < num_comps; ++c)
max_decs = ojph_max(max_decs, comps[c].get_num_decompositions());
for (ui32 r = 0; r <= max_decs; ++r)
for (ui32 c = 0; c < num_comps; ++c)
if (r <= comps[c].get_num_decompositions())
tlm->set_next_pair(sot.get_tile_index(),
comps[c].get_num_bytes(r));
}
}
void tile::flush(outfile_base *file)
{
ui32 max_decompositions = 0;
for (ui32 c = 0; c < num_comps; ++c)
max_decompositions = ojph_max(max_decompositions,
comps[c].get_num_decompositions());
if (tilepart_div == OJPH_TILEPART_NO_DIVISIONS)
{
//write tile header
if (!sot.write(file, this->num_bytes))
OJPH_ERROR(0x00030081, "Error writing to file");
//write start of data
ui16 t = swap_byte(JP2K_MARKER::SOD);
if (!file->write(&t, 2))
OJPH_ERROR(0x00030082, "Error writing to file");
}
//sequence the writing of precincts according to progression order
if (prog_order == OJPH_PO_LRCP || prog_order == OJPH_PO_RLCP)
{
if (tilepart_div == OJPH_TILEPART_NO_DIVISIONS)
{
for (ui32 r = 0; r <= max_decompositions; ++r)
for (ui32 c = 0; c < num_comps; ++c)
comps[c].write_precincts(r, file);
}
else if (tilepart_div == OJPH_TILEPART_RESOLUTIONS)
{
for (ui32 r = 0; r <= max_decompositions; ++r)
{
ui32 bytes = 0;
for (ui32 c = 0; c < num_comps; ++c)
bytes += comps[c].get_num_bytes(r);
//write tile header
if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
OJPH_ERROR(0x00030083, "Error writing to file");
//write start of data
ui16 t = swap_byte(JP2K_MARKER::SOD);
if (!file->write(&t, 2))
OJPH_ERROR(0x00030084, "Error writing to file");
//write precincts
for (ui32 c = 0; c < num_comps; ++c)
comps[c].write_precincts(r, file);
}
}
else
{
ui32 num_tileparts = num_comps * (max_decompositions + 1);
for (ui32 r = 0; r <= max_decompositions; ++r)
for (ui32 c = 0; c < num_comps; ++c)
if (r <= comps[c].get_num_decompositions()) {
//write tile header
if (!sot.write(file, comps[c].get_num_bytes(r),
(ui8)(c + r * num_comps), (ui8)num_tileparts))
OJPH_ERROR(0x00030085, "Error writing to file");
//write start of data
ui16 t = swap_byte(JP2K_MARKER::SOD);
if (!file->write(&t, 2))
OJPH_ERROR(0x00030086, "Error writing to file");
comps[c].write_precincts(r, file);
}
}
}
else if (prog_order == OJPH_PO_RPCL)
{
for (ui32 r = 0; r <= max_decompositions; ++r)
{
if (tilepart_div == OJPH_TILEPART_RESOLUTIONS)
{
ui32 bytes = 0;
for (ui32 c = 0; c < num_comps; ++c)
bytes += comps[c].get_num_bytes(r);
//write tile header
if (!sot.write(file, bytes, (ui8)r, (ui8)(max_decompositions + 1)))
OJPH_ERROR(0x00030087, "Error writing to file");
//write start of data
ui16 t = swap_byte(JP2K_MARKER::SOD);
if (!file->write(&t, 2))
OJPH_ERROR(0x00030088, "Error writing to file");
}
while (true)
{
bool found = false;
ui32 comp_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 c = 0; c < num_comps; ++c)
{
if (!comps[c].get_top_left_precinct(r, cur))
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; comp_num = c; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; comp_num = c; }
}
if (found == true)
comps[comp_num].write_one_precinct(r, file);
else
break;
}
}
}
else if (prog_order == OJPH_PO_PCRL)
{
while (true)
{
bool found = false;
ui32 comp_num = 0;
ui32 res_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 c = 0; c < num_comps; ++c)
{
for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
{
if (!comps[c].get_top_left_precinct(r, cur))
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x == smallest.x &&
c < comp_num)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x == smallest.x &&
c == comp_num && r < res_num)
{ smallest = cur; comp_num = c; res_num = r; }
}
}
if (found == true)
comps[comp_num].write_one_precinct(res_num, file);
else
break;
}
}
else if (prog_order == OJPH_PO_CPRL)
{
for (ui32 c = 0; c < num_comps; ++c)
{
if (tilepart_div == OJPH_TILEPART_COMPONENTS)
{
ui32 bytes = comps[c].get_num_bytes();
//write tile header
if (!sot.write(file, bytes, (ui8)c, (ui8)num_comps))
OJPH_ERROR(0x0003008A, "Error writing to file");
//write start of data
ui16 t = swap_byte(JP2K_MARKER::SOD);
if (!file->write(&t, 2))
OJPH_ERROR(0x0003008B, "Error writing to file");
}
while (true)
{
bool found = false;
ui32 res_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 r = 0; r <= max_decompositions; ++r)
{
if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; res_num = r; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; res_num = r; }
}
if (found == true)
comps[c].write_one_precinct(res_num, file);
else
break;
}
}
}
else
assert(0);
}
void tile::parse_tile_header(const param_sot &sot, infile_base *file,
const ui64& tile_start_location)
{
if (sot.get_tile_part_index() != next_tile_part)
{
if (resilient)
OJPH_INFO(0x00030091, "wrong tile part index")
else
OJPH_ERROR(0x00030091, "wrong tile part index")
}
++next_tile_part;
//tile_end_location used on failure
ui64 tile_end_location = tile_start_location + sot.get_payload_length();
ui32 data_left = sot.get_payload_length(); //bytes left to parse
data_left -= (ui32)((ui64)file->tell() - tile_start_location);
if (data_left == 0)
return;
ui32 max_decompositions = 0;
for (ui32 c = 0; c < num_comps; ++c)
max_decompositions = ojph_max(max_decompositions,
comps[c].get_num_decompositions());
try
{
//sequence the reading of precincts according to progression order
if (prog_order == OJPH_PO_LRCP || prog_order == OJPH_PO_RLCP)
{
max_decompositions -= skipped_res_for_read;
for (ui32 r = 0; r <= max_decompositions; ++r)
for (ui32 c = 0; c < num_comps; ++c)
if (data_left > 0)
comps[c].parse_precincts(r, data_left, file);
}
else if (prog_order == OJPH_PO_RPCL)
{
max_decompositions -= skipped_res_for_read;
for (ui32 r = 0; r <= max_decompositions; ++r)
{
while (true)
{
bool found = false;
ui32 comp_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 c = 0; c < num_comps; ++c)
{
if (!comps[c].get_top_left_precinct(r, cur))
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; comp_num = c; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; comp_num = c; }
}
if (found == true && data_left > 0)
comps[comp_num].parse_one_precinct(r, data_left, file);
else
break;
}
}
}
else if (prog_order == OJPH_PO_PCRL)
{
while (true)
{
bool found = false;
ui32 comp_num = 0;
ui32 res_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 c = 0; c < num_comps; ++c)
{
for (ui32 r = 0; r <= comps[c].get_num_decompositions(); ++r)
{
if (!comps[c].get_top_left_precinct(r, cur))
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x == smallest.x &&
c < comp_num)
{ smallest = cur; comp_num = c; res_num = r; }
else if (cur.y == smallest.y && cur.x == smallest.x &&
c == comp_num && r < res_num)
{ smallest = cur; comp_num = c; res_num = r; }
}
}
if (found == true && data_left > 0)
comps[comp_num].parse_one_precinct(res_num, data_left, file);
else
break;
}
}
else if (prog_order == OJPH_PO_CPRL)
{
for (ui32 c = 0; c < num_comps; ++c)
{
while (true)
{
bool found = false;
ui32 res_num = 0;
point smallest(INT_MAX, INT_MAX), cur;
for (ui32 r = 0; r <= max_decompositions; ++r)
{
if (!comps[c].get_top_left_precinct(r, cur)) //res exist?
continue;
else
found = true;
if (cur.y < smallest.y)
{ smallest = cur; res_num = r; }
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; res_num = r; }
}
if (found == true && data_left > 0)
comps[c].parse_one_precinct(res_num, data_left, file);
else
break;
}
}
}
else
assert(0);
}
catch (const char *error)
{
if (resilient)
OJPH_INFO(0x00030092, "%s", error)
else
OJPH_ERROR(0x00030092, "%s", error)
}
file->seek((si64)tile_end_location, infile_base::OJPH_SEEK_SET);
}
}
}
ojph::infile_base
Definition ojph_file.h:267
ojph::infile_base::seek
seek
Definition ojph_file.h:269
ojph::infile_base::OJPH_SEEK_SET
@ OJPH_SEEK_SET
Definition ojph_file.h:270
ojph::infile_base::tell
virtual si64 tell()=0
ojph::line_buf
Definition ojph_mem.h:161
ojph::local::codestream
Definition ojph_codestream_local.h:69
ojph::local::codestream::is_resilient
bool is_resilient()
Definition ojph_codestream_local.h:105
ojph::local::codestream::get_profile
si32 get_profile() const
Definition ojph_codestream_local.h:119
ojph::local::codestream::get_tilepart_div
ui32 get_tilepart_div() const
Definition ojph_codestream_local.h:120
ojph::local::codestream::get_coc
const param_cod * get_coc(ui32 comp_num)
Definition ojph_codestream_local.h:89
ojph::local::codestream::get_skipped_res_for_read
ui32 get_skipped_res_for_read()
Definition ojph_codestream_local.h:129
ojph::local::codestream::get_siz
const param_siz * get_siz()
Definition ojph_codestream_local.h:83
ojph::local::codestream::get_allocator
mem_fixed_allocator * get_allocator()
Definition ojph_codestream_local.h:97
ojph::local::codestream::get_nlt
const param_nlt * get_nlt()
Definition ojph_codestream_local.h:95
ojph::local::codestream::access_cod
ojph::param_cod access_cod()
Definition ojph_codestream_local.h:85
ojph::local::codestream::get_cod
const param_cod * get_cod()
Definition ojph_codestream_local.h:87
ojph::local::codestream::is_tlm_needed
bool is_tlm_needed() const
Definition ojph_codestream_local.h:121
ojph::local::tile_comp
Definition ojph_tile_comp.h:63
ojph::local::tile_comp::pre_alloc
static void pre_alloc(codestream *codestream, ui32 comp_num, const rect &comp_rect, const rect &recon_comp_rect)
Definition ojph_tile_comp.cpp:54
ojph::local::tile::num_comps
ui32 num_comps
Definition ojph_tile.h:80
ojph::local::tile::nlt_type3
ui8 * nlt_type3
Definition ojph_tile.h:93
ojph::local::tile::pull
bool pull(line_buf *, ui32 comp_num)
Definition ojph_tile.cpp:405
ojph::local::tile::resilient
bool resilient
Definition ojph_tile.h:84
ojph::local::tile::tilepart_div
ui32 tilepart_div
Definition ojph_tile.h:102
ojph::local::tile::next_tile_part
int next_tile_part
Definition ojph_tile.h:98
ojph::local::tile::lines
line_buf * lines
Definition ojph_tile.h:83
ojph::local::tile::tile_rect
rect tile_rect
Definition ojph_tile.h:79
ojph::local::tile::finalize_alloc
void finalize_alloc(codestream *codestream, const rect &tile_rect, ui32 tile_idx, ui32 &offset, ui32 &num_tileparts)
Definition ojph_tile.cpp:171
ojph::local::tile::pre_alloc
static void pre_alloc(codestream *codestream, const rect &tile_rect, const rect &recon_tile_rect, ui32 &num_tileparts)
Definition ojph_tile.cpp:56
ojph::local::tile::need_tlm
bool need_tlm
Definition ojph_tile.h:103
ojph::local::tile::prepare_for_flush
void prepare_for_flush()
Definition ojph_tile.cpp:501
ojph::local::tile::comps
tile_comp * comps
Definition ojph_tile.h:81
ojph::local::tile::fill_tlm
void fill_tlm(param_tlm *tlm)
Definition ojph_tile.cpp:510
ojph::local::tile::recon_comp_rects
rect * recon_comp_rects
Definition ojph_tile.h:86
ojph::local::tile::reversible
bool * reversible
Definition ojph_tile.h:85
ojph::local::tile::profile
int profile
Definition ojph_tile.h:101
ojph::local::tile::num_bytes
ui32 num_bytes
Definition ojph_tile.h:105
ojph::local::tile::is_signed
bool * is_signed
Definition ojph_tile.h:91
ojph::local::tile::flush
void flush(outfile_base *file)
Definition ojph_tile.cpp:564
ojph::local::tile::num_lines
ui32 num_lines
Definition ojph_tile.h:82
ojph::local::tile::cur_line
ui32 * cur_line
Definition ojph_tile.h:92
ojph::local::tile::prog_order
int prog_order
Definition ojph_tile.h:94
ojph::local::tile::skipped_res_for_read
ui32 skipped_res_for_read
Definition ojph_tile.h:88
ojph::local::tile::sot
param_sot sot
Definition ojph_tile.h:97
ojph::local::tile::push
bool push(line_buf *line, ui32 comp_num)
Definition ojph_tile.cpp:312
ojph::local::tile::employ_color_transform
bool employ_color_transform
Definition ojph_tile.h:84
ojph::local::tile::comp_rects
rect * comp_rects
Definition ojph_tile.h:86
ojph::local::tile::parse_tile_header
void parse_tile_header(const param_sot &sot, infile_base *file, const ui64 &tile_start_location)
Definition ojph_tile.cpp:757
ojph::local::tile::line_offsets
ui32 * line_offsets
Definition ojph_tile.h:87
ojph::local::tile::num_bits
ui32 * num_bits
Definition ojph_tile.h:90
ojph::mem_fixed_allocator
Definition ojph_mem.h:59
ojph::mem_fixed_allocator::pre_alloc_data
void pre_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:72
ojph::mem_fixed_allocator::pre_alloc_obj
void pre_alloc_obj(size_t num_ele)
Definition ojph_mem.h:78
ojph::mem_fixed_allocator::post_alloc_data
T * post_alloc_data(size_t num_ele, ui32 pre_size)
Definition ojph_mem.h:112
ojph::mem_fixed_allocator::post_alloc_obj
T * post_alloc_obj(size_t num_ele)
Definition ojph_mem.h:119
ojph::outfile_base
Definition ojph_file.h:75
ojph::outfile_base::write
virtual size_t write(const void *ptr, size_t size)=0
ojph::param_cod::get_progression_order
int get_progression_order() const
Definition ojph_params.cpp:299
ojph::param_nlt::OJPH_NLT_NO_NLT
@ OJPH_NLT_NO_NLT
Definition ojph_params.h:249
ojph::param_nlt::OJPH_NLT_BINARY_COMPLEMENT_NLT
@ OJPH_NLT_BINARY_COMPLEMENT_NLT
Definition ojph_params.h:252
ojph::local
Definition ojph_bitbuffer_read.h:52
ojph::local::rct_forward
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:90
ojph::local::ict_forward
void(* ict_forward)(const float *r, const float *g, const float *b, float *y, float *cb, float *cr, ui32 repeat)
Definition ojph_colour.cpp:100
ojph::local::irv_convert_to_integer_nlt_type3
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)
Definition ojph_colour.cpp:79
ojph::local::irv_convert_to_float
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)
Definition ojph_colour.cpp:74
ojph::local::ict_backward
void(* ict_backward)(const float *y, const float *cb, const float *cr, float *r, float *g, float *b, ui32 repeat)
Definition ojph_colour.cpp:105
ojph::local::rct_backward
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:95
ojph::local::SOD
@ SOD
Definition ojph_params_local.h:146
ojph::local::irv_convert_to_integer
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)
Definition ojph_colour.cpp:69
ojph::local::swap_byte
static ui16 swap_byte(ui16 t)
Definition ojph_codestream_local.h:58
ojph::local::irv_convert_to_float_nlt_type3
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)
Definition ojph_colour.cpp:84
ojph::local::rev_convert_nlt_type3
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:63
ojph::local::rev_convert
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:57
ojph
Definition ojph_img_io.h:52
ojph::si64
int64_t si64
Definition ojph_defs.h:57
ojph::OJPH_PO_LRCP
@ OJPH_PO_LRCP
Definition ojph_params_local.h:59
ojph::OJPH_PO_RLCP
@ OJPH_PO_RLCP
Definition ojph_params_local.h:60
ojph::OJPH_PO_CPRL
@ OJPH_PO_CPRL
Definition ojph_params_local.h:63
ojph::OJPH_PO_PCRL
@ OJPH_PO_PCRL
Definition ojph_params_local.h:62
ojph::OJPH_PO_RPCL
@ OJPH_PO_RPCL
Definition ojph_params_local.h:61
ojph::ui64
uint64_t ui64
Definition ojph_defs.h:56
ojph::ui16
uint16_t ui16
Definition ojph_defs.h:52
ojph::OJPH_TILEPART_RESOLUTIONS
@ OJPH_TILEPART_RESOLUTIONS
Definition ojph_params_local.h:100
ojph::OJPH_TILEPART_NO_DIVISIONS
@ OJPH_TILEPART_NO_DIVISIONS
Definition ojph_params_local.h:99
ojph::OJPH_TILEPART_COMPONENTS
@ OJPH_TILEPART_COMPONENTS
Definition ojph_params_local.h:101
ojph::OJPH_TILEPART_MASK
@ OJPH_TILEPART_MASK
Definition ojph_params_local.h:103
ojph::si32
int32_t si32
Definition ojph_defs.h:55
ojph::error
message_error error
Definition ojph_message.cpp:134
ojph::ui32
uint32_t ui32
Definition ojph_defs.h:54
ojph::ui8
uint8_t ui8
Definition ojph_defs.h:50
ojph_codestream_local.h
ojph_colour.h
ojph_max
#define ojph_max(a, b)
Definition ojph_defs.h:73
ojph_div_ceil
#define ojph_div_ceil(a, b)
Definition ojph_defs.h:70
ojph_mem.h
OJPH_INFO
#define OJPH_INFO(t,...)
MACROs to insert file and line number for info, warning, and error.
Definition ojph_message.h:284
OJPH_ERROR
#define OJPH_ERROR(t,...)
Definition ojph_message.h:288
ojph_params.h
ojph_tile.h
ojph_tile_comp.h
ojph::local::param_cod
Definition ojph_params_local.h:385
ojph::local::param_cod::is_employing_color_transform
bool is_employing_color_transform() const
Definition ojph_params_local.h:537
ojph::local::param_cod::get_num_decompositions
ui8 get_num_decompositions() const
Definition ojph_params_local.h:504
ojph::local::param_cod::is_reversible
bool is_reversible() const
Definition ojph_params.cpp:841
ojph::local::param_nlt
Definition ojph_params_local.h:802
ojph::local::param_nlt::get_nonlinear_transform
bool get_nonlinear_transform(ui32 comp_num, ui8 &bit_depth, bool &is_signed, ui8 &nl_type) const
Definition ojph_params.cpp:1954
ojph::local::param_siz
Definition ojph_params_local.h:166
ojph::local::param_siz::get_bit_depth
ui32 get_bit_depth(ui32 comp_num) const
Definition ojph_params_local.h:252
ojph::local::param_siz::is_signed
bool is_signed(ui32 comp_num) const
Definition ojph_params_local.h:257
ojph::local::param_siz::get_num_components
ui16 get_num_components() const
Definition ojph_params_local.h:251
ojph::local::param_siz::get_recon_downsampling
point get_recon_downsampling(ui32 comp_num) const
Definition ojph_params.cpp:749
ojph::local::param_siz::get_downsampling
point get_downsampling(ui32 comp_num) const
Definition ojph_params_local.h:262
ojph::local::param_sot
Definition ojph_params_local.h:925
ojph::local::param_tlm
Definition ojph_params_local.h:962
ojph::local::param_tlm::set_next_pair
void set_next_pair(ui16 Ttlm, ui32 Ptlm)
Definition ojph_params.cpp:2239
ojph::point
Definition ojph_base.h:58
ojph::point::y
ui32 y
Definition ojph_base.h:60
ojph::point::x
ui32 x
Definition ojph_base.h:60
ojph::rect
Definition ojph_base.h:65
ojph::rect::siz
size siz
Definition ojph_base.h:67
ojph::rect::org
point org
Definition ojph_base.h:66
ojph::size::w
ui32 w
Definition ojph_base.h:50
ojph::size::h
ui32 h
Definition ojph_base.h:51