Php-替换透明png图像的基色

Php-替换透明png图像的基色,php,image,colors,png,transparency,Php,Image,Colors,Png,Transparency,我搜索了很多,只找到了很少的解决方案(在google和stackoverflow上,所以请不要将这一个标记为重复的,除非有真正重复的问题),但问题是硬边。有没有合适的方法来改变png图像的底色,比如说黑色的png图像,背景是透明的,但要保留软边 这是一个示例图像: 我希望它看起来像这样: 但我找到的解决方案给了我这个: 因为我将在我的本地主机上使用它,只供个人使用,所以任何能够帮助实现这一点的php库都是非常感谢的 更新: 这是给我第三张图片的功能: function LoadPNG($i

我搜索了很多,只找到了很少的解决方案(在google和stackoverflow上,所以请不要将这一个标记为重复的,除非有真正重复的问题),但问题是硬边。有没有合适的方法来改变png图像的底色,比如说黑色的png图像,背景是透明的,但要保留软边

这是一个示例图像:

我希望它看起来像这样:

但我找到的解决方案给了我这个:

因为我将在我的本地主机上使用它,只供个人使用,所以任何能够帮助实现这一点的php库都是非常感谢的

更新:

这是给我第三张图片的功能:

function LoadPNG($imgname)
{
    $im = imagecreatefrompng ($imgname);
    imagetruecolortopalette($im,false, 255);
    $index = imagecolorclosest ( $im,  0,0,0 ); // GET BLACK COLOR
    imagecolorset($im,$index,0,150,255); // SET COLOR TO BLUE
    $name = basename($imgname);
    imagepng($im, getcwd()."/tmp/$name" ); // save image as png
    imagedestroy($im);
}
$dir = getcwd()."/img/";
$images = glob($dir."/*.png",GLOB_BRACE);
foreach($images as $image) {
    LoadPNG($image);
}
最初,这个函数是用于GIF图像(255种颜色的调色板)的解决方案,所以我想这就是为什么会有硬边。我正在寻找一个解决方案(改进这个脚本),以保持透明度和软边缘的PNG图像

编辑2:

我在这里发现了一种使用html5画布和javascript的有趣方法:

如果可能的话,也许有人能想到如何将其翻译成PHP

新解决方案


在回答中,第三张图片看起来不太好,因为
imagetruecolortopalette($im,true,255)渲染丑陋的图像:

因为第二张图片看起来不好,第三张也不好看

代码:


起初的

制作truecolortopalette后($im,true,255);
因此。。
正如我已经说过的,我花了很多时间搜索,到目前为止我发现的是使用html5画布、javascript和ajax

我使用的唯一库是javascript库jQuery,但它是可选的。代码可以很容易地重写为使用普通javascript

工作原理:

1) js从ajax.php中提取数据,ajax.php返回所有文件的数组

2) 然后js循环遍历文件列表,并对每个项目执行
更改(src,color)

3) js函数
change(src,color)
从源代码加载图像,替换其颜色,并向
#Cell
添加一个img元素并显示它(用于调试)

4)
change()
还调用
save(src、filename、cname)
函数 5) js函数
save(src,filename,cname)
发送带有图像数据的ajax请求,并
ajax.php
将图像保存到服务器

下面是代码:

ajax.php

<?php
$r = $_REQUEST;
$act = $r['action'];
if($act == "get_all") {
    $js = "";
    $dir = getcwd()."/img/";
    $images = glob($dir."/*.png",GLOB_BRACE);
    foreach($images as $image) {
        $name = basename($image);
        $js[] = $name;
    }
    echo json_encode($js);
    die();
}
elseif($act == "save") {
    $img = $r['file'];
    $name = $r['name'];
    $color = $r['color'];
    $dir = "results/$color";
    if(!file_exists($dir) || !is_dir($dir)) mkdir($dir,777,true);
    $file = $dir."/$name";
    file_put_contents($file,file_get_contents("data://".$img));
    if(file_exists($file)) echo "Success";
    else echo $file;
    die();
}

