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) {