Detect and canonicalize identity tables

Change-Id: Ifa0804279565d7521614ea08fe603f57bb1ff5cf
Reviewed-on: https://skia-review.googlesource.com/120380
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/profiles/misc/Apple_Wide_Color.icc.txt b/profiles/misc/Apple_Wide_Color.icc.txt
index c410607..ede8059 100644
--- a/profiles/misc/Apple_Wide_Color.icc.txt
+++ b/profiles/misc/Apple_Wide_Color.icc.txt
@@ -16,15 +16,9 @@
 
  A2B : "A", CLUT, "M", Matrix, "B"
  "A" : 3 inputs
-  A0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 17 x 17 x 17 (16 bpp)
  "M" : 3 inputs
   M0 : 2.3999939, 0.947906494, 0.0520935059, 0.0773925781, 0.0393066406, 0, 0
@@ -34,15 +28,9 @@
        | 0.239345714 0.694691539 0.065977998 0.000000000 |
        | 0.000457757 0.047393076 0.777148783 0.000000000 |
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	2c562d a2d713 4b6615 1a0e30 1e114a 614a06 3d8912
 	763f31 1c1711 734b27 a6a90d 4c5f06 2b442b 452790
diff --git a/profiles/misc/Coated_FOGRA39_CMYK.icc.txt b/profiles/misc/Coated_FOGRA39_CMYK.icc.txt
index 23a3e1b..953243a 100644
--- a/profiles/misc/Coated_FOGRA39_CMYK.icc.txt
+++ b/profiles/misc/Coated_FOGRA39_CMYK.icc.txt
@@ -35,15 +35,9 @@
   ~= : 0.1588x^3 + 0.08634x^2 + 0.7548x (Max error: 0.001332)
 CLUT : 11 x 11 x 11 x 11 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	111c23 3a220f 0c0e06 1b131a 1c1305 18220c 251f11
 	27253e 000102 101615 232f4c 4a2f21 2c2e1e 030201
diff --git a/profiles/misc/ColorLogic_ISO_Coated_CMYK.icc.txt b/profiles/misc/ColorLogic_ISO_Coated_CMYK.icc.txt
index 402f3bf..e93be1f 100644
--- a/profiles/misc/ColorLogic_ISO_Coated_CMYK.icc.txt
+++ b/profiles/misc/ColorLogic_ISO_Coated_CMYK.icc.txt
@@ -38,12 +38,8 @@
   B0 : 16-bit table with 256 entries
   ~= : 1, 0.996109, 0, 0, 0, 0, 0  (Max error: 6e-08)
   ~= : 0.02724x^3 + -0.03113x^2 + 1.004x (Max error: 0.003891)
-  B1 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  B2 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	101b21 382210 0c0d06 1a1318 1b1205 18210c 231e11
 	26243c 000102 101514 232e4a 492f21 2c2d1e 030201
diff --git a/profiles/misc/DisplayCal_ASUS_NonMonotonic.icc.txt b/profiles/misc/DisplayCal_ASUS_NonMonotonic.icc.txt
index 4d5c920..cdcbc19 100644
--- a/profiles/misc/DisplayCal_ASUS_NonMonotonic.icc.txt
+++ b/profiles/misc/DisplayCal_ASUS_NonMonotonic.icc.txt
@@ -55,15 +55,9 @@
   ~= : -0.01502x^3 + 0.02485x^2 + 0.9902x (Max error: 0.01886)
 CLUT : 33 x 33 x 33 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	1a2c18 526c09 263409 0c0619 0f0727 2f2402 264611
 	351b17 0e0b08 372313 505205 273004 162315 22124a
diff --git a/profiles/misc/Japan_Color_2001_Coated.icc.txt b/profiles/misc/Japan_Color_2001_Coated.icc.txt
index ac6bdbf..014dcee 100644
--- a/profiles/misc/Japan_Color_2001_Coated.icc.txt
+++ b/profiles/misc/Japan_Color_2001_Coated.icc.txt
@@ -32,15 +32,9 @@
   ~= : 0.01829x^3 + 0.3262x^2 + 0.6555x (Max error: 0.01191)
 CLUT : 9 x 9 x 9 x 9 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	101d25 3d240f 0b0d05 1b131b 1d1406 17230c 241f11
 	26233f 000001 0f1615 243052 4c3022 2c2e1d 020100
