Da bietet Magento von Haus aus eine Wasserzeichen Funktion, unterstützt aber nicht vernünftig transparente PNGs… no comment.
Problem ist, dass Magento die PHP Funktion imagecopymerge() für das zusammenfügen der Bilder benutzt. Leider ist die Funktion noch nicht so ganz ausgereift und möchte man einfach auf seine Produktbilder ein transparentes PNG als Wasserzeichen legen, so sollte man auf die imagecopy() Funktion zurückgreifen.
Das Zusammenfügen der Bilder erfolgt in der /lib/Varien/Image/Adapter/Gd2.php In meinem nutze ich einfach unskalierte PNGs, skalieren funktioniert in meiner abgeänderten Gd2.php NICHT.
Hier meine geänderte Gd2.php (Magento 1.5)
array('output' => 'imagegif', 'create' => 'imagecreatefromgif'),
IMAGETYPE_JPEG => array('output' => 'imagejpeg', 'create' => 'imagecreatefromjpeg'),
IMAGETYPE_PNG => array('output' => 'imagepng', 'create' => 'imagecreatefrompng'),
IMAGETYPE_XBM => array('output' => 'imagexbm', 'create' => 'imagecreatefromxbm'),
IMAGETYPE_WBMP => array('output' => 'imagewbmp', 'create' => 'imagecreatefromxbm'),
);
public function open($filename)
{
$this->_fileName = $filename;
$this->getMimeType();
$this->_getFileAttributes();
$this->_imageHandler = call_user_func($this->_getCallback('create'), $this->_fileName);
}
public function save($destination=null, $newName=null)
{
$fileName = ( !isset($destination) ) ? $this->_fileName : $destination;
if( isset($destination) && isset($newName) ) {
$fileName = $destination . "/" . $newName;
} elseif( isset($destination) && !isset($newName) ) {
$info = pathinfo($destination);
$fileName = $destination;
$destination = $info['dirname'];
} elseif( !isset($destination) && isset($newName) ) {
$fileName = $this->_fileSrcPath . "/" . $newName;
} else {
$fileName = $this->_fileSrcPath . $this->_fileSrcName;
}
$destinationDir = ( isset($destination) ) ? $destination : $this->_fileSrcPath;
if( !is_writable($destinationDir) ) {
try {
$io = new Varien_Io_File();
$io->mkdir($destination);
} catch (Exception $e) {
throw new Exception("Unable to write file into directory '{$destinationDir}'. Access forbidden.");
}
}
// keep alpha transparency
$isAlpha = false;
$this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
if ($isAlpha) {
$this->_fillBackgroundColor($this->_imageHandler);
}
$functionParameters = array();
$functionParameters[] = $this->_imageHandler;
$functionParameters[] = $fileName;
// set quality param for JPG file type
if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_JPEG)
{
$functionParameters[] = $this->quality();
}
// set quality param for PNG file type
if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_PNG)
{
$quality = round(($this->quality() / 100) * 10);
if ($quality 10) {
$quality = 10;
}
$quality = 10 - $quality;
$functionParameters[] = $quality;
}
call_user_func_array($this->_getCallback('output'), $functionParameters);
}
public function display()
{
header("Content-type: ".$this->getMimeType());
call_user_func($this->_getCallback('output'), $this->_imageHandler);
}
/**
* Obtain function name, basing on image type and callback type
*
* @param string $callbackType
* @param int $fileType
* @return string
* @throws Exception
*/
private function _getCallback($callbackType, $fileType = null, $unsupportedText = 'Unsupported image format.')
{
if (null === $fileType) {
$fileType = $this->_fileType;
}
if (empty(self::$_callbacks[$fileType])) {
throw new Exception($unsupportedText);
}
if (empty(self::$_callbacks[$fileType][$callbackType])) {
throw new Exception('Callback not found.');
}
return self::$_callbacks[$fileType][$callbackType];
}
private function _fillBackgroundColor(&$imageResourceTo)
{
// try to keep transparency, if any
if ($this->_keepTransparency) {
$isAlpha = false;
$transparentIndex = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
try {
// fill truecolor png with alpha transparency
if ($isAlpha) {
if (!imagealphablending($imageResourceTo, false)) {
throw new Exception('Failed to set alpha blending for PNG image.');
}
$transparentAlphaColor = imagecolorallocatealpha($imageResourceTo, 0, 0, 0, 127);
if (false === $transparentAlphaColor) {
throw new Exception('Failed to allocate alpha transparency for PNG image.');
}
if (!imagefill($imageResourceTo, 0, 0, $transparentAlphaColor)) {
throw new Exception('Failed to fill PNG image with alpha transparency.');
}
if (!imagesavealpha($imageResourceTo, true)) {
throw new Exception('Failed to save alpha transparency into PNG image.');
}
return $transparentAlphaColor;
}
// fill image with indexed non-alpha transparency
elseif (false !== $transparentIndex) {
list($r, $g, $b) = array_values(imagecolorsforindex($this->_imageHandler, $transparentIndex));
$transparentColor = imagecolorallocate($imageResourceTo, $r, $g, $b);
if (false === $transparentColor) {
throw new Exception('Failed to allocate transparent color for image.');
}
if (!imagefill($imageResourceTo, 0, 0, $transparentColor)) {
throw new Exception('Failed to fill image with transparency.');
}
imagecolortransparent($imageResourceTo, $transparentColor);
return $transparentColor;
}
}
catch (Exception $e) {
// fallback to default background color
}
}
list($r, $g, $b) = $this->_backgroundColor;
$color = imagecolorallocate($imageResourceTo, $r, $g, $b);
if (!imagefill($imageResourceTo, 0, 0, $color)) {
throw new Exception("Failed to fill image background with color {$r} {$g} {$b}.");
}
return $color;
}
/**
* Gives true for a PNG with alpha, false otherwise
*
* @param string $fileName
* @return boolean
*/
public function checkAlpha($fileName)
{
return ((ord(file_get_contents($fileName, false, null, 25, 1)) & 6) & 4) == 4;
}
private function _getTransparency($imageResource, $fileType, &$isAlpha = false, &$isTrueColor = false)
{
$isAlpha = false;
$isTrueColor = false;
// assume that transparency is supported by gif/png only
if ((IMAGETYPE_GIF === $fileType) || (IMAGETYPE_PNG === $fileType)) {
// check for specific transparent color
$transparentIndex = imagecolortransparent($imageResource);
if ($transparentIndex >= 0) {
return $transparentIndex;
}
// assume that truecolor PNG has transparency
elseif (IMAGETYPE_PNG === $fileType) {
$isAlpha = $this->checkAlpha($this->_fileName);
$isTrueColor = true;
return $transparentIndex; // -1
}
}
if (IMAGETYPE_JPEG === $fileType) {
$isTrueColor = true;
}
return false;
}
/**
* Change the image size
*
* @param int $frameWidth
* @param int $frameHeight
*/
public function resize($frameWidth = null, $frameHeight = null)
{
if (empty($frameWidth) && empty($frameHeight)) {
throw new Exception('Invalid image dimensions.');
}
// calculate lacking dimension
if (!$this->_keepFrame) {
if (null === $frameWidth) {
$frameWidth = round($frameHeight * ($this->_imageSrcWidth / $this->_imageSrcHeight));
}
elseif (null === $frameHeight) {
$frameHeight = round($frameWidth * ($this->_imageSrcHeight / $this->_imageSrcWidth));
}
}
else {
if (null === $frameWidth) {
$frameWidth = $frameHeight;
}
elseif (null === $frameHeight) {
$frameHeight = $frameWidth;
}
}
// define coordinates of image inside new frame
$srcX = 0;
$srcY = 0;
$dstX = 0;
$dstY = 0;
$dstWidth = $frameWidth;
$dstHeight = $frameHeight;
if ($this->_keepAspectRatio) {
// do not make picture bigger, than it is, if required
if ($this->_constrainOnly) {
if (($frameWidth >= $this->_imageSrcWidth) && ($frameHeight >= $this->_imageSrcHeight)) {
$dstWidth = $this->_imageSrcWidth;
$dstHeight = $this->_imageSrcHeight;
}
}
// keep aspect ratio
if ($this->_imageSrcWidth / $this->_imageSrcHeight >= $frameWidth / $frameHeight) {
$dstHeight = round(($dstWidth / $this->_imageSrcWidth) * $this->_imageSrcHeight);
} else {
$dstWidth = round(($dstHeight / $this->_imageSrcHeight) * $this->_imageSrcWidth);
}
}
// define position in center (TODO: add positions option)
$dstY = round(($frameHeight - $dstHeight) / 2);
$dstX = round(($frameWidth - $dstWidth) / 2);
// get rid of frame (fallback to zero position coordinates)
if (!$this->_keepFrame) {
$frameWidth = $dstWidth;
$frameHeight = $dstHeight;
$dstY = 0;
$dstX = 0;
}
// create new image
$isAlpha = false;
$isTrueColor = false;
$this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor);
if ($isTrueColor) {
$newImage = imagecreatetruecolor($frameWidth, $frameHeight);
}
else {
$newImage = imagecreate($frameWidth, $frameHeight);
}
// fill new image with required color
$this->_fillBackgroundColor($newImage);
// resample source image and copy it into new frame
imagecopyresampled($newImage, $this->_imageHandler, $dstX, $dstY, $srcX, $srcY, $dstWidth, $dstHeight, $this->_imageSrcWidth, $this->_imageSrcHeight);
$this->_imageHandler = $newImage;
$this->refreshImageDimensions();
}
public function rotate($angle)
{
/*
$isAlpha = false;
$backgroundColor = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
list($r, $g, $b) = $this->_backgroundColor;
if ($isAlpha) {
$backgroundColor = imagecolorallocatealpha($this->_imageHandler, 0, 0, 0, 127);
}
elseif (false === $backgroundColor) {
$backgroundColor = imagecolorallocate($this->_imageHandler, $r, $g, $b);
}
$this->_imageHandler = imagerotate($this->_imageHandler, $angle, $backgroundColor);
//*/
$this->_imageHandler = imagerotate($this->_imageHandler, $angle, $this->imageBackgroundColor);
$this->refreshImageDimensions();
}
public function watermark($watermarkImage, $positionX=0, $positionY=0, $watermarkImageOpacity=30, $repeat=false)
{
list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType, ) = getimagesize($watermarkImage);
$this->_getFileAttributes();
$watermark = call_user_func($this->_getCallback('create', $watermarkFileType, 'Unsupported watermark image format.'), $watermarkImage);
$merged = false;
if( $this->getWatermarkWidth() && $this->getWatermarkHeigth() && ($this->getWatermarkPosition() != self::POSITION_STRETCH) ) {
}
if( $this->getWatermarkPosition() == self::POSITION_TILE ) {
$repeat = true;
} elseif( $this->getWatermarkPosition() == self::POSITION_STRETCH ) {
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} elseif( $this->getWatermarkPosition() == self::POSITION_CENTER ) {
$positionX = ($this->_imageSrcWidth/2 - imagesx($watermark)/2);
$positionY = ($this->_imageSrcHeight/2 - imagesy($watermark)/2);
imagecopymerge($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $this->getWatermarkImageOpacity());
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} elseif( $this->getWatermarkPosition() == self::POSITION_TOP_RIGHT ) {
$positionX = ($this->_imageSrcWidth - imagesx($watermark));
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} elseif( $this->getWatermarkPosition() == self::POSITION_TOP_LEFT ) {
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT ) {
$positionX = ($this->_imageSrcWidth - imagesx($watermark));
$positionY = ($this->_imageSrcHeight - imagesy($watermark));
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT ) {
$positionY = ($this->_imageSrcHeight - imagesy($watermark));
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
}
if( $repeat === false && $merged === false ) {
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
} else {
$offsetX = $positionX;
$offsetY = $positionY;
while( $offsetY _imageSrcHeight+imagesy($watermark)) ) {
while( $offsetX _imageSrcWidth+imagesx($watermark)) ) {
imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
$offsetX += imagesx($watermark);
}
$offsetX = $positionX;
$offsetY += imagesy($watermark);
}
}
imagedestroy($watermark);
$this->refreshImageDimensions();
}
public function crop($top=0, $bottom=0, $right=0, $left=0)
{
if( $left == 0 && $top == 0 && $right == 0 && $bottom == 0 ) {
return;
}
$newWidth = $this->_imageSrcWidth - $left - $right;
$newHeight = $this->_imageSrcHeight - $top - $bottom;
$canvas = imagecreatetruecolor($newWidth, $newHeight);
if ($this->_fileType == IMAGETYPE_PNG) {
$this->_saveAlpha($canvas);
}
imagecopyresampled($canvas, $this->_imageHandler, $top, $bottom, $right, $left, $this->_imageSrcWidth, $this->_imageSrcHeight, $newWidth, $newHeight);
$this->_imageHandler = $canvas;
$this->refreshImageDimensions();
}
public function checkDependencies()
{
foreach( $this->_requiredExtensions as $value ) {
if( !extension_loaded($value) ) {
throw new Exception("Required PHP extension '{$value}' was not loaded.");
}
}
}
private function refreshImageDimensions()
{
$this->_imageSrcWidth = imagesx($this->_imageHandler);
$this->_imageSrcHeight = imagesy($this->_imageHandler);
}
function __destruct()
{
@imagedestroy($this->_imageHandler);
}
/*
* Fixes saving PNG alpha channel
*/
private function _saveAlpha($imageHandler)
{
$background = imagecolorallocate($imageHandler, 0, 0, 0);
ImageColorTransparent($imageHandler, $background);
imagealphablending($imageHandler, false);
imagesavealpha($imageHandler, true);
}
}
Backup nicht vergessen ;)