mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
e6b877df27
# Conflicts: # control/Director.php # control/HTTP.php # core/startup/ParameterConfirmationToken.php # docs/en/00_Getting_Started/01_Installation/05_Common_Problems.md # docs/en/00_Getting_Started/04_Directory_Structure.md # docs/en/00_Getting_Started/05_Coding_Conventions.md # docs/en/01_Tutorials/01_Building_A_Basic_Site.md # docs/en/01_Tutorials/02_Extending_A_Basic_Site.md # docs/en/01_Tutorials/03_Forms.md # docs/en/01_Tutorials/04_Site_Search.md # docs/en/01_Tutorials/05_Dataobject_Relationship_Management.md # docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md # docs/en/02_Developer_Guides/13_i18n/index.md # docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md # docs/en/03_Upgrading/index.md # docs/en/changelogs/index.md # docs/en/howto/customize-cms-menu.md # docs/en/howto/navigation-menu.md # docs/en/index.md # docs/en/installation/index.md # docs/en/installation/windows-manual-iis-6.md # docs/en/misc/contributing/code.md # docs/en/misc/contributing/issues.md # docs/en/misc/module-release-process.md # docs/en/reference/dataobject.md # docs/en/reference/execution-pipeline.md # docs/en/reference/grid-field.md # docs/en/reference/modeladmin.md # docs/en/reference/rssfeed.md # docs/en/reference/templates.md # docs/en/topics/commandline.md # docs/en/topics/debugging.md # docs/en/topics/email.md # docs/en/topics/forms.md # docs/en/topics/index.md # docs/en/topics/module-development.md # docs/en/topics/modules.md # docs/en/topics/page-type-templates.md # docs/en/topics/page-types.md # docs/en/topics/search.md # docs/en/topics/testing/index.md # docs/en/topics/testing/testing-guide-troubleshooting.md # docs/en/topics/theme-development.md # docs/en/tutorials/1-building-a-basic-site.md # docs/en/tutorials/2-extending-a-basic-site.md # docs/en/tutorials/3-forms.md # docs/en/tutorials/4-site-search.md # docs/en/tutorials/5-dataobject-relationship-management.md # docs/en/tutorials/building-a-basic-site.md # docs/en/tutorials/dataobject-relationship-management.md # docs/en/tutorials/extending-a-basic-site.md # docs/en/tutorials/forms.md # docs/en/tutorials/index.md # docs/en/tutorials/site-search.md # main.php # model/SQLQuery.php # security/ChangePasswordForm.php # security/MemberLoginForm.php # tests/control/ControllerTest.php # tests/core/startup/ParameterConfirmationTokenTest.php # tests/model/SQLQueryTest.php # tests/security/SecurityTest.php # tests/view/SSViewerTest.php # view/SSTemplateParser.php # view/SSTemplateParser.php.inc # view/SSViewer.php
202 lines
4.8 KiB
PHP
202 lines
4.8 KiB
PHP
<?php
|
|
|
|
use SilverStripe\Filesystem\Storage\AssetContainer;
|
|
use SilverStripe\Filesystem\Storage\AssetStore;
|
|
|
|
/**
|
|
* @package framework
|
|
* @subpackage filesystem
|
|
*/
|
|
|
|
if(!class_exists('Imagick')) {
|
|
return;
|
|
}
|
|
|
|
class ImagickBackend extends Imagick implements Image_Backend {
|
|
|
|
/**
|
|
* @config
|
|
* @var int
|
|
*/
|
|
private static $default_quality = 75;
|
|
|
|
/**
|
|
* Create a new backend with the given object
|
|
*
|
|
* @param AssetContainer $assetContainer Object to load from
|
|
*/
|
|
public function __construct(AssetContainer $assetContainer = null) {
|
|
parent::__construct();
|
|
|
|
if($assetContainer) {
|
|
$this->loadFromContainer($assetContainer);
|
|
}
|
|
}
|
|
|
|
public function loadFromContainer(AssetContainer $assetContainer) {
|
|
$stream = $assetContainer->getStream();
|
|
$this->readimagefile($stream);
|
|
fclose($stream);
|
|
$this->setDefaultQuality();
|
|
}
|
|
|
|
public function loadFrom($path) {
|
|
$this->readimage($path);
|
|
$this->setDefaultQuality();
|
|
}
|
|
|
|
protected function setDefaultQuality() {
|
|
$this->setQuality(Config::inst()->get('ImagickBackend', 'default_quality'));
|
|
}
|
|
|
|
public function writeToStore(AssetStore $assetStore, $filename, $hash = null, $variant = null, $config = array()) {
|
|
// Write to temporary file, taking care to maintain the extension
|
|
$path = tempnam(sys_get_temp_dir(), 'imagemagick');
|
|
if($extension = pathinfo($filename, PATHINFO_EXTENSION)) {
|
|
$path .= "." . $extension;
|
|
}
|
|
$this->writeimage($path);
|
|
$result = $assetStore->setFromLocalFile($path, $filename, $hash, $variant, $config);
|
|
unlink($path);
|
|
return $result;
|
|
}
|
|
|
|
public function writeTo($path) {
|
|
Filesystem::makeFolder(dirname($path));
|
|
if(is_dir(dirname($path))) {
|
|
$this->writeImage($path);
|
|
}
|
|
}
|
|
|
|
public function setQuality($quality) {
|
|
$this->setImageCompressionQuality($quality);
|
|
}
|
|
|
|
public function resize($width, $height) {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
if($width < 0 || $height < 0) {
|
|
throw new InvalidArgumentException("Image resizing dimensions cannot be negative");
|
|
}
|
|
if(!$width && !$height) {
|
|
throw new InvalidArgumentException("No dimensions given when resizing image");
|
|
}
|
|
if(!$width) {
|
|
throw new InvalidArgumentException("Width not given when resizing image");
|
|
}
|
|
if(!$height) {
|
|
throw new InvalidArgumentException("Height not given when resizing image");
|
|
}
|
|
|
|
//use whole numbers, ensuring that size is at least 1x1
|
|
$width = max(1, round($width));
|
|
$height = max(1, round($height));
|
|
|
|
$geometry = $this->getImageGeometry();
|
|
|
|
// Check that a resize is actually necessary.
|
|
if ($width === $geometry["width"] && $height === $geometry["height"]) {
|
|
return $this;
|
|
}
|
|
|
|
$new = clone $this;
|
|
$new->resizeImage($width, $height, self::FILTER_LANCZOS, 1);
|
|
|
|
return $new;
|
|
}
|
|
|
|
public function resizeRatio($maxWidth, $maxHeight, $useAsMinimum = false) {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
$geometry = $this->getImageGeometry();
|
|
|
|
$widthRatio = $maxWidth / $geometry["width"];
|
|
$heightRatio = $maxHeight / $geometry["height"];
|
|
|
|
if( $widthRatio < $heightRatio ) {
|
|
return $useAsMinimum
|
|
? $this->resizeByHeight( $maxHeight )
|
|
: $this->resizeByWidth( $maxWidth );
|
|
} else {
|
|
return $useAsMinimum
|
|
? $this->resizeByWidth( $maxWidth )
|
|
: $this->resizeByHeight( $maxHeight );
|
|
}
|
|
}
|
|
|
|
public function resizeByWidth($width) {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
$geometry = $this->getImageGeometry();
|
|
|
|
$heightScale = $width / $geometry["width"];
|
|
return $this->resize( $width, $heightScale * $geometry["height"] );
|
|
}
|
|
|
|
public function resizeByHeight($height) {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
$geometry = $this->getImageGeometry();
|
|
|
|
$scale = $height / $geometry["height"];
|
|
return $this->resize( $scale * $geometry["width"], $height );
|
|
}
|
|
|
|
public function paddedResize($width, $height, $backgroundColor = "FFFFFF") {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
$new = $this->resizeRatio($width, $height);
|
|
$new->setImageBackgroundColor("#".$backgroundColor);
|
|
$w = $new->getImageWidth();
|
|
$h = $new->getImageHeight();
|
|
$new->extentImage($width,$height,($w-$width)/2,($h-$height)/2);
|
|
return $new;
|
|
}
|
|
|
|
public function croppedResize($width, $height) {
|
|
if(!$this->valid()) {
|
|
return null;
|
|
}
|
|
|
|
$width = round($width);
|
|
$height = round($height);
|
|
$geo = $this->getImageGeometry();
|
|
|
|
// Check that a resize is actually necessary.
|
|
if ($width == $geo["width"] && $height == $geo["height"]) {
|
|
return $this;
|
|
}
|
|
|
|
$new = clone $this;
|
|
$new->setBackgroundColor(new ImagickPixel('transparent'));
|
|
|
|
if(($geo['width']/$width) < ($geo['height']/$height)){
|
|
$new->cropImage(
|
|
$geo['width'],
|
|
floor($height*$geo['width']/$width),
|
|
0,
|
|
($geo['height'] - ($height*$geo['width']/$width))/2
|
|
);
|
|
}else{
|
|
$new->cropImage(
|
|
ceil($width*$geo['height']/$height),
|
|
$geo['height'],
|
|
($geo['width'] - ($width*$geo['height']/$height))/2,
|
|
0
|
|
);
|
|
}
|
|
$new->ThumbnailImage($width,$height,true);
|
|
return $new;
|
|
}
|
|
}
|