LibGfx/JPEG2000: Read COC marker segments, both in main and tile headers

Not yet used for anything.
This commit is contained in:
Nico Weber 2024-04-22 18:56:38 -04:00 committed by Tim Flynn
parent 8eb3d436e6
commit b364a58753
Notes: sideshowbarker 2024-07-16 22:26:05 +09:00

View File

@ -334,6 +334,36 @@ static ErrorOr<CodingStyleDefault> read_coding_style_default(ReadonlyBytes data)
return cod;
}
// A.6.2 Coding style component (COC)
struct CodingStyleComponent {
u16 component_index { 0 }; // "Ccoc" in spec.
// Table A.23 Coding style parameter values for the Scoc parameter
bool has_explicit_precinct_size { false }; // "Scoc" in spec.
CodingStyleParameters parameters;
};
static ErrorOr<CodingStyleComponent> read_coding_style_component(ReadonlyBytes data, size_t number_of_components)
{
FixedMemoryStream stream { data };
// Table A.22 Coding style component parameter values
CodingStyleComponent coc;
if (number_of_components < 257)
coc.component_index = TRY(stream.read_value<u8>());
else
coc.component_index = TRY(stream.read_value<BigEndian<u16>>());
u8 Scoc = TRY(stream.read_value<u8>());
coc.has_explicit_precinct_size = Scoc & 1;
dbgln_if(JPEG2000_DEBUG, "JPEG2000ImageDecoderPlugin: COC marker segment: component_index={}", coc.component_index);
coc.parameters = TRY(read_coding_style_parameters(data.slice(TRY(stream.tell())), "COC"sv, coc.has_explicit_precinct_size));
return coc;
}
// A.6.4 Quantization default (QCD)
struct QuantizationDefault {
enum QuantizationStyle {
@ -479,6 +509,7 @@ struct TilePartData {
struct TileData {
Optional<CodingStyleDefault> cod;
Vector<CodingStyleComponent> cocs;
Optional<QuantizationDefault> qcd;
Vector<QuantizationComponent> qccs;
Vector<TilePartData> tile_parts;
@ -502,6 +533,7 @@ struct JPEG2000LoadingContext {
// Data from marker segments:
ImageAndTileSize siz;
CodingStyleDefault cod;
Vector<CodingStyleComponent> cocs;
QuantizationDefault qcd;
Vector<QuantizationComponent> qccs;
Vector<Comment> coms;
@ -587,6 +619,8 @@ static ErrorOr<void> parse_codestream_main_header(JPEG2000LoadingContext& contex
return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple COD markers in main header");
context.cod = TRY(read_coding_style_default(marker.data.value()));
saw_COD_marker = true;
} else if (marker.marker == J2K_COC) {
context.cocs.append(TRY(read_coding_style_component(marker.data.value(), context.siz.components.size())));
} else if (marker.marker == J2K_QCD) {
if (saw_QCD_marker)
return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple QCD markers in main header");
@ -617,7 +651,8 @@ static ErrorOr<void> parse_codestream_main_header(JPEG2000LoadingContext& contex
[](Empty) -> size_t { VERIFY_NOT_REACHED(); },
[](Vector<QuantizationDefault::ReversibleStepSize> const& step_sizes) { return step_sizes.size(); },
[](Vector<QuantizationDefault::IrreversibleStepSize> const& step_sizes) { return step_sizes.size(); });
if (context.qcd.quantization_style != QuantizationDefault::ScalarDerived && step_sizes_count < context.cod.number_of_decomposition_levels * 3u + 1u)
// FIXME: What if number_of_decomposition_levels is in context.cocs and varies by component?
if (context.qcd.quantization_style != QuantizationDefault::ScalarDerived && step_sizes_count < context.cod.parameters.number_of_decomposition_levels * 3u + 1u)
return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Not enough step sizes for number of decomposition levels");
return {};
@ -676,6 +711,8 @@ static ErrorOr<void> parse_codestream_tile_header(JPEG2000LoadingContext& contex
if (tile.cod.has_value())
return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple COD markers in tile header");
tile.cod = TRY(read_coding_style_default(marker.data.value()));
} else if (marker.marker == J2K_COC) {
tile.cocs.append(TRY(read_coding_style_component(marker.data.value(), context.siz.components.size())));
} else if (marker.marker == J2K_QCD) {
if (tile.qcd.has_value())
return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple QCD markers in tile header");