mirror of
https://github.com/team-charls/charls
synced 2025-03-28 21:03:13 +00:00
Validate interleave mode against component count (#119)
If component count is 1 then only interleave mode none may be used. Validate this during encoding and decoding.
This commit is contained in:
parent
e90cba4817
commit
04b08b7718
@ -333,9 +333,9 @@ public:
|
||||
/// This will be returned as a callback_failed error code.
|
||||
/// </remarks>
|
||||
/// <param name="comment_handler">Function object to the comment handler.</param>
|
||||
jpegls_decoder& at_comment(const std::function<void(const void* data, size_t size)> comment_handler)
|
||||
jpegls_decoder& at_comment(std::function<void(const void* data, size_t size)> comment_handler)
|
||||
{
|
||||
comment_handler_ = comment_handler;
|
||||
comment_handler_ = std::move(comment_handler);
|
||||
check_jpegls_errc(
|
||||
charls_jpegls_decoder_at_comment(decoder_.get(), comment_handler_ ? at_comment_callback : nullptr, this));
|
||||
return *this;
|
||||
|
@ -108,7 +108,7 @@ static void* bmp_read_pixel_data(FILE* fp, const uint32_t offset, const bmp_dib_
|
||||
}
|
||||
|
||||
|
||||
static void* handle_encoder_failure(const charls_jpegls_errc error, const char* step, charls_jpegls_encoder* encoder,
|
||||
static void* handle_encoder_failure(const charls_jpegls_errc error, const char* step, const charls_jpegls_encoder* encoder,
|
||||
void* buffer)
|
||||
{
|
||||
printf("Failed to %s: %i, %s\n", step, error, charls_get_error_message(error));
|
||||
|
@ -222,7 +222,7 @@ int main(const int argc, char** argv)
|
||||
convert_bgr_to_rgb(bmp_image.pixel_data, bmp_image.dib_header.width,
|
||||
static_cast<size_t>(bmp_image.dib_header.height), bmp_image.stride);
|
||||
|
||||
auto encoded_buffer{encode_bmp_image_to_jpegls(bmp_image, options.interleave_mode, options.near_lossless)};
|
||||
const auto encoded_buffer{encode_bmp_image_to_jpegls(bmp_image, options.interleave_mode, options.near_lossless)};
|
||||
save_buffer_to_file(encoded_buffer.data(), encoded_buffer.size(), options.output_filename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -39,9 +39,7 @@ struct charls_jpegls_encoder final
|
||||
|
||||
void interleave_mode(const charls::interleave_mode interleave_mode)
|
||||
{
|
||||
check_argument(interleave_mode >= charls::interleave_mode::none &&
|
||||
interleave_mode <= charls::interleave_mode::sample,
|
||||
jpegls_errc::invalid_argument_interleave_mode);
|
||||
check_interleave_mode(interleave_mode, jpegls_errc::invalid_argument_interleave_mode);
|
||||
|
||||
interleave_mode_ = interleave_mode;
|
||||
}
|
||||
@ -122,6 +120,7 @@ struct charls_jpegls_encoder final
|
||||
{
|
||||
check_argument(source.data || source.size == 0);
|
||||
check_operation(is_frame_info_configured() && state_ != state::initial);
|
||||
check_interleave_mode_against_component_count();
|
||||
|
||||
if (!is_valid(preset_coding_parameters_, calculate_maximum_sample_value(frame_info_.bits_per_sample), near_lossless_,
|
||||
&validated_pc_parameters_))
|
||||
@ -249,6 +248,12 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void check_interleave_mode_against_component_count() const
|
||||
{
|
||||
if (frame_info_.component_count == 1 && interleave_mode_ != interleave_mode::none)
|
||||
throw_jpegls_error(jpegls_errc::invalid_argument_interleave_mode);
|
||||
}
|
||||
|
||||
void transition_to_tables_and_miscellaneous_state()
|
||||
{
|
||||
if (state_ == state::tables_and_miscellaneous)
|
||||
|
@ -499,8 +499,7 @@ void jpeg_stream_reader::read_start_of_scan()
|
||||
throw_jpegls_error(jpegls_errc::invalid_parameter_near_lossless);
|
||||
|
||||
const auto mode{static_cast<interleave_mode>(read_byte())}; // Read ILV parameter
|
||||
if (!(mode == interleave_mode::none || mode == interleave_mode::line || mode == interleave_mode::sample))
|
||||
throw_jpegls_error(jpegls_errc::invalid_parameter_interleave_mode);
|
||||
check_interleave_mode(mode);
|
||||
parameters_.interleave_mode = mode;
|
||||
|
||||
if ((read_byte() & 0xFU) != 0) // Read Ah (no meaning) and Al (point transform).
|
||||
@ -677,6 +676,15 @@ void jpeg_stream_reader::check_parameter_coherent() const
|
||||
}
|
||||
|
||||
|
||||
void jpeg_stream_reader::check_interleave_mode(const interleave_mode mode) const
|
||||
{
|
||||
constexpr auto errc{jpegls_errc::invalid_parameter_interleave_mode};
|
||||
charls::check_interleave_mode(mode, errc);
|
||||
if (frame_info_.component_count == 1 && mode != interleave_mode::none)
|
||||
throw_jpegls_error(errc);
|
||||
}
|
||||
|
||||
|
||||
uint32_t jpeg_stream_reader::maximum_sample_value() const noexcept
|
||||
{
|
||||
if (preset_coding_parameters_.maximum_sample_value != 0)
|
||||
|
@ -90,6 +90,7 @@ private:
|
||||
int try_read_hp_color_transform_segment();
|
||||
void add_component(uint8_t component_id);
|
||||
void check_parameter_coherent() const;
|
||||
void check_interleave_mode(interleave_mode mode) const;
|
||||
uint32_t maximum_sample_value() const noexcept;
|
||||
|
||||
enum class state
|
||||
|
@ -331,6 +331,13 @@ inline void check_argument(const bool expression, const jpegls_errc error_value
|
||||
}
|
||||
|
||||
|
||||
inline void check_interleave_mode(const charls::interleave_mode mode, const jpegls_errc error_value)
|
||||
{
|
||||
if (!(mode == interleave_mode::none || mode == interleave_mode::line || mode == interleave_mode::sample))
|
||||
impl::throw_jpegls_error(error_value);
|
||||
}
|
||||
|
||||
|
||||
CONSTEXPR int32_t calculate_maximum_sample_value(const int32_t bits_per_sample)
|
||||
{
|
||||
ASSERT(bits_per_sample > 0 && bits_per_sample <= 16);
|
||||
|
@ -438,6 +438,16 @@ public:
|
||||
assert_expect_exception(jpegls_errc::invalid_parameter_near_lossless, [&reader] { reader.read_start_of_scan(); });
|
||||
}
|
||||
|
||||
TEST_METHOD(read_header_line_interleave_in_sos_for_single_component_should_throw) // NOLINT
|
||||
{
|
||||
read_header_incorrect_interleave_in_sos_for_single_component_should_throw(interleave_mode::line);
|
||||
}
|
||||
|
||||
TEST_METHOD(read_header_sample_interleave_in_sos_for_single_component_should_throw) // NOLINT
|
||||
{
|
||||
read_header_incorrect_interleave_in_sos_for_single_component_should_throw(interleave_mode::sample);
|
||||
}
|
||||
|
||||
TEST_METHOD(read_header_with_duplicate_component_id_in_start_of_frame_segment_should_throw) // NOLINT
|
||||
{
|
||||
jpeg_test_stream_writer writer;
|
||||
@ -849,6 +859,20 @@ private:
|
||||
|
||||
reader.read_header(); // if it doesn't throw test is passed.
|
||||
}
|
||||
|
||||
static void read_header_incorrect_interleave_in_sos_for_single_component_should_throw(const interleave_mode mode)
|
||||
{
|
||||
jpeg_test_stream_writer writer;
|
||||
writer.write_start_of_image();
|
||||
writer.write_start_of_frame_segment(512, 512, 8, 1);
|
||||
writer.write_start_of_scan_segment(0, 1, 0, mode);
|
||||
|
||||
jpeg_stream_reader reader;
|
||||
reader.source({writer.buffer.data(), writer.buffer.size()});
|
||||
reader.read_header();
|
||||
|
||||
assert_expect_exception(jpegls_errc::invalid_parameter_interleave_mode, [&reader] { reader.read_start_of_scan(); });
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace charls::test
|
||||
|
@ -113,6 +113,19 @@ public:
|
||||
[&encoder] { encoder.interleave_mode(static_cast<charls::interleave_mode>(3)); });
|
||||
}
|
||||
|
||||
TEST_METHOD(interleave_mode_does_not_match_component_count) // NOLINT
|
||||
{
|
||||
constexpr frame_info frame_info{512, 512, 8, 1};
|
||||
vector<uint8_t> source(static_cast<size_t>(frame_info.width) * frame_info.height);
|
||||
|
||||
assert_expect_exception(jpegls_errc::invalid_argument_interleave_mode, [&frame_info, &source] {
|
||||
jpegls_encoder::encode(source, frame_info, interleave_mode::sample);
|
||||
});
|
||||
assert_expect_exception(jpegls_errc::invalid_argument_interleave_mode, [&frame_info, &source] {
|
||||
jpegls_encoder::encode(source, frame_info, interleave_mode::line);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_METHOD(near_lossless) // NOLINT
|
||||
{
|
||||
jpegls_encoder encoder;
|
||||
@ -598,7 +611,8 @@ public:
|
||||
encoder.frame_info({3, 1, 16, 1});
|
||||
ignore = encoder.encode(source);
|
||||
|
||||
assert_expect_exception(jpegls_errc::invalid_operation, [&encoder] { ignore = encoder.write_comment("after-encoding"); });
|
||||
assert_expect_exception(jpegls_errc::invalid_operation,
|
||||
[&encoder] { ignore = encoder.write_comment("after-encoding"); });
|
||||
}
|
||||
|
||||
TEST_METHOD(write_comment_before_encode) // NOLINT
|
||||
|
Loading…
x
Reference in New Issue
Block a user