通过PHP / JS更改PNG图像颜色

时间:2018-02-14 23:05:23

标签: javascript php image png

我可以通过php / js函数更改png图像的图像颜色吗?

我想仅在非透明区域更改颜色。这里有一个示例图像:

image

我想仅在可见的T恤上更换颜色而不是在所有区域。

3 个答案:

答案 0 :(得分:1)

请发布您实际的透明PNG输入文件。在ImageMagick命令行中,我认为应该将白色着色为天蓝色。

convert image.png \
\( -clone 0 -alpha off -fill skyblue -colorize 100 \) \
\( -clone 0 -alpha extract \) \
-compose multiply -composite \
result.png

我不太了解PHP Imagick。所以我会把答案留给有人翻译成Imagick。

答案 1 :(得分:0)

您可以使用PHP imagick库。我认为这是最好的方式。

Imagick class

例如:

<?php

$imageInPath = __DIR__. '\\image-before.png';
$imageOutPath = __DIR__. '\\image-after.png';

$overlayColor = '#F00'; // Red for example
$fuzz = 0;

$overlay = new Imagick( $imageInPath ); // Create imagick object
$overlay->opaquePaintImage ( $overlay->getImagePixelColor(0, 0) , $overlayColor , $fuzz , true ); // Fill the opaque area

$image = new Imagick($imageInPath); // Create imagick object
$image->compositeImage($overlay, Imagick::COMPOSITE_DARKEN  , 0, 0); // Compose the original image with the overlay
$image->writeImage( $imageOutPath ); // Save the image to the given path

?>

此代码段假设第一个像素(x = 0,y = 0)是透明的。

您可以使用另一个COMPOSITE常量更改在图片上应用叠加层的方式。你可以在这里获得想象常数的完整列表:Imagick constants

不要忘记安装Imagick库并在php.ini文件中启用它以使其正常工作。

答案 2 :(得分:0)

ImageMagick可能是一个很好的选择(检查PHP.net's Imagick referencephpimagick.com),因为它将在服务器上执行操作,并且“理论上”无论如何都可以工作(例如, ,即使客户的JS被关闭了。)

如果您无法使用它(例如,您的托管有限),通过JavaScript的选项是使用屏幕外画布,将图像绘制到它,从中生成PNG,然后最后将其添加到页。

以下是一些工作代码的示例:

// shirtPath: the url to the shirt
// overlayPath: the url to the overlay image
// callback: a callback that is given the image once it's generated
function generateShirtOverlay(shirtPath,overlayPath,callback) {
    // load the images
    var loadedImages = 0;
    function imageLoaded() {
        loadedImages++;
        if(loadedImages == 2) {
            composeImages();
        }
    }
    var shirtImage = new Image(),
        overlayImage = new Image();
    // set the image onload callbacks
    shirtImage.onload = imageLoaded;
    overlayImage.onload = imageLoaded;
    // load the images
    shirtImage.src = shirtPath;
    overlayImage.src = overlayPath;

    var generatedImage = new Image();
    function composeImages() {
        // get image sizes
        var width = shirtImage.width,
            height = shirtImage.height,
            overlayWidth = overlayImage.width,
            overlayHeight = overlayImage.height;

        // create a canvas
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;

        // draw the shirt to it
        var context = canvas.getContext("2d");
        context.drawImage(shirtImage,0,0);

        // set the global composite operator to multiply
        // this overlays the image nicely, keeping the
        // dark areas on the shirt dark
        context.globalCompositeOperation = "multiply";
        // draw the overlay image, centering it if it's
        // not the same size
        context.drawImage(overlayImage,
                    (width - overlayWidth) / 2,
                    (height - overlayHeight) / 2
                );

        // a bit of masking magic! for details, see:
        // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
        context.globalCompositeOperation = "destination-in";
        // draw the shirt again; this clips the overlay image
        // at the shirt's edges
        context.drawImage(shirtImage,0,0);

        // finally, extract a PNG from the canvas
        var png = canvas.toDataURL("image/png");
        generatedImage.onload = returnComposedImage();
        // and load it to an image object
        generatedImage.src = png;
    }

    function returnComposedImage() {
        if(typeof callback == "function")
            callback(generatedImage);
    }
}

可以调用此函数来生成图像。最终,它会调用回调,提供生成的图像。然后,由于它是一个Image对象,您可以将它直接添加到页面中,例如:

function addImageToPage(image) {
    document.body.appendChild(image);
}
generateShirtOverlay("images/shirt.png", "images/design1.png", addImageToPage);

请注意,客户端呈现的缺点是并非所有浏览器都支持所有这些画布功能。此外,客户端的开销稍微增加一些。幸运的是,由于这不是一个非常复杂的操作,因此该方法仅使用图像混合模式,并且不需要迭代像素。