Use span and improve spelling (#301)

This commit is contained in:
Victor Derks 2024-01-20 22:09:55 +01:00 committed by GitHub
parent cb6a9d715f
commit 1ba2294516
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 356 additions and 88 deletions

View File

@ -43,6 +43,8 @@
<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/Rules/=Union_0020members/@EntryIndexedValue">&lt;NamingElement Priority="12"&gt;&lt;Descriptor Static="Indeterminate" Constexpr="Indeterminate" Const="Indeterminate" Volatile="Indeterminate" Accessibility="NOT_APPLICABLE"&gt;&lt;type Name="union member" /&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="aa_bb" /&gt;&lt;/NamingElement&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/CppEnableCppCli/IsEnabled/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002EDaemon_002ESettings_002EMigration_002ESwaWarningsModeSettingsMigrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=G_0020G/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=Modified_0020Modified/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/GrammarAndSpelling/GrammarChecking/Exceptions/=than/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=alphatest/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=anymap/@EntryIndexedValue">True</s:Boolean>
@ -89,6 +91,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=losslesstraits/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=maxval/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=memchr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=memset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mrfx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=nightshot/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=NODISCARD/@EntryIndexedValue">True</s:Boolean>

View File

@ -313,16 +313,299 @@ overwrite_buffer allocate_overwrite_buffer(const size_t size)
return buffer;
}
static void bm_resize_overwrite_buffer(benchmark::State& state)
{
for (const auto _ : state)
{
benchmark::DoNotOptimize(allocate_buffer(size_t{512} * 512 * 16));
benchmark::DoNotOptimize(allocate_buffer(size_t{1024} * 1024 * 8 * 3));
benchmark::DoNotOptimize(allocate_overwrite_buffer(size_t{512} * 512 * 16));
benchmark::DoNotOptimize(allocate_overwrite_buffer(size_t{1024} * 1024 * 8 * 3));
}
}
BENCHMARK(bm_resize_overwrite_buffer);
int memset_buffer(uint8_t* data, const size_t size)
{
memset(data, 0, size);
return 0;
}
static void bm_memset_buffer(benchmark::State& state)
{
std::vector<uint8_t> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(memset_buffer(buffer.data(), size_t{512} * 512 * 16));
benchmark::DoNotOptimize(memset_buffer(buffer.data(), size_t{1024} * 1024 * 8 * 3));
}
}
BENCHMARK(bm_memset_buffer);
bool has_ff_byte_classic(const unsigned int value)
{
// Check if any byte is equal to 0xFF
return ((value & 0xFF) == 0xFF) || (((value >> 8) & 0xFF) == 0xFF) || (((value >> 16) & 0xFF) == 0xFF) ||
(((value >> 24) & 0xFF) == 0xFF);
}
static void bm_has_ff_byte_classic(benchmark::State& state)
{
for (const auto _ : state)
{
benchmark::DoNotOptimize(has_ff_byte_classic(0));
benchmark::DoNotOptimize(has_ff_byte_classic(0xFF));
}
}
BENCHMARK(bm_has_ff_byte_classic);
bool has_ff_byte_loop(const unsigned int value)
{
// Iterate over each byte and check if it is equal to 0xFF
for (int i = 0; i < sizeof(unsigned int); ++i)
{
if ((value & (0xFF << (8 * i))) == (0xFFU << (8 * i)))
{
return true;
}
}
return false;
}
static void bm_has_ff_byte_loop(benchmark::State& state)
{
for (const auto _ : state)
{
benchmark::DoNotOptimize(has_ff_byte_loop(0));
benchmark::DoNotOptimize(has_ff_byte_loop(0xFF));
}
}
BENCHMARK(bm_has_ff_byte_loop);
bool has_ff_byte_simd(const unsigned int value) {
// Use SSE instructions for parallel comparison
const __m128i xmm_value = _mm_set1_epi32(value);
const __m128i xmm_ff = _mm_set1_epi32(0xFF);
// Compare each byte for equality with 0xFF
const __m128i comparison = _mm_cmpeq_epi8(xmm_value, xmm_ff);
// Check if any comparison result is true
return _mm_testz_si128(comparison, comparison) == 0;
}
static void bm_has_ff_byte_simd(benchmark::State& state)
{
for (const auto _ : state)
{
benchmark::DoNotOptimize(has_ff_byte_simd(0));
benchmark::DoNotOptimize(has_ff_byte_simd(0xFF));
}
}
BENCHMARK(bm_has_ff_byte_simd);
const std::byte* find_jpeg_marker_start_byte(const std::byte* position, const std::byte* end_position) noexcept
{
constexpr std::byte jpeg_marker_start_byte{0xFF};
// Use memchr to find next start byte (0xFF). memchr is optimized on some platforms to search faster.
return static_cast<const std::byte*>(
memchr(position, std::to_integer<int>(jpeg_marker_start_byte), end_position - position));
}
static void bm_find_jpeg_marker_start_byte(benchmark::State& state)
{
const std::vector<std::byte> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(find_jpeg_marker_start_byte(buffer.data(), buffer.data() + buffer.size()));
}
}
BENCHMARK(bm_find_jpeg_marker_start_byte);
// A simple overload with uint64_t\uint32_t doesn't work for macOS. size_t is not the same type as uint64_t.
template<int BitCount, typename T>
constexpr bool is_uint_v = sizeof(T) == BitCount / 8 && std::is_integral_v<T> && !std::is_signed_v<T>;
template<typename T>
[[nodiscard]]
auto byte_swap(const T value) noexcept
{
if constexpr (is_uint_v<16, T>)
{
#ifdef _MSC_VER
return _byteswap_ushort(value);
#else
// Note: GCC and Clang will optimize this pattern to a built-in intrinsic.
return static_cast<uint16_t>(value << 8 | value >> 8);
#endif
}
else if constexpr (is_uint_v<32, T>)
{
#ifdef _MSC_VER
return _byteswap_ulong(value);
#else
// Note: GCC and Clang will optimize this pattern to a built-in intrinsic.
return value >> 24 | (value & 0x00FF0000) >> 8 | (value & 0x0000FF00) << 8 | value << 24;
#endif
}
else
{
static_assert(is_uint_v<64, T>);
#ifdef _MSC_VER
return _byteswap_uint64(value);
#else
// Note: GCC and Clang will optimize this pattern to a built-in intrinsic.
return (value << 56) | ((value << 40) & 0x00FF'0000'0000'0000) | ((value << 24) & 0x0000'FF00'0000'0000) |
((value << 8) & 0x0000'00FF'0000'0000) | ((value >> 8) & 0x0000'0000'FF00'0000) |
((value >> 24) & 0x0000'0000'00FF'0000) | ((value >> 40) & 0x0000'0000'0000'FF00) | (value >> 56);
#endif
}
}
template<typename T>
[[nodiscard]]
T read_unaligned(const void* buffer) noexcept
{
// Note: MSVC, GCC and clang will replace this with a direct register read if the CPU architecture allows it
// On x86, x64 and ARM64 this will just be 1 register load.
T value;
memcpy(&value, buffer, sizeof(T));
return value;
}
template<typename T>
T read_big_endian_unaligned(const void* buffer) noexcept
{
#ifdef LITTLE_ENDIAN_ARCHITECTURE
return byte_swap(read_unaligned<T>(buffer));
#else
return read_unaligned<T>(buffer);
#endif
}
uint32_t read_all_bytes_with_ff_check(const std::byte* position, const std::byte* end_position)
{
uint32_t result{};
for (; position < end_position; position += sizeof(uint32_t))
{
if (const uint32_t value{read_big_endian_unaligned<uint32_t>(position)};
has_ff_byte_simd(value))
{
result++;
}
else
{
result |= value;
}
}
return result;
}
static void bm_read_all_bytes_with_ff_check(benchmark::State& state)
{
const std::vector<std::byte> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(read_all_bytes_with_ff_check(buffer.data(), buffer.data() + buffer.size()));
}
}
BENCHMARK(bm_read_all_bytes_with_ff_check);
bool has_ff_byte_simd64(const uint64_t value)
{
// Use SSE instructions for parallel comparison
const __m128i xmm_value = _mm_set1_epi64x(value);
const __m128i xmm_ff = _mm_set1_epi32(0xFF);
// Compare each byte for equality with 0xFF
const __m128i comparison = _mm_cmpeq_epi8(xmm_value, xmm_ff);
// Check if any comparison result is true
return _mm_testz_si128(comparison, comparison) == 0;
}
uint64_t read_all_bytes_with_ff_check64(const std::byte* position, const std::byte* end_position)
{
uint64_t result{};
for (; position < end_position; position += sizeof(uint64_t))
{
if (const uint64_t value{read_big_endian_unaligned<uint64_t>(position)}; has_ff_byte_simd64(value))
{
result++;
}
else
{
result |= value;
}
}
return result;
}
static void bm_read_all_bytes_with_ff_check64(benchmark::State& state)
{
const std::vector<std::byte> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(read_all_bytes_with_ff_check64(buffer.data(), buffer.data() + buffer.size()));
}
}
BENCHMARK(bm_read_all_bytes_with_ff_check64);
uint32_t read_all_bytes_no_check(const std::byte* position, const std::byte* end_position)
{
uint32_t result{};
for (; position < end_position; position += sizeof(uint32_t))
{
const uint32_t value{read_big_endian_unaligned<uint32_t>(position)};
result |= value;
}
return result;
}
static void bm_read_all_bytes_no_check(benchmark::State& state)
{
const std::vector<std::byte> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(read_all_bytes_no_check(buffer.data(), buffer.data() + buffer.size()));
}
}
BENCHMARK(bm_read_all_bytes_no_check);
uint64_t read_all_bytes_no_check64(const std::byte* position, const std::byte* end_position)
{
uint64_t result{};
for (; position < end_position; position += sizeof(uint64_t))
{
const uint64_t value{read_big_endian_unaligned<uint64_t>(position)};
result |= value;
}
return result;
}
static void bm_read_all_bytes_no_check64(benchmark::State& state)
{
const std::vector<std::byte> buffer(size_t{1024} * 1024 * 8 * 3);
for (const auto _ : state)
{
benchmark::DoNotOptimize(read_all_bytes_no_check64(buffer.data(), buffer.data() + buffer.size()));
}
}
BENCHMARK(bm_read_all_bytes_no_check64);
BENCHMARK_MAIN();