diff --git a/profiles/misc/Lexmark_X110.icc.txt b/profiles/misc/Lexmark_X110.icc.txt
index 610914d..8e42ed6 100644
--- a/profiles/misc/Lexmark_X110.icc.txt
+++ b/profiles/misc/Lexmark_X110.icc.txt
@@ -14,26 +14,14 @@
 
  A2B : "A", CLUT, "B"
  "A" : 3 inputs
-  A0 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
-  A1 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
-  A2 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 17 x 17 x 17 (8 bpp)
  "B" : 3 outputs
-  B0 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
-  B1 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
-  B2 : 8-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 4.678e-08x^3 + -6.455e-08x^2 + 1x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	6fa094 d8f243 a7d043 825cbe 8365c0 a39f15 5c8161
 	a871bd 5a5249 aa8b81 d2f028 a6cb1b 729e83 937fb7
diff --git a/profiles/misc/MartiMaria_browsertest_A2B.icc.txt b/profiles/misc/MartiMaria_browsertest_A2B.icc.txt
index 4252db3..65efbaf 100644
--- a/profiles/misc/MartiMaria_browsertest_A2B.icc.txt
+++ b/profiles/misc/MartiMaria_browsertest_A2B.icc.txt
@@ -14,26 +14,14 @@
 
  A2B : "A", CLUT, "B"
  "A" : 3 inputs
-  A0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 17 x 17 x 17 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	181915 7b8069 7b8069 7b8069 7b8069 7b8069 090a08
 	7b8069 7b8069 7b8069 7b8069 7b8069 7b8069 7b8069
diff --git a/profiles/misc/MartiMaria_browsertest_HARD.icc.txt b/profiles/misc/MartiMaria_browsertest_HARD.icc.txt
index 32cd262..68a83bf 100644
--- a/profiles/misc/MartiMaria_browsertest_HARD.icc.txt
+++ b/profiles/misc/MartiMaria_browsertest_HARD.icc.txt
@@ -30,26 +30,14 @@
        | 0.824905396 0.000000000 0.824905396 |
  A2B : "A", CLUT, "B"
  "A" : 3 inputs
-  A0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  A2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 17 x 17 x 17 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	181915 7b8069 7b8069 7b8069 7b8069 7b8069 090a08
 	7b8069 7b8069 7b8069 7b8069 7b8069 7b8069 7b8069
diff --git a/profiles/misc/Phase_One_P25.icc.txt b/profiles/misc/Phase_One_P25.icc.txt
index 7751a67..d9738f8 100644
--- a/profiles/misc/Phase_One_P25.icc.txt
+++ b/profiles/misc/Phase_One_P25.icc.txt
@@ -40,15 +40,9 @@
   ~= : 3.103x^3 + -5.715x^2 + 3.611x (Max error: 0.2053)
 CLUT : 33 x 33 x 33 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	1d5c40 86f80b 4a7913 2e1551 341674 8a6006 38a75e
 	b45e34 2f2417 af6d2b b4ae06 547302 1f4c33 6822be
diff --git a/profiles/misc/PrintOpen_ISO_Coated_CMYK.icc.txt b/profiles/misc/PrintOpen_ISO_Coated_CMYK.icc.txt
index 265fcf3..3d95f54 100644
--- a/profiles/misc/PrintOpen_ISO_Coated_CMYK.icc.txt
+++ b/profiles/misc/PrintOpen_ISO_Coated_CMYK.icc.txt
@@ -21,29 +21,15 @@
 
  A2B : "A", CLUT, "B"
  "A" : 4 inputs
-  A0 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  A1 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  A2 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  A3 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A3 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 16 x 16 x 16 x 16 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  B1 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
-  B2 : 16-bit table with 256 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 6e-08) (Linear)
-  ~= : 3.766e-07x^3 + -4.643e-07x^2 + 1x (Max error: 1.192e-07)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	162328 3a2310 090a05 1d151d 1b1306 18230c 211b10
 	2a2742 000101 101615 253047 4c3123 27291b 020201
