Skip to content

Commit

Permalink
Improve names and reduce line buffer
Browse files Browse the repository at this point in the history
- 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)
  • Loading branch information
vbaderks committed Aug 2, 2024
1 parent 1127459 commit 39fc173
Show file tree
Hide file tree
Showing 17 changed files with 105 additions and 107 deletions.
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions src/CharLS.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
4 changes: 2 additions & 2 deletions src/CharLS.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand All @@ -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">
Expand Down
24 changes: 3 additions & 21 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,15 @@

#pragma once

#include <algorithm>
#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};
Expand All @@ -33,18 +26,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.
Expand Down
2 changes: 1 addition & 1 deletion src/jpeg_stream_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
13 changes: 13 additions & 0 deletions src/jpegls_algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
23 changes: 13 additions & 10 deletions src/jpegls_preset_coding_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#pragma once

#include "charls/public_types.h"
#include "constants.h"
#include "jpegls_algorithm.h"
#include "util.h"

#include <algorithm>
Expand All @@ -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};
Expand Down Expand Up @@ -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))
Expand All @@ -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;
Expand Down
10 changes: 5 additions & 5 deletions src/context_regular_mode.h → src/regular_mode_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
{
}

Expand Down Expand Up @@ -63,8 +63,8 @@ class context_regular_mode final
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_;
Expand Down
8 changes: 4 additions & 4 deletions src/context_run_mode.h → src/run_mode_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#pragma once

#include "constants.h"
#include "jpegls_algorithm.h"
#include "util.h"

#include <cassert>
Expand All @@ -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)}
{
}
Expand Down
16 changes: 8 additions & 8 deletions src/scan_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -147,14 +147,14 @@ class scan_codec

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;
}

Expand All @@ -174,8 +174,8 @@ class scan_codec
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_{};

Expand Down
35 changes: 18 additions & 17 deletions src/scan_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ class scan_decoder : protected scan_codec
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
Expand Down Expand Up @@ -119,19 +119,20 @@ class scan_decoder : protected scan_codec
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;
}

Expand All @@ -153,7 +154,7 @@ class scan_decoder : protected scan_codec
}

const bool set{(read_cache_ & (static_cast<cache_t>(1) << (cache_t_bit_count - 1))) != 0};
skip(1);
skip_bits(1);
return set;
}

Expand Down Expand Up @@ -185,10 +186,10 @@ class scan_decoder : protected scan_codec
{
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)
{
Expand Down Expand Up @@ -293,9 +294,9 @@ class scan_decoder : protected scan_codec
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;
}
Expand Down
Loading

0 comments on commit 39fc173

Please sign in to comment.