To add an image field and preview functionality in a Magento 2 Admin UI Component form, you need to follow these steps:

1. Create the Database Column for the Image Field

First, ensure that your database table has a column to store the image's file name or path.

2. Modify the UI Component XML File

You'll need to update your UI Component form XML file to include an image uploader. Here's an example of how you can do this:
 
<field name="image">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="dataType" xsi:type="string">string</item>
            <item name="label" xsi:type="string" translate="true">Image</item>
            <item name="visible" xsi:type="boolean">true</item>
            <item name="allowedExtensions" xsi:type="string">jpg jpeg png</item>
            <item name="maxFileSize" xsi:type="number">2097152</item>
            <item name="formElement" xsi:type="string">imageUploader</item>
            <item name="previewTmpl" xsi:type="string">Vendor_Module/image-preview</item>
            <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
            <item name="dataScope" xsi:type="string">image</item>
            <item name="sortOrder" xsi:type="number">40</item>
            <item name="uploaderConfig" xsi:type="array">
                <item name="url" xsi:type="url" path="route/index/controller">
                    <param name="target_element_id">image</param>
                    <param name="type">image</param>
                </item>
            </item>
            <item name="validation" xsi:type="array">
                <item name="required-entry" xsi:type="boolean">true</item>
            </item>
        </item>
    </argument>
</field>

3. Create the Controller for Image Upload

You need to create a controller to handle the image upload. This controller will process the uploaded image and save it to the appropriate directory. Create Upload.php at Vendor/Module/Controller/Adminhtml/Index:
 
<?php

namespace Vendor\Module\Controller\adminhtml\Index;

use Exception;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Vendor\Module\Model\ImageUploader;

class Upload extends Action
{

    /**
     * @var ImageUploader
     */
    public $imageUploader;

    /**
     * Upload constructor.
     * @param Context $context
     * @param ImageUploader $imageUploader
     */
    public function __construct(
        Context $context,
        ImageUploader $imageUploader
    ) {
        parent::__construct($context);
        $this->imageUploader = $imageUploader;
    }

    /**
     * @return mixed
     */
    public function _isAllowed() {
        return $this->_authorization->isAllowed('Vendor_Module::upload');
    }

    /**
     * @return mixed
     */
    public function execute() {
        try {
            $result = $this->imageUploader->saveFileToTmpDir('image');
            $result['cookie'] = [
                'name' => $this->_getSession()->getName(),
                'value' => $this->_getSession()->getSessionId(),
                'lifetime' => $this->_getSession()->getCookieLifetime(),
                'path' => $this->_getSession()->getCookiePath(),
                'domain' => $this->_getSession()->getCookieDomain(),
            ];
        } catch (Exception $e) {
            $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()];
        }
        return $this->resultFactory->create(ResultFactory::TYPE_JSON)->setData($result);
    }
}

4. Create Save.php

Create Save.php at Vendor/Module/Controller/Adminhtml/Index:
 
<?php

namespace Vendor\Module\Controller\adminhtml\Index;


use Exception;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\App\Cache\Manager;
use Vendor\Module\Model\ImageUploader;
use Vendor\Module\Model\ModelCollectionFactory;
/**
 * Class Save
 * @package Vendorname\Helloworld\Controller\Adminhtml\Index
 */
class Save extends Action
{
    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @var ManagerInterface
     */
    protected $_messageManager;
    /**
     * @var TypeListInterface
     */
    protected $cacheManager;
    private ImageUploader $imageUploader;
    private ModelCollectionFactory $modelCollectionFactory;

    /**
     * Save constructor.
     * @param Context $context
     * @param PageFactory $resultPageFactory
     * @param ImageUploader $imageUploaderModel
     * @param ManagerInterface $messageManager
     * @param Manager $cacheManager
     * @param ModelCollectionFactory $modelCollectionFactory
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        ImageUploader $imageUploader,
        ManagerInterface $messageManager,
        Manager $cacheManager,
        ModelCollectionFactory $modelCollectionFactory
    )
    {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
        $this->imageUploader = $imageUploader;
        $this->messageManager = $messageManager;
        $this->cacheManager = $cacheManager;
        $this->modelCollectionFactory = $modelCollectionFactory;
    }

    /**
     * @return mixed
     */
    public function execute()
    {
        try {
            $resultPageFactory = $this->resultRedirectFactory->create();
            $data = $this->getRequest()->getPostValue();
            $model = $this->modelCollectionFactory->create();
            $model->setData($data);
            $model = $this->imageData($model, $data);
            $model->save();
            $this->messageManager->addSuccessMessage(__("Data Saved Successfully."));
            $buttonData = $this->getRequest()->getParam('back');
            if ($buttonData == 'edit' && $model->getId()) {
                return $resultPageFactory->setPath('*/*/', ['id' => $model->getId()]);
            }
            if ($buttonData == 'new') {
                return $resultPageFactory->setPath('*/*/');
            }
            if ($buttonData == 'close') {
                $this->_redirect('*/*/');
            }
        }
        catch (Exception $e) {
            $this->_messageManager->addErrorMessage(__($e));
        }
        return $resultPageFactory->setPath('*/*/');
    }

