Harmonize image decoders' call_sequence states
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index a870bb9..a3a8802 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -16885,7 +16885,7 @@
           self->private_impl.f_frame_config_io_position,
           (self->private_impl.f_channel_masks[3] == 0));
     }
-    self->private_impl.f_call_sequence = 1;
+    self->private_impl.f_call_sequence = 3;
 
     goto ok;
     ok:
@@ -16953,7 +16953,7 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    if (self->private_impl.f_call_sequence < 1) {
+    if (self->private_impl.f_call_sequence < 3) {
       if (a_src) {
         a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
       }
@@ -16965,13 +16965,13 @@
       if (status.repr) {
         goto suspend;
       }
-    } else if (self->private_impl.f_call_sequence == 1) {
+    } else if (self->private_impl.f_call_sequence == 3) {
       if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add(a_src->meta.pos, ((uint64_t)(iop_a_src - io0_a_src)))) {
         status = wuffs_base__make_status(wuffs_base__error__bad_restart);
         goto exit;
       }
-    } else if (self->private_impl.f_call_sequence == 2) {
-      self->private_impl.f_call_sequence = 3;
+    } else if (self->private_impl.f_call_sequence == 4) {
+      self->private_impl.f_call_sequence = 255;
       status = wuffs_base__make_status(wuffs_base__note__end_of_data);
       goto ok;
     } else {
@@ -16994,7 +16994,7 @@
           false,
           4278190080);
     }
-    self->private_impl.f_call_sequence = 2;
+    self->private_impl.f_call_sequence = 4;
 
     goto ok;
     ok:
@@ -17070,7 +17070,7 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    if (self->private_impl.f_call_sequence < 2) {
+    if (self->private_impl.f_call_sequence < 4) {
       if (a_src) {
         a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
       }
@@ -17082,7 +17082,7 @@
       if (status.repr) {
         goto suspend;
       }
-    } else if (self->private_impl.f_call_sequence == 2) {
+    } else if (self->private_impl.f_call_sequence == 4) {
     } else {
       status = wuffs_base__make_status(wuffs_base__note__end_of_data);
       goto ok;
@@ -17182,7 +17182,7 @@
       iop_a_src += self->private_data.s_decode_frame[0].scratch;
       self->private_impl.f_pending_pad = 0;
     }
-    self->private_impl.f_call_sequence = 3;
+    self->private_impl.f_call_sequence = 255;
 
     goto ok;
     ok:
@@ -17931,7 +17931,7 @@
     return 0;
   }
 
-  if (self->private_impl.f_call_sequence > 1) {
+  if (self->private_impl.f_call_sequence > 3) {
     return 1;
   }
   return 0;
@@ -17950,7 +17950,7 @@
     return 0;
   }
 
-  if (self->private_impl.f_call_sequence > 2) {
+  if (self->private_impl.f_call_sequence > 4) {
     return 1;
   }
   return 0;
@@ -17979,7 +17979,7 @@
   if (a_index != 0) {
     return wuffs_base__make_status(wuffs_base__error__bad_argument);
   }
-  self->private_impl.f_call_sequence = 1;
+  self->private_impl.f_call_sequence = 3;
   self->private_impl.f_frame_config_io_position = a_io_position;
   return wuffs_base__make_status(NULL);
 }
@@ -27625,7 +27625,7 @@
           self->private_impl.f_frame_config_io_position,
           true);
     }
-    self->private_impl.f_call_sequence = 1;
+    self->private_impl.f_call_sequence = 3;
 
     goto ok;
     ok:
@@ -27695,7 +27695,7 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    if (self->private_impl.f_call_sequence < 1) {
+    if (self->private_impl.f_call_sequence < 3) {
       if (a_src) {
         a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
       }
@@ -27707,13 +27707,13 @@
       if (status.repr) {
         goto suspend;
       }
-    } else if (self->private_impl.f_call_sequence == 1) {
+    } else if (self->private_impl.f_call_sequence == 3) {
       if (self->private_impl.f_frame_config_io_position != wuffs_base__u64__sat_add(a_src->meta.pos, ((uint64_t)(iop_a_src - io0_a_src)))) {
         status = wuffs_base__make_status(wuffs_base__error__bad_restart);
         goto exit;
       }
-    } else if (self->private_impl.f_call_sequence == 2) {
-      self->private_impl.f_call_sequence = 3;
+    } else if (self->private_impl.f_call_sequence == 4) {
+      self->private_impl.f_call_sequence = 255;
       status = wuffs_base__make_status(wuffs_base__note__end_of_data);
       goto ok;
     } else {
@@ -27736,7 +27736,7 @@
           false,
           4278190080);
     }