diff --git a/profiles/misc/SWOP_Coated_20_GCR_CMYK.icc.txt b/profiles/misc/SWOP_Coated_20_GCR_CMYK.icc.txt
index 61e81af..7c9bd74 100644
--- a/profiles/misc/SWOP_Coated_20_GCR_CMYK.icc.txt
+++ b/profiles/misc/SWOP_Coated_20_GCR_CMYK.icc.txt
@@ -29,15 +29,9 @@
   ~= : 0.3427x^3 + -0.04205x^2 + 0.6993x (Max error: 0.02761)
 CLUT : 16 x 16 x 16 x 16 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	121d22 36200e 090a05 191117 181106 131d0a 221d12
 	252136 000000 0e1312 242d47 472e1f 252618 010100
diff --git a/profiles/misc/US_Web_Coated_SWOP_CMYK.icc.txt b/profiles/misc/US_Web_Coated_SWOP_CMYK.icc.txt
index ec092b8..2eb04e9 100644
--- a/profiles/misc/US_Web_Coated_SWOP_CMYK.icc.txt
+++ b/profiles/misc/US_Web_Coated_SWOP_CMYK.icc.txt
@@ -31,15 +31,9 @@
   ~= : 0.4144x^3 + -0.5098x^2 + 1.095x (Max error: 0.008042)
 CLUT : 9 x 9 x 9 x 9 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B1 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
-  B2 : 16-bit table with 2 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 0) (Linear)
-  ~= : 0x^3 + 1x^2 + 0x (Max error: 0)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	121f24 392210 0a0c06 1b141c 1d1407 151f0c 242014
 	23223b 000001 0f1514 212d48 482f22 242619 020101
diff --git a/profiles/misc/XRite_GRACol7_340_CMYK.icc.txt b/profiles/misc/XRite_GRACol7_340_CMYK.icc.txt
index a8b7f58..627d8cc 100644
--- a/profiles/misc/XRite_GRACol7_340_CMYK.icc.txt
+++ b/profiles/misc/XRite_GRACol7_340_CMYK.icc.txt
@@ -22,29 +22,15 @@
 
  A2B : "A", CLUT, "B"
  "A" : 4 inputs
-  A0 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
-  A1 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
-  A2 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
-  A3 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
+  A0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  A3 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 CLUT : 17 x 17 x 17 x 17 (16 bpp)
  "B" : 3 outputs
-  B0 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
-  B1 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
-  B2 : 16-bit table with 4096 entries
-  ~= : 1, 1, 0, 0, 0, 0, 0  (Max error: 7.7e-06) (Linear)
-  ~= : 5.8e-07x^3 + -6.545e-07x^2 + 1x (Max error: 7.689e-06)
+  B0 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B1 : 1, 1, 0, 0, 0, 0, 0 (Linear)
+  B2 : 1, 1, 0, 0, 0, 0, 0 (Linear)
 252 random bytes transformed to linear XYZD50 bytes:
 	121d23 3b2510 0c0e07 1c151b 1e1607 17210e 252013
 	242239 010102 111616 212b45 493020 26281a 030201
