std/jpeg: allow DQT markers after SOF marker
Fixes #120
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 931dbf5..21aab39 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -8635,7 +8635,6 @@
extern const char wuffs_jpeg__error__missing_huffman_table[];
extern const char wuffs_jpeg__error__missing_quantization_table[];
extern const char wuffs_jpeg__error__truncated_input[];
-extern const char wuffs_jpeg__error__unsupported_dqt_after_sof_markers[];
extern const char wuffs_jpeg__error__unsupported_arithmetic_coding[];
extern const char wuffs_jpeg__error__unsupported_fractional_sampling[];
extern const char wuffs_jpeg__error__unsupported_hierarchical_coding[];
@@ -8835,12 +8834,14 @@
uint64_t f_frame_config_io_position;
uint32_t f_payload_length;
bool f_seen_dqt[4];
+ bool f_saved_seen_dqt[4];
bool f_seen_dht[8];
uint64_t f_bitstream_bits;
uint32_t f_bitstream_n_bits;
uint32_t f_bitstream_ri;
uint32_t f_bitstream_wi;
uint8_t f_quant_tables[4][64];
+ uint8_t f_saved_quant_tables[4][64];
uint8_t f_huff_tables_symbols[8][256];
uint32_t f_huff_tables_slow[8][16];
uint16_t f_huff_tables_fast[8][256];
@@ -36591,7 +36592,6 @@
const char wuffs_jpeg__error__missing_huffman_table[] = "#jpeg: missing Huffman table";
const char wuffs_jpeg__error__missing_quantization_table[] = "#jpeg: missing Quantization table";
const char wuffs_jpeg__error__truncated_input[] = "#jpeg: truncated input";
-const char wuffs_jpeg__error__unsupported_dqt_after_sof_markers[] = "#jpeg: unsupported DQT after SOF markers";
const char wuffs_jpeg__error__unsupported_arithmetic_coding[] = "#jpeg: unsupported arithmetic coding";
const char wuffs_jpeg__error__unsupported_fractional_sampling[] = "#jpeg: unsupported fractional sampling";
const char wuffs_jpeg__error__unsupported_hierarchical_coding[] = "#jpeg: unsupported hierarchical coding";
@@ -38182,6 +38182,14 @@
v_i += 1;
}
self->private_impl.f_seen_dqt[v_q] = true;
+ if (self->private_impl.f_sof_marker == 0) {
+ v_i = 0;
+ while (v_i < 64) {
+ self->private_impl.f_saved_quant_tables[v_q][v_i] = self->private_impl.f_quant_tables[v_q][v_i];
+ v_i += 1;
+ }
+ self->private_impl.f_saved_seen_dqt[v_q] = true;
+ }
}
goto ok;
@@ -38978,13 +38986,23 @@
}
goto label__0__break;
} else if (v_marker == 219) {
- status = wuffs_base__make_status(wuffs_jpeg__error__unsupported_dqt_after_sof_markers);
- goto exit;
- } else if (v_marker == 221) {
if (a_src) {
a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
}
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+ status = wuffs_jpeg__decoder__decode_dqt(self, a_src);
+ if (a_src) {
+ iop_a_src = a_src->data.ptr + a_src->meta.ri;
+ }
+ if (status.repr) {
+ goto suspend;
+ }
+ goto label__0__continue;
+ } else if (v_marker == 221) {
+ if (a_src) {
+ a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+ }
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
status = wuffs_jpeg__decoder__decode_dri(self, a_src);
if (a_src) {
iop_a_src = a_src->data.ptr + a_src->meta.ri;
@@ -39006,7 +39024,7 @@
}
}
self->private_data.s_do_decode_frame[0].scratch = self->private_impl.f_payload_length;
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
if (self->private_data.s_do_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
self->private_data.s_do_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
iop_a_src = io2_a_src;
@@ -40049,6 +40067,7 @@
}
uint32_t v_i = 0;
+ uint32_t v_j = 0;
if (self->private_impl.f_call_sequence < 32) {
return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
@@ -40059,6 +40078,14 @@
self->private_impl.f_call_sequence = 40;
self->private_impl.f_frame_config_io_position = a_io_position;
self->private_impl.f_restart_interval = self->private_impl.f_saved_restart_interval;
+ while (v_i < 4) {
+ self->private_impl.f_seen_dqt[v_i] = self->private_impl.f_saved_seen_dqt[v_i];
+ while (v_j < 64) {
+ self->private_impl.f_quant_tables[v_i][v_j] = self->private_impl.f_saved_quant_tables[v_i][v_j];
+ v_j += 1;
+ }
+ v_i += 1;
+ }
while (v_i < 8) {
self->private_impl.f_seen_dht[v_i] = false;
v_i += 1;
diff --git a/std/jpeg/decode_jpeg.wuffs b/std/jpeg/decode_jpeg.wuffs
index c3bcaae..5a2715b 100644
--- a/std/jpeg/decode_jpeg.wuffs
+++ b/std/jpeg/decode_jpeg.wuffs
@@ -22,7 +22,6 @@
pub status "#missing Huffman table"
pub status "#missing Quantization table"
pub status "#truncated input"
-pub status "#unsupported DQT after SOF markers"
pub status "#unsupported arithmetic coding"
pub status "#unsupported fractional sampling"
pub status "#unsupported hierarchical coding"
@@ -117,8 +116,9 @@
payload_length : base.u32[..= 0xFFFF],
- seen_dqt : array[4] base.bool,
- seen_dht : array[8] base.bool,
+ seen_dqt : array[4] base.bool,
+ saved_seen_dqt : array[4] base.bool,
+ seen_dht : array[8] base.bool,
// These fields yield bitstream bits in Most Significant Bits order.
bitstream_bits : base.u64,
@@ -126,7 +126,8 @@
bitstream_ri : base.u32[..= 0x800],
bitstream_wi : base.u32[..= 0x800],
- quant_tables : array[4] array[64] base.u8,
+ quant_tables : array[4] array[64] base.u8,
+ saved_quant_tables : array[4] array[64] base.u8,
// huff_tables_symbols[(tc*4)|th][i] is the i'th Huffman code's symbol.
huff_tables_symbols : array[8] array[256] base.u8,
@@ -350,6 +351,15 @@
i += 1
} endwhile
this.seen_dqt[q] = true
+
+ if this.sof_marker == 0 {
+ i = 0
+ while i < 64 {
+ this.saved_quant_tables[q][i] = this.quant_tables[q][i]
+ i += 1
+ } endwhile
+ this.saved_seen_dqt[q] = true
+ }
} endwhile
}
@@ -680,7 +690,8 @@
break
} else if marker == 0xDB { // DQT (Define Quantization Table).
- return "#unsupported DQT after SOF markers"
+ this.decode_dqt?(src: args.src)
+ continue
} else if marker == 0xDD { // DRI (Define Restart Interval).
this.decode_dri?(src: args.src)
@@ -1466,6 +1477,7 @@
pub func decoder.restart_frame!(index: base.u64, io_position: base.u64) base.status {
var i : base.u32
+ var j : base.u32
if this.call_sequence < 0x20 {
return base."#bad call sequence"
@@ -1476,6 +1488,16 @@
this.call_sequence = 0x28
this.frame_config_io_position = args.io_position
this.restart_interval = this.saved_restart_interval
+ while i < 4 {
+ this.seen_dqt[i] = this.saved_seen_dqt[i]
+ while j < 64,
+ inv i < 4,
+ {
+ this.quant_tables[i][j] = this.saved_quant_tables[i][j]
+ j += 1
+ } endwhile
+ i += 1
+ } endwhile
while i < 8 {
this.seen_dht[i] = false
i += 1