keras/src/layers/preprocessing/random_crop.py/RandomCrop/call
class RandomCrop:    def call(self, inputs, training=True):
        inputs = self.backend.cast(inputs, self.compute_dtype)
        input_shape = self.backend.shape(inputs)
        is_batched = len(input_shape) > 3
        if not is_batched:
            inputs = self.backend.numpy.expand_dims(inputs, axis=0)

        h_diff = input_shape[self.height_axis] - self.height
        w_diff = input_shape[self.width_axis] - self.width

        def random_crop():
            input_height, input_width = (
                input_shape[self.height_axis],
                input_shape[self.width_axis],
            )

            seed_generator = self._get_seed_generator(self.backend._backend)
            h_start = self.backend.cast(
                self.backend.random.uniform(
                    (),
                    0,
                    maxval=float(input_height - self.height + 1),
                    seed=seed_generator,
                ),
                "int32",
            )
            w_start = self.backend.cast(
                self.backend.random.uniform(
                    (),
                    0,
                    maxval=float(input_width - self.width + 1),
                    seed=seed_generator,
                ),
                "int32",
            )
            if self.data_format == "channels_last":
                return self.backend.core.slice(
                    inputs,
                    self.backend.numpy.stack([0, h_start, w_start, 0]),
                    [
                        self.backend.shape(inputs)[0],
                        self.height,
                        self.width,
                        self.backend.shape(inputs)[3],
                    ],
                )
            else:
                return self.backend.core.slice(
                    inputs,
                    self.backend.numpy.stack([0, 0, h_start, w_start]),
                    [
                        self.backend.shape(inputs)[0],
                        self.backend.shape(inputs)[1],
                        self.height,
                        self.width,
                    ],
                )

        def resize():
            outputs = image_utils.smart_resize(
                inputs,
                [self.height, self.width],
                data_format=self.data_format,
                backend_module=self.backend,
            )
            # smart_resize will always output float32, so we need to re-cast.
            return self.backend.cast(outputs, self.compute_dtype)

        if isinstance(h_diff, int) and isinstance(w_diff, int):
            if training and h_diff >= 0 and w_diff >= 0:
                outputs = random_crop()
            else:
                outputs = resize()
        else:
            predicate = self.backend.numpy.logical_and(
                training,
                self.backend.numpy.logical_and(h_diff >= 0, w_diff >= 0),
            )
            outputs = self.backend.cond(
                predicate,
                random_crop,
                resize,
            )

        if not is_batched:
            outputs = self.backend.numpy.squeeze(outputs, axis=0)
        return outputs