return imagerotate($this->image, (360.0 - $degrees), ($this->color ?: 0));
}
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImage()
+ */
+ public function overlayImage($file, $x, $y, $opacity) {
+ $overlayImage = new self();
+ $overlayImage->loadFile($file);
+
+ // fix PNG alpha channel handling
+ // see http://php.net/manual/en/function.imagecopymerge.php#92787
+ $cut = imagecreatetruecolor($overlayImage->getWidth(), $overlayImage->getHeight());
+ imagecopy($cut, $this->image, 0, 0, $x, $y, $overlayImage->getWidth(), $overlayImage->getHeight());
+ imagecopy($cut, $overlayImage->image, 0, 0, 0, 0, $overlayImage->getWidth(), $overlayImage->getHeight());
+ imagecopymerge($this->image, $cut, $x, $y, 0, 0, $overlayImage->getWidth(), $overlayImage->getHeight(), $opacity * 100);
+ }
+
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImageRelative()
+ */
+ public function overlayImageRelative($file, $position, $margin, $opacity) {
+ // does nothing
+ }
+
/**
* @see \wcf\system\image\adapter\IImageAdapter::isSupported()
*/
*/
public function rotate($degrees);
+ /**
+ * Overlays the given image at an absolute position.
+ *
+ * @param string $file
+ * @param integer $x
+ * @param integer $y
+ * @param float $opacity
+ */
+ public function overlayImage($file, $x, $y, $opacity);
+
+ /**
+ * Overlays the given image at a relative position.
+ *
+ * @param string $file
+ * @param string $position
+ * @param integer $margin
+ * @param float $opacity
+ */
+ public function overlayImageRelative($file, $position, $margin, $opacity);
+
/**
* Determines if an image adapter is supported.
*
*/
protected $adapter = null;
+ /**
+ * supported relative positions
+ * @var array<string>
+ */
+ protected $relativePositions = array(
+ 'topLeft',
+ 'topCenter',
+ 'topRight',
+ 'middleLeft',
+ 'middleCenter',
+ 'middleRight',
+ 'bottomLeft',
+ 'bottomCenter',
+ 'bottomRight'
+ );
+
/**
* Creates a new ImageAdapter instance.
*
return $this->adapter->rotate($degrees);
}
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImage()
+ */
+ public function overlayImage($file, $x, $y, $opacity) {
+ // validate file
+ if (!file_exists($file)) {
+ throw new SystemException("Image '".$file."' does not exist.");
+ }
+
+ $this->adapter->overlayImage($file, $x, $y, $opacity);
+ }
+
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImage()
+ */
+ public function overlayImageRelative($file, $position, $margin, $opacity) {
+ // validate file
+ if (!file_exists($file)) {
+ throw new SystemException("Image '".$file."' does not exist.");
+ }
+
+ // validate position
+ if (!in_array($position, $this->relativePositions)) {
+ throw new SystemException("Unknown relative position '".$position."'.");
+ }
+
+ // validate margin
+ if ($margin < 0 || $margin >= $this->getHeight() / 2 || $margin >= $this->getWidth() / 2) {
+ throw new SystemException("Margin has to be positive and respect image dimensions.");
+ }
+
+ $adapterClassName = get_class($this->adapter);
+ $overlayImage = new $adapterClassName();
+ $overlayImage->loadFile($file);
+ $overlayHeight = $overlayImage->getHeight();
+ $overlayWidth = $overlayImage->getWidth();
+
+ // calculate y coordinate
+ $x = 0;
+ switch ($position) {
+ case 'topLeft':
+ case 'middleLeft':
+ case 'bottomLeft':
+ $x = $margin;
+ break;
+
+ case 'topCenter':
+ case 'middleCenter':
+ case 'bottomCenter':
+ $x = floor(($this->getWidth() - $overlayWidth) / 2);
+ break;
+
+ case 'topRight':
+ case 'middleRight':
+ case 'bottomRight':
+ $x = $this->getWidth() - $overlayWidth - $margin;
+ break;
+ }
+
+ // calculate y coordinate
+ $y = 0;
+ switch ($position) {
+ case 'topLeft':
+ case 'topCenter':
+ case 'topRight':
+ $y = $margin;
+ break;
+
+ case 'middleLeft':
+ case 'middleCenter':
+ case 'middleRight':
+ $y = floor(($this->getHeight() - $overlayHeight) / 2);
+ break;
+
+ case 'bottomLeft':
+ case 'bottomCenter':
+ case 'bottomRight':
+ $y = $this->getHeight() - $overlayHeight - $margin;
+ break;
+ }
+
+ $this->overlayImage($file, $x, $y, $opacity);
+ }
+
/**
* @see \wcf\system\image\adapter\IImageAdapter::isSupported()
*/
*/
public function loadFile($file) {
try {
+ $this->imagick->clear();
$this->imagick->readImage($file);
}
catch (\ImagickException $e) {
return $image;
}
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImage()
+ */
+ public function overlayImage($file, $x, $y, $opacity) {
+ try {
+ $overlayImage = new \Imagick($file);
+ }
+ catch (\ImagickException $e) {
+ throw new SystemException("Image '".$file."' is not readable or does not exist.");
+ }
+
+ $overlayImage->evaluateImage(\Imagick::EVALUATE_MULTIPLY, $opacity, \Imagick::CHANNEL_OPACITY);
+ $this->imagick->compositeImage($overlayImage, \Imagick::COMPOSITE_OVER, $x, $y);
+ $this->imagick = $this->imagick->flattenImages();
+ }
+
+ /**
+ * @see \wcf\system\image\adapter\IImageAdapter::overlayImageRelative()
+ */
+ public function overlayImageRelative($file, $position, $margin, $opacity) {
+ // does nothing
+ }
+
/**
* @see \wcf\system\image\adapter\IImageAdapter::isSupported()
*/