diff --git a/src/core/codestream/ojph_params.cpp b/src/core/codestream/ojph_params.cpp index f56a793..54e884e 100644 --- a/src/core/codestream/ojph_params.cpp +++ b/src/core/codestream/ojph_params.cpp @@ -372,17 +372,17 @@ namespace ojph { // //////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - void param_nlt::set_type3_transformation(ui32 comp_num, bool enable) + //////////////////////////////////////////////////////////////////////////// + void param_nlt::set_nonlinearity(ui32 comp_num, nonlinearity type) { - state->set_type3_transformation(comp_num, enable); + state->set_nonlinearity(comp_num, type); } - ////////////////////////////////////////////////////////////////////////// - bool param_nlt::get_type3_transformation(ui32 comp_num, ui8& bit_depth, - bool& is_signed) + //////////////////////////////////////////////////////////////////////////// + bool param_nlt::get_nonlinearity(ui32 comp_num, ui8& bit_depth, + bool& is_signed, nonlinearity& type) const { - return state->get_type3_transformation(comp_num, bit_depth, is_signed); + return state->get_nonlinearity(comp_num, bit_depth, is_signed, type); } //////////////////////////////////////////////////////////////////////////// @@ -1333,7 +1333,7 @@ namespace ojph { // first stage; find out if all components captured by the default // entry (ALL_COMPS) has the same bit_depth/signedness, - // while doing this, set the BDnlt for components not captured but the + // while doing this, set the BDnlt for components not captured by the // default entry (ALL_COMPS) ui32 bit_depth = 0; // unknown yet bool is_signed = false; // unknown yet @@ -1405,23 +1405,29 @@ namespace ojph { trim_non_existing_components(num_comps); - if (is_any_enabled() == false) - return; - siz.set_Rsiz_flag(param_siz::RSIZ_EXT_FLAG | param_siz::RSIZ_NLT_FLAG); + if (is_any_enabled() == true) + siz.set_Rsiz_flag(param_siz::RSIZ_EXT_FLAG | param_siz::RSIZ_NLT_FLAG); } ////////////////////////////////////////////////////////////////////////// - void param_nlt::set_type3_transformation(ui32 comp_num, bool enable) + void param_nlt::set_nonlinearity(ui32 comp_num, nonlinearity type) { + if (type != ojph::param_nlt::OJPH_NLT_NO_NLT && + type != ojph::param_nlt::OJPH_NLT_BINARY_COMPLEMENT_NLT) + OJPH_ERROR(0x00050171, "Nonliearity other than types 0 " + "(No Nonlinearity) and 3 (Binary Binary Complement to Sign Magnitude " + "Conversion) is not supported yet"); param_nlt* p = get_comp_object(comp_num); if (p == NULL) p = add_object(comp_num); - p->enabled = enable; + p->Tnlt = type; + p->enabled = true; } ////////////////////////////////////////////////////////////////////////// - bool param_nlt::get_type3_transformation(ui32 comp_num, ui8& bit_depth, - bool& is_signed) const + bool + param_nlt::get_nonlinearity(ui32 comp_num, ui8& bit_depth, bool& is_signed, + nonlinearity& type) const { const param_nlt* p = get_comp_object(comp_num); p = p ? p : this; @@ -1430,8 +1436,10 @@ namespace ojph { bit_depth = (ui8)((p->BDnlt & 0x7F) + 1); bit_depth = bit_depth <= 38 ? bit_depth : 38; is_signed = (p->BDnlt & 0x80) == 0x80; + type = (nonlinearity)p->Tnlt; + return true; } - return p->enabled; + return false; } ////////////////////////////////////////////////////////////////////////// @@ -1499,14 +1507,10 @@ namespace ojph { ////////////////////////////////////////////////////////////////////////// const param_nlt* param_nlt::get_comp_object(ui32 comp_num) const { - if (Cnlt == comp_num) - return this; - else { - param_nlt* p = next; - while (p && p->Cnlt != comp_num) - p = p->next; - return p; - } + const param_nlt* p = this; + while (p && p->Cnlt != comp_num) + p = p->next; + return p; } ////////////////////////////////////////////////////////////////////////// @@ -1540,8 +1544,11 @@ namespace ojph { { param_nlt* p = this->next; while (p) { - if (p->enabled == true && p->Cnlt >= num_comps) + if (p->enabled == true && p->Cnlt >= num_comps) { p->enabled = false; + OJPH_INFO(0x00050161, "We are removing the NLT marker segment " + "for the non-existing component %d", p->Cnlt); + } p = p->next; } } diff --git a/src/core/codestream/ojph_params_local.h b/src/core/codestream/ojph_params_local.h index b458ca5..23547cb 100644 --- a/src/core/codestream/ojph_params_local.h +++ b/src/core/codestream/ojph_params_local.h @@ -673,12 +673,13 @@ namespace ojph { struct param_nlt { using special_comp_num = ojph::param_nlt::special_comp_num; + using nonlinearity = ojph::param_nlt::nonlinearity; public: param_nlt() { Lnlt = 6; Cnlt = special_comp_num::ALL_COMPS; // default BDnlt = 0; - Tnlt = 3; + Tnlt = nonlinearity::OJPH_NLT_NO_NLT; enabled = false; next = NULL; alloced_next = false; } @@ -691,9 +692,9 @@ namespace ojph { } void check_validity(param_siz& siz); - void set_type3_transformation(ui32 comp_num, bool enable); - bool get_type3_transformation(ui32 comp_num, ui8& bit_depth, - bool& is_signed) const; + void set_nonlinearity(ui32 comp_num, nonlinearity type); + bool get_nonlinearity(ui32 comp_num, ui8& bit_depth, + bool& is_signed, nonlinearity& type) const; bool write(outfile_base* file) const; void read(infile_base* file); diff --git a/src/core/common/ojph_params.h b/src/core/common/ojph_params.h index 602fd99..dfc4e91 100644 --- a/src/core/common/ojph_params.h +++ b/src/core/common/ojph_params.h @@ -141,6 +141,12 @@ namespace ojph { { public: enum special_comp_num : ui16 { ALL_COMPS = 65535 }; + enum nonlinearity : ui8 { + OJPH_NLT_NO_NLT = 0, // supported + OJPH_NLT_GAMMA_STYLE_NLT = 1, // not supported + OJPH_NLT_LUT_STYLE_NLT = 2, // not supported + OJPH_NLT_BINARY_COMPLEMENT_NLT = 3 // supported + }; public: param_nlt(local::param_nlt* p) : state(p) {} @@ -148,26 +154,53 @@ namespace ojph { * @brief enables or disables type 3 nonlinearity for a component * or the default setting * - * If you think that you need type 3 nonlinearity for all components, - * call this function with comp_num set to 65535 and enable to true. + * When creating a codestream for writing, call this function before + * you call codestream::write_headers. + * + * There are a few things to know here. + * The NLT marker segment contains the nonlinearity type and the + * bit depth and signedness of the component to which it applies. + * There is the default component ALL_COMPS which applies to all + * components unless it is overridden by another NLT segment marker. + * The library checks that the settings make sense, and also make + * sure that bit depth and signedness are correct, creating any missing + * NLT marker segments. + * If all components have the same bit depth and signedness, and need + * nonlinearity type 3 (Binary Complement to Sign Magnitude Conversion), + * then the best option is to set ALL_COMPS to type 3. + * Otherwise, the best option is to set type 3 only to components that + * need it, leaving out the default ALL_COMPS nonlinearity not set. + * Another option is for the end-user can set the ALL_COMPS to type 3, + * and then put exception for the components that does not need type 3, + * by setting them to type 0. + * + * It also worth noting that type 3 nonlinearity has no effect on + * positive image samples. It is also not recommended for integer-valued + * types. It is only recommended for floating-points image samples for + * which some of the samples are negative, where type 3 nonlinearity + * should be beneficial. This is because the encoding engine expects + * two-complement representation for negative values while floating point + * numbers have a sign bit followed by an exponent, which has a biased + * integer representation. The core idea is to make floating-point + * representation more compatible with integer representation. * * @param comp_num: component number, or 65535 for the default setting - * @param enable: true to enable nlt type 3 for this component or the - default setting, false to disable nlt type 3. + * @param type: desired non-linearity from enum nonlinearity */ - void set_type3_transformation(ui32 comp_num, bool enable); + void set_nonlinearity(ui32 comp_num, nonlinearity type); /** - * @brief get the state (enabled or disabled) of type 3 nonlinearity - * for a component or the default setting + * @brief get the nonlinearity type associated with comp_num, which + * should be one from enum nonlinearity * * @param comp_num: component number, or 65535 for the default setting * @param bit_depth: returns the bit depth of the component/default * @param is_signed: returns true if the component/default is signed - * @return true if enabled or false if not. + * @param type: nonlinearity type + * @return true if the nonlinearity for comp_num is set */ - bool get_type3_transformation(ui32 comp_num, ui8& bit_depth, - bool& is_signed); + bool get_nonlinearity(ui32 comp_num, ui8& bit_depth, + bool& is_signed, nonlinearity& type) const; private: local::param_nlt* state;