setQuality(Config::inst()->get('ImagickBackend','default_quality')); } /** * writeTo * * @param string $path * @return void */ public function writeTo($path) { Filesystem::makeFolder(dirname($path)); if(is_dir(dirname($path))) self::writeImage($path); } /** * set_default_quality * * @deprecated 4.0 Use the "ImagickBackend.default_quality" config setting instead * @param int $quality * @return void */ public static function set_default_quality($quality) { Deprecation::notice('4.0', 'Use the "ImagickBackend.default_quality" config setting instead'); if(is_numeric($quality) && (int) $quality >= 0 && (int) $quality <= 100) { Config::inst()->update('ImagickBackend', 'default_quality', (int) $quality); } } /** * setQuality * * @param int $quality * @return void */ public function setQuality($quality) { self::setImageCompressionQuality($quality); } /** * setImageResource * * Set the backend-specific resource handling the manipulations. Replaces Image::setGD() * * @param mixed $resource * @return void */ public function setImageResource($resource) { trigger_error("Imagick::setImageResource is not supported", E_USER_ERROR); } /** * getImageResource * * Get the backend-specific resource handling the manipulations. Replaces Image::getGD() * * @return mixed */ public function getImageResource() { return $this; } /** * hasImageResource * * @return boolean */ public function hasImageResource() { return true; // $this is the resource, necessarily } /** * @todo Implement memory checking for Imagick? See {@link GD} * * @param string $filename * @param string $manipulation * @return boolean */ public function imageAvailable($filename, $manipulation) { return true; } /** * resize * * @param int $width * @param int $height * @return Image_Backend */ public function resize($width, $height) { if(!$this->valid()) return; 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; } /** * resizeRatio * * @param int $width * @param int $height * @return Image_Backend */ public function resizeRatio($maxWidth, $maxHeight, $useAsMinimum = false) { if(!$this->valid()) return; $maxWidth = intval($maxWidth); $maxHeight = intval($maxHeight); $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 ); } /** * resizeByWidth * * @param int $width * @return Image_Backend */ public function resizeByWidth($width) { if(!$this->valid()) return; $width = intval($width); $geometry = $this->getImageGeometry(); $heightScale = $width / $geometry["width"]; return $this->resize( $width, $heightScale * $geometry["height"] ); } /** * resizeByHeight * * @param int $height * @return Image_Backend */ public function resizeByHeight($height) { if(!$this->valid()) return; $height = intval($height); $geometry = $this->getImageGeometry(); $scale = $height / $geometry["height"]; return $this->resize( $scale * $geometry["width"], $height ); } /** * paddedResize * * @param int $width * @param int $height * @param int $transparencyPercent * @return Image_Backend */ public function paddedResize($width, $height, $backgroundColor = "FFFFFF", $transparencyPercent = 0) { $width = intval($width); $height = intval($height); //keep the % within bounds of 0-100 $transparencyPercent = min(100, max(0, $transparencyPercent)); $new = $this->resizeRatio($width, $height); if($transparencyPercent) { $alphaHex = $this->calculateAlphaHex($transparencyPercent); $new->setImageBackgroundColor("#{$backgroundColor}{$alphaHex}"); } else { $new->setImageBackgroundColor("#{$backgroundColor}"); } $w = $new->getImageWidth(); $h = $new->getImageHeight(); $new->extentImage($width,$height,($w-$width)/2,($h-$height)/2); return $new; } /** * Convert a percentage (or 'true') to a two char hex code to signifiy the level of an alpha channel * * @param $percent * @return string */ public function calculateAlphaHex($percent) { if($percent > 100) { $percent = 100; } // unlike GD, this uses 255 instead of 127, and is reversed. Lower = more transparent $alphaHex = dechex(255 - floor(255 * bcdiv($percent, 100, 2))); if(strlen($alphaHex) == 1) { $alphaHex = '0' .$alphaHex; } return $alphaHex; } /** * croppedResize * * @param int $width * @param int $height * @return Image_Backend */ public function croppedResize($width, $height) { if(!$this->valid()) return; $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; } /** * Crop's part of image. * @param int $top y position of left upper corner of crop rectangle * @param int $left x position of left upper corner of crop rectangle * @param int $width rectangle width * @param int $height rectangle height * @return Image_Backend */ public function crop($top, $left, $width, $height) { $top = intval($top); $left = intval($left); $width = intval($width); $height = intval($height); $new = clone $this; $new->cropImage($width, $height, $left, $top); return $new; } /** * @param Image $frontend * @return void */ public function onBeforeDelete($frontend) { // Not in use } } }