diff --git a/typo3/sysext/core/Classes/Resource/ProcessedFile.php b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
index 10f4ed9cf46de5b8c4ff0060f7480bdb8f36d5a9..0412dd4b1c62e4f19d5a4d53b8d488fcbfd085ee 100644
--- a/typo3/sysext/core/Classes/Resource/ProcessedFile.php
+++ b/typo3/sysext/core/Classes/Resource/ProcessedFile.php
@@ -184,7 +184,7 @@ class ProcessedFile extends AbstractFile
         if ($this->identifier === null) {
             throw new \RuntimeException('Cannot update original file!', 1350582054);
         }
-        $processingFolder = $this->originalFile->getStorage()->getProcessingFolder();
+        $processingFolder = $this->originalFile->getStorage()->getProcessingFolder($this->originalFile);
         $addedFile = $this->storage->updateProcessedFile($filePath, $this, $processingFolder);
 
         // Update some related properties
@@ -256,7 +256,7 @@ class ProcessedFile extends AbstractFile
 
         $this->name = $name;
         // @todo this is a *weird* hack that will fail if the storage is non-hierarchical!
-        $this->identifier = $this->storage->getProcessingFolder()->getIdentifier() . $this->name;
+        $this->identifier = $this->storage->getProcessingFolder($this->originalFile)->getIdentifier() . $this->name;
 
         $this->updated = true;
     }
diff --git a/typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php b/typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php
index 10c559bfad3e76a00986ae6df9c0c4f52f159335..b6b222ed2575a6ec9ee36500be1b150f8d761071 100644
--- a/typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php
+++ b/typo3/sysext/core/Classes/Resource/Processing/LocalImageProcessor.php
@@ -108,7 +108,7 @@ class LocalImageProcessor implements ProcessorInterface
     {
         // the storage of the processed file, not of the original file!
         $storage = $task->getTargetFile()->getStorage();
-        $processingFolder = $storage->getProcessingFolder();
+        $processingFolder = $storage->getProcessingFolder($task->getSourceFile());
 
         // explicitly check for the raw filename here, as we check for files that existed before we even started
         // processing, i.e. that were processed earlier
diff --git a/typo3/sysext/core/Classes/Resource/ResourceStorage.php b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
index bf210e77f9874c531c1e4786459e528ef40aabe8..b8bb97357ddcbd8848b845ec2666070e4eefcacb 100644
--- a/typo3/sysext/core/Classes/Resource/ResourceStorage.php
+++ b/typo3/sysext/core/Classes/Resource/ResourceStorage.php
@@ -154,6 +154,11 @@ class ResourceStorage implements ResourceStorageInterface
      */
     protected $fileAndFolderNameFilters = array();
 
+    /**
+     * Levels numbers used to generate hashed subfolders in the processing folder
+     */
+    const PROCESSING_FOLDER_LEVELS = 2;
+
     /**
      * Constructor for a storage object.
      *
@@ -1204,10 +1209,9 @@ class ResourceStorage implements ResourceStorageInterface
             throw new \InvalidArgumentException('File "' . $localFilePath . '" does not exist.', 1319552746);
         }
         if ($processingFolder === null) {
-            $processingFolder = $this->getProcessingFolder();
+            $processingFolder = $this->getProcessingFolder($processedFile->getOriginalFile());
         }
         $fileIdentifier = $this->driver->addFile($localFilePath, $processingFolder->getIdentifier(), $processedFile->getName());
-
         // @todo check if we have to update the processed file other then the identifier
         $processedFile->setIdentifier($fileIdentifier);
         return $processedFile;
@@ -2856,9 +2860,10 @@ class ResourceStorage implements ResourceStorageInterface
      * Getter function to return the folder where the files can
      * be processed. Does not check for access rights here.
      *
+     * @param File $file Specific file you want to have the processing folder for
      * @return Folder
      */
-    public function getProcessingFolder()
+    public function getProcessingFolder(File $file = null)
     {
         if (!isset($this->processingFolder)) {
             $processingFolder = self::DEFAULT_ProcessingFolder;
@@ -2892,7 +2897,62 @@ class ResourceStorage implements ResourceStorageInterface
                 );
             }
         }