View File

@ -96,25 +96,13 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Checked|Win32'">
<LinkIncremental>true</LinkIncremental>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Checked|x64'">
<LinkIncremental>true</LinkIncremental>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Checked|ARM64'">
<LinkIncremental>true</LinkIncremental>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Label="Global">

View File

@ -62,7 +62,7 @@ charls_jpegls_decoder_set_source_buffer(CHARLS_IN charls_jpegls_decoder* decoder
/// <summary>
/// Tries to read the SPIFF header from the source buffer.
/// If a SPIFF header exists its content will be put into the spiff_header parameter and header_found will be set to 1.
/// Call charls_jpegls_decoder_read_header to read the normal JPEG header afterwards.
/// Call charls_jpegls_decoder_read_header to read the normal JPEG header afterward.
/// </summary>
/// <param name="decoder">Reference to the decoder instance.</param>
/// <param name="spiff_header">Output argument, will hold the SPIFF header when one could be found.</param>
@ -240,7 +240,7 @@ public:
/// Destination container that will hold the image data on return. Container will be resized automatically.
/// </param>
/// <param name="maximum_size_in_bytes">
/// The maximum output size that may be allocated, default is 94 MiB (enough to decode 8 bit color 8K image).
/// The maximum output size that may be allocated, default is 94 MiB (enough to decode 8-bit color 8K image).
/// </param>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
/// <exception cref="std::bad_alloc">Thrown when memory for the decoder could not be allocated.</exception>
@ -291,7 +291,7 @@ public:
/// The passed container needs to remain valid until the stream is fully decoded.
/// </summary>
/// <param name="source_container">
/// A STL like container that provides the functions data() and size() and the type value_type.
/// STL like container that provides the functions data() and size() and the type value_type.
/// </param>
/// <param name="parse_header">
/// If true the SPIFF and JPEG header will be directly read from the source.
@ -324,7 +324,7 @@ public:
/// This container needs to remain valid until the stream is fully decoded.
/// </summary>
/// <param name="source_container">
/// A STL like container that provides the functions data() and size() and the type value_type.
/// STL like container that provides the functions data() and size() and the type value_type.
/// </param>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
template<typename Container, typename ContainerValueType = typename Container::value_type>
@ -335,9 +335,9 @@ public:
/// <summary>
/// Tries to read the SPIFF header from the JPEG-LS stream.
/// If a SPIFF header exists its will be returned otherwise the struct will be filled with default values.
/// If a SPIFF header exists it will be returned otherwise the struct will be filled with default values.
/// The header_found parameter will be set to true if the spiff header could be read.
/// Call read_header to read the normal JPEG header afterwards.
/// Call read_header to read the normal JPEG header afterward.
/// </summary>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
/// <returns>True if a valid SPIFF header could be found.</returns>
@ -351,9 +351,9 @@ public:
/// <summary>
/// Tries to read the SPIFF header from the JPEG-LS stream.
/// If a SPIFF header exists its will be returned otherwise the struct will be filled with default values.
/// If a SPIFF header exists it will be returned otherwise the struct will be filled with default values.
/// The header_found parameter will be set to true if the spiff header could be read.
/// Call read_header to read the normal JPEG header afterwards.
/// Call read_header to read the normal JPEG header afterward.
/// </summary>
/// <param name="ec">The out-parameter for error reporting.</param>
/// <returns>True if a valid SPIFF header could be found.</returns>
@ -401,7 +401,7 @@ public:
/// <summary>
/// Returns true if a valid SPIFF header was found.
/// </summary>
/// <returns>True of false, depending if a SPIFF header was found.</returns>
/// <returns>True when a SPIFF header was found, false otherwise.</returns>
[[nodiscard]]
bool spiff_header_has_value() const noexcept
{
@ -541,7 +541,7 @@ public:
/// Will decode the JPEG-LS byte stream set with source into the destination container.
/// </summary>
/// <param name="destination_container">
/// A STL like container that provides the functions data() and size() and the type value_type.
/// STL like container that provides the functions data() and size() and the type value_type.
/// </param>
/// <param name="stride">Number of bytes to the next line in the buffer, when zero, decoder will compute it.</param>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>

View File

@ -85,7 +85,7 @@ charls_jpegls_encoder_set_interleave_mode(CHARLS_IN charls_jpegls_encoder* encod
/// <summary>
/// Configures the preset coding parameters the encoder should use.
/// If not set the encoder will use the default preset coding parameters as defined by the JPEG-LS standard.
/// Only when the coding parameters are different than the default parameters or when `include_pc_parameters_jai` is set,
/// Only when the coding parameters are different from the default parameters or when `include_pc_parameters_jai` is set,
/// they will be written to the JPEG-LS stream during the encode phase.
/// </summary>
/// <param name="encoder">Reference to the encoder instance.</param>
@ -99,7 +99,7 @@ charls_jpegls_encoder_set_preset_coding_parameters(CHARLS_IN charls_jpegls_encod
/// <summary>
/// Configures the HP color transformation the encoder should use.
/// If not set the encoder will use no color transformation.
/// Color transformations are a HP extension and not defined by the JPEG-LS standard and can only be set for 3 component
/// Color transformations are an HP extension and not defined by the JPEG-LS standard and can only be set for 3 component
/// encodings.
/// </summary>
/// <param name="encoder">Reference to the encoder instance.</param>
@ -117,7 +117,7 @@ charls_jpegls_encoder_set_color_transformation(CHARLS_IN charls_jpegls_encoder*
/// Size for dynamic extras like SPIFF entries and other tables are not included in this size.
/// </remarks>
/// <param name="encoder">Reference to the encoder instance.</param>
/// <param name="size_in_bytes">Reference to the size that will be set when the functions returns.</param>
/// <param name="size_in_bytes">Reference to the size that will be set when the function returns.</param>
/// <returns>The result of the operation: success or a failure code.</returns>
CHARLS_CHECK_RETURN CHARLS_API_IMPORT_EXPORT charls_jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_jpegls_encoder_get_estimated_destination_size(CHARLS_IN const charls_jpegls_encoder* encoder,
@ -186,7 +186,7 @@ charls_jpegls_encoder_write_spiff_entry(CHARLS_IN charls_jpegls_encoder* encoder
/// <summary>
/// Writes a SPIFF end of directory entry to the destination.
/// The encoder will normally does this automatically. It is made available
/// The encoder will normally do this automatically. It is made available
/// for the scenario to create SPIFF headers in front of existing JPEG-LS streams.
/// </summary>
/// <remarks>
@ -204,7 +204,7 @@ charls_jpegls_encoder_write_spiff_end_of_directory_entry(CHARLS_IN charls_jpegls
/// Function should be called before encoding the image data.
/// </remarks>
/// <param name="encoder">Reference to the encoder instance.</param>
/// <param name="comment">The 'comment' bytes. Application specific, usually human readable string.</param>
/// <param name="comment">The 'comment' bytes. Application specific, usually a human-readable string.</param>
/// <param name="comment_size_bytes">The size in bytes of the comment [0-65533].</param>
/// <returns>The result of the operation: success or a failure code.</returns>
CHARLS_ATTRIBUTE_ACCESS((access(read_only, 2, 3)))
@ -252,7 +252,7 @@ charls_jpegls_encoder_encode_from_buffer(CHARLS_IN charls_jpegls_encoder* encode
/// Returns the size in bytes, that are written to the destination.
/// </summary>
/// <param name="encoder">Reference to the encoder instance.</param>
/// <param name="bytes_written">Reference to the size that will be set when the functions returns.</param>
/// <param name="bytes_written">Reference to the size that will be set when the function returns.</param>
/// <returns>The result of the operation: success or a failure code.</returns>
CHARLS_CHECK_RETURN CHARLS_API_IMPORT_EXPORT charls_jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_jpegls_encoder_get_bytes_written(CHARLS_IN const charls_jpegls_encoder* encoder,
@ -368,7 +368,7 @@ public:
/// <summary>
/// Configures the HP color transformation the encoder should use.
/// If not set the encoder will use no color transformation.
/// Color transformations are a HP extension and not defined by the JPEG-LS standard
/// Color transformations are an HP extension and not defined by the JPEG-LS standard
/// and can only be set for 3 component encodings.
/// </summary>
/// <param name="color_transformation">The color transformation parameters.</param>
@ -409,7 +409,7 @@ public:
}
/// <summary>
/// Set the the container that will contain the encoded JPEG-LS byte stream data after encoding.
/// Set the container that will contain the encoded JPEG-LS byte stream data after encoding.
/// This container needs to remain valid during the encoding process.
/// </summary>
/// <param name="destination_container">
@ -471,7 +471,7 @@ public:
/// <summary>
/// Writes a SPIFF end of directory entry to the destination.
/// The encoder will normally does this automatically. It is made available
/// The encoder will normally do this automatically. It is made available
/// for the scenario to create SPIFF headers in front of existing JPEG-LS streams.
/// </summary>
/// <remarks>

View File

@ -262,12 +262,12 @@ enum class [[nodiscard]] jpegls_errc
invalid_marker_segment_size = impl::CHARLS_JPEGLS_ERRC_INVALID_MARKER_SEGMENT_SIZE,
/// <summary>
/// This error is returned when the stream contains more then one SOI marker.
/// This error is returned when the stream contains more than one SOI marker.
/// </summary>
duplicate_start_of_image_marker = impl::CHARLS_JPEGLS_ERRC_DUPLICATE_START_OF_IMAGE_MARKER,
/// <summary>
/// This error is returned when the stream contains more then one SOF marker.
/// This error is returned when the stream contains more than one SOF marker.
/// </summary>
duplicate_start_of_frame_marker = impl::CHARLS_JPEGLS_ERRC_DUPLICATE_START_OF_FRAME_MARKER,
@ -309,7 +309,7 @@ enum class [[nodiscard]] jpegls_errc
restart_marker_not_found = impl::CHARLS_JPEGLS_ERRC_RESTART_MARKER_NOT_FOUND,
/// <summary>
/// This error is returned when a callback function returns a non zero value.
/// This error is returned when a callback function returns a nonzero value.
/// </summary>
callback_failed = impl::CHARLS_JPEGLS_ERRC_CALLBACK_FAILED,
@ -380,12 +380,12 @@ enum class [[nodiscard]] jpegls_errc
invalid_argument_encoding_options = impl::CHARLS_JPEGLS_ERRC_INVALID_ARGUMENT_ENCODING_OPTIONS,
/// <summary>
/// This error is returned when the stream contains a width parameter defined more then once or in an incompatible way.
/// This error is returned when the stream contains a width parameter defined more than once or in an incompatible way.
/// </summary>
invalid_parameter_width = impl::CHARLS_JPEGLS_ERRC_INVALID_PARAMETER_WIDTH,
/// <summary>
/// This error is returned when the stream contains a height parameter defined more then once in an incompatible way.
/// This error is returned when the stream contains a height parameter defined more than once in an incompatible way.
/// </summary>
invalid_parameter_height = impl::CHARLS_JPEGLS_ERRC_INVALID_PARAMETER_HEIGHT,
@ -477,7 +477,7 @@ enum class encoding_options : unsigned
/// <summary>
/// Writes explicitly the default JPEG-LS preset coding parameters when the
/// bits per sample is larger then 12 bits.
/// bits per sample is larger than 12 bits.
/// The Java Advanced Imaging (JAI) JPEG-LS codec has a defect that causes it to use invalid
/// preset coding parameters for these types of images.
/// Most users of this codec are aware of this problem and have implemented a work-around.
@ -533,7 +533,7 @@ enum class color_transformation
hp2 = impl::CHARLS_COLOR_TRANSFORMATION_HP2,
/// <summary>
/// Defines the reversible lossless color transformation of Y-Cb-Cr):
/// Defines the reversible lossless color transformation of Y-Cb-Cr:
/// R = R - G
/// B = B - G
/// G = G + (R + B) / 4
@ -841,7 +841,7 @@ typedef int32_t charls_spiff_resolution_units;
/// Defines the information that can be stored in a SPIFF header as defined in ISO/IEC 10918-3, Annex F
/// </summary>
/// <remark>
/// The type I.8 is an unsigned 8 bit integer, the type I.32 is an 32 bit unsigned integer in the file header itself.
/// The type I.8 is an unsigned 8-bit integer, the type I.32 is an 32-bit unsigned integer in the file header itself.
/// The type is indicated by the symbol “F.” are 4-byte parameters in “fixed point” notation.
/// The 16 most significant bits are essentially the same as a parameter of type I.16 and indicate the integer
/// part of this number.
@ -947,7 +947,7 @@ using charls_at_comment_handler = int32_t(CHARLS_API_CALLING_CONVENTION*)(const
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="application_data_id">Id of the APPn segment [0 .. 15].</param>
/// <param name="application_data_id">Identifier of the APPn segment [0 - 15].</param>
/// <param name="data">Reference to the data of the APPn segment.</param>
/// <param name="size">Size in bytes of the data of the APPn segment.</param>
/// <param name="user_context">Free to use context information that can be set during the installation of the

View File

@ -122,15 +122,14 @@ struct charls_jpegls_encoder final
vertical_resolution, horizontal_resolution});
}
void write_spiff_entry(const uint32_t entry_tag, CHARLS_IN_READS_BYTES(entry_data_size_bytes) const void* entry_data,
const size_t entry_data_size_bytes)
void write_spiff_entry(const uint32_t entry_tag, const span<const byte> entry_data)
{
check_argument(entry_data || entry_data_size_bytes == 0);
check_argument(entry_data.data() || entry_data.empty());
check_argument(entry_tag != spiff_end_of_directory_entry_type);
check_argument(entry_data_size_bytes <= 65528, jpegls_errc::invalid_argument_size);
check_argument(entry_data.size() <= 65528, jpegls_errc::invalid_argument_size);
check_operation(state_ == state::spiff_header);
writer_.write_spiff_directory_entry(entry_tag, entry_data, entry_data_size_bytes);
writer_.write_spiff_directory_entry(entry_tag, entry_data);
}
void write_spiff_end_of_directory_entry()
@ -541,7 +540,7 @@ charls_jpegls_encoder_write_spiff_entry(charls_jpegls_encoder* encoder, const ui
const size_t entry_data_size_bytes) noexcept
try
{
check_pointer(encoder)->write_spiff_entry(entry_tag, entry_data, entry_data_size_bytes);
check_pointer(encoder)->write_spiff_entry(entry_tag, {static_cast<const byte*>(entry_data), entry_data_size_bytes});
return jpegls_errc::success;
}
catch (...)

View File

@ -101,7 +101,7 @@ struct default_traits final
/// <summary>
/// Returns the value of errorValue modulo RANGE. ITU.T.87, A.4.5 (code segment A.9)
/// This ensures the error is reduced to the range (-⌊RANGE/2⌋ .. ⌈RANGE/2⌉-1)
/// This ensures the error is reduced to the range (-⌊RANGE/2⌋ - ⌈RANGE/2⌉-1)
/// </summary>
[[nodiscard]]
FORCE_INLINE int32_t modulo_range(int32_t error_value) const noexcept

View File

@ -44,11 +44,11 @@ void jpeg_stream_writer::write_spiff_header_segment(const spiff_header& header)
ASSERT(header.height > 0);
ASSERT(header.width > 0);
static constexpr array<uint8_t, 6> spiff_magic_id{{'S', 'P', 'I', 'F', 'F', '\0'}};
static constexpr array spiff_magic_id{byte{'S'}, byte{'P'}, byte{'I'}, byte{'F'}, byte{'F'}, byte{'\0'}};
// Create a JPEG APP8 segment in Still Picture Interchange File Format (SPIFF), v2.0
write_segment_header(jpeg_marker_code::application_data8, 30);
write_bytes(spiff_magic_id.data(), spiff_magic_id.size());
write_bytes(spiff_magic_id);
write_uint8(spiff_major_revision_number);
write_uint8(spiff_minor_revision_number);
write_uint8(to_underlying_type(header.profile_id));
@ -64,12 +64,12 @@ void jpeg_stream_writer::write_spiff_header_segment(const spiff_header& header)
}
USE_DECL_ANNOTATIONS void jpeg_stream_writer::write_spiff_directory_entry(const uint32_t entry_tag, const void* entry_data,
const size_t entry_data_size_bytes)
USE_DECL_ANNOTATIONS void jpeg_stream_writer::write_spiff_directory_entry(const uint32_t entry_tag,
const span<const byte> entry_data)
{
write_segment_header(jpeg_marker_code::application_data8, sizeof(uint32_t) + entry_data_size_bytes);
write_segment_header(jpeg_marker_code::application_data8, sizeof(uint32_t) + entry_data.size());
write_uint32(entry_tag);
write_bytes(entry_data, entry_data_size_bytes);
write_bytes(entry_data);
}
@ -78,11 +78,10 @@ void jpeg_stream_writer::write_spiff_end_of_directory_entry()
// Note: ISO/IEC 10918-3, Annex F.2.2.3 documents that the EOD entry segment should have a length of 8
// but only 6 data bytes. This approach allows to wrap existing bit streams\encoders with a SPIFF header.
// In this implementation the SOI marker is added as data bytes to simplify the design.
static constexpr array<uint8_t, 6> spiff_end_of_directory{
{0, 0, 0, spiff_end_of_directory_entry_type, 0xFF, to_underlying_type(jpeg_marker_code::start_of_image)}};
write_segment_header(jpeg_marker_code::application_data8, spiff_end_of_directory.size());
write_bytes(spiff_end_of_directory.data(), spiff_end_of_directory.size());
static constexpr array spiff_end_of_directory{byte{0}, byte{0},
byte{0}, byte{spiff_end_of_directory_entry_type},
byte{0xFF}, byte{to_underlying_type(jpeg_marker_code::start_of_image)}};
write_segment(jpeg_marker_code::application_data8, spiff_end_of_directory);
}
@ -122,17 +121,14 @@ bool jpeg_stream_writer::write_start_of_frame_segment(const frame_info& frame)
void jpeg_stream_writer::write_color_transform_segment(const color_transformation transformation)
{
const array<uint8_t, 5> segment{'m', 'r', 'f', 'x', static_cast<uint8_t>(transformation)};
write_segment_header(jpeg_marker_code::application_data8, segment.size());
write_bytes(segment.data(), segment.size());
const array segment{byte{'m'}, byte{'r'}, byte{'f'}, byte{'x'}, static_cast<byte>(transformation)};
write_segment(jpeg_marker_code::application_data8, segment);
}
void jpeg_stream_writer::write_comment_segment(const span<const byte> comment)
{
write_segment_header(jpeg_marker_code::comment, comment.size());
write_bytes(comment);
write_segment(jpeg_marker_code::comment, comment);
}
@ -140,11 +136,9 @@ void jpeg_stream_writer::write_application_data_segment(const int32_t applicatio
const span<const byte> application_data)
{
ASSERT(application_data_id >= minimum_application_data_id && application_data_id <= maximum_application_data_id);
write_segment_header(
write_segment(
static_cast<jpeg_marker_code>(static_cast<int32_t>(jpeg_marker_code::application_data0) + application_data_id),
application_data.size());
write_bytes(application_data);
application_data);
}

View File

@ -33,8 +33,7 @@ public:
/// <param name="header">Header info to write into the SPIFF segment.</param>
void write_spiff_header_segment(const spiff_header& header);
void write_spiff_directory_entry(uint32_t entry_tag, CHARLS_IN_READS_BYTES(entry_data_size_bytes) const void* entry_data,
size_t entry_data_size_bytes);
void write_spiff_directory_entry(uint32_t entry_tag, span<const std::byte> entry_data);
/// <summary>
/// Write a JPEG SPIFF end of directory (APP8) segment.
@ -43,7 +42,7 @@ public:
void write_spiff_end_of_directory_entry();
/// <summary>
/// Writes a HP color transformation (APP8) segment.
/// Writes an HP color transformation (APP8) segment.
/// </summary>
/// <param name="transformation">Color transformation to put into the segment.</param>
void write_color_transform_segment(color_transformation transformation);
@ -178,7 +177,8 @@ private:
#else
const UnsignedIntType big_endian_value{value};
#endif
write_bytes(&big_endian_value, sizeof big_endian_value);
const void* bytes{&big_endian_value};
write_bytes({static_cast<const std::byte*>(bytes), sizeof big_endian_value});
}
void write_byte(const std::byte value) noexcept
@ -189,14 +189,9 @@ private:
void write_bytes(const span<const std::byte> data) noexcept
{
write_bytes(data.data(), data.size());
}
void write_bytes(CHARLS_IN_READS_BYTES(size) const void* data, const size_t size) noexcept
{
ASSERT(byte_offset_ + size <= destination_.size());
memcpy(destination_.data() + byte_offset_, data, size);
byte_offset_ += size;
ASSERT(byte_offset_ + data.size() <= destination_.size());
memcpy(destination_.data() + byte_offset_, data.data(), data.size());
byte_offset_ += data.size();
}
void write_marker(const jpeg_marker_code marker_code) noexcept
@ -214,6 +209,12 @@ private:
write_byte(static_cast<std::byte>(marker_code));
}
void write_segment(const jpeg_marker_code marker_code, const span<const std::byte> data)
{
write_segment_header(marker_code, data.size());
write_bytes(data);
}
span<std::byte> destination_{};
size_t byte_offset_{};
uint8_t component_id_{1};

View File

@ -37,6 +37,7 @@ public:
{
}
// ReSharper disable once CppNonExplicitConvertingConstructor
template<typename OtherType, size_t Size>
constexpr span(const std::array<OtherType, Size>& data) noexcept : data_{data.data()}, size_{Size}
{

View File

@ -3,7 +3,6 @@
#include "../src/default_traits.h"
#include "../src/lossless_traits.h"
#include "../src/process_decoded_line.h"
#include "util.h"

View File

@ -248,9 +248,9 @@ public:
array<byte, 10> buffer{};
jpeg_stream_writer writer{{buffer.data(), buffer.size()}};
const array data{byte{0x77}, byte{0x66}};
constexpr array data{byte{0x77}, byte{0x66}};
writer.write_spiff_directory_entry(2, data.data(), data.size());
writer.write_spiff_directory_entry(2, data);
// Verify Entry Magic Number (EMN)
Assert::AreEqual(byte{0xFF}, buffer[0]);

View File

@ -55,7 +55,7 @@ int32_t unmap_error_value_original(const int32_t mapped_error_value) noexcept
/// <remarks>
/// This version will be auto optimized by GCC(trunk, not 10.2) using a cmove,
/// and clang(11.0) 8 instructions,. MSVC will create branches.
/// and clang(11.0) 8 instructions, MSVC will create branches.
/// Optimized version uses 6 to 5 instructions.
/// </remarks>
int32_t unmap_error_value_alternative1(const int32_t mapped_error_value) noexcept

View File

@ -52,7 +52,7 @@ public:
strategy.append_to_bit_stream_forward(0xffff, 16);
strategy.append_to_bit_stream_forward(0xffff, 16);
// Buffer is full with FFs and _isFFWritten = true: Flush can only write 30 date bits.
// Buffer is full of FFs and _isFFWritten = true: Flush can only write 30 date bits.
strategy.append_to_bit_stream_forward(0x3, 31);
strategy.flush_forward();