diff --git a/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php b/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php
index a2eed617adafae47a0233f711a4079ee5c318f34..1f32964d5a9462f635318077313bbf96be9d27f9 100644
--- a/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php
+++ b/typo3/sysext/core/Classes/Imaging/GraphicalFunctions.php
@@ -406,6 +406,54 @@ class GraphicalFunctions
         return null;
     }
 
+    /**
+     * @internal until API is finalized
+     */
+    public function crop(string $imageFile, string $targetFileExtension, string $cropInformation): ?array
+    {
+        // check if it is a json object
+        $cropData = json_decode($cropInformation);
+        if ($cropData) {
+            $offsetLeft = (int)($cropData->x ?? 0);
+            $offsetTop = (int)($cropData->y ?? 0);
+            $newWidth = (int)($cropData->width ?? 0);
+            $newHeight = (int)($cropData->height ?? 0);
+        } else {
+            [$offsetLeft, $offsetTop, $newWidth, $newHeight] = explode(',', $cropInformation, 4);
+        }
+
+        return $this->imageMagickConvert(
+            $imageFile,
+            $targetFileExtension,
+            '',
+            '',
+            sprintf('-crop %dx%d+%d+%d +repage -quality %d', $newWidth, $newHeight, $offsetLeft, $offsetTop, $this->jpegQuality),
+            '',
+            ['noScale' => true],
+            true
+        );
+    }
+
+    /**
+     * This applies an image onto the $inputFile with an additional backgroundImage for the mask
+     * @internal until API is finalized
+     */
+    public function mask(string $inputFile, string $outputFile, string $maskImage, string $maskBackgroundImage, string $params)
+    {
+        $tmpStr = $this->randomName();
+        //	m_mask
+        $intermediateMaskFile = $tmpStr . '_mask.png';
+        $this->imageMagickExec($maskImage, $intermediateMaskFile, $params);
+        //	m_bgImg
+        $intermediateMaskBackgroundFile = $tmpStr . '_bgImg.miff';
+        $this->imageMagickExec($maskBackgroundImage, $intermediateMaskBackgroundFile, $params);
+        // The image onto the background
+        $this->combineExec($intermediateMaskBackgroundFile, $inputFile, $intermediateMaskFile, $outputFile);
+        // Unlink the temp-images...
+        @unlink($intermediateMaskFile);
+        @unlink($intermediateMaskBackgroundFile);
+    }
+
     /**
      * Gets the input image dimensions.
      *
diff --git a/typo3/sysext/core/Classes/Resource/Processing/LocalCropScaleMaskHelper.php b/typo3/sysext/core/Classes/Resource/Processing/LocalCropScaleMaskHelper.php
index 43c5dda78d958201763c5ef8d59349575978eded..2d2c4aeb825beb172a420de5728b8db14a508cdf 100644
--- a/typo3/sysext/core/Classes/Resource/Processing/LocalCropScaleMaskHelper.php
+++ b/typo3/sysext/core/Classes/Resource/Processing/LocalCropScaleMaskHelper.php
@@ -20,7 +20,6 @@ use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\Resource\FileInterface;
 use TYPO3\CMS\Core\Resource\ProcessedFile;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
  * Helper class to locally perform a crop/scale/mask task with the TYPO3 image processing classes.
@@ -69,39 +68,12 @@ class LocalCropScaleMaskHelper
             $configuration['fileExtension'] = $task->getTargetFileExtension();
         }
 
-        $options = $this->getConfigurationForImageCropScaleMask($targetFile, $imageOperations);
+        $options = $this->getConfigurationForImageCropScaleMask($targetFile);
 
         $croppedImage = null;
         if (!empty($configuration['crop'])) {
-            // check if it is a json object
-            $cropData = json_decode($configuration['crop']);
-            if ($cropData) {
-                $offsetLeft = (int)($cropData->x ?? 0);
-                $offsetTop = (int)($cropData->y ?? 0);
-                $newWidth = (int)($cropData->width ?? 0);
-                $newHeight = (int)($cropData->height ?? 0);
-            } else {
-                [$offsetLeft, $offsetTop, $newWidth, $newHeight] = explode(',', $configuration['crop'], 4);
-            }
-
-            $backupPrefix = $imageOperations->filenamePrefix;
-            $imageOperations->filenamePrefix = 'crop_';
-
-            $jpegQuality = MathUtility::forceIntegerInRange($GLOBALS['TYPO3_CONF_VARS']['GFX']['jpg_quality'], 10, 100, 85);
-
             // the result info is an array with 0=width,1=height,2=extension,3=filename
-            $result = $imageOperations->imageMagickConvert(
-                $originalFileName,
-                $configuration['fileExtension'],
-                '',
-                '',
-                sprintf('-crop %dx%d+%d+%d +repage -quality %d', $newWidth, $newHeight, $offsetLeft, $offsetTop, $jpegQuality),
-                '',
-                ['noScale' => true],
-                true
-            );
-            $imageOperations->filenamePrefix = $backupPrefix;
-
+            $result = $imageOperations->crop($originalFileName, $configuration['fileExtension'], $configuration['crop']);
             if ($result !== null) {
                 $originalFileName = $croppedImage = $result[3];
             }
@@ -118,8 +90,8 @@ class LocalCropScaleMaskHelper
                 $configuration['additionalParameters'],
                 $configuration['frame'] ?? '',
                 $options,
-                // in case file is in `/typo3temp/`, it must create a result
-                $this->isTemporaryFile($originalFileName)
+                // in case file is in `/typo3temp/` from the crop operation above, it must create a result
+                $result !== null
             );
         } else {
             $targetFileName = $this->getFilenameForImageCropScaleMask($task);
@@ -127,10 +99,10 @@ class LocalCropScaleMaskHelper
             $maskImage = $configuration['maskImages']['maskImage'] ?? null;
             $maskBackgroundImage = $configuration['maskImages']['backgroundImage'];
             if ($maskImage instanceof FileInterface && $maskBackgroundImage instanceof FileInterface) {
-                $temporaryExtension = 'png';
+                // This converts the original image to a temporary PNG file during all steps of the masking process
                 $tempFileInfo = $imageOperations->imageMagickConvert(
                     $originalFileName,
-                    $temporaryExtension,
+                    'png',
                     $configuration['width'] ?? '',
                     $configuration['height'] ?? '',
                     $configuration['additionalParameters'],
@@ -138,43 +110,30 @@ class LocalCropScaleMaskHelper
                     $options
                 );
                 if (is_array($tempFileInfo)) {
-                    $maskBottomImage = $configuration['maskImages']['maskBottomImage'];
-                    if ($maskBottomImage instanceof FileInterface) {
-                        $maskBottomImageMask = $configuration['maskImages']['maskBottomImageMask'];
-                    } else {
-                        $maskBottomImageMask = null;
-                    }
-
-                    //	Scaling:	****
-                    $tempScale = [];
+                    // Scaling
                     $command = '-geometry ' . $tempFileInfo[0] . 'x' . $tempFileInfo[1] . '!';
                     $command = $this->modifyImageMagickStripProfileParameters($command, $configuration);
-                    $tmpStr = $imageOperations->randomName();
-                    //	m_mask
-                    $tempScale['m_mask'] = $tmpStr . '_mask.' . $temporaryExtension;
-                    $imageOperations->imageMagickExec($maskImage->getForLocalProcessing(true), $tempScale['m_mask'], $command);
-                    //	m_bgImg
-                    $tempScale['m_bgImg'] = $tmpStr . '_bgImg.miff';
-                    $imageOperations->imageMagickExec($maskBackgroundImage->getForLocalProcessing(), $tempScale['m_bgImg'], $command);
-                    //	m_bottomImg / m_bottomImg_mask
+
+                    $imageOperations->mask(
+                        $tempFileInfo[3],
+                        $temporaryFileName,
+                        $maskImage->getForLocalProcessing(),
+                        $maskBackgroundImage->getForLocalProcessing(),
+                        $command
+                    );
+                    $maskBottomImage = $configuration['maskImages']['maskBottomImage'] ?? null;
+                    $maskBottomImageMask = $configuration['maskImages']['maskBottomImageMask'] ?? null;
                     if ($maskBottomImage instanceof FileInterface && $maskBottomImageMask instanceof FileInterface) {
-                        $tempScale['m_bottomImg'] = $tmpStr . '_bottomImg.' . $temporaryExtension;
-                        $imageOperations->imageMagickExec($maskBottomImage->getForLocalProcessing(), $tempScale['m_bottomImg'], $command);
-                        $tempScale['m_bottomImg_mask'] = ($tmpStr . '_bottomImg_mask.') . $temporaryExtension;
-                        $imageOperations->imageMagickExec($maskBottomImageMask->getForLocalProcessing(), $tempScale['m_bottomImg_mask'], $command);
-                        // BEGIN combining:
-                        // The image onto the background
-                        $imageOperations->combineExec($tempScale['m_bgImg'], $tempScale['m_bottomImg'], $tempScale['m_bottomImg_mask'], $tempScale['m_bgImg']);
+                        // Uses the temporary PNG file from the previous step and applies another mask
+                        $imageOperations->mask(
+                            $temporaryFileName,
+                            $temporaryFileName,
+                            $maskBottomImage->getForLocalProcessing(),
+                            $maskBottomImageMask->getForLocalProcessing(),
+                            $command
+                        );
                     }
-                    // The image onto the background
-                    $imageOperations->combineExec($tempScale['m_bgImg'], $tempFileInfo[3], $tempScale['m_mask'], $temporaryFileName);
                     $tempFileInfo[3] = $temporaryFileName;
-                    // Unlink the temp-images...
-                    foreach ($tempScale as $tempFile) {
-                        if (@is_file($tempFile)) {
-                            unlink($tempFile);
-                        }
-                    }
                 }
                 $result = $tempFileInfo;
             }
@@ -202,10 +161,7 @@ class LocalCropScaleMaskHelper
         return $result;
     }
 
-    /**
-     * @return array
-     */
-    protected function getConfigurationForImageCropScaleMask(ProcessedFile $processedFile, GraphicalFunctions $imageOperations)
+    protected function getConfigurationForImageCropScaleMask(ProcessedFile $processedFile): array
     {
         $configuration = $processedFile->getProcessingConfiguration();
 
@@ -239,14 +195,7 @@ class LocalCropScaleMaskHelper
     protected function getFilenameForImageCropScaleMask(TaskInterface $task)
     {
         $configuration = $task->getTargetFile()->getProcessingConfiguration();
-        $targetFileExtension = $task->getSourceFile()->getExtension();
-        $processedFileExtension = $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] ? 'png' : 'gif';
-        if (is_array($configuration['maskImages']) && $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled'] && $task->getSourceFile()->getExtension() != $processedFileExtension) {
-            $targetFileExtension = 'jpg';
-        } elseif ($configuration['fileExtension']) {
-            $targetFileExtension = $configuration['fileExtension'];
-        }
-
+        $targetFileExtension = $configuration['fileExtension'] ?? $task->getSourceFile()->getExtension();
         return $task->getTargetFile()->generateProcessedFileNameWithoutExtension() . '.' . ltrim(trim($targetFileExtension), '.');
     }
 
