mirror of
https://github.com/team-charls/charls
synced 2025-03-28 21:03:13 +00:00
Improve names and reduce line buffer (#312)
- Move constant values that are only used once to the method that uses these constant values (reduces scope) - Rename context_regular_mode to regular_mode_context and context_run_mode to run_mode_context - Reduce the line buffer from 4 extra items to 2 (2 are needed for the borders). - Replace dynamic run_index buffer with static buffer (max size is only 4 items)
This commit is contained in:
parent
1127459953
commit
1460f8df5f
@ -106,8 +106,6 @@ target_sources(charls
|
||||
"${CMAKE_CURRENT_LIST_DIR}/color_transform.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/conditional_static_cast.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/constants.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/context_regular_mode.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/context_run_mode.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/default_traits.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/golomb_lut.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/golomb_lut.cpp"
|
||||
@ -127,6 +125,8 @@ target_sources(charls
|
||||
"${CMAKE_CURRENT_LIST_DIR}/process_encoded_line.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/quantization_lut.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/quantization_lut.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/regular_mode_context.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/run_mode_context.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/scan_codec.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/scan_decoder.h"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/scan_decoder_impl.h"
|
||||
|
@ -236,8 +236,8 @@
|
||||
<ClInclude Include="color_transform.h" />
|
||||
<ClInclude Include="conditional_static_cast.h" />
|
||||
<ClInclude Include="constants.h" />
|
||||
<ClInclude Include="context_regular_mode.h" />
|
||||
<ClInclude Include="context_run_mode.h" />
|
||||
<ClInclude Include="regular_mode_context.h" />
|
||||
<ClInclude Include="run_mode_context.h" />
|
||||
<ClInclude Include="process_encoded_line.h" />
|
||||
<ClInclude Include="scan_decoder.h" />
|
||||
<ClInclude Include="default_traits.h" />
|
||||
|
@ -33,7 +33,7 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="context_regular_mode.h">
|
||||
<ClInclude Include="regular_mode_context.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="scan_encoder_impl.h">
|
||||
@ -57,7 +57,7 @@
|
||||
<ClInclude Include="color_transform.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="context_run_mode.h">
|
||||
<ClInclude Include="run_mode_context.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="scan_decoder.h">
|
||||
|
@ -3,22 +3,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
namespace charls {
|
||||
|
||||
// Default threshold values for JPEG-LS statistical modeling as defined in ISO/IEC 14495-1, table C.3
|
||||
// for the case MAXVAL = 255 and NEAR = 0.
|
||||
// Can be overridden at compression time, however this is rarely done.
|
||||
constexpr int default_threshold1{3}; // BASIC_T1
|
||||
constexpr int default_threshold2{7}; // BASIC_T2
|
||||
constexpr int default_threshold3{21}; // BASIC_T3
|
||||
|
||||
constexpr int default_reset_value{64}; // Default RESET value as defined in ISO/IEC 14495-1, table C.2
|
||||
constexpr int32_t default_reset_value{64}; // Default RESET value as defined in ISO/IEC 14495-1, table C.2
|
||||
|
||||
constexpr int32_t maximum_component_count{255};
|
||||
constexpr size_t maximum_component_count_in_scan{4};
|
||||
constexpr int32_t minimum_component_index{};
|
||||
constexpr int32_t maximum_component_index{maximum_component_count - 1};
|
||||
constexpr int32_t minimum_bits_per_sample{2};
|
||||
@ -33,18 +27,7 @@ constexpr int32_t maximum_table_id{255};
|
||||
constexpr int32_t minimum_entry_size{1};
|
||||
constexpr int32_t maximum_entry_size{255};
|
||||
|
||||
constexpr int max_k_value{16}; // This is an implementation limit (theoretical limit is 32)
|
||||
|
||||
constexpr int compute_maximum_near_lossless(const int maximum_sample_value) noexcept
|
||||
{
|
||||
return std::min(maximum_near_lossless, maximum_sample_value / 2); // As defined by ISO/IEC 14495-1, C.2.3
|
||||
}
|
||||
|
||||
// Computes the initial value for A. See ISO/IEC 14495-1, A.8, step 1.d and A.2.1
|
||||
constexpr int32_t initialization_value_for_a(const int32_t range) noexcept
|
||||
{
|
||||
return std::max(2, (range + 32) / 64);
|
||||
}
|
||||
constexpr int32_t max_k_value{16}; // This is an implementation limit (theoretical limit is 32)
|
||||
|
||||
// ISO/IEC 14495-1, section 4.8.1 defines the SPIFF version numbers to be used for the SPIFF header in combination with
|
||||
// JPEG-LS.
|
||||
|
@ -547,7 +547,7 @@ void jpeg_stream_reader::read_start_of_scan_segment()
|
||||
const size_t component_count_in_scan{read_uint8()};
|
||||
|
||||
// ISO 10918-1, B2.3. defines the limits for the number of image components parameter in an SOS.
|
||||
if (UNLIKELY(component_count_in_scan < 1U || component_count_in_scan > 4U ||
|
||||
if (UNLIKELY(component_count_in_scan == 0U || component_count_in_scan > maximum_component_count_in_scan ||
|
||||
component_count_in_scan > static_cast<size_t>(frame_info_.component_count)))
|
||||
throw_jpegls_error(jpegls_errc::invalid_parameter_component_count);
|
||||
|
||||
|
@ -8,6 +8,19 @@
|
||||
|
||||
namespace charls {
|
||||
|
||||
constexpr int compute_maximum_near_lossless(const int maximum_sample_value) noexcept
|
||||
{
|
||||
return std::min(maximum_near_lossless, maximum_sample_value / 2); // As defined by ISO/IEC 14495-1, C.2.3
|
||||
}
|
||||
|
||||
|
||||
// Computes the initial value for A. See ISO/IEC 14495-1, A.8, step 1.d and A.2.1
|
||||
constexpr int32_t initialization_value_for_a(const int32_t range) noexcept
|
||||
{
|
||||
return std::max(2, (range + 32) / 64);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is the optimized inverse algorithm of ISO/IEC 14495-1, A.5.2, Code Segment A.11 (second else branch)
|
||||
/// It will map unsigned values back to signed values.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "charls/public_types.h"
|
||||
#include "constants.h"
|
||||
#include "jpegls_algorithm.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -24,6 +24,12 @@ inline jpegls_pc_parameters compute_default(const int32_t maximum_sample_value,
|
||||
ASSERT(maximum_sample_value <= std::numeric_limits<uint16_t>::max());
|
||||
ASSERT(near_lossless >= 0 && near_lossless <= compute_maximum_near_lossless(maximum_sample_value));
|
||||
|
||||
// Default threshold values for JPEG-LS statistical modeling as defined in ISO/IEC 14495-1, table C.3
|
||||
// for the case MAXVAL = 255 and NEAR = 0.
|
||||
constexpr int default_threshold1{3}; // BASIC_T1
|
||||
constexpr int default_threshold2{7}; // BASIC_T2
|
||||
constexpr int default_threshold3{21}; // BASIC_T3
|
||||
|
||||
if (maximum_sample_value >= 128)
|
||||
{
|
||||
const int32_t factor{(std::min(maximum_sample_value, 4095) + 128) / 256};
|
||||
@ -91,7 +97,8 @@ inline bool is_valid(const jpegls_pc_parameters& pc_parameters, const int32_t ma
|
||||
(pc_parameters.threshold1 < near_lossless + 1 || pc_parameters.threshold1 > maximum_sample_value))
|
||||
return false;
|
||||
|
||||
const auto [_, d_threshold1, d_threshold2, d_threshold3, d_reset_value]{compute_default(maximum_sample_value, near_lossless)};
|
||||
const auto [_, d_threshold1, d_threshold2, d_threshold3,
|
||||
d_reset_value]{compute_default(maximum_sample_value, near_lossless)};
|
||||
if (const int32_t threshold1{pc_parameters.threshold1 != 0 ? pc_parameters.threshold1 : d_threshold1};
|
||||
pc_parameters.threshold2 != 0 &&
|
||||
(pc_parameters.threshold2 < threshold1 || pc_parameters.threshold2 > maximum_sample_value))
|
||||
@ -109,14 +116,10 @@ inline bool is_valid(const jpegls_pc_parameters& pc_parameters, const int32_t ma
|
||||
if (validated_parameters)
|
||||
{
|
||||
validated_parameters->maximum_sample_value = maximum_sample_value;
|
||||
validated_parameters->threshold1 =
|
||||
pc_parameters.threshold1 != 0 ? pc_parameters.threshold1 : d_threshold1;
|
||||
validated_parameters->threshold2 =
|
||||
pc_parameters.threshold2 != 0 ? pc_parameters.threshold2 : d_threshold2;
|
||||
validated_parameters->threshold3 =
|
||||
pc_parameters.threshold3 != 0 ? pc_parameters.threshold3 : d_threshold3;
|
||||
validated_parameters->reset_value =
|
||||
pc_parameters.reset_value != 0 ? pc_parameters.reset_value : d_reset_value;
|
||||
validated_parameters->threshold1 = pc_parameters.threshold1 != 0 ? pc_parameters.threshold1 : d_threshold1;
|
||||
validated_parameters->threshold2 = pc_parameters.threshold2 != 0 ? pc_parameters.threshold2 : d_threshold2;
|
||||
validated_parameters->threshold3 = pc_parameters.threshold3 != 0 ? pc_parameters.threshold3 : d_threshold3;
|
||||
validated_parameters->reset_value = pc_parameters.reset_value != 0 ? pc_parameters.reset_value : d_reset_value;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -15,12 +15,12 @@ namespace charls {
|
||||
/// to maintain the statistic information for the context modeling.
|
||||
/// As the operations on these variables use the same index it is more efficient to combine A,B,C and N.
|
||||
/// </summary>
|
||||
class context_regular_mode final
|
||||
class regular_mode_context final
|
||||
{
|
||||
public:
|
||||
context_regular_mode() = default;
|
||||
regular_mode_context() = default;
|
||||
|
||||
explicit context_regular_mode(const int32_t range) noexcept : a_{initialization_value_for_a(range)}
|
||||
explicit regular_mode_context(const int32_t range) noexcept : a_{initialization_value_for_a(range)}
|
||||
{
|
||||
}
|
||||
|
||||
@ -63,8 +63,8 @@ public:
|
||||
ASSERT(n_ != 0);
|
||||
|
||||
// This part is from: Code segment A.13 – Update of bias-related variables B[Q] and C[Q]
|
||||
constexpr int32_t max_c{127}; // Minimum allowed value of c_[0..364]. ISO 14495-1, section 3.3
|
||||
constexpr int32_t min_c{-128}; // Minimum allowed value of c_[0..364]. ISO 14495-1, section 3.3
|
||||
constexpr int32_t max_c{127}; // MAX_C: maximum allowed value of C[0..364]. ISO 14495-1, section 3.3
|
||||
constexpr int32_t min_c{-128}; // MIN_C: Minimum allowed value of C[0..364]. ISO 14495-1, section 3.3
|
||||
if (b_ + n_ <= 0)
|
||||
{
|
||||
b_ += n_;
|
@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "constants.h"
|
||||
#include "jpegls_algorithm.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <cassert>
|
||||
@ -16,12 +16,12 @@ namespace charls {
|
||||
/// to maintain the statistic information for the context modeling.
|
||||
/// Index 365 and 366 are used for run mode interruption contexts.
|
||||
/// </summary>
|
||||
class context_run_mode final
|
||||
class run_mode_context final
|
||||
{
|
||||
public:
|
||||
context_run_mode() = default;
|
||||
run_mode_context() = default;
|
||||
|
||||
context_run_mode(const int32_t run_interruption_type, const int32_t range) noexcept :
|
||||
run_mode_context(const int32_t run_interruption_type, const int32_t range) noexcept :
|
||||
run_interruption_type_{run_interruption_type}, a_{initialization_value_for_a(range)}
|
||||
{
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "context_regular_mode.h"
|
||||
#include "context_run_mode.h"
|
||||
#include "regular_mode_context.h"
|
||||
#include "run_mode_context.h"
|
||||
#include "jpegls_algorithm.h"
|
||||
#include "quantization_lut.h"
|
||||
#include "coding_parameters.h"
|
||||
@ -147,14 +147,14 @@ protected:
|
||||
|
||||
void reset_parameters(const int32_t range) noexcept
|
||||
{
|
||||
const context_regular_mode context_initial_value(range);
|
||||
for (auto& context : contexts_)
|
||||
const regular_mode_context context_initial_value(range);
|
||||
for (auto& context : regular_mode_contexts_)
|
||||
{
|
||||
context = context_initial_value;
|
||||
}
|
||||
|
||||
context_run_mode_[0] = context_run_mode(0, range);
|
||||
context_run_mode_[1] = context_run_mode(1, range);
|
||||
run_mode_contexts_[0] = run_mode_context(0, range);
|
||||
run_mode_contexts_[1] = run_mode_context(1, range);
|
||||
run_index_ = 0;
|
||||
}
|
||||
|
||||
@ -174,8 +174,8 @@ protected:
|
||||
int32_t t2_{};
|
||||
int32_t t3_{};
|
||||
int32_t run_index_{};
|
||||
std::array<context_regular_mode, 365> contexts_;
|
||||
std::array<context_run_mode, 2> context_run_mode_;
|
||||
std::array<regular_mode_context, 365> regular_mode_contexts_;
|
||||
std::array<run_mode_context, 2> run_mode_contexts_;
|
||||
uint32_t width_;
|
||||
uint8_t reset_value_{};
|
||||
|
||||
|
@ -54,12 +54,12 @@ protected:
|
||||
fill_read_cache();
|
||||
}
|
||||
|
||||
FORCE_INLINE void skip(const int32_t length) noexcept
|
||||
FORCE_INLINE void skip_bits(const int32_t bit_count) noexcept
|
||||
{
|
||||
ASSERT(length);
|
||||
ASSERT(bit_count);
|
||||
|
||||
valid_bits_ -= length; // Note: valid_bits_ may become negative to indicate that extra bits are needed.
|
||||
read_cache_ = read_cache_ << length;
|
||||
valid_bits_ -= bit_count; // Note: valid_bits_ may become negative to indicate that extra bits are needed.
|
||||
read_cache_ = read_cache_ << bit_count;
|
||||
}
|
||||
|
||||
void on_line_end(const void* source, const size_t pixel_count, const size_t pixel_stride) const
|
||||
@ -119,19 +119,20 @@ protected:
|
||||
return (high_bits << k) + read_value(k);
|
||||
}
|
||||
|
||||
FORCE_INLINE int32_t read_value(const int32_t length)
|
||||
FORCE_INLINE int32_t read_value(const int32_t bit_count)
|
||||
{
|
||||
if (valid_bits_ < length)
|
||||
ASSERT(0 < bit_count && bit_count < 32);
|
||||
|
||||
if (valid_bits_ < bit_count)
|
||||
{
|
||||
fill_read_cache();
|
||||
if (UNLIKELY(valid_bits_ < length))
|
||||
if (UNLIKELY(valid_bits_ < bit_count))
|
||||
impl::throw_jpegls_error(jpegls_errc::invalid_encoded_data);
|
||||
}
|
||||
|
||||
ASSERT(length != 0 && length <= valid_bits_);
|
||||
ASSERT(length < 32);
|
||||
const auto result{static_cast<int32_t>(read_cache_ >> (cache_t_bit_count - length))};
|
||||
skip(length);
|
||||
ASSERT(bit_count <= valid_bits_);
|
||||
const auto result{static_cast<int32_t>(read_cache_ >> (cache_t_bit_count - bit_count))};
|
||||
skip_bits(bit_count);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -153,7 +154,7 @@ protected:
|
||||
}
|
||||
|
||||
const bool set{(read_cache_ & (static_cast<cache_t>(1) << (cache_t_bit_count - 1))) != 0};
|
||||
skip(1);
|
||||
skip_bits(1);
|
||||
return set;
|
||||
}
|
||||
|
||||
@ -185,10 +186,10 @@ protected:
|
||||
{
|
||||
if (const int32_t count{peek_0_bits()}; count >= 0)
|
||||
{
|
||||
skip(count + 1);
|
||||
skip_bits(count + 1);
|
||||
return count;
|
||||
}
|
||||
skip(15);
|
||||
skip_bits(15);
|
||||
|
||||
for (int32_t high_bits_count{15};; ++high_bits_count)
|
||||
{
|
||||
@ -293,9 +294,9 @@ private:
|
||||
if (position_ < position_ff_ - (sizeof(cache_t) - 1))
|
||||
{
|
||||
read_cache_ |= read_big_endian_unaligned<cache_t>(position_) >> valid_bits_;
|
||||
const int bytes_to_read{(cache_t_bit_count - valid_bits_) / 8};
|
||||
position_ += bytes_to_read;
|
||||
valid_bits_ += bytes_to_read * 8;
|
||||
const int bytes_consumed{(cache_t_bit_count - valid_bits_) / 8};
|
||||
position_ += bytes_consumed;
|
||||
valid_bits_ += bytes_consumed * 8;
|
||||
ASSERT(valid_bits_ >= max_readable_cache_bits);
|
||||
return true;
|
||||
}
|
||||
|
@ -89,13 +89,13 @@ private:
|
||||
// In ILV_NONE mode, do_scan is called for each component
|
||||
void decode_lines()
|
||||
{
|
||||
const uint32_t pixel_stride{width_ + 4U};
|
||||
const uint32_t pixel_stride{width_ + 2U};
|
||||
const size_t component_count{
|
||||
parameters().interleave_mode == interleave_mode::line ? static_cast<size_t>(frame_info().component_count) : 1U};
|
||||
uint32_t restart_interval_counter{};
|
||||
|
||||
std::array<int32_t, maximum_component_count_in_scan> run_index{};
|
||||
std::vector<pixel_type> line_buffer(component_count * pixel_stride * 2);
|
||||
std::vector<int32_t> run_index(component_count);
|
||||
|
||||
for (uint32_t line{};;)
|
||||
{
|
||||
@ -149,8 +149,8 @@ private:
|
||||
|
||||
// After a restart marker it is required to reset the decoder.
|
||||
reset();
|
||||
std::fill(line_buffer.begin(), line_buffer.end(), pixel_type{});
|
||||
std::fill(run_index.begin(), run_index.end(), 0);
|
||||
std::fill(line_buffer.begin(), line_buffer.end(), pixel_type{});
|
||||
reset_parameters(traits_.range);
|
||||
}
|
||||
}
|
||||
@ -278,14 +278,14 @@ private:
|
||||
FORCE_INLINE sample_type decode_regular(const int32_t qs, const int32_t predicted)
|
||||
{
|
||||
const int32_t sign{bit_wise_sign(qs)};
|
||||
context_regular_mode& context{contexts_[apply_sign(qs, sign)]};
|
||||
regular_mode_context& context{regular_mode_contexts_[apply_sign(qs, sign)]};
|
||||
const int32_t k{context.get_golomb_coding_parameter()};
|
||||
const int32_t predicted_value{traits_.correct_prediction(predicted + apply_sign(context.c(), sign))};
|
||||
|
||||
int32_t error_value;
|
||||
if (const golomb_code& code = golomb_lut[k].get(peek_byte()); code.length() != 0)
|
||||
{
|
||||
skip(code.length());
|
||||
skip_bits(code.length());
|
||||
error_value = code.value();
|
||||
ASSERT(std::abs(error_value) < 65535);
|
||||
}
|
||||
@ -305,7 +305,7 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
int32_t decode_run_interruption_error(context_run_mode& context)
|
||||
int32_t decode_run_interruption_error(run_mode_context& context)
|
||||
{
|
||||
const int32_t k{context.get_golomb_code()};
|
||||
const int32_t e_mapped_error_value{
|
||||
@ -318,9 +318,9 @@ private:
|
||||
[[nodiscard]]
|
||||
triplet<sample_type> decode_run_interruption_pixel(triplet<sample_type> ra, triplet<sample_type> rb)
|
||||
{
|
||||
const int32_t error_value1{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value2{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value3{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value1{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
const int32_t error_value2{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
const int32_t error_value3{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
|
||||
return {traits_.compute_reconstructed_sample(rb.v1, error_value1 * sign(rb.v1 - ra.v1)),
|
||||
traits_.compute_reconstructed_sample(rb.v2, error_value2 * sign(rb.v2 - ra.v2)),
|
||||
@ -330,10 +330,10 @@ private:
|
||||
[[nodiscard]]
|
||||
quad<sample_type> decode_run_interruption_pixel(quad<sample_type> ra, quad<sample_type> rb)
|
||||
{
|
||||
const int32_t error_value1{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value2{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value3{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value4{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value1{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
const int32_t error_value2{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
const int32_t error_value3{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
const int32_t error_value4{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
|
||||
return {traits_.compute_reconstructed_sample(rb.v1, error_value1 * sign(rb.v1 - ra.v1)),
|
||||
traits_.compute_reconstructed_sample(rb.v2, error_value2 * sign(rb.v2 - ra.v2)),
|
||||
@ -346,11 +346,11 @@ private:
|
||||
{
|
||||
if (std::abs(ra - rb) <= traits_.near_lossless)
|
||||
{
|
||||
const int32_t error_value{decode_run_interruption_error(context_run_mode_[1])};
|
||||
const int32_t error_value{decode_run_interruption_error(run_mode_contexts_[1])};
|
||||
return static_cast<sample_type>(traits_.compute_reconstructed_sample(ra, error_value));
|
||||
}
|
||||
|
||||
const int32_t error_value{decode_run_interruption_error(context_run_mode_[0])};
|
||||
const int32_t error_value{decode_run_interruption_error(run_mode_contexts_[0])};
|
||||
return static_cast<sample_type>(traits_.compute_reconstructed_sample(rb, error_value * sign(rb - ra)));
|
||||
}
|
||||
|
||||
|
@ -88,12 +88,12 @@ private:
|
||||
// In ILV_NONE mode, do_scan is called for each component
|
||||
void encode_lines()
|
||||
{
|
||||
const uint32_t pixel_stride{width_ + 4U};
|
||||
const uint32_t pixel_stride{width_ + 2U};
|
||||
const size_t component_count{
|
||||
parameters().interleave_mode == interleave_mode::line ? static_cast<size_t>(frame_info().component_count) : 1U};
|
||||
|
||||
std::array<int32_t, maximum_component_count_in_scan> run_index{};
|
||||
std::vector<pixel_type> line_buffer(component_count * pixel_stride * 2);
|
||||
std::vector<int32_t> run_index(component_count);
|
||||
|
||||
for (uint32_t line{}; line < frame_info().height; ++line)
|
||||
{
|
||||
@ -269,7 +269,7 @@ private:
|
||||
FORCE_INLINE sample_type encode_regular(const int32_t qs, const int32_t x, const int32_t predicted)
|
||||
{
|
||||
const int32_t sign{bit_wise_sign(qs)};
|
||||
context_regular_mode& context{contexts_[apply_sign(qs, sign)]};
|
||||
regular_mode_context& context{regular_mode_contexts_[apply_sign(qs, sign)]};
|
||||
const int32_t k{context.get_golomb_coding_parameter()};
|
||||
const int32_t predicted_value{traits_.correct_prediction(predicted + apply_sign(context.c(), sign))};
|
||||
const int32_t error_value{traits_.compute_error_value(apply_sign(x - predicted_value, sign))};
|
||||
@ -309,7 +309,7 @@ private:
|
||||
traits_.quantized_bits_per_pixel);
|
||||
}
|
||||
|
||||
void encode_run_interruption_error(context_run_mode& context, const int32_t error_value)
|
||||
void encode_run_interruption_error(run_mode_context& context, const int32_t error_value)
|
||||
{
|
||||
const int32_t k{context.get_golomb_code()};
|
||||
const bool map{context.compute_map(error_value, k)};
|
||||
@ -327,12 +327,12 @@ private:
|
||||
if (std::abs(ra - rb) <= traits_.near_lossless)
|
||||
{
|
||||
const int32_t error_value{traits_.compute_error_value(x - ra)};
|
||||
encode_run_interruption_error(context_run_mode_[1], error_value);
|
||||
encode_run_interruption_error(run_mode_contexts_[1], error_value);
|
||||
return static_cast<sample_type>(traits_.compute_reconstructed_sample(ra, error_value));
|
||||
}
|
||||
|
||||
const int32_t error_value{traits_.compute_error_value((x - rb) * sign(rb - ra))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value);
|
||||
return static_cast<sample_type>(traits_.compute_reconstructed_sample(rb, error_value * sign(rb - ra)));
|
||||
}
|
||||
|
||||
@ -341,13 +341,13 @@ private:
|
||||
const triplet<sample_type> rb)
|
||||
{
|
||||
const int32_t error_value1{traits_.compute_error_value(sign(rb.v1 - ra.v1) * (x.v1 - rb.v1))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value1);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value1);
|
||||
|
||||
const int32_t error_value2{traits_.compute_error_value(sign(rb.v2 - ra.v2) * (x.v2 - rb.v2))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value2);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value2);
|
||||
|
||||
const int32_t error_value3{traits_.compute_error_value(sign(rb.v3 - ra.v3) * (x.v3 - rb.v3))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value3);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value3);
|
||||
|
||||
return {traits_.compute_reconstructed_sample(rb.v1, error_value1 * sign(rb.v1 - ra.v1)),
|
||||
traits_.compute_reconstructed_sample(rb.v2, error_value2 * sign(rb.v2 - ra.v2)),
|
||||
@ -359,16 +359,16 @@ private:
|
||||
const quad<sample_type> rb)
|
||||
{
|
||||
const int32_t error_value1{traits_.compute_error_value(sign(rb.v1 - ra.v1) * (x.v1 - rb.v1))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value1);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value1);
|
||||
|
||||
const int32_t error_value2{traits_.compute_error_value(sign(rb.v2 - ra.v2) * (x.v2 - rb.v2))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value2);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value2);
|
||||
|
||||
const int32_t error_value3{traits_.compute_error_value(sign(rb.v3 - ra.v3) * (x.v3 - rb.v3))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value3);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value3);
|
||||
|
||||
const int32_t error_value4{traits_.compute_error_value(sign(rb.v4 - ra.v4) * (x.v4 - rb.v4))};
|
||||
encode_run_interruption_error(context_run_mode_[0], error_value4);
|
||||
encode_run_interruption_error(run_mode_contexts_[0], error_value4);
|
||||
|
||||
return {traits_.compute_reconstructed_sample(rb.v1, error_value1 * sign(rb.v1 - ra.v1)),
|
||||
traits_.compute_reconstructed_sample(rb.v2, error_value2 * sign(rb.v2 - ra.v2)),
|
||||
|
@ -79,7 +79,7 @@
|
||||
<ClCompile Include="charls_jpegls_decoder_test.cpp" />
|
||||
<ClCompile Include="charls_jpegls_encoder_test.cpp" />
|
||||
<ClCompile Include="compliance_test.cpp" />
|
||||
<ClCompile Include="context_run_mode_test.cpp" />
|
||||
<ClCompile Include="run_mode_context_test.cpp" />
|
||||
<ClCompile Include="golomb_table_test.cpp" />
|
||||
<ClCompile Include="scan_decoder_test.cpp" />
|
||||
<ClCompile Include="default_traits_test.cpp" />
|
||||
|
@ -98,7 +98,7 @@
|
||||
<ClCompile Include="jpegls_algorithm_test.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="context_run_mode_test.cpp">
|
||||
<ClCompile Include="run_mode_context_test.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util_test.cpp">
|
||||
|
@ -3,19 +3,19 @@
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "../src/context_run_mode.h"
|
||||
#include "../src/run_mode_context.h"
|
||||
|
||||
|
||||
using Microsoft::VisualStudio::CppUnitTestFramework::Assert;
|
||||
|
||||
namespace charls::test {
|
||||
|
||||
TEST_CLASS(context_run_mode_test)
|
||||
TEST_CLASS(run_mode_context_test)
|
||||
{
|
||||
public:
|
||||
TEST_METHOD(update_variable) // NOLINT
|
||||
{
|
||||
context_run_mode context;
|
||||
run_mode_context context;
|
||||
|
||||
context.update_variables(3, 27, 0);
|
||||
|
@ -234,13 +234,12 @@ void verify_decoded_bytes(const interleave_mode interleave_mode, const frame_inf
|
||||
|
||||
void test_compliance(const vector<byte>& encoded_source, const vector<byte>& uncompressed_source, const bool check_encode)
|
||||
{
|
||||
jpegls_decoder decoder{encoded_source, true};
|
||||
|
||||
if (check_encode)
|
||||
{
|
||||
Assert::IsTrue(verify_encoded_bytes(uncompressed_source, encoded_source));
|
||||
}
|
||||
|
||||
jpegls_decoder decoder{encoded_source, true};
|
||||
const auto destination{decoder.decode<vector<byte>>()};
|
||||
|
||||
if (decoder.near_lossless() == 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user