Bug 1588310 - Improving progressive JPEG scans. r=tnikkel

When loading a progressive jpegs with non-interleaved DC scans,
we add a check to see if we have already seen data from all DC
channels and only start rendering when this is the case.

Differential Revision: https://phabricator.services.mozilla.com/D95683
This commit is contained in:
Moritz Firsching 2020-12-05 23:42:23 +00:00
Родитель 777beda23d
Коммит f735d0e7d5
1 изменённых файлов: 41 добавлений и 5 удалений

Просмотреть файл

@ -441,23 +441,59 @@ LexerTransition<nsJPEGDecoder::State> nsJPEGDecoder::ReadJPEGData(
if (mState == JPEG_DECOMPRESS_PROGRESSIVE) {
LOG_SCOPE((mozilla::LogModule*)sJPEGLog,
"nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
auto AllComponentsSeen = [](jpeg_decompress_struct& mInfo) {
bool all_components_seen = true;
if (mInfo.coef_bits) {
for (int c = 0; c < mInfo.num_components; ++c) {
bool current_component_seen = mInfo.coef_bits[c][0] != -1;
all_components_seen &= current_component_seen;
}
}
return all_components_seen;
};
int status;
int scan_to_display_first = 0;
bool all_components_seen;
all_components_seen = AllComponentsSeen(mInfo);
if (all_components_seen) {
scan_to_display_first = mInfo.input_scan_number;
}
do {
status = jpeg_consume_input(&mInfo);
if (status == JPEG_REACHED_SOS || status == JPEG_REACHED_EOI ||
status == JPEG_SUSPENDED) {
// record the first scan where all components are present
all_components_seen = AllComponentsSeen(mInfo);
if (!scan_to_display_first && all_components_seen) {
scan_to_display_first = mInfo.input_scan_number;
}
}
} while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI));
if (!all_components_seen) {
return Transition::ContinueUnbuffered(
State::JPEG_DATA); // I/O suspension
}
// make sure we never try to access the non-exsitent scan 0
if (!scan_to_display_first) {
scan_to_display_first = 1;
}
while (mState != JPEG_DONE) {
if (mInfo.output_scanline == 0) {
int scan = mInfo.input_scan_number;
// if we haven't displayed anything yet (output_scan_number==0)
// and we have enough data for a complete scan, force output
// of the last full scan
if ((mInfo.output_scan_number == 0) && (scan > 1) &&
(status != JPEG_REACHED_EOI))
// of the last full scan, but only if this last scan has seen
// DC data from all components
if ((mInfo.output_scan_number == 0) &&
(scan > scan_to_display_first) &&
(status != JPEG_REACHED_EOI)) {
scan--;
}
MOZ_ASSERT(scan > 0, "scan number to small!");
if (!jpeg_start_output(&mInfo, scan)) {
MOZ_LOG(sJPEGDecoderAccountingLog, LogLevel::Debug,
("} (I/O suspension after jpeg_start_output() -"