Skip to content

Commit

Permalink
Update the API to align with the C# implementation (#320)
Browse files Browse the repository at this point in the history
  • Loading branch information
vbaderks authored Aug 23, 2024
1 parent e462982 commit 2c48039
Show file tree
Hide file tree
Showing 32 changed files with 327 additions and 330 deletions.
2 changes: 1 addition & 1 deletion doc/style_and_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ sense to define a good naming convention. Not all JPEG-LS names are good C++ var
| JPEG-LS Symbol | C++ name | Description |
| -------------- | ------------------------ |------------ |
| a, b, c, d | a, b, c, d | positions of samples in the causal template |
| bpp | bits_per_pixel | number of bits needed to represent MAXVAL (not less than 2) |
| bpp | bits_per_sample | number of bits needed to represent MAXVAL (not less than 2) |
| D1, D2, D3, Di | d1, d2, d3, di | local gradients |
| EMErrval | e_mapped_error_value | Errval mapped to non-negative integers in run interruption mode |
| Errval | error_value | prediction error (quantized or unquantized, before and after modulo reduction) |
Expand Down
2 changes: 1 addition & 1 deletion fuzzing/libfuzzer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, const size_t size)
if (const auto& frame_info{decoder.frame_info()};
frame_info.height < 500 && frame_info.width < 500 && frame_info.component_count < 4)
{
std::vector<uint8_t> destination(decoder.destination_size());
std::vector<uint8_t> destination(decoder.get_destination_size());
decoder.decode(destination);
}
}
Expand Down
38 changes: 19 additions & 19 deletions include/charls/charls_jpegls_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,11 @@ charls_decoder_get_mapping_table_id(CHARLS_IN const charls_jpegls_decoder* decod
/// Function should be called after processing the complete JPEG-LS stream.
/// </remarks>
/// <param name="decoder">Reference to the decoder instance.</param>
/// <param name="table_id">Mapping table ID to lookup.</param>
/// <param name="mapping_table_id">Mapping table ID to lookup.</param>
/// <param name="index">Output argument, will hold the mapping table index or -1 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_decoder_get_mapping_table_index(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t table_id,
charls_decoder_find_mapping_table_index(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t mapping_table_id,
CHARLS_OUT int32_t* index) CHARLS_NOEXCEPT CHARLS_ATTRIBUTE((nonnull));

/// <summary>
Expand All @@ -268,13 +268,13 @@ charls_decoder_get_mapping_table_count(CHARLS_IN const charls_jpegls_decoder* de
/// Function should be called after processing the complete JPEG-LS stream.
/// </remarks>
/// <param name="decoder">Reference to the decoder instance.</param>
/// <param name="index">Index of the requested mapping table.</param>
/// <param name="mapping_table_index">Index of the requested mapping table.</param>
/// <param name="mapping_table_info">
/// Output argument, will hold the mapping table information 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_decoder_get_mapping_table_info(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t index,
charls_decoder_get_mapping_table_info(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t mapping_table_index,
CHARLS_OUT charls_mapping_table_info* mapping_table_info) CHARLS_NOEXCEPT
CHARLS_ATTRIBUTE((nonnull));

Expand All @@ -285,15 +285,15 @@ charls_decoder_get_mapping_table_info(CHARLS_IN const charls_jpegls_decoder* dec
/// Function should be called after processing the complete JPEG-LS stream.
/// </remarks>
/// <param name="decoder">Reference to the decoder instance.</param>
/// <param name="index">Index of the requested mapping table.</param>
/// <param name="table_data">Output argument, will hold the data of the mapping table when the function returns.</param>
/// <param name="table_size_bytes">Length of the mapping table buffer in bytes.</param>
/// <param name="mapping_table_index">Index of the requested mapping table.</param>
/// <param name="mapping_table_data">Output argument, will hold the data of the mapping table when the function returns.</param>
/// <param name="mapping_table_size_bytes">Length of the mapping table buffer in bytes.</param>
/// <returns>The result of the operation: success or a failure code.</returns>
CHARLS_ATTRIBUTE_ACCESS((access(write_only, 3, 4)))
CHARLS_CHECK_RETURN CHARLS_API_IMPORT_EXPORT charls_jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_decoder_get_mapping_table_data(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t index,
CHARLS_OUT_WRITES_BYTES(table_size_bytes) void* table_data,
size_t table_size_bytes) CHARLS_NOEXCEPT CHARLS_ATTRIBUTE((nonnull));
charls_decoder_get_mapping_table_data(CHARLS_IN const charls_jpegls_decoder* decoder, int32_t mapping_table_index,
CHARLS_OUT_WRITES_BYTES(mapping_table_size_bytes) void* mapping_table_data,
size_t mapping_table_size_bytes) CHARLS_NOEXCEPT CHARLS_ATTRIBUTE((nonnull));

#ifdef __cplusplus

Expand Down Expand Up @@ -328,7 +328,7 @@ class jpegls_decoder final
{
jpegls_decoder decoder{source, true};

const size_t destination_size{decoder.destination_size()};
const size_t destination_size{decoder.get_destination_size()};
if (destination_size > maximum_size_in_bytes)
impl::throw_jpegls_error(jpegls_errc::not_enough_memory);

Expand Down Expand Up @@ -531,14 +531,14 @@ class jpegls_decoder final
/// <summary>
/// Returns the NEAR parameter that was used to encode the scan. A value of 0 means lossless.
/// </summary>
/// <param name="component">The component index for which the NEAR parameter should be retrieved.</param>
/// <param name="component_index">The component index for which the NEAR parameter should be retrieved.</param>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
/// <returns>The value of the NEAR parameter.</returns>
[[nodiscard]]
int32_t near_lossless(const int32_t component = 0) const
int32_t get_near_lossless(const int32_t component_index = 0) const
{
int32_t near_lossless;
check_jpegls_errc(charls_jpegls_decoder_get_near_lossless(decoder(), component, &near_lossless));
check_jpegls_errc(charls_jpegls_decoder_get_near_lossless(decoder(), component_index, &near_lossless));
return near_lossless;
}

Expand Down Expand Up @@ -589,7 +589,7 @@ class jpegls_decoder final
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
/// <returns>The required size in bytes of the destination buffer.</returns>
[[nodiscard]]
size_t destination_size(const uint32_t stride = 0) const
size_t get_destination_size(const uint32_t stride = 0) const
{
size_t size_in_bytes;
check_jpegls_errc(charls_jpegls_decoder_get_destination_size(decoder(), stride, &size_in_bytes));
Expand Down Expand Up @@ -635,7 +635,7 @@ class jpegls_decoder final
[[nodiscard]]
Container decode(const uint32_t stride = 0)
{
Container destination(destination_size() / sizeof(ContainerValueType));
Container destination(get_destination_size() / sizeof(ContainerValueType));

decode(destination.data(), destination.size() * sizeof(ContainerValueType), stride);
return destination;
Expand Down Expand Up @@ -701,16 +701,16 @@ class jpegls_decoder final
/// <remarks>
/// Function should be called after processing the complete JPEG-LS stream.
/// </remarks>
/// <param name="table_id">Mapping table ID to lookup.</param>
/// <param name="mapping_table_id">Mapping table ID to lookup.</param>
/// <returns>
/// The index of the mapping table or -1 (mapping_table_missing) when the table is not present in the JPEG-LS stream.
/// </returns>
/// <exception cref="charls::jpegls_error">An error occurred during the operation.</exception>
[[nodiscard]]
int32_t get_mapping_table_index(const int32_t table_id) const
int32_t find_mapping_table_index(const int32_t mapping_table_id) const
{
int32_t index;
check_jpegls_errc(charls_decoder_get_mapping_table_index(decoder(), table_id, &index));
check_jpegls_errc(charls_decoder_find_mapping_table_index(decoder(), mapping_table_id, &index));
return index;
}

Expand Down
4 changes: 2 additions & 2 deletions include/charls/public_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ enum charls_jpegls_errc
CHARLS_JPEGLS_ERRC_RESTART_MARKER_NOT_FOUND = 23,
CHARLS_JPEGLS_ERRC_END_OF_IMAGE_MARKER_NOT_FOUND = 24,
CHARLS_JPEGLS_ERRC_UNKNOWN_COMPONENT_ID = 25,
CHARLS_JPEGLS_ERRC_ABBREVIATED_FORMAT_AND_SPIFF_HEADER = 26,
CHARLS_JPEGLS_ERRC_ABBREVIATED_FORMAT_AND_SPIFF_HEADER_MISMATCH = 26,
CHARLS_JPEGLS_ERRC_INVALID_PARAMETER_WIDTH = 27,
CHARLS_JPEGLS_ERRC_INVALID_PARAMETER_HEIGHT = 28,
CHARLS_JPEGLS_ERRC_INVALID_PARAMETER_BITS_PER_SAMPLE = 29,
Expand Down Expand Up @@ -325,7 +325,7 @@ enum class [[nodiscard]] jpegls_errc
/// <summary>
/// This error is returned for stream with only mapping tables and a spiff header.
/// </summary>
abbreviated_format_and_spiff_header = impl::CHARLS_JPEGLS_ERRC_ABBREVIATED_FORMAT_AND_SPIFF_HEADER,
abbreviated_format_and_spiff_header_mismatch = impl::CHARLS_JPEGLS_ERRC_ABBREVIATED_FORMAT_AND_SPIFF_HEADER_MISMATCH,

/// <summary>
/// This error is returned when the stream contains a width parameter defined more than once or in an incompatible way.
Expand Down
1 change: 1 addition & 0 deletions spelling.dic
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ cppcoreguidelines
uint
json
intrinsics
palletised
49 changes: 26 additions & 23 deletions src/charls_jpegls_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct charls_jpegls_decoder final
}

[[nodiscard]]
size_t destination_size(const size_t stride) const
size_t get_destination_size(const size_t stride) const
{
const auto [width, height, bits_per_sample, component_count]{frame_info_checked()};

Expand Down Expand Up @@ -138,11 +138,11 @@ struct charls_jpegls_decoder final
}

[[nodiscard]]
int32_t get_mapping_table_index(const int32_t table_id) const
int32_t find_mapping_table_index(const int32_t mapping_table_id) const
{
check_state_completed();
check_argument_range(minimum_table_id, maximum_table_id, table_id);
return reader_.get_mapping_table_index(static_cast<uint8_t>(table_id));
check_argument_range(minimum_mapping_table_id, maximum_mapping_table_id, mapping_table_id);
return reader_.find_mapping_table_index(static_cast<uint8_t>(mapping_table_id));
}

[[nodiscard]]
Expand All @@ -153,18 +153,18 @@ struct charls_jpegls_decoder final
}

[[nodiscard]]
mapping_table_info get_mapping_table_info(const int32_t index) const
mapping_table_info get_mapping_table_info(const int32_t mapping_table_index) const
{
check_table_index(index);
return reader_.get_mapping_table_info(index);
check_mapping_table_index(mapping_table_index);
return reader_.get_mapping_table_info(mapping_table_index);
}

void get_mapping_table_data(const int32_t index, const span<byte> table) const
void get_mapping_table_data(const int32_t mapping_table_index, const span<byte> table_data) const
{
check_table_index(index);
check_argument(table.data() || table.empty());
check_mapping_table_index(mapping_table_index);
check_argument(table_data.data() || table_data.empty());

reader_.get_mapping_table_data(index, table);
reader_.get_mapping_table_data(mapping_table_index, table_data);
}

void decode(span<byte> destination, size_t stride)
Expand Down Expand Up @@ -239,9 +239,9 @@ struct charls_jpegls_decoder final
check_operation(state_ == state::completed);
}

void check_table_index(const int32_t index) const
void check_mapping_table_index(const int32_t mapping_table_index) const
{
check_argument_range(0, mapping_table_count() - 1, index);
check_argument_range(0, mapping_table_count() - 1, mapping_table_index);
}

void check_parameter_coherent() const
Expand Down Expand Up @@ -400,7 +400,7 @@ USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_jpegls_dec
const charls_jpegls_decoder* decoder, const uint32_t stride, size_t* destination_size_bytes) noexcept
try
{
*check_pointer(destination_size_bytes) = check_pointer(decoder)->destination_size(stride);
*check_pointer(destination_size_bytes) = check_pointer(decoder)->get_destination_size(stride);
return jpegls_errc::success;
}
catch (...)
Expand Down Expand Up @@ -462,11 +462,11 @@ catch (...)
}


USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_decoder_get_mapping_table_index(const charls_jpegls_decoder* decoder, const int32_t table_id, int32_t* index) noexcept
USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_decoder_find_mapping_table_index(
const charls_jpegls_decoder* decoder, const int32_t mapping_table_id, int32_t* index) noexcept
try
{
*check_pointer(index) = check_pointer(decoder)->get_mapping_table_index(table_id);
*check_pointer(index) = check_pointer(decoder)->find_mapping_table_index(mapping_table_id);
return jpegls_errc::success;
}
catch (...)
Expand All @@ -488,11 +488,12 @@ catch (...)
}


USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_decoder_get_mapping_table_info(
const charls_jpegls_decoder* decoder, const int32_t index, mapping_table_info* mapping_table_info) noexcept
USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_decoder_get_mapping_table_info(const charls_jpegls_decoder* decoder, const int32_t mapping_table_index,
charls_mapping_table_info* mapping_table_info) noexcept
try
{
*check_pointer(mapping_table_info) = check_pointer(decoder)->get_mapping_table_info(index);
*check_pointer(mapping_table_info) = check_pointer(decoder)->get_mapping_table_info(mapping_table_index);
return jpegls_errc::success;
}
catch (...)
Expand All @@ -501,11 +502,13 @@ catch (...)
}


USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION charls_decoder_get_mapping_table_data(
const charls_jpegls_decoder* decoder, const int32_t index, void* table_data, const size_t table_size_bytes) noexcept
USE_DECL_ANNOTATIONS jpegls_errc CHARLS_API_CALLING_CONVENTION
charls_decoder_get_mapping_table_data(const charls_jpegls_decoder* decoder, const int32_t mapping_table_index,
void* mapping_table_data, const size_t mapping_table_size_bytes) noexcept
try
{
check_pointer(decoder)->get_mapping_table_data(index, {static_cast<byte*>(table_data), table_size_bytes});
check_pointer(decoder)->get_mapping_table_data(mapping_table_index,
{static_cast<byte*>(mapping_table_data), mapping_table_size_bytes});
return jpegls_errc::success;
}
catch (...)
Expand Down
65 changes: 30 additions & 35 deletions src/charls_jpegls_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct charls_jpegls_encoder final
void set_mapping_table_id(const int32_t component_index, const int32_t table_id)
{
check_argument_range(minimum_component_index, maximum_component_index, component_index);
check_argument_range(0, maximum_table_id, table_id);
check_argument_range(0, maximum_mapping_table_id, table_id);

writer_.set_mapping_table_id(static_cast<size_t>(component_index), table_id);
}
Expand Down Expand Up @@ -163,8 +163,8 @@ struct charls_jpegls_encoder final

