Refactor avifImageRGBToYUVLibYUV8bpc() and avif.h

Remove libyuv tables in avif.h.
Use look-up tables in avifImageRGBToYUVLibYUV8bpc().
Fix libyuv RGB-to-YUV 4:0:0 being used for any avifMatrixCoefficients
and not only for BT.601.
diff --git a/include/avif/avif.h b/include/avif/avif.h
index 71cf54f..08555cb 100644
--- a/include/avif/avif.h
+++ b/include/avif/avif.h
@@ -528,30 +528,8 @@
 // conversion, if necessary. Pixels in an avifRGBImage buffer are always full range, and conversion
 // routines will fail if the width and height don't match the associated avifImage.
 
-// If libavif is built with libyuv fast paths enabled and the AVIF_RGB_TO_YUV_AVOID_LIBYUV or
-// AVIF_YUV_TO_RGB_AVOID_LIBYUV flag is not set, libavif will use libyuv for conversion between
-// RGB and YUV if the following requirements are met:
-
-// Conversion from YUV to RGB:
-// * YUV depth: 8 or 10
-// * RGB depth: 8
-// * rgb.format: AVIF_RGB_FORMAT_RGBA, AVIF_RGB_FORMAT_BGRA (420/422 support for
-//               AVIF_RGB_FORMAT_ABGR, AVIF_RGB_FORMAT_ARGB, AVIF_RGB_FORMAT_RGB_565)
-// * CICP is one of the following combinations (CP/TC/MC/Range):
-//   * x/x/[2|5|6]/Full
-//   * [5|6]/x/12/Full
-//   * x/x/[1|2|5|6|9]/Limited
-//   * [1|2|5|6|9]/x/12/Limited
-
-// Conversion from RGB to YUV:
-// * YUV depth: 8
-// * RGB depth: 8
-// * One of the following combinations (avifRGBFormat to avifPixelFormat/MC/Range):
-//   *  BGRA            to  YUV400        /  x  /[Full|Limited]
-//   *  BGRA            to [YUV420|YUV422]/[5|6]/[Full|Limited]
-//   *  BGRA            to  YUV444        /[5|6]/ Limited
-//   *  BGR             to  YUV420        /[5|6]/[Full|Limited]
-//   * [RGBA|ARGB|ABGR] to  YUV420        /[5|6]/ Limited
+// If libavif is built with a version of libyuv offering a fast conversion between RGB and YUV for
+// the given inputs, libavif will use it. See reformat_libyuv.c for the details.
 
 // Note to libavif maintainers: The lookup tables in avifImageYUVToRGBLibYUV
 // rely on the ordering of this enum values for their correctness. So changing
diff --git a/src/reformat.c b/src/reformat.c
index 9559fad..099778a 100644
--- a/src/reformat.c
+++ b/src/reformat.c
@@ -32,6 +32,9 @@
         rgb->format < AVIF_RGB_FORMAT_RGB || rgb->format >= AVIF_RGB_FORMAT_COUNT) {
         return AVIF_FALSE;
     }
+    if (image->yuvRange != AVIF_RANGE_LIMITED && image->yuvRange != AVIF_RANGE_FULL) {
+        return AVIF_FALSE;
+    }
 
     // These matrix coefficients values are currently unsupported. Revise this list as more support is added.
     //
diff --git a/src/reformat_libyuv.c b/src/reformat_libyuv.c
index 267fb02..1bef108 100644
--- a/src/reformat_libyuv.c
+++ b/src/reformat_libyuv.c
@@ -127,101 +127,67 @@
     // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address,
     // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR.
 