-    self->private_impl.f_call_sequence = 2;
+    self->private_impl.f_call_sequence = 4;
 
     goto ok;
     ok:
@@ -27826,7 +27826,7 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    if (self->private_impl.f_call_sequence < 2) {
+    if (self->private_impl.f_call_sequence < 4) {
       if (a_src) {
         a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
       }
@@ -27838,7 +27838,7 @@
       if (status.repr) {
         goto suspend;
       }
-    } else if (self->private_impl.f_call_sequence == 2) {
+    } else if (self->private_impl.f_call_sequence == 4) {
     } else {
       status = wuffs_base__make_status(wuffs_base__note__end_of_data);
       goto ok;
@@ -27901,7 +27901,7 @@
         v_dst_y += 1;
       }
     }
-    self->private_impl.f_call_sequence = 3;
+    self->private_impl.f_call_sequence = 255;
 
     goto ok;
     ok:
@@ -27980,7 +27980,7 @@
     return 0;
   }
 
-  if (self->private_impl.f_call_sequence > 1) {
+  if (self->private_impl.f_call_sequence > 3) {
     return 1;
   }
   return 0;
@@ -27999,7 +27999,7 @@
     return 0;
   }
 
-  if (self->private_impl.f_call_sequence > 2) {
+  if (self->private_impl.f_call_sequence > 4) {
     return 1;
   }
   return 0;
@@ -28028,7 +28028,7 @@
   if (a_index != 0) {
     return wuffs_base__make_status(wuffs_base__error__bad_argument);
   }
-  self->private_impl.f_call_sequence = 1;
+  self->private_impl.f_call_sequence = 3;
   self->private_impl.f_frame_config_io_position = a_io_position;
   return wuffs_base__make_status(NULL);
 }
diff --git a/std/bmp/decode_bmp.wuffs b/std/bmp/decode_bmp.wuffs
index 96f91f0..2833402 100644
--- a/std/bmp/decode_bmp.wuffs
+++ b/std/bmp/decode_bmp.wuffs
@@ -33,6 +33,31 @@
 	width  : base.u32[..= 0x7FFF_FFFF],
 	height : base.u32[..= 0x7FFF_FFFF],
 
+	// Call sequence states:
+	//  - 0x00: initial state.
+	//  - 0x03: image config decoded.
+	//  - 0x04: frame config decoded.
+	//  - 0xFF: end-of-data, usually after (the non-animated) frame decoded.
+	//
+	// State transitions:
+	//
+	//  - 0x00 -> 0x03: via DIC
+	//  - 0x00 -> 0x04: via DFC with implicit DIC
+	//  - 0x00 -> 0xFF: via DF  with implicit DIC and DFC
+	//
+	//  - 0x03 -> 0x04: via DFC
+	//  - 0x03 -> 0xFF: via DF  with implicit DFC
+	//
+	//  - 0x04 -> 0xFF: via DFC
+	//  - 0x04 -> 0xFF: via DF
+	//
+	//  - ???? -> 0x03: via RF  for ???? > 0x00
+	//
+	// Where:
+	//  - DF  is decode_frame
+	//  - DFC is decode_frame_config, implicit means nullptr args.dst
+	//  - DIC is decode_image_config, implicit means nullptr args.dst
+	//  - RF  is restart_frame
 	call_sequence : base.u8,
 
 	top_down    : base.bool,
@@ -364,18 +389,18 @@
 			first_frame_is_opaque: this.channel_masks[3] == 0)
 	}
 
