Report ICCP metadata
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 091e922..4ca0fed 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -3379,6 +3379,7 @@
uint32_t f_height;
uint8_t f_call_sequence;
bool f_ignore_metadata;
+ bool f_report_metadata_iccp;
bool f_report_metadata_xmp;
uint32_t f_metadata_fourcc_value;
uint64_t f_metadata_chunk_length_value;
@@ -3461,6 +3462,7 @@
uint8_t v_block_size;
bool v_is_animexts;
bool v_is_netscape;
+ bool v_is_iccp;
bool v_is_xmp;
uint64_t scratch;
} s_decode_ae[1];
@@ -8520,6 +8522,12 @@
78, 69, 84, 83, 67, 65, 80, 69, 50, 46, 48,
};
+static const uint8_t //
+ wuffs_gif__iccrgbg1012[11] //
+ WUFFS_BASE__POTENTIALLY_UNUSED = {
+ 73, 67, 67, 82, 71, 66, 71, 49, 48, 49, 50,
+};
+
static const uint8_t //
wuffs_gif__xmpdataxmp[11] //
WUFFS_BASE__POTENTIALLY_UNUSED = {
@@ -8766,7 +8774,9 @@
return wuffs_base__make_empty_struct();
}
- if (a_fourcc == 1481461792) {
+ if (a_fourcc == 1229144912) {
+ self->private_impl.f_report_metadata_iccp = a_report;
+ } else if (a_fourcc == 1481461792) {
self->private_impl.f_report_metadata_xmp = a_report;
}
return wuffs_base__make_empty_struct();
@@ -8830,18 +8840,37 @@
status = wuffs_base__suspension__short_read;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
}
- self->private_impl.f_metadata_chunk_length_value =
- (((uint64_t)(wuffs_base__load_u8be(iop_a_src))) + 1);
- if (self->private_impl.f_metadata_chunk_length_value > 1) {
- self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
- (a_src.private_impl.buf
- ? wuffs_base__u64__sat_add(
- a_src.private_impl.buf->meta.pos,
- ((uint64_t)(iop_a_src - a_src.private_impl.buf->data.ptr)))
- : 0),
- self->private_impl.f_metadata_chunk_length_value);
- status = wuffs_base__warning__metadata_reported;
- goto ok;
+ if (self->private_impl.f_metadata_fourcc_value == 1481461792) {
+ self->private_impl.f_metadata_chunk_length_value =
+ (((uint64_t)(wuffs_base__load_u8be(iop_a_src))) + 1);
+ if (self->private_impl.f_metadata_chunk_length_value > 1) {
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src.private_impl.buf
+ ? wuffs_base__u64__sat_add(
+ a_src.private_impl.buf->meta.pos,
+ ((uint64_t)(iop_a_src -
+ a_src.private_impl.buf->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ }
+ } else {
+ self->private_impl.f_metadata_chunk_length_value =
+ ((uint64_t)(wuffs_base__load_u8be(iop_a_src)));
+ if (self->private_impl.f_metadata_chunk_length_value > 0) {
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src.private_impl.buf
+ ? wuffs_base__u64__sat_add(
+ a_src.private_impl.buf->meta.pos,
+ ((uint64_t)(iop_a_src -
+ a_src.private_impl.buf->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ }
}
(iop_a_src += 1, wuffs_base__make_empty_struct());
self->private_impl.f_call_sequence = 2;
@@ -9926,6 +9955,7 @@
uint8_t v_block_size = 0;
bool v_is_animexts = false;
bool v_is_netscape = false;
+ bool v_is_iccp = false;
bool v_is_xmp = false;
uint8_t* iop_a_src = NULL;
@@ -9948,6 +9978,7 @@
v_block_size = self->private_data.s_decode_ae[0].v_block_size;
v_is_animexts = self->private_data.s_decode_ae[0].v_is_animexts;
v_is_netscape = self->private_data.s_decode_ae[0].v_is_netscape;
+ v_is_iccp = self->private_data.s_decode_ae[0].v_is_iccp;
v_is_xmp = self->private_data.s_decode_ae[0].v_is_xmp;
}
switch (coro_susp_point) {
@@ -9983,6 +10014,7 @@
}
v_is_animexts = true;
v_is_netscape = true;
+ v_is_iccp = true;
v_is_xmp = true;
v_block_size = 0;
while (v_block_size < 11) {
@@ -9999,6 +10031,8 @@
(v_is_animexts && (v_c == wuffs_gif__animexts1dot0[v_block_size]));
v_is_netscape =
(v_is_netscape && (v_c == wuffs_gif__netscape2dot0[v_block_size]));
+ v_is_iccp =
+ (v_is_iccp && (v_c == wuffs_gif__iccrgbg1012[v_block_size]));
v_is_xmp = (v_is_xmp && (v_c == wuffs_gif__xmpdataxmp[v_block_size]));
#if defined(__GNUC__)
#pragma GCC diagnostic push
@@ -10092,12 +10126,32 @@
self->private_impl.f_num_loops += 1;
}
} else if (self->private_impl.f_ignore_metadata) {
- } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) {
+ } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) {
while (((uint64_t)(io1_a_src - iop_a_src)) <= 0) {
status = wuffs_base__suspension__short_read;
WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
}
self->private_impl.f_metadata_chunk_length_value =
+ ((uint64_t)(wuffs_base__load_u8be(iop_a_src)));
+ (iop_a_src += 1, wuffs_base__make_empty_struct());
+ self->private_impl.f_metadata_fourcc_value = 1229144912;
+ self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
+ (a_src.private_impl.buf
+ ? wuffs_base__u64__sat_add(
+ a_src.private_impl.buf->meta.pos,
+ ((uint64_t)(iop_a_src -
+ a_src.private_impl.buf->data.ptr)))
+ : 0),
+ self->private_impl.f_metadata_chunk_length_value);
+ self->private_impl.f_call_sequence = 1;
+ status = wuffs_base__warning__metadata_reported;
+ goto ok;
+ } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) {
+ while (((uint64_t)(io1_a_src - iop_a_src)) <= 0) {
+ status = wuffs_base__suspension__short_read;
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
+ }
+ self->private_impl.f_metadata_chunk_length_value =
(((uint64_t)(wuffs_base__load_u8be(iop_a_src))) + 1);
self->private_impl.f_metadata_fourcc_value = 1481461792;
self->private_impl.f_metadata_io_position = wuffs_base__u64__sat_add(
@@ -10119,7 +10173,7 @@
a_src.private_impl.buf->meta.ri =
((size_t)(iop_a_src - a_src.private_impl.buf->data.ptr));
}
- WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
+ WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
status = wuffs_gif__decoder__skip_blocks(self, a_src);
if (a_src.private_impl.buf) {
iop_a_src =
@@ -10141,6 +10195,7 @@
self->private_data.s_decode_ae[0].v_block_size = v_block_size;
self->private_data.s_decode_ae[0].v_is_animexts = v_is_animexts;
self->private_data.s_decode_ae[0].v_is_netscape = v_is_netscape;
+ self->private_data.s_decode_ae[0].v_is_iccp = v_is_iccp;
self->private_data.s_decode_ae[0].v_is_xmp = v_is_xmp;
goto exit;
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 46bc404..fe27f28 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -85,6 +85,7 @@
call_sequence base.u8,
ignore_metadata base.bool,
+ report_metadata_iccp base.bool,
report_metadata_xmp base.bool,
metadata_fourcc_value base.u32,
metadata_chunk_length_value base.u64,
@@ -190,7 +191,9 @@
}
pub func decoder.set_report_metadata!(fourcc base.u32, report base.bool) {
- if args.fourcc == 0x584D5020 { // "XMP "
+ if args.fourcc == 0x49434350 { // "ICCP"
+ this.report_metadata_iccp = args.report
+ } else if args.fourcc == 0x584D5020 { // "XMP "
this.report_metadata_xmp = args.report
}
}
@@ -207,13 +210,24 @@
{
yield? base."$short read"
}
- // The +1 is because XMP metadata's encoding includes each block's leading
- // byte (the block size) as part of the metadata passed to the caller.
- this.metadata_chunk_length_value = args.src.peek_u8_as_u64() + 1
- if this.metadata_chunk_length_value > 1 {
- this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
- return base."@metadata reported"
+
+ if this.metadata_fourcc_value == 0x584D5020 { // "XMP "
+ // The +1 is because XMP metadata's encoding includes each block's leading
+ // byte (the block size) as part of the metadata passed to the caller.
+ this.metadata_chunk_length_value = args.src.peek_u8_as_u64() + 1
+ if this.metadata_chunk_length_value > 1 {
+ this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
+ return base."@metadata reported"
+ }
+ } else {
+ this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
+ if this.metadata_chunk_length_value > 0 {
+ args.src.skip_fast!(actual:1, worst_case:1)
+ this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
+ return base."@metadata reported"
+ }
}
+
args.src.skip_fast!(actual:1, worst_case:1)
this.call_sequence = 2
this.metadata_fourcc_value = 0
@@ -521,6 +535,11 @@
0x4E, 0x45, 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2E, 0x30,
]
+// iccrgbg1012 is "ICCRGBG1012" as bytes.
+pri const iccrgbg1012 array[11] base.u8 = [
+ 0x49, 0x43, 0x43, 0x52, 0x47, 0x42, 0x47, 0x31, 0x30, 0x31, 0x32,
+]
+
// xmpdataxmp is "XMP DataXMP" as bytes.
pri const xmpdataxmp array[11] base.u8 = [
0x58, 0x4D, 0x50, 0x20, 0x44, 0x61, 0x74, 0x61, 0x58, 0x4D, 0x50,
@@ -532,6 +551,7 @@
var block_size base.u8
var is_animexts base.bool
var is_netscape base.bool
+ var is_iccp base.bool
var is_xmp base.bool
// This "while true" always executes exactly once, as it ends with a
@@ -554,12 +574,14 @@
}
is_animexts = true
is_netscape = true
+ is_iccp = true
is_xmp = true
block_size = 0 // Re-purpose the block_size variable as a counter.
while block_size < 11 {
c = args.src.read_u8?()
is_animexts = is_animexts and (c == animexts1dot0[block_size])
is_netscape = is_netscape and (c == netscape2dot0[block_size])
+ is_iccp = is_iccp and (c == iccrgbg1012[block_size])
is_xmp = is_xmp and (c == xmpdataxmp[block_size])
block_size += 1
}
@@ -597,6 +619,19 @@
} else if this.ignore_metadata {
// No-op.
+ } else if is_iccp and this.report_metadata_iccp {
+ while args.src.available() <= 0,
+ post args.src.available() > 0,
+ {
+ yield? base."$short read"
+ }
+ this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
+ args.src.skip_fast!(actual:1, worst_case:1)
+ this.metadata_fourcc_value = 0x49434350 // "ICCP"
+ this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
+ this.call_sequence = 1
+ return base."@metadata reported"
+
} else if is_xmp and this.report_metadata_xmp {
while args.src.available() <= 0,
post args.src.available() > 0,
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 8b37259..14f2da3 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -987,7 +987,7 @@
switch (wuffs_gif__decoder__metadata_fourcc(&dec)) {
case WUFFS_BASE__FOURCC__ICCP:
- // TODO: want = "etc";
+ want = "\x16\x26\x36\x46\x56\x76\x86\x96";
seen_iccp = true;
break;
case WUFFS_BASE__FOURCC__XMP:
@@ -1040,7 +1040,8 @@
}
if (iccp != seen_iccp) {
- // TODO.
+ RETURN_FAIL("seen_iccp (iccp=%d, xmp=%d): got %d, want %d", iccp, xmp,
+ seen_iccp, iccp);
}
if (xmp != seen_xmp) {