@@ -272,9 +221,4 @@ class LocalCropScaleMaskHelper
         }
         return $parameters;
     }
-
-    protected function isTemporaryFile(string $filePath): bool
-    {
-        return str_starts_with($filePath, Environment::getPublicPath() . '/typo3temp/');
-    }
 }
diff --git a/typo3/sysext/core/Classes/Resource/Processing/LocalPreviewHelper.php b/typo3/sysext/core/Classes/Resource/Processing/LocalPreviewHelper.php
index 8b12df30c94f82bd59453159bbea13f0fd607b97..fdb8c9a48a407e7fc50fece231a1fa9030c439b6 100644
--- a/typo3/sysext/core/Classes/Resource/Processing/LocalPreviewHelper.php
+++ b/typo3/sysext/core/Classes/Resource/Processing/LocalPreviewHelper.php
@@ -15,9 +15,8 @@
 
 namespace TYPO3\CMS\Core\Resource\Processing;
 
-use TYPO3\CMS\Core\Imaging\ImageMagickFile;
+use TYPO3\CMS\Core\Imaging\GraphicalFunctions;
 use TYPO3\CMS\Core\Resource\File;
-use TYPO3\CMS\Core\Utility\CommandUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Frontend\Imaging\GifBuilder;
@@ -148,17 +147,11 @@ class LocalPreviewHelper
     {
         // Create the temporary file
         if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_enabled']) {
-            $arguments = CommandUtility::escapeShellArguments([
-                'width' => $configuration['width'],
-                'height' => $configuration['height'],
-            ]);
-            $parameters = '-sample ' . $arguments['width'] . 'x' . $arguments['height']
-                . ' ' . ImageMagickFile::fromFilePath($originalFileName, 0)
-                . ' ' . CommandUtility::escapeShellArgument($targetFilePath);
-
-            $cmd = CommandUtility::imageMagickCommand('convert', $parameters) . ' 2>&1';
-            CommandUtility::exec($cmd);
-
+            $imageService = GeneralUtility::makeInstance(GraphicalFunctions::class);
+            $result = $imageService->imageMagickConvert($originalFileName, 'WEB', $configuration['width'], $configuration['height'], '', '0', ['sample' => true]);
+            if ($result) {
+                $targetFilePath = $result[3];
+            }
             if (!file_exists($targetFilePath)) {
                 // Create an error gif
                 $graphicalFunctions = GeneralUtility::makeInstance(GifBuilder::class);