Watermark get black background when transparent

I had the same issue after patching 1.9.2.2 and 1.9.2.3. SUPEE-9767 adds an extended validate method in

app/code/core/Mage/Core/Model/File/Validator/Image.php

Mine was:

public function validate($filePath)
{
    $fileInfo = getimagesize($filePath);
    if (is_array($fileInfo) and isset($fileInfo[2])) {
        if ($this->isImageType($fileInfo[2])) {
            return null;
        }
    }
    throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid MIME type.'));
}

And changed to:

public function validate($filePath)
{
    list($imageWidth, $imageHeight, $fileType) = getimagesize($filePath);
    if ($fileType) {
        if ($this->isImageType($fileType)) {
            //replace tmp image with re-sampled copy to exclude images with malicious data
            $image = imagecreatefromstring(file_get_contents($filePath));
            if ($image !== false) {
                $img = imagecreatetruecolor($imageWidth, $imageHeight);
                imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
                switch ($fileType) {
                    case IMAGETYPE_GIF:
                        imagegif($img, $filePath);
                        break;
                    case IMAGETYPE_JPEG:
                        imagejpeg($img, $filePath, 100);
                        break;
                    case IMAGETYPE_PNG:
                        imagepng($img, $filePath);
                        break;
                    default:
                        return;
                }
                imagedestroy($img);
                imagedestroy($image);
                return null;
            } else {
                throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid image.'));
            }
        }
    }
    throw Mage::exception('Mage_Core', Mage::helper('core')->__('Invalid MIME type.'));
}

The problem seems to be the imagecopyresampled call without setting transparency first as it merges the default black background from imagecreatetruecolor.

What I did was move imagecopyresampled into the switch statement and add the transparency calls before imagecopysampled in the png case (you could also use it for gif).

So now my if/switch looks like this:

if ($image !== false) {
    $img = imagecreatetruecolor($imageWidth, $imageHeight);

    switch ($fileType) {
        case IMAGETYPE_GIF:
            imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
            imagegif($img, $filePath);
            break;
        case IMAGETYPE_JPEG:
            imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
            imagejpeg($img, $filePath, 100);
            break;
        case IMAGETYPE_PNG:
            imagecolortransparent($img, imagecolorallocatealpha($img, 0, 0, 0, 127));
            imagealphablending($img, false);
            imagesavealpha($img, true);
            imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
            imagepng($img, $filePath);
            break;
        default:
            return;
    }
    imagedestroy($img);
    imagedestroy($image);
    return null;
}

This kept my png transparency during product image uploads. Dont know if this will help with the watermark and obviously if you do use this copy the file into your local folder.

app/code/local/Mage/Core/Model/File/Validator/Image.php


I'd try to save the image again (maybe with another programm). And if it does'nt help you can try this:

app/code/local/Varien/Image/Adapter/Gd2.php and copy the contents of /lib/Varien/Image/Adapter/Gd2.php

Change:

$this->_fillBackgroundColor($newImage);

To:

$this->_fillBackgroundColor($newImage, $frameWidth, $frameHeight);

Change:

if (!imagefill($imageResourceTo, 0, 0, $color)) {

To:

if (!imagefilledrectangle($imageResourceTo, 0, 0, $w, $h, $color)) {

Source: https://www.gravitywell.co.uk/latest/how-to/posts/fixing-black-magento-adds-to-image-backgrounds/


Edit: this has been fixed in Magento 1.9.3.4 / SUPEE-9767 V2

app/code/core/Mage/Core/Model/File/Validator/Image.php

Changed from:

if ($image !== false) {
    $img = imagecreatetruecolor($imageWidth, $imageHeight);
    imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
    switch ($fileType) {
        case IMAGETYPE_GIF:
            imagegif($img, $filePath);
            break;
        case IMAGETYPE_JPEG:
            imagejpeg($img, $filePath, 100);
            break;
        case IMAGETYPE_PNG:
            imagepng($img, $filePath);
            break;
        default:
            return;
    }

To:

if ($image !== false) {
    $img = imagecreatetruecolor($imageWidth, $imageHeight);
    imagealphablending($img, false);
    imagecopyresampled($img, $image, 0, 0, 0, 0, $imageWidth, $imageHeight, $imageWidth, $imageHeight);
    imagesavealpha($img, true);

    switch ($fileType) {
         case IMAGETYPE_GIF:
            $transparencyIndex = imagecolortransparent($image);
            if ($transparencyIndex >= 0) {
                imagecolortransparent($img, $transparencyIndex);
                for ($y = 0; $y < $imageHeight; ++$y) {
                    for ($x = 0; $x < $imageWidth; ++$x) {
                        if (((imagecolorat($img, $x, $y) >> 24) & 0x7F)) {
                            imagesetpixel($img, $x, $y, $transparencyIndex);
                        }
                    }
                }
            }
            if (!imageistruecolor($image)) {
                imagetruecolortopalette($img, false, imagecolorstotal($image));
            }
            imagegif($img, $filePath);
            break;
        case IMAGETYPE_JPEG:
            imagejpeg($img, $filePath, 100);
            break;
        case IMAGETYPE_PNG:
            imagepng($img, $filePath);
            break;
        default:
            break;
    }