-    if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) {
-        // Generic mapping from any RGB layout (with or without alpha) to monochrome.
-        int (*RGBtoY)(const uint8_t *, int, uint8_t *, int, int, int) = NULL;
-
-        if (image->yuvRange == AVIF_RANGE_LIMITED) {
-            if (rgb->format == AVIF_RGB_FORMAT_BGRA) {
-                RGBtoY = ARGBToI400;
-            }
-        } else { // image->yuvRange == AVIF_RANGE_FULL
-            if (rgb->format == AVIF_RGB_FORMAT_BGRA) {
-                RGBtoY = ARGBToJ400;
-            }
-        }
-
-        if (!RGBtoY) {
-            return AVIF_RESULT_NOT_IMPLEMENTED;
-        }
-        if (RGBtoY(rgb->pixels, rgb->rowBytes, image->yuvPlanes[AVIF_CHAN_Y], image->yuvRowBytes[AVIF_CHAN_Y], image->width, image->height)) {
-            return AVIF_RESULT_REFORMAT_FAILED;
-        }
-        return AVIF_RESULT_OK;
-    }
-
-    // Generic mapping from any RGB layout (with or without alpha) to any YUV layout (subsampled or not).
-    int (*RGBtoYUV)(const uint8_t *, int, uint8_t *, int, uint8_t *, int, uint8_t *, int, int, int) = NULL;
-
     // libyuv only handles BT.601 for RGB to YUV, and not all range/order/subsampling combinations.
     // BT.470BG has the same coefficients as BT.601.
     if ((image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT470BG) || (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT601)) {
-        if (rgb->format == AVIF_RGB_FORMAT_BGRA) {
-            if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
-                if (image->yuvRange == AVIF_RANGE_FULL) {
-                    RGBtoYUV = ARGBToJ420;
-                } else {
-                    RGBtoYUV = ARGBToI420;
+        if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV400) {
+            // Lookup table for RGB To Y (monochrome).
+            typedef int (*RGBtoY)(const uint8_t *, int, uint8_t *, int, int, int);
+            // Second dimension is for avifRange.
+            RGBtoY lutRgbToY[AVIF_RGB_FORMAT_COUNT][2] = {
+                { NULL, NULL },             // RGB
+                { NULL, NULL },             // RGBA
+                { NULL, NULL },             // ARGB
+                { NULL, NULL },             // BGR
+                { ARGBToI400, ARGBToJ400 }, // BGRA
+                { NULL, NULL },             // ABGR
+                { NULL, NULL }              // RGB_565
+            };
+            RGBtoY rgbToY = lutRgbToY[rgb->format][image->yuvRange];
+            if (rgbToY != NULL) {
+                if (rgbToY(rgb->pixels,
+                           rgb->rowBytes,
+                           image->yuvPlanes[AVIF_CHAN_Y],
+                           image->yuvRowBytes[AVIF_CHAN_Y],
+                           image->width,
+                           image->height) != 0) {
+                    return AVIF_RESULT_REFORMAT_FAILED;
                 }
-            } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV422) {
-                if (image->yuvRange == AVIF_RANGE_FULL) {
-                    RGBtoYUV = ARGBToJ422;
-                } else {
-                    RGBtoYUV = ARGBToI422;
-                }
-            } else if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV444) {
-                if (image->yuvRange == AVIF_RANGE_LIMITED) {
-                    RGBtoYUV = ARGBToI444;
-                }
+                return AVIF_RESULT_OK;
             }
-        } else if (rgb->format == AVIF_RGB_FORMAT_BGR) {
-            if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
-                if (image->yuvRange == AVIF_RANGE_FULL) {
-                    RGBtoYUV = RGB24ToJ420;
-                } else {
-                    RGBtoYUV = RGB24ToI420;
+        } else {
+            // Lookup table for RGB To YUV Matrix (average filter).
+            typedef int (*RGBtoYUV)(const uint8_t *, int, uint8_t *, int, uint8_t *, int, uint8_t *, int, int, int);
+            // Third dimension is for avifRange.
+            RGBtoYUV lutRgbToYuv[AVIF_RGB_FORMAT_COUNT][AVIF_PIXEL_FORMAT_COUNT][2] = {
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } },                 // RGB
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { ABGRToI420, avifABGRToJ420 }, { NULL, NULL } }, // RGBA
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { BGRAToI420, NULL }, { NULL, NULL } },           // ARGB
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { RGB24ToI420, RGB24ToJ420 }, { NULL, NULL } },   // BGR
+                { { NULL, NULL }, { ARGBToI444, NULL }, { ARGBToI422, ARGBToJ422 }, { ARGBToI420, ARGBToJ420 }, { NULL, NULL } }, // BGRA
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { RGBAToI420, NULL }, { NULL, NULL } }, // ABGR
+                { { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL }, { NULL, NULL } }        // RGB_565
+            };
+            RGBtoYUV rgbToYuv = lutRgbToYuv[rgb->format][image->yuvFormat][image->yuvRange];
+            if (rgbToYuv != NULL) {
+                if (rgbToYuv(rgb->pixels,
+                             rgb->rowBytes,
+                             image->yuvPlanes[AVIF_CHAN_Y],
+                             image->yuvRowBytes[AVIF_CHAN_Y],
+                             image->yuvPlanes[AVIF_CHAN_U],
+                             image->yuvRowBytes[AVIF_CHAN_U],
+                             image->yuvPlanes[AVIF_CHAN_V],
+                             image->yuvRowBytes[AVIF_CHAN_V],
+                             image->width,
+                             image->height) != 0) {
+                    return AVIF_RESULT_REFORMAT_FAILED;
                 }
-            }
-        } else if (rgb->format == AVIF_RGB_FORMAT_RGBA) {
-            if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
-                if (image->yuvRange == AVIF_RANGE_FULL) {
-                    RGBtoYUV = avifABGRToJ420;
-                } else {
-                    RGBtoYUV = ABGRToI420;
-                }
-            }
-        } else if (rgb->format == AVIF_RGB_FORMAT_ARGB) {
-            if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
-                if (image->yuvRange == AVIF_RANGE_LIMITED) {
-                    RGBtoYUV = BGRAToI420;
-                }
-            }
-        } else if (rgb->format == AVIF_RGB_FORMAT_ABGR) {
-            if (image->yuvFormat == AVIF_PIXEL_FORMAT_YUV420) {
-                if (image->yuvRange == AVIF_RANGE_LIMITED) {
-                    RGBtoYUV = RGBAToI420;
-                }
+                return AVIF_RESULT_OK;
             }
         }
     }