-	this.call_sequence = 1
+	this.call_sequence = 3
 }
 
 pub func decoder.decode_frame_config?(dst: nptr base.frame_config, src: base.io_reader) {
-	if this.call_sequence < 1 {
+	if this.call_sequence < 3 {
 		this.decode_image_config?(dst: nullptr, src: args.src)
-	} else if this.call_sequence == 1 {
+	} else if this.call_sequence == 3 {
 		if this.frame_config_io_position <> args.src.position() {
 			return base."#bad restart"
 		}
-	} else if this.call_sequence == 2 {
-		this.call_sequence = 3
+	} else if this.call_sequence == 4 {
+		this.call_sequence = 0xFF
 		return base."@end of data"
 	} else {
 		return base."@end of data"
@@ -396,15 +421,15 @@
 			background_color: 0xFF00_0000)
 	}
 
-	this.call_sequence = 2
+	this.call_sequence = 4
 }
 
 pub func decoder.decode_frame?(dst: ptr base.pixel_buffer, src: base.io_reader, blend: base.pixel_blend, workbuf: slice base.u8, opts: nptr base.decode_frame_options) {
 	var status : base.status
 
-	if this.call_sequence < 2 {
+	if this.call_sequence < 4 {
 		this.decode_frame_config?(dst: nullptr, src: args.src)
-	} else if this.call_sequence == 2 {
+	} else if this.call_sequence == 4 {
 		// No-op.
 	} else {
 		return base."@end of data"
@@ -455,7 +480,7 @@
 		this.pending_pad = 0
 	}
 
-	this.call_sequence = 3
+	this.call_sequence = 0xFF
 }
 
 pri func decoder.swizzle_none!(dst: ptr base.pixel_buffer, src: base.io_reader) base.status {
@@ -1091,14 +1116,14 @@
 }
 
 pub func decoder.num_decoded_frame_configs() base.u64 {
-	if this.call_sequence > 1 {
+	if this.call_sequence > 3 {
 		return 1
 	}
 	return 0
 }
 
 pub func decoder.num_decoded_frames() base.u64 {
-	if this.call_sequence > 2 {
+	if this.call_sequence > 4 {
 		return 1
 	}
 	return 0
@@ -1111,7 +1136,7 @@
 	if args.index <> 0 {
 		return base."#bad argument"
 	}
-	this.call_sequence = 1
+	this.call_sequence = 3
 	this.frame_config_io_position = args.io_position
 	return ok
 }
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 17d83c5..21e6fb7 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -19,40 +19,49 @@
 	height : base.u32,
 
 	// Call sequence states:
-	//  - 0: initial state.
-	//  - 1: metadata reported; image config decode is in progress.
-	//  - 2: metadata finished; image config decode is in progress.
-	//  - 3: image config decoded, including the first frame's bounds, but not
-	//       the first frame's pixels.
-	//  - 4: frame config decoded.
-	//  - 5: frame decoded.
+	//  - 0x00: initial state.
+	//  - 0x01: metadata reported; image config decode is in progress.
+	//  - 0x02: metadata finished; image config decode is in progress.
+	//  - 0x03: image config decoded, including the first frame's bounds, but
+	//          not the first frame's pixels.
+	//  - 0x04: frame config decoded.
+	//  - 0x05: frame decoded.
+	//
+	// GIF is unusual (distinguishing state 0x03 / state 0x05) in that the
+	// first frame's bounds can affect the overall image bounds (as per
+	// test/data/artificial/gif-frame-out-of-bounds.gif.make-artificial.txt).
+	// Decoding the first frame's bounds is part of DIC even though,
+	// conceptually, it should be part of the first DFC.
 	//
 	// State transitions:
 	//
-	//  - 0 -> 1: via IC (metadata reported)
-	//  - 0 -> 3: via IC (metadata not reported)
-	//  - 0 -> 4: via FC with implicit IC
-	//  - 0 -> 5: via F  with implicit IC and FC
+	//  - 0x00 -> 0x01: via DIC (metadata reported)
+	//  - 0x00 -> 0x03: via DIC (metadata not reported)
+	//  - 0x00 -> 0x04: via DFC with implicit DIC
+	//  - 0x00 -> 0x05: via DF  with implicit DIC and DFC
 	//
-	//  - 1 -> 2: via AMC
+	//  - 0x01 -> 0x02: via AMC
 	//
-	//  - 2 -> 1: via IC (metadata reported)
-	//  - 2 -> 3: via IC (metadata not reported)
+	//  - 0x02 -> 0x01: via DIC (metadata reported)
+	//  - 0x02 -> 0x03: via DIC (metadata not reported)
 	//
-	//  - 3 -> 4: via FC
-	//  - 3 -> 5: via F  with implicit FC
+	//  - 0x03 -> 0x04: via DFC
+	//  - 0x03 -> 0x05: via DF  with implicit DFC
 	//
-	//  - 4 -> 4: via FC with implicit F
-	//  - 4 -> 5: via F
+	//  - 0x04 -> 0x04: via DFC with implicit DF
+	//  - 0x04 -> 0x05: via DF
 	//
-	//  - 5 -> 4: via FC
-	//  - 5 -> 5: via F  with implicit FC
+	//  - 0x05 -> 0x04: via DFC
+	//  - 0x05 -> 0x05: via DF  with implicit DFC
+	//
+	//  - ???? -> 0x05: via RF  for ???? > 0x00
 	//
 	// Where:
 	//  - AMC is ack_metadata_chunk
-	//  - F   is decode_frame,        implicit means skip_frame
-	//  - FC  is decode_frame_config, implicit means nullptr args.dst
-	//  - IC  is decode_image_config, implicit means nullptr args.dst
+	//  - DF  is decode_frame,        implicit means skip_frame
+	//  - DFC is decode_frame_config, implicit means nullptr args.dst
+	//  - DIC is decode_image_config, implicit means nullptr args.dst
+	//  - RF  is restart_frame
 	call_sequence : base.u8,
 
 	ignore_metadata      : base.bool,
diff --git a/std/wbmp/decode_wbmp.wuffs b/std/wbmp/decode_wbmp.wuffs
index caff601..2bec4c3 100644
--- a/std/wbmp/decode_wbmp.wuffs
+++ b/std/wbmp/decode_wbmp.wuffs
@@ -20,6 +20,31 @@
 	width  : base.u32,
 	height : base.u32,
 
+	// Call sequence states:
+	//  - 0x00: initial state.
+	//  - 0x03: image config decoded.
+	//  - 0x04: frame config decoded.
+	//  - 0xFF: end-of-data, usually after (the non-animated) frame decoded.
+	//
+	// State transitions:
+	//
+	//  - 0x00 -> 0x03: via DIC
+	//  - 0x00 -> 0x04: via DFC with implicit DIC
+	//  - 0x00 -> 0xFF: via DF  with implicit DIC and DFC
+	//
+	//  - 0x03 -> 0x04: via DFC
+	//  - 0x03 -> 0xFF: via DF  with implicit DFC
+	//
+	//  - 0x04 -> 0xFF: via DFC
+	//  - 0x04 -> 0xFF: via DF
+	//
+	//  - ???? -> 0x03: via RF  for ???? > 0x00
+	//
+	// Where:
+	//  - DF  is decode_frame
+	//  - DFC is decode_frame_config, implicit means nullptr args.dst
+	//  - DIC is decode_image_config, implicit means nullptr args.dst
+	//  - RF  is restart_frame
 	call_sequence : base.u8,
 
 	frame_config_io_position : base.u64,
@@ -91,18 +116,18 @@
 			first_frame_is_opaque: true)
 	}
 
-	this.call_sequence = 1
+	this.call_sequence = 3
 }
 
 pub func decoder.decode_frame_config?(dst: nptr base.frame_config, src: base.io_reader) {
-	if this.call_sequence < 1 {
+	if this.call_sequence < 3 {
 		this.decode_image_config?(dst: nullptr, src: args.src)
-	} else if this.call_sequence == 1 {
+	} else if this.call_sequence == 3 {
 		if this.frame_config_io_position <> args.src.position() {
 			return base."#bad restart"
 		}
-	} else if this.call_sequence == 2 {
-		this.call_sequence = 3
+	} else if this.call_sequence == 4 {
+		this.call_sequence = 0xFF
 		return base."@end of data"
 	} else {
 		return base."@end of data"
@@ -123,7 +148,7 @@
 			background_color: 0xFF00_0000)
 	}
 
-	this.call_sequence = 2
+	this.call_sequence = 4
 }
 
 pub func decoder.decode_frame?(dst: ptr base.pixel_buffer, src: base.io_reader, blend: base.pixel_blend, workbuf: slice base.u8, opts: nptr base.decode_frame_options) {
@@ -139,9 +164,9 @@
 	var src                 : array[1] base.u8
 	var c                   : base.u8
 
-	if this.call_sequence < 2 {
+	if this.call_sequence < 4 {
 		this.decode_frame_config?(dst: nullptr, src: args.src)
-	} else if this.call_sequence == 2 {
+	} else if this.call_sequence == 4 {
 		// No-op.
 	} else {
 		return base."@end of data"
@@ -221,7 +246,7 @@
 		} endwhile
 	}
 
-	this.call_sequence = 3
+	this.call_sequence = 0xFF
 }
 
 pub func decoder.frame_dirty_rect() base.rect_ie_u32 {
@@ -237,14 +262,14 @@
 }
 
 pub func decoder.num_decoded_frame_configs() base.u64 {
-	if this.call_sequence > 1 {
+	if this.call_sequence > 3 {
 		return 1
 	}
 	return 0
 }
 
 pub func decoder.num_decoded_frames() base.u64 {
-	if this.call_sequence > 2 {
+	if this.call_sequence > 4 {
 		return 1
 	}
 	return 0
@@ -257,7 +282,7 @@
 	if args.index <> 0 {
 		return base."#bad argument"
 	}
-	this.call_sequence = 1
+	this.call_sequence = 3
 	this.frame_config_io_position = args.io_position
 	return ok
 }