void write_mapping_table(const int32_t table_id, const int32_t entry_size, const span<const byte> table_data)
{
check_argument_range(minimum_table_id, maximum_table_id, table_id);
check_argument_range(minimum_entry_size, maximum_entry_size, entry_size);
check_argument_range(minimum_mapping_table_id, maximum_mapping_table_id, table_id);
check_argument_range(minimum_mapping_entry_size, maximum_mapping_entry_size, entry_size);
check_argument(table_data.data() || table_data.empty());
check_argument(table_data.size() >= static_cast<size_t>(entry_size), jpegls_errc::invalid_argument_size);
check_operation(state_ >= state::destination_set && state_ < state::completed);
Expand All @@ -178,21 +178,13 @@ struct charls_jpegls_encoder final
check_argument(source.data() || source.empty());
check_operation(is_frame_info_configured() && state_ != state::initial);
check_interleave_mode_against_component_count();
stride = check_stride_and_source(source.size(), stride);

const int32_t maximum_sample_value{calculate_maximum_sample_value(frame_info_.bits_per_sample)};
if (UNLIKELY(
!is_valid(user_preset_coding_parameters_, maximum_sample_value, near_lossless_, &preset_coding_parameters_)))
throw_jpegls_error(jpegls_errc::invalid_argument_jpegls_pc_parameters);

if (stride == auto_calculate_stride)
{
stride = calculate_stride();
}
else
{
check_stride(stride, source.size());
}

transition_to_tables_and_miscellaneous_state();
write_color_transform_segment();
write_start_of_frame_segment();
Expand Down Expand Up @@ -283,36 +275,39 @@ struct charls_jpegls_encoder final
}

