Assembler test for Dim, ImageFormat enums.

Adds SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT, and the
translation tables for its values from the spv::ImageFormat values.
diff --git a/include/libspirv/libspirv.h b/include/libspirv/libspirv.h
index 4c9c700..f0e7b79 100644
--- a/include/libspirv/libspirv.h
+++ b/include/libspirv/libspirv.h
@@ -158,6 +158,7 @@
   SPV_OPERAND_TYPE_DIMENSIONALITY,
   SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE,
   SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
+  SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT,
   SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
   SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
   SPV_OPERAND_TYPE_LINKAGE_TYPE,
@@ -169,7 +170,10 @@
   SPV_OPERAND_TYPE_LOOP_CONTROL,
   SPV_OPERAND_TYPE_FUNCTION_CONTROL,
   SPV_OPERAND_TYPE_MEMORY_SEMANTICS,
+
+  // The ID for an execution scope value.
   SPV_OPERAND_TYPE_EXECUTION_SCOPE,
+
   SPV_OPERAND_TYPE_GROUP_OPERATION,
   SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS,
   SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO,
diff --git a/source/opcode.cpp b/source/opcode.cpp
index 8701eaf..3c0c2f7 100644
--- a/source/opcode.cpp
+++ b/source/opcode.cpp
@@ -115,7 +115,7 @@
     case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
     case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
     case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
-    case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_NONE; //TODO
+    case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
     case OperandImageChannelOrder: return SPV_OPERAND_TYPE_NONE; //TODO
     case OperandImageChannelDataType: return SPV_OPERAND_TYPE_NONE; //TODO
     case OperandImageOperands: return SPV_OPERAND_TYPE_NONE; //TODO
diff --git a/source/operand.cpp b/source/operand.cpp
index 372cfd7..819f591 100644
--- a/source/operand.cpp
+++ b/source/operand.cpp
@@ -410,6 +410,62 @@
      {SPV_OPERAND_TYPE_NONE}},
 };
 