此代码并没有举例说明问题,但可以像这样变换颜色:

使用图像的ALPHA通道确定颜色。对于其他结果,只需使用
imagecolorallocatealpha()

函数colorizebasedonaplachannnel($file、$targetR、$targetG、$targetB、$targetName){
$im_src=imagecreatefrompng($file);
$width=imagesx($im_src);
$height=imagesy($im\u src);
$im_dst=imagecreatefrompng($file);
//请注意:
//让我们将图像中的颜色数减少到一种
imagefilledrectangle($im_dst,0,0,$width,$height,0xFFFFFF);
对于($x=0;$x 24&0xFF);
$col=imagecolorallocatealpha($imdst,
$targetR-(整数)(1.0/255.0*$alpha*(双精度)$targetR),
$targetG-(整数)(1.0/255.0*$alpha*(双精度)$targetG),
$targetB-(整数)(1.0/255.0*$alpha*(双精度)$targetB),
$alpha
);
if(false==$col){
死(‘对不起,没颜色了……’);
}
imagesetpixel($im_dst,$x,$y,$col);
}
}
imagepng($im_dst,$targetName);
图像销毁(imu dst);
}
取消链接(dirname(_文件)'/newleaf.png');
取消链接(dirname(_文件)'/newleaf1.png');
取消链接(dirname(_文件)'/newleaf2.png');
$img=dirname(_文件__)。'/leaf.png';
colorizebasedonaplachannnel($img,0,0,0xFF,'newleaf1.png');
colorizebasedonaplachannnel($img,0xFF,0,0xFF,'newleaf2.png');
?>
起初的


扩展到,我还需要能够根据RGBA目标颜色调整每个像素的透明度

我还修复了暗边的问题——这是每个像素的颜色由原始alpha级别调整的结果,而不仅仅是单独调整alpha

//R,G,B=0-255范围
//A=0.0至1.0范围
函数colorizebasedonaplhachannel($file、$targetR、$targetG、$targetB、$targetta、$targetName){
$im_src=imagecreatefrompng($file);
$width=imagesx($im_src);
$height=imagesy($im\u src);
$im_dst=imagecreatefrompng($file);
//关闭alpha混合并设置alpha标志
imagealphablending($imdst,false);
imagesavealpha($imdst,true);
//首先填充透明(否则将导致黑色背景)
imagefill($imu-dst,0,0,imagecolorallocatealpha($im-dst,0,0,0127));
对于($x=0;$x 24&0xFF);
$col=imagecolorallocatealpha($imdst,
$targetR-(整数)(1.0/255.0*(双倍)$targetR),
$targetG-(整数)(1.0/255.0*(双倍)$targetG),
$targetB-(整数)(1.0/255.0*(双倍)$targetB),
(($alpha-127)*$targetA)+127
);
if(false==$col){
死(‘对不起,没颜色了……’);
}
imagesetpixel($im_dst,$x,$y,$col);
}
}
imagepng($im_dst,$targetName);
图像销毁(imu dst);
}

使用
SteAp
的公认代码作为起点(因为我没有用它实现透明度,只是一个白色背景),我修改了上述代码,结果是:

<?php 