diff --git a/src/ICCProfile.c b/src/ICCProfile.c
index 9c504cd..a21abd0 100644
--- a/src/ICCProfile.c
+++ b/src/ICCProfile.c
@@ -226,7 +226,7 @@
         curve->parametric.e  = 0.0f;
         curve->parametric.f  = 0.0f;
         if (value_count == 0) {
-            // Empty tables are a shorthand for linear
+            // Empty tables are a shorthand for an identity curve
             curve->parametric.g = 1.0f;
         } else {
             // Single entry tables are a shorthand for simple gamma
@@ -581,15 +581,51 @@
 }
 
 static bool read_a2b(const skcms_ICCTag* tag, skcms_A2B* a2b, bool pcs_is_xyz) {
+    bool ok = false;
     if (tag->type == make_signature('m', 'f', 't', '1')) {
-        return read_tag_mft1(tag, a2b);
+        ok = read_tag_mft1(tag, a2b);
     } else if (tag->type == make_signature('m', 'f', 't', '2')) {
-        return read_tag_mft2(tag, a2b);
+        ok = read_tag_mft2(tag, a2b);
     } else if (tag->type == make_signature('m', 'A', 'B', ' ')) {
-        return read_tag_mab(tag, a2b, pcs_is_xyz);
+        ok = read_tag_mab(tag, a2b, pcs_is_xyz);
+    }
+    if (!ok) {
+        return false;
     }
 
-    return false;
+    // Detect and canonicalize identity tables.
+    skcms_Curve* curves[] = {
+        a2b->input_channels  > 0 ? a2b->input_curves  + 0 : NULL,
+        a2b->input_channels  > 1 ? a2b->input_curves  + 1 : NULL,
+        a2b->input_channels  > 2 ? a2b->input_curves  + 2 : NULL,
+        a2b->input_channels  > 3 ? a2b->input_curves  + 3 : NULL,
+        a2b->matrix_channels > 0 ? a2b->matrix_curves + 0 : NULL,
+        a2b->matrix_channels > 1 ? a2b->matrix_curves + 1 : NULL,
+        a2b->matrix_channels > 2 ? a2b->matrix_curves + 2 : NULL,
+        a2b->output_channels > 0 ? a2b->output_curves + 0 : NULL,
+        a2b->output_channels > 1 ? a2b->output_curves + 1 : NULL,
+        a2b->output_channels > 2 ? a2b->output_curves + 2 : NULL,
+    };
+
+    for (int i = 0; i < ARRAY_COUNT(curves); i++) {
+        skcms_Curve* curve = curves[i];
+
+        if (curve && curve->table_entries && curve->table_entries <= (uint32_t)INT_MAX) {
+            int N = (int)curve->table_entries;
+
+            skcms_TransferFunction tf;
+            if (N == skcms_fit_linear(curve, N, 1.0f/(2*N), &tf)
+                && tf.c == 1.0f
+                && tf.f == 0.0f) {
+                curve->table_entries = 0;
+                curve->table_8       = NULL;
+                curve->table_16      = NULL;
+                curve->parametric    = (skcms_TransferFunction){1,1,0,0,0,0,0};
+            }
+        }
+    }
+
+    return true;
 }
 
 void skcms_GetTagByIndex(const skcms_ICCProfile* profile, uint32_t idx, skcms_ICCTag* tag) {
diff --git a/src/TransferFunction.c b/src/TransferFunction.c
index 6ddc977..56245ad 100644
--- a/src/TransferFunction.c
+++ b/src/TransferFunction.c
@@ -116,8 +116,8 @@
 //
 // Our overall strategy is then:
 //    For a couple tolerances,
-//       - fit_linear():     fit c,d,f iteratively to as many points as our tolerance allows
-//       - fit_nonlinear():  fit g,a,b using Gauss-Newton given c,d,f (and by constraint, e)
+//       - skcms_fit_linear(): fit c,d,f iteratively to as many points as our tolerance allows
+//       - fit_nonlinear():    fit g,a,b using Gauss-Newton given c,d,f (and by constraint, e)
 //    Return the parameters with least maximum error.
 //
 // To run Gauss-Newton to find g,a,b, we'll also need the gradient of the non-linear piece:
@@ -161,8 +161,8 @@
             -   g*powf_(D, g-1);
 }
 
-// Returns the number of points that are approximated by the line, to within tol.
-static int fit_linear(const skcms_Curve* curve, int N, float tol, skcms_TransferFunction* tf) {
+int skcms_fit_linear(const skcms_Curve* curve, int N, float tol, skcms_TransferFunction* tf) {
+    assert(N > 1);
     // We iteratively fit the first points to the TF's linear piece.
     // We want the cx + f line to pass through the first and last points we fit exactly.
     //
@@ -267,7 +267,7 @@
     const float kTolerances[] = { 1.5f / 65535.0f, 1.0f / 512.0f };
     for (int t = 0; t < ARRAY_COUNT(kTolerances); t++) {
         skcms_TransferFunction tf;
-        int L = fit_linear(curve, N, kTolerances[t], &tf);
+        int L = skcms_fit_linear(curve, N, kTolerances[t], &tf);
 
         if (L == N) {
             // If the entire data set was linear, move the coefficients to the nonlinear portion
diff --git a/src/TransferFunction.h b/src/TransferFunction.h
index c98c78d..284b136 100644
--- a/src/TransferFunction.h
+++ b/src/TransferFunction.h
@@ -14,3 +14,7 @@
 float skcms_TransferFunction_eval(const skcms_TransferFunction*, float);
 
 bool skcms_TransferFunction_invert(const skcms_TransferFunction*, skcms_TransferFunction*);
+
+// Fit c,d,f parameters of an skcms_TransferFunction to the first 2 < L ≤ N
+// evenly-spaced points on an skcms_Curve within a given tolerance, returning L.
+int skcms_fit_linear(const skcms_Curve*, int N, float tol, skcms_TransferFunction*);