// Copyright (c) Team CharLS. // SPDX-License-Identifier: BSD-3-Clause #include "pch.h" #include "jpeg_test_stream_writer.h" #include "util.h" #include "../src/jpeg_stream_reader.h" #include "../src/jpeg_stream_writer.h" #include #include #include using Microsoft::VisualStudio::CppUnitTestFramework::Assert; using std::array; using std::numeric_limits; using std::vector; namespace charls { namespace test { TEST_CLASS(jpeg_stream_reader_test) { public: TEST_METHOD(read_header_from_to_small_input_buffer_throws) // NOLINT { array buffer{}; jpeg_stream_reader reader; reader.source({buffer.data(), 0}); assert_expect_exception(jpegls_errc::source_buffer_too_small, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_from_buffer_preceded_with_fill_bytes) // NOLINT { constexpr uint8_t extra_start_byte{0xFF}; jpeg_test_stream_writer writer; writer.write_byte(extra_start_byte); writer.write_start_of_image(); writer.write_byte(extra_start_byte); writer.write_start_of_frame_segment(1, 1, 2, 1); writer.write_byte(extra_start_byte); writer.write_start_of_scan_segment(0, 1, 1, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); // if it doesn't throw test is passed. } TEST_METHOD(read_header_from_buffer_not_starting_with_ff_throws) // NOLINT { array buffer{0x0F, 0xFF, 0xD8, 0xFF, 0xFF, 0xDA}; // 0xDA = SOS: Marks the start of scan. jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::jpeg_marker_start_byte_not_found, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_application_data) // NOLINT { for (uint8_t i{}; i != 16; ++i) { read_header_with_application_data(i); } } TEST_METHOD(read_header_with_jpegls_extended_frame_throws) // NOLINT { array buffer{ 0xFF, 0xD8, 0xFF, 0xF9}; // 0xF9 = SOF_57: Marks the start of a JPEG-LS extended (ISO/IEC 14495-2) encoded frame. jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::encoding_not_supported, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_jpegls_preset_parameter_segment) // NOLINT { vector source(100); jpeg_stream_writer writer({source.data(), source.size()}); writer.write_start_of_image(); constexpr jpegls_pc_parameters presets{1, 2, 3, 4, 5}; writer.write_jpegls_preset_parameters_segment(presets); writer.write_start_of_frame_segment({1, 1, 2, 1}); writer.write_start_of_scan_segment(1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({source.data(), source.size()}); reader.read_header(); const auto& actual{reader.preset_coding_parameters()}; Assert::AreEqual(presets.maximum_sample_value, actual.maximum_sample_value); Assert::AreEqual(presets.reset_value, actual.reset_value); Assert::AreEqual(presets.threshold1, actual.threshold1); Assert::AreEqual(presets.threshold2, actual.threshold2); Assert::AreEqual(presets.threshold3, actual.threshold3); } TEST_METHOD(read_header_with_too_small_jpegls_preset_parameter_segment_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF8, // LSE: Marks the start of a JPEG-LS preset parameters segment. 0x00, 0x02, 0x01}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_small_jpegls_preset_parameter_segment_with_coding_parameters_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF8, // LSE: Marks the start of a JPEG-LS preset parameters segment. 0x00, 0x0A, 0x01}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_large_jpegls_preset_parameter_segment_with_coding_parameters_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF8, // LSE: Marks the start of a JPEG-LS preset parameters segment. 0x00, 0x0C, 0x01}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_jpegls_preset_parameter_with_extended_id_throws) // NOLINT { constexpr array ids{{0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xC, 0xD}}; for (const auto id : ids) { read_header_with_jpeg_ls_preset_parameter_with_extended_id_throws(id); } } TEST_METHOD(read_header_with_too_small_segment_size_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF7, // SOF_55: Marks the start of JPEG-LS extended scan. 0x00, 0x01, 0xFF, 0xDA}; // SOS: Marks the start of scan. jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_small_start_of_frame_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF7, // SOF_55: Marks the start of JPEG-LS extended scan. 0x00, 0x07}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_small_start_of_frame_in_component_info_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF7, // SOF_55: Marks the start of JPEG-LS extended scan. 0x00, 0x07}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_large_start_of_frame_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.buffer.push_back(0); writer.buffer[5]++; jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_sos_before_sof_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_scan_segment(0, 1, 128, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::unexpected_marker_found, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_extra_sof_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_frame_segment(512, 512, 8, 3); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::duplicate_start_of_frame_marker, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_too_large_near_lossless_in_sos_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_scan_segment(0, 1, 128, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_parameter_near_lossless, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_too_large_near_lossless_in_sos_throws2) // NOLINT { constexpr jpegls_pc_parameters preset_coding_parameters{200, 0, 0, 0, 0}; jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_jpegls_preset_parameters_segment(preset_coding_parameters); writer.write_start_of_frame_segment(512, 512, 8, 3); constexpr int bad_near_lossless{(200 / 2) + 1}; writer.write_start_of_scan_segment(0, 1, bad_near_lossless, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_parameter_near_lossless, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_line_interleave_in_sos_for_single_component_throws) // NOLINT { read_header_incorrect_interleave_in_sos_for_single_component_throws(interleave_mode::line); } TEST_METHOD(read_header_sample_interleave_in_sos_for_single_component_throws) // NOLINT { read_header_incorrect_interleave_in_sos_for_single_component_throws(interleave_mode::sample); } TEST_METHOD(read_header_with_duplicate_component_id_in_start_of_frame_segment_throws) // NOLINT { jpeg_test_stream_writer writer; writer.componentIdOverride = 7; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::duplicate_component_id_in_sof_segment, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_to_many_components_in_start_of_frame_segment_throws) // NOLINT { 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, 2, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_parameter_component_count, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_no_components_in_start_of_frame_segment_throws) // NOLINT { 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, 0, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_parameter_component_count, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_more_then_max_components_in_start_of_frame_segment_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 5); writer.write_start_of_scan_segment(0, 5, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_parameter_component_count, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_small_start_of_scan_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF7, // SOF_55: Marks the start of JPEG-LS extended scan. 0x00, 0x08, // size 0x08, // bits per sample 0x00, 0x01, // width 0x00, 0x01, // height 0x01, // component count 0xFF, 0xDA, // SOS 0x00, 0x03}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_too_small_start_of_scan_component_count_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xF7, // SOF_55: Marks the start of JPEG-LS extended scan. 0x00, 0x08, // size 0x08, // bits per sample 0x00, 0x01, // width 0x00, 0x01, // height 0x01, // component count 0xFF, 0xDA, // SOS 0x00, 0x07, 0x01}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_directly_end_of_image_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xD9}; // 0xD9 = EOI jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::unexpected_end_of_image_marker, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_duplicate_start_of_image_throws) // NOLINT { array buffer{0xFF, 0xD8, 0xFF, 0xD8}; // 0xD8 = SOI. jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::duplicate_start_of_image_marker, [&reader] { reader.read_header(); }); } TEST_METHOD(read_spiff_header) // NOLINT { read_spiff_header(0); } TEST_METHOD(read_spiff_header_low_version_newer) // NOLINT { read_spiff_header(1); } TEST_METHOD(read_spiff_header_high_version_to_new) // NOLINT { vector buffer{create_test_spiff_header(3)}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); spiff_header spiff_header{}; bool spiff_header_found{}; reader.read_header(&spiff_header, &spiff_header_found); Assert::IsFalse(spiff_header_found); } TEST_METHOD(read_spiff_header_without_end_of_directory) // NOLINT { vector buffer = create_test_spiff_header(2, 0, false); jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); spiff_header spiff_header{}; bool spiff_header_found{}; reader.read_header(&spiff_header, &spiff_header_found); Assert::IsTrue(spiff_header_found); assert_expect_exception(jpegls_errc::missing_end_of_spiff_directory, [&reader] { reader.read_header(); }); } TEST_METHOD(read_header_with_define_restart_interval_16_bit) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_define_restart_interval(numeric_limits::max() - 5, 2); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); Assert::AreEqual(static_cast(numeric_limits::max() - 5), reader.parameters().restart_interval); } TEST_METHOD(read_header_with_define_restart_interval_24_bit) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_define_restart_interval(numeric_limits::max() + 5, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); Assert::AreEqual(static_cast(numeric_limits::max() + 5), reader.parameters().restart_interval); } TEST_METHOD(read_header_with_define_restart_interval_32_bit) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_define_restart_interval(numeric_limits::max() - 7, 4); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); Assert::AreEqual(numeric_limits::max() - 7, reader.parameters().restart_interval); } TEST_METHOD(read_header_with_2_define_restart_intervals) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_define_restart_interval(numeric_limits::max(), 4); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_define_restart_interval(0, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); Assert::AreEqual(0U, reader.parameters().restart_interval); } TEST_METHOD(read_header_with_bad_define_restart_interval) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_start_of_frame_segment(512, 512, 8, 3); constexpr array buffer{}; writer.write_segment(jpeg_marker_code::define_restart_interval, buffer.data(), buffer.size()); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::invalid_marker_segment_size, [&reader] { reader.read_header(); }); } TEST_METHOD(read_jpegls_stream_with_restart_marker_outside_entropy_data) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_restart_marker(0); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); assert_expect_exception(jpegls_errc::unexpected_restart_marker, [&reader] { reader.read_header(); }); } TEST_METHOD(read_comment) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::comment, "hello", 5); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); struct callback_output { const void* data{}; size_t size{}; }; callback_output actual; reader.at_comment({[](const void* data, const size_t size, void* user_context) noexcept -> int32_t { auto* actual_output{static_cast(user_context)}; actual_output->data = data; actual_output->size = size; return 0; }, &actual}); reader.read_header(); Assert::AreEqual(size_t{5}, actual.size); Assert::IsTrue(memcmp("hello", actual.data, actual.size) == 0); } TEST_METHOD(read_empty_comment) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::comment, "", 0); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); struct callback_output { const void* data{}; size_t size{}; }; callback_output actual; reader.at_comment({[](const void* data, const size_t size, void* user_context) noexcept -> int32_t { auto* actual_output{static_cast(user_context)}; actual_output->data = data; actual_output->size = size; return 0; }, &actual}); reader.read_header(); Assert::AreEqual(size_t{}, actual.size); Assert::IsNull(actual.data); } TEST_METHOD(read_comment_from_too_small_buffer_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::comment, "", 0); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size() - 1}); bool called{}; reader.at_comment({[](const void*, const size_t, void* user_context) noexcept -> int32_t { auto* actual_called{static_cast(user_context)}; *actual_called = true; return 0; }, &called}); assert_expect_exception(jpegls_errc::source_buffer_too_small, [&reader] { reader.read_header(); }); Assert::IsFalse(called); } TEST_METHOD(read_application_data) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::application_data8, "hello", 5); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); struct callback_output { int32_t id{}; const void* data{}; size_t size{}; }; callback_output actual; reader.at_application_data( {[](const int32_t id, const void* data, const size_t size, void* user_context) noexcept -> int32_t { auto* actual_output{static_cast(user_context)}; actual_output->id = id; actual_output->data = data; actual_output->size = size; return 0; }, &actual}); reader.read_header(); Assert::AreEqual(8, actual.id); Assert::AreEqual(size_t{5}, actual.size); Assert::IsTrue(memcmp("hello", actual.data, actual.size) == 0); } TEST_METHOD(read_empty_application_data) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::application_data15, "", 0); writer.write_start_of_frame_segment(512, 512, 8, 3); writer.write_start_of_scan_segment(0, 1, 0, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); struct callback_output { int32_t id{}; const void* data{}; size_t size{}; }; callback_output actual; reader.at_application_data( {[](const int32_t id, const void* data, const size_t size, void* user_context) noexcept -> int32_t { auto* actual_output{static_cast(user_context)}; actual_output->id = id; actual_output->data = data; actual_output->size = size; return 0; }, &actual}); reader.read_header(); Assert::AreEqual(15, actual.id); Assert::AreEqual(size_t{}, actual.size); Assert::IsNull(actual.data); } TEST_METHOD(read_application_data_from_too_small_buffer_throws) // NOLINT { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_segment(jpeg_marker_code::application_data14, "", 0); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size() - 1}); bool called{}; reader.at_application_data({[](int32_t, const void*, const size_t, void* user_context) noexcept -> int32_t { auto* actual_called{static_cast(user_context)}; *actual_called = true; return 0; }, &called}); assert_expect_exception(jpegls_errc::source_buffer_too_small, [&reader] { reader.read_header(); }); Assert::IsFalse(called); } private: static void read_spiff_header(const uint8_t low_version) { vector buffer{create_test_spiff_header(2, low_version)}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); spiff_header spiff_header{}; bool spiff_header_found{}; reader.read_header(&spiff_header, &spiff_header_found); Assert::IsTrue(spiff_header_found); Assert::AreEqual(static_cast(spiff_profile_id::none), static_cast(spiff_header.profile_id)); Assert::AreEqual(3, spiff_header.component_count); Assert::AreEqual(800U, spiff_header.height); Assert::AreEqual(600U, spiff_header.width); Assert::AreEqual(static_cast(spiff_color_space::rgb), static_cast(spiff_header.color_space)); Assert::AreEqual(8, spiff_header.bits_per_sample); Assert::AreEqual(static_cast(spiff_compression_type::jpeg_ls), static_cast(spiff_header.compression_type)); Assert::AreEqual(static_cast(spiff_resolution_units::dots_per_inch), static_cast(spiff_header.resolution_units)); Assert::AreEqual(96U, spiff_header.vertical_resolution); Assert::AreEqual(1024U, spiff_header.horizontal_resolution); } static void read_header_with_application_data(const uint8_t data_number) { jpeg_test_stream_writer writer; writer.write_start_of_image(); writer.write_byte(0xFF); writer.write_byte(0xE0 + data_number); writer.write_byte(0x00); writer.write_byte(0x02); writer.write_start_of_frame_segment(1, 1, 2, 1); writer.write_start_of_scan_segment(0, 1, 1, interleave_mode::none); jpeg_stream_reader reader; reader.source({writer.buffer.data(), writer.buffer.size()}); reader.read_header(); // if it doesn't throw test is passed. } static void read_header_incorrect_interleave_in_sos_for_single_component_throws(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()}); assert_expect_exception(jpegls_errc::invalid_parameter_interleave_mode, [&reader] { reader.read_header(); }); } static void read_header_with_jpeg_ls_preset_parameter_with_extended_id_throws(const uint8_t id) { array buffer{0xFF, 0xD8, 0xFF, 0xF8, // LSE: Marks the start of a JPEG-LS preset parameters segment. 0x00, 0x03, id}; jpeg_stream_reader reader; reader.source({buffer.data(), buffer.size()}); assert_expect_exception(jpegls_errc::jpegls_preset_extended_parameter_type_not_supported, [&reader] { reader.read_header(); }); } }; }} // namespace charls::test