function colorizeKeepAplhaChannnel( $inputFilePathIn, $targetRedIn, $targetGreenIn, $targetBlueIn, $outputFilePathIn ) {
    $im_src = imagecreatefrompng( $inputFilePathIn );
    $im_dst = imagecreatefrompng( $inputFilePathIn );
    $width = imagesx($im_src);
    $height = imagesy($im_src);

    // Note this: FILL IMAGE WITH TRANSPARENT BG
    imagefill($im_dst, 0, 0, IMG_COLOR_TRANSPARENT);
    imagesavealpha($im_dst,true);
    imagealphablending($im_dst, true);

    $flagOK = 1;
    for( $x=0; $x<$width; $x++ ) {
        for( $y=0; $y<$height; $y++ ) {
            $rgb = imagecolorat( $im_src, $x, $y );
            $colorOldRGB = imagecolorsforindex($im_src, $rgb);
            $alpha = $colorOldRGB["alpha"];
            $colorNew = imagecolorallocatealpha($im_src, $targetRedIn, $targetGreenIn, $targetBlueIn, $alpha);

            $flagFoundColor = true;
            // uncomment next 3 lines to substitute only 1 color (in this case, BLACK/greys)
/*
            $colorOld = imagecolorallocatealpha($im_src, $colorOldRGB["red"], $colorOldRGB["green"], $colorOldRGB["blue"], 0); // original color WITHOUT alpha channel
            $color2Change = imagecolorallocatealpha($im_src, 0, 0, 0, 0); // opaque BLACK - change to desired color
            $flagFoundColor = ($color2Change == $colorOld);
*/

            if ( false === $colorNew ) {
                //echo( "FALSE COLOR:$colorNew alpha:$alpha<br/>" );
                $flagOK = 0; 
            } else if ($flagFoundColor) {
                imagesetpixel( $im_dst, $x, $y, $colorNew );
                //echo "x:$x y:$y col=$colorNew alpha:$alpha<br/>";
            } 
        }
    }
    $flagOK2 = imagepng($im_dst, $outputFilePathIn);

    if ($flagOK && $flagOK2) {
        echo ("<strong>Congratulations, your conversion was successful </strong><br/>new file $outputFilePathIn<br/>");
    } else if ($flagOK2 && !$flagOK) {
        echo ("<strong>ERROR, your conversion was UNsuccessful</strong><br/>Please verify if your PNG is truecolor<br/>input file $inputFilePathIn<br/>");
    } else if (!$flagOK2 && $flagOK) {
        $dirNameOutput = dirname($outputFilePathIn)."/";
        echo ("<strong>ERROR, your conversion was successful, but could not save file</strong><br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>");
    } else {
        $dirNameOutput = dirname($outputFilePathIn)."/";
        echo ("<strong>ERROR, your conversion was UNsuccessful AND could not save file</strong><br/>Please verify if your PNG is truecolor<br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>");
    }

    echo ("TargetName:$outputFilePathIn wid:$width height:$height CONVERTED:|$flagOK| SAVED:|$flagOK2|<br/>");
    imagedestroy($im_dst);
    imagedestroy($im_src);
}




$targetRed = 0;
$targetGreen = 180;
$targetBlue = 0;

//$inputFileName = 'frameSquareBlack_88x110.png';
$inputFileName = 'testMe.png';
$dirName = "../img/profilePics/";
$nameTemp = basename($inputFileName, ".png");
$outputFileName = $nameTemp."_$targetRed"."_$targetGreen"."_$targetBlue.png";
$inputFilePath = $dirName.$inputFileName;
$outputFilePath = $dirName.$outputFileName;

//echo "inputFileName:$inputFilePath<br>outputName:$outputFilePath<br>";
colorizeKeepAplhaChannnel( $inputFilePath, $targetRed, $targetGreen, $targetBlue, $outputFilePath);
?>
<br/><br/>
Original <br/>
<img src="<?php echo $inputFilePath; ?>">
<br /><br />Colorized<br/>
<img src="<?php echo $outputFilePath; ?>">
<br />



原件
"> 着色的 ">

此变体将所有颜色更改为所选颜色(不仅仅是黑色,一个简单的IF可以解决问题-取消注释)
<!doctype html>
        <html>
<head>
    <script src="jquery.js" type="text/javascript"></script>
    <script src="demo.js" type="text/javascript"></script>
</head>
<body>
<div id="ctrl">
    <input type="text" id="color" value="#666666" placeholder="Color in HEX format (ex. #ff0000)" />
    <input type="text" id="cname" value="grey" placeholder="Color name (destionation dir name)" />
    <button type="button" id="doit">Change</button>
</div>
<div id="Cell">

</div>
</body>

