Skip to content

Commit

Permalink
Convert template class scan_codec_factory into template method
Browse files Browse the repository at this point in the history
The class scan_codec_factory has no state and can be replaced by just a template function.
  • Loading branch information
vbaderks committed Dec 28, 2023
1 parent eb6657f commit 5171b15
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 102 deletions.
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# -clang-diagnostic-unsafe-buffer-usage => Rationale: Too many false warnings, access is verified with other tools.
# -clang-analyzer-core.NonNullParamChecker => Rationale: cannot be effective disabled, already checked by other checkers.
# -misc-non-private-member-variables-in-classes => Rationale: design can be ok, manual review is better
# -misc-include-cleaner => complains about no direct includes
# -modernize-use-trailing-return-type => Rationale: A style recommendation, this style is selected for CharLS
# -readability-magic-numbers => Rationale: To critical rule, used numbers are logical
# -readability-named-parameter => Rationale: to many non problematic warnings
Expand Down Expand Up @@ -81,6 +82,7 @@ Checks: '*,
-clang-diagnostic-unsafe-buffer-usage,
-clang-analyzer-core.NonNullParamChecker,
-misc-non-private-member-variables-in-classes,
-misc-include-cleaner,
-modernize-use-trailing-return-type,
-readability-magic-numbers,
-readability-named-parameter,
Expand Down
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ root = true
charset = utf-8
indent_style = space
trim_trailing_whitespace = true
spelling_exclusion_path = spelling.dic