    /**
     * @param $model
     * @param $data
     * @return mixed
     */
    public function imageData($model, $data)
    {
        if ($model->getId()) {
            $pageData = $this->modelCollectionFactory->create();
            $pageData->load($model->getId());
            if (isset($data['image'][0]['name'])) {
                $imageName1 = $pageData->getThumbnail();
                $imageName2 = $data['image'][0]['name'];
                if ($imageName1 != $imageName2) {
                    $imageUrl = $data['image'][0]['url'];
                    $imageName = $data['image'][0]['name'];
                    $data['image'] = $this->imageUploader->saveMediaImage($imageName, $imageUrl);
                } else {
                    $data['image'] = $data['image'][0]['name'];
                }
            } else {
                $data['image'] = '';
            }
        } else {
            if (isset($data['image'][0]['name'])) {
                $imageUrl = $data['image'][0]['url'];
                $imageName = $data['image'][0]['name'];
                $data['image'] = $this->imageUploader->saveMediaImage($imageName, $imageUrl);
            }
        }
        $model->setData($data);
        return $model;
    }
}

5. Create a Model Class

Create a new controller at Vendor/Module/Model/ImageUpload.php:
 
<?php

namespace Vendor\Module\Model;

use Exception;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\WriteInterface;
use Magento\Framework\UrlInterface;
use Magento\MediaStorage\Helper\File\Storage\Database;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;

class ImageUploader
{
    const BASE_TMP_PATH = "your_folder_name/temp/";
    const BASE_PATH = "your_folder_name/temp/";
    const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png'];

    /**
     * @var string
     */
    public $baseTmpPath;
    /**
     * @var string
     */
    public $basePath;
    /**
     * @var string[]
     */
    public $allowedExtensions;
    /**
     * @var Database
     */
    private $coreFileStorageDatabase;
    /**
     * @var WriteInterface
     */
    private $mediaDirectory;
    /**
     * @var UploaderFactory
     */
    private $uploaderFactory;
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * ImageUploader constructor.
     * @param Database $coreFileStorageDatabase
     * @param Filesystem $filesystem
     * @param UploaderFactory $uploaderFactory
     * @param StoreManagerInterface $storeManager
     * @param LoggerInterface $logger
     * @throws FileSystemException
     */
    public function __construct(
        Database $coreFileStorageDatabase,
        Filesystem $filesystem,
        UploaderFactory $uploaderFactory,
        StoreManagerInterface $storeManager,
        LoggerInterface $logger
    ) {
        $this->coreFileStorageDatabase = $coreFileStorageDatabase;
        $this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        $this->uploaderFactory = $uploaderFactory;
        $this->storeManager = $storeManager;
        $this->logger = $logger;
        $this->baseTmpPath = self::BASE_TMP_PATH;
        $this->basePath = self::BASE_PATH;
        $this->allowedExtensions = self::ALLOWED_EXTENSIONS;
    }