</html>
$(document).ready(function() {
    $(document).on("click","#doit",function() {
        var c = $("#color");
        if(c.val() != "") {
            $("#Cell").html("");
            $.post("ajax.php",{ action: "get_all" },function(s) {
                var images = $.parseJSON(s);
                $.each(images, function(index, element) {
                    change(images[index], c.val());
                });
            });
        }
    });
});
function change(src,color) {
    var myImg = new Image();
    myImg.src = "img/"+src;
    myImg.onload = function() {
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        ctx.drawImage(myImg,0,0);
        var imgd = ctx.getImageData(0, 0, myImg.width, myImg.height);
        canvas.height = myImg.height;
        canvas.width = myImg.width;
        var new_color = HexToRGB(color);
        // console.log(imgd)
        for (i = 0; i <imgd.data.length; i += 4) {
            imgd.data[i]   = new_color.R;
            imgd.data[i+1] = new_color.G;
            imgd.data[i+2] = new_color.B;
        }
        ctx.putImageData(imgd, 0, 0);
        var newImage=new Image()
        newImage.src=canvas.toDataURL("image/png");
        $(newImage).css("margin","5px");
        $(newImage).attr('data-title',src);
        $("#Cell").append(newImage);
        var c = $("#cname");
        if(c.val() == "") c.val("temp");
        save(newImage.src,src, c.val());
    };
}
function save(src,filename,cname) {
    $.post("ajax.php", { action: "save", file: src, name: filename, color: cname },function(s) {
        console.log(s);
    })
}
function HexToRGB(Hex)
{
    var Long = parseInt(Hex.replace(/^#/, ""), 16);
    return {
        R: (Long >>> 16) & 0xff,
        G: (Long >>> 8) & 0xff,
        B: Long & 0xff
    };
}
function colorizeBasedOnAplhaChannnel( $file, $targetR, $targetG, $targetB, $targetName ) {

    $im_src = imagecreatefrompng( $file );

    $width = imagesx($im_src);
    $height = imagesy($im_src);

    $im_dst = imagecreatefrompng( $file );

    // Note this:
    // Let's reduce the number of colors in the image to ONE
    imagefilledrectangle( $im_dst, 0, 0, $width, $height, 0xFFFFFF );

    for( $x=0; $x<$width; $x++ ) {
        for( $y=0; $y<$height; $y++ ) {

            $alpha = ( imagecolorat( $im_src, $x, $y ) >> 24 & 0xFF );

            $col = imagecolorallocatealpha( $im_dst,
                $targetR - (int) ( 1.0 / 255.0  * $alpha * (double) $targetR ),
                $targetG - (int) ( 1.0 / 255.0  * $alpha * (double) $targetG ),
                $targetB - (int) ( 1.0 / 255.0  * $alpha * (double) $targetB ),
                $alpha
                );

            if ( false === $col ) {
                die( 'sorry, out of colors...' );
            }

            imagesetpixel( $im_dst, $x, $y, $col );

        }

    }

    imagepng( $im_dst, $targetName);
    imagedestroy($im_dst);

}

unlink( dirname ( __FILE__ ) . '/newleaf.png' );
unlink( dirname ( __FILE__ ) . '/newleaf1.png' );
unlink( dirname ( __FILE__ ) . '/newleaf2.png' );

$img = dirname ( __FILE__ ) . '/leaf.png';
colorizeBasedOnAplhaChannnel( $img, 0, 0, 0xFF, 'newleaf1.png' );
colorizeBasedOnAplhaChannnel( $img, 0xFF, 0, 0xFF, 'newleaf2.png' );
?>

Original
<img src="leaf.png">
<br />
<img src="newleaf1.png">
<br />
<img src="newleaf2.png">
<?php 

function colorizeKeepAplhaChannnel( $inputFilePathIn, $targetRedIn, $targetGreenIn, $targetBlueIn, $outputFilePathIn ) {
    $im_src = imagecreatefrompng( $inputFilePathIn );
    $im_dst = imagecreatefrompng( $inputFilePathIn );
    $width = imagesx($im_src);
    $height = imagesy($im_src);

    // Note this: FILL IMAGE WITH TRANSPARENT BG
    imagefill($im_dst, 0, 0, IMG_COLOR_TRANSPARENT);
    imagesavealpha($im_dst,true);
    imagealphablending($im_dst, true);

    $flagOK = 1;
    for( $x=0; $x<$width; $x++ ) {
        for( $y=0; $y<$height; $y++ ) {
            $rgb = imagecolorat( $im_src, $x, $y );
            $colorOldRGB = imagecolorsforindex($im_src, $rgb);
            $alpha = $colorOldRGB["alpha"];
            $colorNew = imagecolorallocatealpha($im_src, $targetRedIn, $targetGreenIn, $targetBlueIn, $alpha);

            $flagFoundColor = true;
            // uncomment next 3 lines to substitute only 1 color (in this case, BLACK/greys)
/*
            $colorOld = imagecolorallocatealpha($im_src, $colorOldRGB["red"], $colorOldRGB["green"], $colorOldRGB["blue"], 0); // original color WITHOUT alpha channel
            $color2Change = imagecolorallocatealpha($im_src, 0, 0, 0, 0); // opaque BLACK - change to desired color
            $flagFoundColor = ($color2Change == $colorOld);
*/

            if ( false === $colorNew ) {
                //echo( "FALSE COLOR:$colorNew alpha:$alpha<br/>" );
                $flagOK = 0; 
            } else if ($flagFoundColor) {
                imagesetpixel( $im_dst, $x, $y, $colorNew );
                //echo "x:$x y:$y col=$colorNew alpha:$alpha<br/>";
            } 
        }
    }
    $flagOK2 = imagepng($im_dst, $outputFilePathIn);

    if ($flagOK && $flagOK2) {
        echo ("<strong>Congratulations, your conversion was successful </strong><br/>new file $outputFilePathIn<br/>");
    } else if ($flagOK2 && !$flagOK) {
        echo ("<strong>ERROR, your conversion was UNsuccessful</strong><br/>Please verify if your PNG is truecolor<br/>input file $inputFilePathIn<br/>");
    } else if (!$flagOK2 && $flagOK) {
        $dirNameOutput = dirname($outputFilePathIn)."/";
        echo ("<strong>ERROR, your conversion was successful, but could not save file</strong><br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>");
    } else {
        $dirNameOutput = dirname($outputFilePathIn)."/";
        echo ("<strong>ERROR, your conversion was UNsuccessful AND could not save file</strong><br/>Please verify if your PNG is truecolor<br/>Please verify that you have PERMISSION to save to directory $dirName <br/>input file $inputFilePathIn<br/>");
    }

    echo ("TargetName:$outputFilePathIn wid:$width height:$height CONVERTED:|$flagOK| SAVED:|$flagOK2|<br/>");
    imagedestroy($im_dst);
    imagedestroy($im_src);
}




$targetRed = 0;
$targetGreen = 180;
$targetBlue = 0;

//$inputFileName = 'frameSquareBlack_88x110.png';
$inputFileName = 'testMe.png';
$dirName = "../img/profilePics/";
$nameTemp = basename($inputFileName, ".png");
$outputFileName = $nameTemp."_$targetRed"."_$targetGreen"."_$targetBlue.png";
$inputFilePath = $dirName.$inputFileName;
$outputFilePath = $dirName.$outputFileName;

//echo "inputFileName:$inputFilePath<br>outputName:$outputFilePath<br>";
colorizeKeepAplhaChannnel( $inputFilePath, $targetRed, $targetGreen, $targetBlue, $outputFilePath);
?>
<br/><br/>
Original <br/>
<img src="<?php echo $inputFilePath; ?>">
<br /><br />Colorized<br/>
<img src="<?php echo $outputFilePath; ?>">
<br />
convert liquid.png -fuzz 100% -fill 'green' +opaque transparent -colorize 100 liquid_im.png