forked from silverstripe/silverstripe-assets
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0cee400
commit 4644826
Showing
2 changed files
with
187 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace SilverStripe\Assets\Conversion; | ||
|
||
use SilverStripe\Assets\Storage\DBFile; | ||
|
||
interface FileConverter | ||
{ | ||
/** | ||
* Checks whether this converter supports a conversion from one file type to another. | ||
* | ||
* @param DBFile|string $from A DBFile instance or specific file extension | ||
* @param array $options Any options defined for this converter which should apply to the conversion | ||
*/ | ||
public function supportsConversion(DBFile|string $from, string $toExtension, array $options = []): bool; | ||
|
||
/** | ||
* Converts the given DBFile instance to another file type. | ||
* | ||
* @param array $options Any options defined for this converter which should apply to the conversion | ||
*/ | ||
public function convert(DBFile $original, string $toExtension, array $options = []): DBFile; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
<?php | ||
|
||
namespace SilverStripe\Assets\Conversion; | ||
|
||
use SilverStripe\Assets\Image_Backend; | ||
use SilverStripe\Assets\InterventionBackend; | ||
use SilverStripe\Assets\Storage\AssetStore; | ||
use SilverStripe\Assets\Storage\DBFile; | ||
use SilverStripe\Core\Injector\Injector; | ||
|
||
/** | ||
* Image converter powered by the Intervention Image library, assuming you haven't swapped out the ImageBackend implementation. | ||
*/ | ||
class InterventionImageConverter implements FileConverter | ||
{ | ||
public function supportsConversion(DBFile|string $from, string $toExtension, array $options = []): bool | ||
{ | ||
// If backend is not InterventionBackend, return false | ||
// GD and Imagick support different things so be dynamic between those | ||
if ($from instanceof DBFile) { | ||
$backend = $from->getImageBackend(); | ||
$from = $from->getExtension() ?: $from->getMimeType(); | ||
} else { | ||
$backend = Injector::inst()->get(Image_Backend::class); | ||
} | ||
// This converter requires intervention image | ||
if (!is_a($backend, InterventionBackend::class)) { | ||
return false; | ||
} | ||
/** @var InterventionBackend $backend */ | ||
$driver = $backend->getImageManager()->config['driver'] ?? null; | ||
return $this->supportedByIntervention($from, $toExtension, $driver); | ||
} | ||
|
||
public function convert(DBFile $original, string $toExtension, array $options = []): DBFile | ||
{ | ||
// TODO allow swapping quality | ||
// TODO find any other options intervention supports | ||
return $original->manipulateExtension( | ||
$toExtension, | ||
function (AssetStore $store, string $filename, string $hash, string $variant) use ($original) { | ||
$backend = $original->getImageBackend(); | ||
$config = ['conflict' => AssetStore::CONFLICT_USE_EXISTING]; | ||
$tuple = $backend->writeToStore($store, $filename, $hash, $variant, $config); | ||
return [$tuple, $backend]; | ||
} | ||
); | ||
} | ||
|
||
private function supportedByIntervention(string $from, string $to, string $driver): bool | ||
{ | ||
// If the driver is somehow not GD or Imagick, we have no way to know what it might support | ||
if ($driver !== 'gd' && $driver !== 'imagick') { | ||
return false; | ||
} | ||
|
||
foreach ([$from, $to] as $format) { | ||
// This follows the logic in intervention's AbstractEncoder::process() method | ||
// and the various methods in the Encoder classes for GD and Imagick | ||
switch (strtolower($format)) { | ||
case 'gif': | ||
case 'image/gif': | ||
// always supported | ||
break; | ||
case 'png': | ||
case 'image/png': | ||
case 'image/x-png': | ||
// always supported | ||
break; | ||
case 'jpg': | ||
case 'jpeg': | ||
case 'jfif': | ||
case 'image/jp2': | ||
case 'image/jpg': | ||
case 'image/jpeg': | ||
case 'image/pjpeg': | ||
case 'image/jfif': | ||
// always supported | ||
break; | ||
case 'tif': | ||
case 'tiff': | ||
case 'image/tiff': | ||
case 'image/tif': | ||
case 'image/x-tif': | ||
case 'image/x-tiff': | ||
if ($driver === 'gd') { | ||
false; | ||
} | ||
// always supported by imagick | ||
break; | ||
case 'bmp': | ||
case 'ms-bmp': | ||
case 'x-bitmap': | ||
case 'x-bmp': | ||
case 'x-ms-bmp': | ||
case 'x-win-bitmap': | ||
case 'x-windows-bmp': | ||
case 'x-xbitmap': | ||
case 'image/ms-bmp': | ||
case 'image/x-bitmap': | ||
case 'image/x-bmp': | ||
case 'image/x-ms-bmp': | ||
case 'image/x-win-bitmap': | ||
case 'image/x-windows-bmp': | ||
case 'image/x-xbitmap': | ||
if ($driver === 'gd' && !function_exists('imagebmp')) { | ||
return false; | ||
} | ||
// always supported by imagick | ||
break; | ||
case 'ico': | ||
case 'image/x-ico': | ||
case 'image/x-icon': | ||
case 'image/vnd.microsoft.icon': | ||
if ($driver === 'gd') { | ||
return false; | ||
} | ||
// always supported by imagick | ||
break; | ||
case 'psd': | ||
case 'image/vnd.adobe.photoshop': | ||
if ($driver === 'gd') { | ||
return false; | ||
} | ||
// always supported by imagick | ||
break; | ||
case 'webp': | ||
case 'image/webp': | ||
case 'image/x-webp': | ||
if ($driver === 'gd' && !function_exists('imagewebp')) { | ||
return false; | ||
} | ||
if ($driver === 'imagick' && !\Imagick::queryFormats('WEBP')) { | ||
return false; | ||
} | ||
break; | ||
case 'avif': | ||
case 'image/avif': | ||
if ($driver === 'gd' && !function_exists('imageavif')) { | ||
return false; | ||
} | ||
if ($driver === 'imagick' && !\Imagick::queryFormats('AVIF')) { | ||
return false; | ||
} | ||
break; | ||
case 'heic': | ||
case 'image/heic': | ||
case 'image/heif': | ||
if ($driver === 'gd') { | ||
return false; | ||
} | ||
if ($driver === 'imagick' && !\Imagick::queryFormats('HEIC')) { | ||
return false; | ||
} | ||
break; | ||
default: | ||
// Anything else is not supported | ||
return false; | ||
} | ||
} | ||
// If we get here both formats are in the explicit list above and are supported | ||
return true; | ||
} | ||
} |