[*.md]
trim_trailing_whitespace = false
Expand Down
1 change: 1 addition & 0 deletions CharLS.sln
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
SECURITY.md = SECURITY.md
sonar-project.properties = sonar-project.properties
spelling.dic = spelling.dic
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "convert-c", "samples\convert.c\convert-c.vcxproj", "{F42C0547-FEB3-40F4-9379-0FF87B44FA0F}"
Expand Down
13 changes: 13 additions & 0 deletions spelling.dic
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
jpegls
cppcoreguidelines
golomb
charls
opto
Errval
Golomb
maxval
unmap
subspan
misc
bugprone
countl
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ target_sources(charls
"${CMAKE_CURRENT_LIST_DIR}/jpegls_preset_coding_parameters.h"
"${CMAKE_CURRENT_LIST_DIR}/jpegls_preset_parameters_type.h"
"${CMAKE_CURRENT_LIST_DIR}/lossless_traits.h"
"${CMAKE_CURRENT_LIST_DIR}/make_scan_codec.h"
"${CMAKE_CURRENT_LIST_DIR}/make_scan_codec.cpp"
"${CMAKE_CURRENT_LIST_DIR}/process_decoded_line.h"
"${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}/scan_codec.h"
"${CMAKE_CURRENT_LIST_DIR}/scan_codec_factory.h"
"${CMAKE_CURRENT_LIST_DIR}/scan_codec_factory.cpp"
"${CMAKE_CURRENT_LIST_DIR}/scan_decoder.h"
"${CMAKE_CURRENT_LIST_DIR}/scan_decoder_impl.h"
"${CMAKE_CURRENT_LIST_DIR}/scan_encoder.h"
Expand Down
4 changes: 2 additions & 2 deletions src/CharLS.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
<ClCompile Include="validate_spiff_header.cpp" />
<ClCompile Include="version.cpp" />
<ClCompile Include="charls_jpegls_decoder.cpp" />
<ClCompile Include="scan_codec_factory.cpp" />
<ClCompile Include="make_scan_codec.cpp" />
<ClCompile Include="charls_jpegls_encoder.cpp" />
<ClCompile Include="jpegls_error.cpp" />
<ClCompile Include="jpeg_stream_reader.cpp" />
Expand All @@ -243,7 +243,7 @@
<ClInclude Include="default_traits.h" />
<ClInclude Include="scan_encoder.h" />
<ClInclude Include="golomb_lut.h" />
<ClInclude Include="scan_codec_factory.h" />
<ClInclude Include="make_scan_codec.h" />
<ClInclude Include="jpegls_algorithm.h" />
<ClInclude Include="jpegls_preset_coding_parameters.h" />
<ClInclude Include="jpeg_marker_code.h" />
Expand Down
4 changes: 2 additions & 2 deletions src/CharLS.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="scan_codec_factory.cpp">
<ClCompile Include="make_scan_codec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="jpegls_error.cpp">
Expand Down Expand Up @@ -69,7 +69,7 @@
<ClInclude Include="scan_encoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="scan_codec_factory.h">
<ClInclude Include="make_scan_codec.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="jpeg_marker_code.h">
Expand Down
22 changes: 13 additions & 9 deletions src/charls_jpegls_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include "constants.h"
#include "jpeg_stream_reader.h"
#include "scan_codec_factory.h"
#include "make_scan_codec.h"
#include "scan_decoder.h"
#include "util.h"

Expand Down Expand Up @@ -53,14 +53,14 @@ struct charls_jpegls_decoder final
[[nodiscard]]
charls::frame_info frame_info_checked() const
{
check_operation(state_ >= state::header_read);
check_header_read();
return frame_info();
}

[[nodiscard]]
int32_t near_lossless(int32_t /*component*/ = 0) const
{
check_operation(state_ >= state::header_read);
check_header_read();

// Note: The JPEG-LS standard allows to define different NEAR parameter for every scan.
return reader_.parameters().near_lossless;
Expand All @@ -69,7 +69,7 @@ struct charls_jpegls_decoder final
[[nodiscard]]
charls::interleave_mode interleave_mode() const
{
check_operation(state_ >= state::header_read);
check_header_read();

// Note: The JPEG-LS standard allows to define different interleave modes for every scan.
// CharLS doesn't support mixed interleave modes, first scan determines the mode.
Expand All @@ -79,14 +79,14 @@ struct charls_jpegls_decoder final
[[nodiscard]]
charls::color_transformation color_transformation() const
{
check_operation(state_ >= state::header_read);
check_header_read();
return reader_.parameters().transformation;
}

[[nodiscard]]
const jpegls_pc_parameters& preset_coding_parameters() const
{
check_operation(state_ >= state::header_read);
check_header_read();
return reader_.preset_coding_parameters();
}

Expand Down Expand Up @@ -134,7 +134,6 @@ struct charls_jpegls_decoder final
{
check_argument(destination.data() || destination.empty());
check_operation(state_ == state::header_read);

check_parameter_coherent();

// Compute the stride for the uncompressed destination buffer.
Expand All @@ -159,9 +158,9 @@ struct charls_jpegls_decoder final

for (size_t plane{};;)
{
const auto scan_codec{scan_codec_factory<scan_decoder>().create_codec(
const auto decoder{make_scan_codec<scan_decoder>(
frame_info(), reader_.parameters(), reader_.get_validated_preset_coding_parameters())};
const size_t bytes_read{scan_codec->decode_scan(reader_.remaining_source(), destination.data(), stride)};
const size_t bytes_read{decoder->decode_scan(reader_.remaining_source(), destination.data(), stride)};
reader_.advance_position(bytes_read);

++plane;
Expand Down Expand Up @@ -193,6 +192,11 @@ struct charls_jpegls_decoder final
return components_in_plane_count * frame_info().width * bit_to_byte_count(frame_info().bits_per_sample);
}

void check_header_read() const
{
check_operation(state_ >= state::header_read);
}

void check_parameter_coherent() const
{
switch (frame_info().component_count)
Expand Down
6 changes: 3 additions & 3 deletions src/charls_jpegls_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "jpeg_stream_writer.h"
#include "jpegls_preset_coding_parameters.h"
#include "scan_codec_factory.h"
#include "make_scan_codec.h"
#include "scan_encoder.h"
#include "util.h"

Expand Down Expand Up @@ -266,9 +266,9 @@ struct charls_jpegls_encoder final
const charls::frame_info frame_info{frame_info_.width, frame_info_.height, frame_info_.bits_per_sample,
component_count};

const auto scan_codec{scan_codec_factory<scan_encoder>().create_codec(
const auto encoder{make_scan_codec<scan_encoder>(
frame_info, {near_lossless_, 0, interleave_mode_, color_transformation_}, preset_coding_parameters_)};
const size_t bytes_written{scan_codec->encode_scan(source, stride, writer_.remaining_destination())};
const size_t bytes_written{encoder->encode_scan(source, stride, writer_.remaining_destination())};

// Synchronize the destination encapsulated in the writer (encode_scan works on a local copy)
writer_.seek(bytes_written);
Expand Down
1 change: 1 addition & 0 deletions src/jpeg_marker_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#pragma once

#include <cstddef>
#include <cstdint>

namespace charls {
Expand Down
117 changes: 62 additions & 55 deletions src/scan_codec_factory.cpp → src/make_scan_codec.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Team CharLS.
// SPDX-License-Identifier: BSD-3-Clause

#include "scan_codec_factory.h"
#include "make_scan_codec.h"

#include "default_traits.h"
#include "jpegls_preset_coding_parameters.h"
Expand Down Expand Up @@ -30,6 +30,7 @@ frame_info update_component_count(const frame_info& frame, const coding_paramete


template<typename ScanProcess, typename Traits>
[[nodiscard]]
unique_ptr<ScanProcess> make_codec(const Traits& traits, const frame_info& frame, const coding_parameters& parameters)
{
if constexpr (std::is_same_v<ScanProcess, scan_encoder>)
Expand All @@ -42,46 +43,9 @@ unique_ptr<ScanProcess> make_codec(const Traits& traits, const frame_info& frame
}
}

} // namespace


template<typename ScanProcess>
unique_ptr<ScanProcess> scan_codec_factory<ScanProcess>::create_codec(const frame_info& frame,
const coding_parameters& parameters,
const jpegls_pc_parameters& preset_coding_parameters)
{
unique_ptr<ScanProcess> codec;

if (preset_coding_parameters.reset_value == default_reset_value)
{
codec = try_create_optimized_codec(frame, parameters);
}

if (!codec)
{
if (frame.bits_per_sample <= 8)
{
default_traits<uint8_t, uint8_t> traits(calculate_maximum_sample_value(frame.bits_per_sample),
parameters.near_lossless, preset_coding_parameters.reset_value);
traits.maximum_sample_value = preset_coding_parameters.maximum_sample_value;
codec = make_codec<ScanProcess, default_traits<uint8_t, uint8_t>>(traits, frame, parameters);
}
else
{
default_traits<uint16_t, uint16_t> traits(calculate_maximum_sample_value(frame.bits_per_sample),
parameters.near_lossless, preset_coding_parameters.reset_value);
traits.maximum_sample_value = preset_coding_parameters.maximum_sample_value;
codec = make_codec<ScanProcess, default_traits<uint16_t, uint16_t>>(traits, frame, parameters);
}
}

codec->set_presets(preset_coding_parameters);
return codec;
}

template<typename ScanProcess>
unique_ptr<ScanProcess> scan_codec_factory<ScanProcess>::try_create_optimized_codec(const frame_info& frame,
const coding_parameters& parameters)
[[nodiscard]]
unique_ptr<ScanProcess> try_make_optimized_codec(const frame_info& frame, const coding_parameters& parameters)
{
if (parameters.interleave_mode == interleave_mode::sample && frame.component_count != 3 && frame.component_count != 4)
return nullptr;
Expand Down Expand Up @@ -116,53 +80,96 @@ unique_ptr<ScanProcess> scan_codec_factory<ScanProcess>::try_create_optimized_co

#endif

const auto maxval{calculate_maximum_sample_value(frame.bits_per_sample)};
const auto maximum_sample_value{calculate_maximum_sample_value(frame.bits_per_sample)};

if (frame.bits_per_sample <= 8)
{
if (parameters.interleave_mode == interleave_mode::sample)
{
if (frame.component_count == 3)
{
return make_codec<ScanProcess>(default_traits<uint8_t, triplet<uint8_t>>(maxval, parameters.near_lossless),
frame, parameters);
return make_codec<ScanProcess>(
default_traits<uint8_t, triplet<uint8_t>>(maximum_sample_value, parameters.near_lossless), frame,
parameters);
}

if (frame.component_count == 4)
{
return make_codec<ScanProcess>(default_traits<uint8_t, quad<uint8_t>>(maxval, parameters.near_lossless),
frame, parameters);
return make_codec<ScanProcess>(
default_traits<uint8_t, quad<uint8_t>>(maximum_sample_value, parameters.near_lossless), frame,
parameters);
}
}

return make_codec<ScanProcess>(default_traits<uint8_t, uint8_t>(maxval, parameters.near_lossless), frame,
parameters);
return make_codec<ScanProcess>(default_traits<uint8_t, uint8_t>(maximum_sample_value, parameters.near_lossless),
frame, parameters);
}
if (frame.bits_per_sample <= 16)
{
if (parameters.interleave_mode == interleave_mode::sample)
{
if (frame.component_count == 3)
{
return make_codec<ScanProcess>(default_traits<uint16_t, triplet<uint16_t>>(maxval, parameters.near_lossless),
frame, parameters);
return make_codec<ScanProcess>(
default_traits<uint16_t, triplet<uint16_t>>(maximum_sample_value, parameters.near_lossless), frame,
parameters);
}

if (frame.component_count == 4)
{
return make_codec<ScanProcess>(default_traits<uint16_t, quad<uint16_t>>(maxval, parameters.near_lossless),
frame, parameters);
return make_codec<ScanProcess>(
default_traits<uint16_t, quad<uint16_t>>(maximum_sample_value, parameters.near_lossless), frame,
parameters);
}
}

return make_codec<ScanProcess>(default_traits<uint16_t, uint16_t>(maxval, parameters.near_lossless), frame,
parameters);
return make_codec<ScanProcess>(default_traits<uint16_t, uint16_t>(maximum_sample_value, parameters.near_lossless),
frame, parameters);
}
return nullptr;
}


template class scan_codec_factory<scan_decoder>;
template class scan_codec_factory<scan_encoder>;
} // namespace


template<typename ScanProcess>
unique_ptr<ScanProcess> make_scan_codec(const frame_info& frame, const coding_parameters& parameters,
const jpegls_pc_parameters& preset_coding_parameters)
{
unique_ptr<ScanProcess> codec;

if (preset_coding_parameters.reset_value == default_reset_value)
{
codec = try_make_optimized_codec<ScanProcess>(frame, parameters);
}

if (!codec)
{
if (frame.bits_per_sample <= 8)
{
default_traits<uint8_t, uint8_t> traits(calculate_maximum_sample_value(frame.bits_per_sample),
parameters.near_lossless, preset_coding_parameters.reset_value);
traits.maximum_sample_value = preset_coding_parameters.maximum_sample_value;
codec = make_codec<ScanProcess, default_traits<uint8_t, uint8_t>>(traits, frame, parameters);
}
else
{
default_traits<uint16_t, uint16_t> traits(calculate_maximum_sample_value(frame.bits_per_sample),
parameters.near_lossless, preset_coding_parameters.reset_value);
traits.maximum_sample_value = preset_coding_parameters.maximum_sample_value;
codec = make_codec<ScanProcess, default_traits<uint16_t, uint16_t>>(traits, frame, parameters);
}
}

codec->set_presets(preset_coding_parameters);
return codec;
}


template std::unique_ptr<scan_decoder> make_scan_codec<scan_decoder>(const frame_info&, const coding_parameters&,
const jpegls_pc_parameters&);
template std::unique_ptr<scan_encoder> make_scan_codec<scan_encoder>(const frame_info&, const coding_parameters&,
const jpegls_pc_parameters&);

} // namespace charls
Loading

0 comments on commit 5171b15

Please sign in to comment.