`tf.keras.utils.image_dataset_from_directory` doesn't support 8-bit BMP when `color_mode` is grayscale
In my opinion, this problem is cause by the **num_channels** has different definition in `image_dataset_from_directory` and `tf.image.decode_image`.

If **color_mode** set as grayscale, **num_channels** will be 1, which cause a problem when `tf.image.decode_image` try to load bmp images in `tf.keras.utils.image_dataset_from_directory`.

My way to solve this problem is to add a condition in `image_dataset_from_directory` to set **num_channels** as 0 when image format is bmp and **color_mode** is grayscale. 
But it raise another problem since the output shape should be (None, image_size, image_size, 1), so I also add a condition in `load_image` to set the shape to (None, image_size, image_size, 1) if output shape is (None, image_size, image_size, 0). @yyingci,
Thank you for the issue. We are working on this. Could you please allow some time to deep dive into this issue and come back with the resolution. Thank you! I solve this problem by editing the **datasetLoader.py** script directly.
To load grayscale bmp image correctly, I add a condition in `image_dataset_from_directory` function
![63008_1](https://github.com/tensorflow/tensorflow/assets/98000114/51dc3b75-1894-4440-96f4-d115d5078a2f)

To keep the output shape, I add a condition in `load_image` function
![63008_2](https://github.com/tensorflow/tensorflow/assets/98000114/5a1b8107-440c-4d22-8c20-b13016d18942)

Here is the entire script, hope it helps.
```
def image_dataset_from_directory(
    directory,
    labels="inferred",
    label_mode="int",
    class_names=None,
    color_mode="rgb",
    batch_size=32,
    image_size=(256, 256),
    shuffle=True,
    seed=None,
    validation_split=None,
    subset=None,
    interpolation="bilinear",
    follow_links=False,
    crop_to_aspect_ratio=False,
    **kwargs,
):
    
    if "smart_resize" in kwargs:
        crop_to_aspect_ratio = kwargs.pop("smart_resize")
    if kwargs:
        raise TypeError(f"Unknown keywords argument(s): {tuple(kwargs.keys())}")
    if labels not in ("inferred", None):
        if not isinstance(labels, (list, tuple)):
            raise ValueError(
                "`labels` argument should be a list/tuple of integer labels, "
                "of the same size as the number of image files in the target "
                "directory. If you wish to infer the labels from the "
                "subdirectory "
                'names in the target directory, pass `labels="inferred"`. '
                "If you wish to get a dataset that only contains images "
                f"(no labels), pass `labels=None`. Received: labels={labels}"
            )
        if class_names:
            raise ValueError(
                "You can only pass `class_names` if "
                f'`labels="inferred"`. Received: labels={labels}, and '
                f"class_names={class_names}"
            )
    if label_mode not in {"int", "categorical", "binary", None}:
        raise ValueError(
            '`label_mode` argument must be one of "int", '
            '"categorical", "binary", '
            f"or None. Received: label_mode={label_mode}"
        )
    if labels is None or label_mode is None:
        labels = None
        label_mode = None

    if color_mode == "rgb":
        num_channels = 3
    elif color_mode == "rgba":
        num_channels = 4
    elif color_mode == "grayscale":
        num_channels = 1
    elif color_mode == "grayscale_bmp":
        num_channels = 0
    else:
        raise ValueError(
            '`color_mode` must be one of {"rgb", "rgba", "grayscale"}. '
            f"Received: color_mode={color_mode}"
        )
    interpolation = image_utils.get_interpolation(interpolation)
    dataset_utils.check_validation_split_arg(
        validation_split, subset, shuffle, seed
    )

    if seed is None:
        seed = np.random.randint(1e6)
    image_paths, labels, class_names = dataset_utils.index_directory(
        directory,
        labels,
        formats=ALLOWLIST_FORMATS,
        class_names=class_names,
        shuffle=shuffle,
        seed=seed,
        follow_links=follow_links,
    )

    if label_mode == "binary" and len(class_names) != 2:
        raise ValueError(
            'When passing `label_mode="binary"`, there must be exactly 2 '
            f"class_names. Received: class_names={class_names}"
        )

    if subset == "both":
        (
            image_paths_train,
            labels_train,
        ) = dataset_utils.get_training_or_validation_split(
            image_paths, labels, validation_split, "training"
        )
        (
            image_paths_val,
            labels_val,
        ) = dataset_utils.get_training_or_validation_split(
            image_paths, labels, validation_split, "validation"
        )
        if not image_paths_train:
            raise ValueError(
                f"No training images found in directory {directory}. "
                f"Allowed formats: {ALLOWLIST_FORMATS}"
            )
        if not image_paths_val:
            raise ValueError(
                f"No validation images found in directory {directory}. "
                f"Allowed formats: {ALLOWLIST_FORMATS}"
            )
        train_dataset = paths_and_labels_to_dataset(
            image_paths=image_paths_train,
            image_size=image_size,
            num_channels=num_channels,
            labels=labels_train,
            label_mode=label_mode,
            num_classes=len(class_names),
            interpolation=interpolation,
            crop_to_aspect_ratio=crop_to_aspect_ratio,
        )
        val_dataset = paths_and_labels_to_dataset(
            image_paths=image_paths_val,
            image_size=image_size,
            num_channels=num_channels,
            labels=labels_val,
            label_mode=label_mode,
            num_classes=len(class_names),
            interpolation=interpolation,
            crop_to_aspect_ratio=crop_to_aspect_ratio,
        )
        train_dataset = train_dataset.prefetch(tf.data.AUTOTUNE)
        val_dataset = val_dataset.prefetch(tf.data.AUTOTUNE)

        if batch_size is not None:
            if shuffle:
                # Shuffle locally at each iteration
                train_dataset = train_dataset.shuffle(
                    buffer_size=batch_size * 8, seed=seed
                )
            train_dataset = train_dataset.batch(batch_size)
            val_dataset = val_dataset.batch(batch_size)
        else:
            if shuffle:
                train_dataset = train_dataset.shuffle(
                    buffer_size=1024, seed=seed
                )

        # Users may need to reference `class_names`.
        train_dataset.class_names = class_names
        val_dataset.class_names = class_names

        # Include file paths for images as attribute.
        train_dataset.file_paths = image_paths_train
        val_dataset.file_paths = image_paths_val
        dataset = [train_dataset, val_dataset]
    else:
        image_paths, labels = dataset_utils.get_training_or_validation_split(
            image_paths, labels, validation_split, subset
        )
        if not image_paths:
            raise ValueError(
                f"No images found in directory {directory}. "
                f"Allowed formats: {ALLOWLIST_FORMATS}"
            )

        dataset = paths_and_labels_to_dataset(
            image_paths=image_paths,
            image_size=image_size,
            num_channels=num_channels,
            labels=labels,
            label_mode=label_mode,
            num_classes=len(class_names),
            interpolation=interpolation,
            crop_to_aspect_ratio=crop_to_aspect_ratio,
        )
        dataset = dataset.prefetch(tf.data.AUTOTUNE)
        if batch_size is not None:
            if shuffle:
                # Shuffle locally at each iteration
                dataset = dataset.shuffle(buffer_size=batch_size * 8, seed=seed)
            dataset = dataset.batch(batch_size)
        else:
            if shuffle:
                dataset = dataset.shuffle(buffer_size=1024, seed=seed)

        # Users may need to reference `class_names`.
        dataset.class_names = class_names

        # Include file paths for images as attribute.
        dataset.file_paths = image_paths
    return dataset

def load_image(
    path, image_size, num_channels, interpolation, crop_to_aspect_ratio=False
):
    """Load an image from a path and resize it."""
    img = tf.io.read_file(path)
    img = tf.image.decode_image(img, channels=num_channels, expand_animations=False)
    if crop_to_aspect_ratio:
        img = image_utils.smart_resize(
            img, image_size, interpolation=interpolation
        )
    else:
        img = tf.image.resize(img, image_size, method=interpolation)
    if num_channels == 0:
        img.set_shape((image_size[0], image_size[1], 1))
    else:
        img.set_shape((image_size[0], image_size[1], num_channels))
    return img
``` @yyingci,
As mentioned it is an error provided by **tensorflow.image.decode_image** where there is a limitation to not support for BMP formats.
Similar issue on the same feature. https://github.com/tensorflow/tensorflow/issues/61893

Thank you! This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. This issue was closed because it has been inactive for 7 days since being marked as stale. Please reopen if you'd like to work on this further. Are you satisfied with the resolution of your issue?
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/63008">Yes</a>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/63008">No</a>

### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

No

### Source

source

### TensorFlow version

tf 2.8

### Custom code

Yes

### OS platform and distribution

Window 10

### Mobile device

Window 10

### Python version

3.8

### Bazel version

_No response_

### GCC/compiler version

_No response_

### CUDA/cuDNN version

11.3/8.2

### GPU model and memory

_No response_

### Current behavior?

`tf.keras.utils.image_dataset_from_directory` doesn't support 8-bit BMP when `color_mode` is grayscale


### Standalone code to reproduce the issue

```shell
import tensorflow as tf

dataset_dir = 'your_dataset_path'

def get_dataset(dataset_dir):
    return tf.keras.utils.image_dataset_from_directory(
            directory=dataset_dir ,
            label_mode='int',
            class_names=['ok', 'ng'],
            color_mode='grayscale',
            batch_size=4,
            image_size=(64, 64),
            shuffle=True,
            seed=369,
            validation_split=0.2,
            subset='training',
            interpolation='bicubic'
        )


dataset = get_dataset(dataset_dir)

for images, labels in dataset.take(1):
    print('Image shape', images.shape)
```


### Relevant log output

```shell
tensorflow.python.framework.errors_impl.InvalidArgumentError: `channels` must be 0, 3 or 4 for BMP, but got 1         
  [[{{node decode_image/DecodeImage}}]] [Op:IteratorGetNext]
```