[[nodiscard]]
size_t calculate_stride() const noexcept
{
const auto stride{static_cast<size_t>(frame_info_.width) * bit_to_byte_count(frame_info_.bits_per_sample)};
if (interleave_mode_ == interleave_mode::none)
return stride;

return stride * frame_info_.component_count;
}

void check_stride(const size_t stride, const size_t source_size) const
size_t check_stride_and_source(const size_t source_size, size_t stride) const
{
const size_t minimum_stride{calculate_stride()};
if (UNLIKELY(stride < minimum_stride))
throw_jpegls_error(jpegls_errc::invalid_argument_stride);

// Simple check to verify user input, and prevent out-of-bound read access.
// Stride parameter defines the number of bytes on a scan line.
if (interleave_mode_ == interleave_mode::none)
const size_t minimum_stride{calculate_minimum_stride()};
if (stride == auto_calculate_stride)
{
if (const size_t minimum_source_size{stride * frame_info_.component_count * frame_info_.height -
(stride - minimum_stride)};
UNLIKELY(source_size < minimum_source_size))
throw_jpegls_error(jpegls_errc::invalid_argument_stride);
stride = minimum_stride;
}
else
{
if (const size_t minimum_source_size{stride * frame_info_.height - (stride - minimum_stride)};
UNLIKELY(source_size < minimum_source_size))
if (UNLIKELY(stride < minimum_stride))
throw_jpegls_error(jpegls_errc::invalid_argument_stride);
}

const size_t not_used_bytes_at_end{stride - minimum_stride};
const size_t minimum_source_size{interleave_mode_ == interleave_mode::none
? (stride * frame_info_.component_count * frame_info_.height) -
not_used_bytes_at_end
: (stride * frame_info_.height) - not_used_bytes_at_end};

if (UNLIKELY(source_size < minimum_source_size))
throw_jpegls_error(jpegls_errc::invalid_argument_size);

return stride;
}

[[nodiscard]]
size_t calculate_minimum_stride() const noexcept
{
const auto stride{static_cast<size_t>(frame_info_.width) * bit_to_byte_count(frame_info_.bits_per_sample)};
if (interleave_mode_ == interleave_mode::none)
return stride;

return stride * frame_info_.component_count;
}

void check_interleave_mode_against_component_count() const
Expand Down
Loading

0 comments on commit 2c48039

Please sign in to comment.