-    // TODO: Use SplitRGBPlane() for AVIF_MATRIX_COEFFICIENTS_IDENTITY if faster than the current implementation
-
-    if (!RGBtoYUV) {
-        return AVIF_RESULT_NOT_IMPLEMENTED;
-    }
-    if (RGBtoYUV(rgb->pixels,
-                 rgb->rowBytes,
-                 image->yuvPlanes[AVIF_CHAN_Y],
-                 image->yuvRowBytes[AVIF_CHAN_Y],
-                 image->yuvPlanes[AVIF_CHAN_U],
-                 image->yuvRowBytes[AVIF_CHAN_U],
-                 image->yuvPlanes[AVIF_CHAN_V],
-                 image->yuvRowBytes[AVIF_CHAN_V],
-                 image->width,
-                 image->height)) {
-        return AVIF_RESULT_REFORMAT_FAILED;
-    }
-    return AVIF_RESULT_OK;
+    // TODO: Use SplitRGBPlane() for AVIF_MATRIX_COEFFICIENTS_IDENTITY if faster than the built-in implementation
+    return AVIF_RESULT_NOT_IMPLEMENTED;
 }
 
 static avifResult avifImageYUVToRGBLibYUV8bpc(const avifImage * image,
@@ -309,7 +275,7 @@
             case AVIF_MATRIX_COEFFICIENTS_ICTCP:
                 break;
         }
-    } else {
+    } else { // image->yuvRange == AVIF_RANGE_LIMITED
         switch (image->matrixCoefficients) {
             case AVIF_MATRIX_COEFFICIENTS_BT709:
                 matrixYUV = &kYuvH709Constants;