    /**
     * @param $imageName
     * @return mixed
     * @throws LocalizedException
     */
    public function moveFileFromTmp($imageName)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $basePath = $this->getBasePath();
        $baseImagePath = $this->getFilePath($basePath, $imageName);
        $baseTmpImagePath = $this->getFilePath($baseTmpPath, $imageName);
        try {
            $this->coreFileStorageDatabase->copyFile(
                $baseTmpImagePath,
                $baseImagePath
            );
            $this->mediaDirectory->renameFile(
                $baseTmpImagePath,
                $baseImagePath
            );
        } catch (Exception $e) {
            throw new LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }
        return $imageName;
    }

    /**
     * @return string
     */
    public function getBaseTmpPath()
    {
        return $this->baseTmpPath;
    }

    /**
     * @param $baseTmpPath
     */
    public function setBaseTmpPath($baseTmpPath)
    {
        $this->baseTmpPath = $baseTmpPath;
    }

    /**
     * @return string
     */
    public function getBasePath()
    {
        return $this->basePath;
    }

    /**
     * @param $basePath
     */
    public function setBasePath($basePath)
    {
        $this->basePath = $basePath;
    }

    /**
     * @param $path
     * @param $imageName
     * @return string
     */
    public function getFilePath($path, $imageName)
    {
        return rtrim($path, '/') . '/' . ltrim($imageName, '/');
    }

    /**
     * @param $fileId
     * @return mixed
     * @throws LocalizedException
     * @throws NoSuchEntityException
     */
    public function saveFileToTmpDir($fileId)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $uploader = $this->uploaderFactory->create(['fileId' => $fileId]);
        $uploader->setAllowedExtensions($this->getAllowedExtensions());
        $uploader->setAllowRenameFiles(true);
        $result = $uploader->save($this->mediaDirectory->getAbsolutePath($baseTmpPath));
        if (!$result) {
            throw new LocalizedException(
                __('File can not be saved to the destination folder.')
            );
        }

        $result['tmp_name'] = str_replace('\\', '/', $result['tmp_name']);
        $result['path'] = str_replace('\\', '/', $result['path']);
        $result['url'] = $this->storeManager
                ->getStore()
                ->getBaseUrl(
                    UrlInterface::URL_TYPE_MEDIA
                ) . $this->getFilePath($baseTmpPath, $result['file']);
        $result['name'] = $result['file'];
        if (isset($result['file'])) {
            try {
                $relativePath = rtrim($baseTmpPath, '/') . '/' . ltrim($result['file'], '/');
                $this->coreFileStorageDatabase->saveFile($relativePath);
            } catch (Exception $e) {
                $this->logger->critical($e);
                throw new LocalizedException(
                    __('Something went wrong while saving the file(s).')
                );
            }
        }
        return $result;
    }

    /**
     * @return string[]
     */
    public function getAllowedExtensions()
    {
        return $this->allowedExtensions;
    }

    /**
     * @param $allowedExtensions
     */
    public function setAllowedExtensions($allowedExtensions)
    {
        $this->allowedExtensions = $allowedExtensions;
    }

    public function saveMediaImage($imageName, $imagePath)
    {
        $baseTmpPath = $this->getBaseTmpPath();
        $basePath = $this->getBasePath();
        $baseImagePath = $this->getFilePath($basePath, $imageName);
        $mediaPath = substr($imagePath, 0, strpos($imagePath, "media"));
        $baseTmpImagePath = str_replace($mediaPath . "media/", "", $imagePath);
        if ($baseImagePath == $baseTmpImagePath) {
            return $imageName;
        }
        try {
            $this->mediaDirectory->copyFile(
                $baseTmpImagePath,
                $baseImagePath
            );
        } catch (Exception $e) {
            throw new LocalizedException(
                __('Something went wrong while saving the file(s).')
            );
        }
        return $imageName;
    }
}

6. Create di.xml

  Create di.xml at Vendor/Module/etc:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Vendor\Module\Model\ImageUploader">
        <arguments>
            <argument name="baseTmpPath" xsi:type="string">your_folder_name/temp</argument>
            <argument name="basePath" xsi:type="string">your_folder_name/temp</argument>
            <argument name="allowedExtensions" xsi:type="array">
                <item name="jpg" xsi:type="string">jpg</item>
                <item name="jpeg" xsi:type="string">jpeg</item>
                <item name="gif" xsi:type="string">gif</item>
                <item name="png" xsi:type="string">png</item>
            </argument>
        </arguments>
    </type>
</config>

7. Create image-preview.html

  Create image-privew.html at Vendor/Module/view/adminhtml/web/template/:
<div class="file-uploader-summary">
    <div class="file-uploader-preview">
        <a attr="href: $parent.getFilePreview($file)" target="_blank">
            <img
                class="preview-image"
                tabindex="0"
                event="load: $parent.onPreviewLoad.bind($parent)"
                attr="
                    src: $parent.getFilePreview($file),
                    alt: $file.name">
        </a>

        <div class="actions">
            <button
                type="button"
                class="action-remove"
                data-role="delete-button"
                attr="title: $t('Delete image')"
                click="$parent.removeFile.bind($parent, $file)">
                <span translate="'Delete image'"/>
            </button>
        </div>
    </div>

    <div class="file-uploader-filename" text="$file.name"/>
    <div class="file-uploader-meta">
        <text args="$file.previewWidth"/>x<text args="$file.previewHeight"/>
    </div>
</div>
Finally, ensure that the image path is being saved to the database properly in your model's save method. By following these steps, you can successfully add an image field to your Magento 2 Admin UI Component form with a preview feature.