Skip to content

Commit caf3800

Browse files
committed
LibGfx/JPEG2000: Correctly dequantize scalar derived quantization files
get_exponent() used to require that its callers apply formula (E-5) to its result for files using scalar-derived quantization. compute_M_b() did that correctly, but copy_and_dequantize_if_needed() didn't. Make get_exponent() do all the necessary computations instead, so that callers can't get it wrong. Improves rendering of the image in 0001530.pdf a lot.
1 parent d00cd98 commit caf3800

File tree

1 file changed

+11
-15
lines changed

1 file changed

+11
-15
lines changed

Userland/Libraries/LibGfx/ImageFormats/JPEG2000Loader.cpp

+11-15
Original file line numberDiff line numberDiff line change
@@ -2013,7 +2013,7 @@ static ErrorOr<void> read_packet_headers(JPEG2000LoadingContext& context)
20132013
return {};
20142014
}
20152015

2016-
static u8 get_exponent(QuantizationDefault const& quantization_parameters, JPEG2000::SubBand sub_band, int resolution_level)
2016+
static u8 get_exponent(QuantizationDefault const& quantization_parameters, JPEG2000::SubBand sub_band, int resolution_level, int N_L)
20172017
{
20182018
switch (quantization_parameters.quantization_style) {
20192019
case QuantizationDefault::QuantizationStyle::NoQuantization: {
@@ -2030,8 +2030,12 @@ static u8 get_exponent(QuantizationDefault const& quantization_parameters, JPEG2
20302030
auto const& steps = quantization_parameters.step_sizes.get<Vector<QuantizationDefault::IrreversibleStepSize>>();
20312031

20322032
if (quantization_parameters.quantization_style == QuantizationDefault::QuantizationStyle::ScalarDerived) {
2033-
// Callers must use (E-5).
2034-
return steps[0].exponent;
2033+
// Table F.1 – Decomposition level nb for sub-band b
2034+
// Note: The spec suggests that this ends with n_b = 1, but if N_L is 0, we have 0LL and nothing else.
2035+
int n_b = resolution_level == 0 ? N_L : (N_L + 1 - resolution_level);
2036+
// (E-5)
2037+
return steps[0].exponent - N_L + n_b;
2038+
// This is the same as `return resolution_level == 0 ? steps[0].exponent : steps[0].exponent - (resolution_level - 1);`
20352039
}
20362040

20372041
if (sub_band == JPEG2000::SubBand::HorizontalLowpassVerticalLowpass) {
@@ -2051,21 +2055,13 @@ static int compute_M_b(JPEG2000LoadingContext& context, TileData& tile, int comp
20512055
// "Mb = G + exp_b - 1 (E-2)
20522056
// where the number of guard bits G and the exponent exp_b are specified in the QCD or QCC marker segments (see A.6.4 and A.6.5)."
20532057
auto quantization_parameters = context.quantization_parameters_for_component(tile, component_index);
2054-
auto exponent = get_exponent(quantization_parameters, sub_band_type, r);
2055-
if (quantization_parameters.quantization_style == QuantizationDefault::QuantizationStyle::ScalarDerived) {
2056-
// Table F.1 – Decomposition level nb for sub-band b
2057-
// Note: The spec suggests that this ends with n_b = 1, but if N_L is 0, we have 0LL and nothing else.
2058-
int n_b = r == 0 ? N_L : (N_L + 1 - r);
2059-
// (E-5)
2060-
exponent = exponent - N_L + n_b;
2061-
// This is the same as `if (r != 0) exponent = exponent - (r - 1);`
2062-
}
2058+
auto exponent = get_exponent(quantization_parameters, sub_band_type, r, N_L);
20632059
return quantization_parameters.number_of_guard_bits + exponent - 1;
20642060
}
20652061

20662062
static ErrorOr<void> decode_bitplanes_to_coefficients(JPEG2000LoadingContext& context)
20672063
{
2068-
auto copy_and_dequantize_if_needed = [&](JPEG2000::Span2D<float> output, ReadonlySpan<float> input, QuantizationDefault const& quantization_parameters, JPEG2000::SubBand sub_band_type, int component_index, int r) {
2064+
auto copy_and_dequantize_if_needed = [&](JPEG2000::Span2D<float> output, ReadonlySpan<float> input, QuantizationDefault const& quantization_parameters, JPEG2000::SubBand sub_band_type, int component_index, int r, int N_L) {
20692065
int w = output.size.width();
20702066
int h = output.size.height();
20712067
VERIFY(w * h == static_cast<int>(input.size()));
@@ -2096,7 +2092,7 @@ static ErrorOr<void> decode_bitplanes_to_coefficients(JPEG2000LoadingContext& co
20962092
}
20972093

20982094
// (E-3)
2099-
auto exponent = get_exponent(quantization_parameters, sub_band_type, r);
2095+
auto exponent = get_exponent(quantization_parameters, sub_band_type, r, N_L);
21002096
float step_size = powf(2.0f, R_b - exponent) * (1.0f + mantissa / powf(2.0f, 11.0f));
21012097

21022098
// (E-6), with r chosen as 0 (see NOTE below (E-6)).
@@ -2144,7 +2140,7 @@ static ErrorOr<void> decode_bitplanes_to_coefficients(JPEG2000LoadingContext& co
21442140
output.size = clipped_precinct_rect.size();
21452141
output.pitch = sub_band.rect.width();
21462142
output.data = sub_band.coefficients.span().slice((clipped_precinct_rect.y() - sub_band.rect.y()) * output.pitch + (clipped_precinct_rect.x() - sub_band.rect.x()));
2147-
copy_and_dequantize_if_needed(output, precinct_coefficients, context.quantization_parameters_for_component(tile, component_index), sub_band_type, component_index, r);
2143+
copy_and_dequantize_if_needed(output, precinct_coefficients, context.quantization_parameters_for_component(tile, component_index), sub_band_type, component_index, r, N_L);
21482144
}
21492145

21502146
return {};

0 commit comments

Comments
 (0)