+static const spv_operand_desc_t samplerImageFormatEntries[] = {
+// In Rev31, all the cases depend on the Shader capability.
+// TODO(dneto): In Rev32, many of these depend on the AdvancedFormats
+// capability instead.
+#define CASE(NAME)                                                             \
+  {                                                                            \
+    #NAME, ImageFormat##NAME, SPV_OPCODE_FLAGS_CAPABILITIES, CapabilityShader, \
+    {                                                                          \
+      SPV_OPERAND_TYPE_NONE                                                    \
+    }                                                                          \
+  }
+  // clang-format off
+  CASE(Unknown),
+  CASE(Rgba32f),
+  CASE(Rgba16f),
+  CASE(R32f),
+  CASE(Rgba8),
+  CASE(Rgba8Snorm),
+  CASE(Rg32f),
+  CASE(Rg16f),
+  CASE(R11fG11fB10f),
+  CASE(R16f),
+  CASE(Rgba16),
+  CASE(Rgb10A2),
+  CASE(Rg16),
+  CASE(Rg8),
+  CASE(R16),
+  CASE(R8),
+  CASE(Rgba16Snorm),
+  CASE(Rg16Snorm),
+  CASE(Rg8Snorm),
+  CASE(R16Snorm),
+  CASE(R8Snorm),
+  CASE(Rgba32i),
+  CASE(Rgba16i),
+  CASE(Rgba8i),
+  CASE(R32i),
+  CASE(Rg32i),
+  CASE(Rg16i),
+  CASE(Rg8i),
+  CASE(R16i),
+  CASE(R8i),
+  CASE(Rgba32ui),
+  CASE(Rgba16ui),
+  CASE(Rgba8ui),
+  CASE(R32ui),
+  CASE(Rgb10a2ui),
+  CASE(Rg32ui),
+  CASE(Rg16ui),
+  CASE(Rg8ui),
+  CASE(R16ui),
+  CASE(R8ui),
+  // clang-format on
+#undef CASE
+};
+
 static const spv_operand_desc_t fpFastMathModeEntries[] = {
     {"None",
      FPFastMathModeMaskNone,
@@ -1333,6 +1389,9 @@
     {SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE,
      sizeof(samplerFilterModeEntries) / sizeof(spv_operand_desc_t),
      samplerFilterModeEntries},
+    {SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT,
+     sizeof(samplerImageFormatEntries) / sizeof(spv_operand_desc_t),
+     samplerImageFormatEntries},
     {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,
      sizeof(fpFastMathModeEntries) / sizeof(spv_operand_desc_t),
      fpFastMathModeEntries},
@@ -1477,6 +1536,8 @@
       return "addressing mode";
     case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
       return "sampler filter mode";
+    case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
+      return "sampler image format";
     case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
       return "floating pointer fast math mode";
     case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
diff --git a/test/TextToBinary.TypeDeclaration.cpp b/test/TextToBinary.TypeDeclaration.cpp
index 3525e3b..bd111a1 100644
--- a/test/TextToBinary.TypeDeclaration.cpp
+++ b/test/TextToBinary.TypeDeclaration.cpp
@@ -44,7 +44,100 @@
   const std::string name;
 };
 
-// Test OpTypePipe
+// Test Dim enums via OpTypeImage
+
+using DimTest = test_fixture::TextToBinaryTestBase<
+    ::testing::TestWithParam<EnumCase<spv::Dim>>>;
+
+TEST_P(DimTest, AnyDim) {
+  std::string input = "%imageType = OpTypeImage %sampledType " +
+                      GetParam().name + " 2 3 0 4 Rgba8";
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::OpTypeImage, {1, 2, GetParam().value, 2, 3, 0, 4,
+                                            spv::ImageFormatRgba8})));
+}
+
+// clang-format off
+#define CASE(NAME) {spv::Dim##NAME, #NAME}
+INSTANTIATE_TEST_CASE_P(
+    TextToBinaryDim, DimTest,
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Dim>>{
+        CASE(1D),
+        CASE(2D),
+        CASE(3D),
+        CASE(Cube),
+        CASE(Rect),
+        CASE(Buffer),
+        // TODO(dneto): Rev32 adds InputTarget.
+    }));
+#undef CASE
+// clang-format on
+
+// Test ImageFormat enums via OpTypeImage
+
+using ImageFormatTest = test_fixture::TextToBinaryTestBase<
+    ::testing::TestWithParam<EnumCase<spv::ImageFormat>>>;
+
+TEST_P(ImageFormatTest, AnyImageFormat) {
+  std::string input =
+      "%imageType = OpTypeImage %sampledType 1D  2 3 0 4 " + GetParam().name;
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::OpTypeImage, {1, 2, spv::Dim1D, 2, 3, 0,
+                                                    4, GetParam().value})));
+}
+
+// clang-format off
+#define CASE(NAME) {spv::ImageFormat##NAME, #NAME}
+INSTANTIATE_TEST_CASE_P(
+    TextToBinaryImageFormat, ImageFormatTest,
+    ::testing::ValuesIn(std::vector<EnumCase<spv::ImageFormat>>{
+        CASE(Unknown),
+        CASE(Rgba32f),
+        CASE(Rgba16f),
+        CASE(R32f),
+        CASE(Rgba8),
+        CASE(Rgba8Snorm),
+        CASE(Rg32f),
+        CASE(Rg16f),
+        CASE(R11fG11fB10f),
+        CASE(R16f),
+        CASE(Rgba16),
+        CASE(Rgb10A2),
+        CASE(Rg16),
+        CASE(Rg8),
+        CASE(R16),
+        CASE(R8),
+        CASE(Rgba16Snorm),
+        CASE(Rg16Snorm),
+        CASE(Rg8Snorm),
+        CASE(R16Snorm),
+        CASE(R8Snorm),
+        CASE(Rgba32i),
+        CASE(Rgba16i),
+        CASE(Rgba8i),
+        CASE(R32i),
+        CASE(Rg32i),
+        CASE(Rg16i),
+        CASE(Rg8i),
+        CASE(R16i),
+        CASE(R8i),
+        CASE(Rgba32ui),
+        CASE(Rgba16ui),
+        CASE(Rgba8ui),
+        CASE(R32ui),
+        CASE(Rgb10a2ui),
+        CASE(Rg32ui),
+        CASE(Rg16ui),
+        CASE(Rg8ui),
+        CASE(R16ui),
+        CASE(R8ui),
+        // TODO(dneto): Rev32 adds InputTarget.
+    }));
+#undef CASE
+// clang-format on
+
+// Test AccessQualifier enums via OpTypePipe.
 
 using OpTypePipeTest = test_fixture::TextToBinaryTestBase<
     ::testing::TestWithParam<EnumCase<spv::AccessQualifier>>>;
@@ -69,6 +162,9 @@
 #undef CASE
 // clang-format on
 
+// TODO(dneto): error message test for sampler addressing mode
+// TODO(dneto): error message test for sampler image format
+
 // TODO(dneto): OpTypeVoid
 // TODO(dneto): OpTypeBool
 // TODO(dneto): OpTypeInt