Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the API to align with the C# implementation #320

Merged
merged 1 commit into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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