-        return $this->processingFolder;
+
+        $processingFolder = $this->processingFolder;
+        if (!empty($file)) {
+            $processingFolder = $this->getNestedProcessingFolder($file, $processingFolder);
+        }
+        return $processingFolder;
+    }
+
+    /**
+     * Getter function to return the the file's corresponding hashed subfolder
+     * of the processed folder
+     *
+     * @param File $file
+     * @param Folder $rootProcessingFolder
+     * @return Folder
+     * @throws Exception\InsufficientFolderWritePermissionsException
+     */
+    protected function getNestedProcessingFolder(File $file, Folder $rootProcessingFolder)
+    {
+        $processingFolder = $rootProcessingFolder;
+        $nestedFolderNames = $this->getNamesForNestedProcessingFolder(
+            $file->getIdentifier(),
+            self::PROCESSING_FOLDER_LEVELS
+        );
+
+        try {
+            foreach ($nestedFolderNames as $folderName) {
+                if ($processingFolder->hasFolder($folderName)) {
+                    $processingFolder = $processingFolder->getSubfolder($folderName);
+                } else {
+                    $processingFolder = $processingFolder->createFolder($folderName);
+                }
+            }
+        } catch (Exception\FolderDoesNotExistException $e) {}
+
+        return $processingFolder;
+    }
+
+    /**
+     * Generates appropriate hashed sub-folder path for a given file identifier
+     *
+     * @param string $fileIdentifier
+     * @param int $levels
+     * @return []
+     */
+    protected function getNamesForNestedProcessingFolder($fileIdentifier, $levels)
+    {
+        $names = [];
+        if ($levels === 0) {
+            return $names;
+        }
+        $hash = md5($fileIdentifier);
+        for ($i = 1; $i <= $levels; $i++) {
+            $names[] = substr($hash, $i, 1);
+        }
+        return $names;
     }
 
     /**
diff --git a/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php b/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
index 33574730684764f7cf52bb04a0f088a58207ca1f..c8bdeac0f6056d688bead58b6bae04aa7c00be18 100644
--- a/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
+++ b/typo3/sysext/core/Tests/Unit/Resource/ResourceStorageTest.php
@@ -752,4 +752,36 @@ class ResourceStorageTest extends BaseTestCase
 
         $this->assertSame(FolderInterface::ROLE_DEFAULT, $role);
     }
+
+    /**
+     * @test
+     */
+    public function getProcessingRootFolderTest()
+    {
+        $this->prepareSubject(array());
+        $processingFolder = $this->subject->getProcessingFolder();
+
+        $this->assertInstanceOf(Folder::class, $processingFolder);
+    }
+
+    /**
+     * @test
+     */
+    public function getNestedProcessingFolderTest()
+    {
+        $mockedDriver = $this->createDriverMock(array('basePath' => $this->getMountRootUrl()), null, null);
+        $this->prepareSubject(array(), true, $mockedDriver);
+        $mockedFile = $this->getSimpleFileMock('/someFile');
+
+        $rootProcessingFolder = $this->subject->getProcessingFolder();
+        $processingFolder = $this->subject->getProcessingFolder($mockedFile);
+
+        $this->assertInstanceOf(Folder::class, $processingFolder);
+        $this->assertNotEquals($rootProcessingFolder, $processingFolder);
+
+        for ($i = ResourceStorage::PROCESSING_FOLDER_LEVELS; $i>0; $i--) {
+            $processingFolder = $processingFolder->getParentFolder();
+        }
+        $this->assertEquals($rootProcessingFolder, $processingFolder);
+    }
 }