Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting differing components in QCD #169

Merged
merged 6 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/apps/ojph_compress/ojph_compress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,11 +834,20 @@ int main(int argc, char * argv[]) {

ojph::param_nlt nlt = codestream.access_nlt();
if (reversible) {
// Note: Even if only ALL_COMPS is set to
// OJPH_NLT_BINARY_COMPLEMENT_NLT, the library can decide if
// one ALL_COMPS NLT marker segment is needed, or multiple
// per component NLT marker segments are needed (when the components
// have different bit depths or signedness).
// Of course for .pfm images all components should have the same
// bit depth and signedness.
if (all_the_same)
nlt.set_type3_transformation(ojph::param_nlt::ALL_COMPS, true);
nlt.set_nonlinear_transform(ojph::param_nlt::ALL_COMPS,
ojph::param_nlt::OJPH_NLT_BINARY_COMPLEMENT_NLT);
else
for (ojph::ui32 c = 0; c < num_comps; ++c)
nlt.set_type3_transformation(c, true);
nlt.set_nonlinear_transform(c,
ojph::param_nlt::OJPH_NLT_BINARY_COMPLEMENT_NLT);
}
else
OJPH_ERROR(0x01000093, "We currently support lossless only for "
Expand Down
12 changes: 10 additions & 2 deletions src/apps/ojph_expand/ojph_expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ int main(int argc, char *argv[]) {
}
else if (is_matching(".pfm", v))
{
OJPH_INFO(0x02000011, "Note: The .pfm implementation is "
"experimental. It is developed for me the test NLT marker segments. "
"For this reason, I am restricting it to images that employ the "
"NLT marker segment, with the assumption that original values are "
"floating-point numbers.");

codestream.set_planar(false);
ojph::param_siz siz = codestream.access_siz();
ojph::param_cod cod = codestream.access_cod();
Expand All @@ -294,8 +300,10 @@ int main(int argc, char *argv[]) {
for (ojph::ui32 c = 0; c < siz.get_num_components(); ++c) {
ojph::ui8 bd = 0;
bool is = true;
bool result = nlt.get_type3_transformation(c, bd, is);
if (result == false)
ojph::ui8 nl_type;
bool result = nlt.get_nonlinear_transform(c, bd, is, nl_type);
if (result == false ||
nl_type != ojph::param_nlt::OJPH_NLT_BINARY_COMPLEMENT_NLT)
OJPH_ERROR(0x0200000E,
"This codestream is not supported; it does not have an "
"NLT segment marker for this component (or no default NLT "
Expand Down
22 changes: 8 additions & 14 deletions src/core/codestream/ojph_codeblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,15 @@ namespace ojph {
{

//////////////////////////////////////////////////////////////////////////
void codeblock::pre_alloc(codestream *codestream, ui32 comp_num,
const size& nominal)
void codeblock::pre_alloc(codestream *codestream, const size& nominal,
ui32 precision)
{
mem_fixed_allocator* allocator = codestream->get_allocator();

assert(byte_alignment / sizeof(ui32) > 1);
const ui32 f = byte_alignment / sizeof(ui32) - 1;
ui32 stride = (nominal.w + f) & ~f; // a multiple of 8

const param_siz* sz = codestream->get_siz();
const param_cod* cd = codestream->get_cod(comp_num);
ui32 precision = cd->propose_precision(sz, comp_num);

if (precision <= 32)
allocator->pre_alloc_data<ui32>(nominal.h * (size_t)stride, 0);
else
Expand All @@ -76,24 +73,21 @@ namespace ojph {
subband *parent, const size& nominal,
const size& cb_size,
coded_cb_header* coded_cb,
ui32 K_max, int line_offset)
ui32 K_max, int line_offset,
ui32 precision)
{
mem_fixed_allocator* allocator = codestream->get_allocator();

const ui32 f = byte_alignment / sizeof(ui32) - 1;
this->stride = (nominal.w + f) & ~f; // a multiple of 8
this->buf_size = this->stride * nominal.h;

ui32 comp_num = parent->get_parent()->get_comp_num();
const param_siz* sz = codestream->get_siz();
const param_cod* cd = codestream->get_cod(comp_num);
ui32 bit_depth = cd->propose_precision(sz, comp_num);
if (bit_depth <= 32) {
precision = BUF32;
if (precision <= 32) {
this->precision = BUF32;
this->buf32 = allocator->post_alloc_data<ui32>(this->buf_size, 0);
}
else {
precision = BUF64;
this->precision = BUF64;
this->buf64 = allocator->post_alloc_data<ui64>(this->buf_size, 0);
}

Expand Down
6 changes: 3 additions & 3 deletions src/core/codestream/ojph_codeblock.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ namespace ojph {
};

public:
static void pre_alloc(codestream *codestream, ui32 comp_num,
const size& nominal);
static void pre_alloc(codestream *codestream, const size& nominal,
ui32 precision);
void finalize_alloc(codestream *codestream, subband* parent,
const size& nominal, const size& cb_size,
coded_cb_header* coded_cb,
ui32 K_max, int tbx0);
ui32 K_max, int tbx0, ui32 precision);
void push(line_buf *line);
void encode(mem_elastic_allocator *elastic);
void recreate(const size& cb_size, coded_cb_header* coded_cb);
Expand Down
28 changes: 15 additions & 13 deletions src/core/codestream/ojph_codestream_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ namespace ojph {

precinct_scratch_needed_bytes = 0;

used_qcc_fields = 0;
qcc = qcc_store;
used_coc_fields = 0;
coc = coc_store;

Expand All @@ -100,8 +98,6 @@ namespace ojph {
////////////////////////////////////////////////////////////////////////////
codestream::~codestream()
{
if (qcc_store != qcc)
delete[] qcc;
if (allocator)
delete allocator;
if (elastic_alloc)
Expand Down Expand Up @@ -633,6 +629,9 @@ namespace ojph {
if (!qcd.write(file))
OJPH_ERROR(0x00030026, "Error writing to file");

if (!qcd.write_qcc(file, num_comps))
OJPH_ERROR(0x0003002D, "Error writing to file");

if (!nlt.write(file))
OJPH_ERROR(0x00030027, "Error writing to file");

Expand Down Expand Up @@ -766,9 +765,7 @@ namespace ojph {
ui32 num_comps = siz.get_num_components();
if (coc == coc_store &&
num_comps * sizeof(param_cod) > sizeof(coc_store))
{
coc = new param_cod[num_comps];
}
coc[used_coc_fields++].read(
file, param_cod::COC_MAIN, num_comps, &cod);
}
Expand All @@ -779,13 +776,18 @@ namespace ojph {
}
else if (marker_idx == 6)
{
ui32 num_comps = siz.get_num_components();
if (qcc == qcc_store &&
num_comps * sizeof(param_qcc) > sizeof(qcc_store))
{
qcc = new param_qcc[num_comps];
}
qcc[used_qcc_fields++].read(file, num_comps);
param_qcd* p = qcd.add_qcc_object(param_qcd::OJPH_QCD_UNKNOWN);
p->read_qcc(file, siz.get_num_components());
if (p->get_comp_idx() >= siz.get_num_components())
OJPH_ERROR(0x00030054, "The codestream carries a QCC narker "
"segment for a component indexed by %d, which is more than the "
"allowed index number, since the codestream has %d components",
p->get_comp_idx(), num_comps);
param_qcd *q = qcd.get_qcc(p->get_comp_idx());
if (p != q && p->get_comp_idx() == q->get_comp_idx())
OJPH_ERROR(0x00030055, "The codestream has two QCC marker "
"segments for one component of index %d",
p->get_comp_idx());
}
else if (marker_idx == 7)
skip_marker(file, "RGN", "RGN is not supported yet",
Expand Down
19 changes: 4 additions & 15 deletions src/core/codestream/ojph_codestream_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,10 @@ namespace ojph {
{ return ojph::param_cod(&cod); }
const param_cod* get_cod() //return internal cod
{ return &cod; }
const param_cod* get_cod(ui32 comp_num) //return internal cod
{ return cod.get_cod(comp_num); }
param_qcd* access_qcd(ui32 comp_num)
{
if (used_qcc_fields > 0)
for (int v = 0; v < used_qcc_fields; ++v)
if (qcc[v].get_comp_num() == comp_num)
return qcc + v;
return &qcd;
}
const param_cod* get_coc(ui32 comp_num) //return internal cod
{ return cod.get_coc(comp_num); }
const param_qcd* access_qcd()
{ return &qcd; }
const param_dfs* access_dfs()
{ if (dfs.exists()) return &dfs; else return NULL; }
const param_nlt* get_nlt()
Expand Down Expand Up @@ -166,9 +160,6 @@ namespace ojph {
param_nlt nlt; // non-linearity point transformation

private: // this is to handle qcc and coc
int used_qcc_fields;
param_qcc *qcc; // quantization component
param_qcc qcc_store[4]; // we allocate 4, we allocate more if needed
int used_coc_fields;
param_cod *coc; // coding style component
param_cod coc_store[4]; // we allocate 4, we allocate more if needed
Expand All @@ -178,8 +169,6 @@ namespace ojph {
param_atk* atk; // a pointer to atk
param_atk atk_store[3];// 0 and 1 are for DWT from Part 1, 2 onward are
// for arbitrary transformation kernels


private:
mem_fixed_allocator *allocator;
mem_elastic_allocator *elastic_alloc;
Expand Down
Loading
Loading