5

画像のセットがあります。この画像には緑色のアルファ色があります。その透明色を別の色に置き換える必要があります(白のアルファ色に置き換えたい)。

その私のコード:

$img = imagecreatefrompng($path . $file); 
$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
for ($y = 0; $y < imagesy($img); $y++) {
    for ($x = 0; $x < imagesx($img); $x++) {
        $rgb = imagecolorat($img, $x, $y);
        $pixel_color = imagecolorsforindex($img, $rgb);
        if ($pixel_color['alpha'] != 0 && $pixel_color['alpha'] != 127){
            imagesetpixel($img, $x, $y, $white_color_transparent);
        }
    }
}

imagealphablending($img, false);
imagesavealpha($img, true);            
imagepng($img, $path .  $file);

前に追加すると、結果の色はidソース画像と同じになります

imagesetpixel($img, $x, $y, $white_color_transparent);

その行:

imagesetpixel($img, $x, $y, $white_color);

透明度のない白い色しか得られません。

4

2 に答える 2

18

あなたの画像を見ずに、それを行う簡単な方法があるかどうかはわかりません。

編集2:

最初の編集で気付いたのは、透明度のある画像では機能せず、背後に不透明なレイヤーがないことです。

これが、ある程度透明な画像を扱うための私の試みです。例からわかるように。それは完全にはうまくいきませんでした。

<?php
//These colors here are the rgba values of the green transparency I used in my test image. You will need to know this to reverse the rgb blending.
$red = 28;
$green = 198;
$blue = 72;
$alpha = .48;

$img = imagecreatefrompng('test.png');

//Adding in the image blending that Zombaya brought up. Need this so it overwrites the pixel instead of blending it
imagealphablending($img, false);
for ($y = 0; $y < imagesy($img); $y++) {
    for ($x = 0; $x < imagesx($img); $x++) {
        $rgb = imagecolorat($img, $x, $y);
        $pixel_color = imagecolorsforindex($img, $rgb);

        //If pixel color matches our alpha layer color, we change it white transparent
        //Not sure how accurate the rounding for the alpha conversion is. Maybe the reason for the green edges in this example:
        if($pixel_color['red'] == $red && 
            $pixel_color['green'] == $green &&
            $pixel_color['blue'] == $blue &&
            $pixel_color['alpha'] == round(127 - ($alpha * 127))){
            $color = imagecolorallocatealpha($img, 255, 255, 255, 127);
        } else {
            //This is the algorithm from the link. But reordered to get the old color before the transparent color went over it.
            $oldR = ($pixel_color['red'] - $alpha * $red) /  (1 - $alpha);
            $oldG = ($pixel_color['green'] - $alpha * $green ) / (1 - $alpha);
            $oldB = ($pixel_color['blue'] - $alpha * $blue) / (1 - $alpha);

            $color = imagecolorallocatealpha($img, $oldR, $oldG, $oldB, $pixel_color['alpha']);
        }
        imagesetpixel($img, $x, $y, $color);
    }
}
imagesavealpha($img, true);            
imagepng($img, 'test_result.png');

ここに画像の説明を入力してください->透明度のないオリジナル

ここに画像の説明を入力してください->透明度のある画像の開始

ここに画像の説明を入力してください->結果の画像。緑のエッジに注意してください。そして、私は赤と緑に同じような不透明度を使用することで幸運に恵まれたかもしれません。白い部分は透明です

編集:

私はこれについてもう少し考えて、このリンクに出くわしました:アルファブレンド量を指定することによってRGBカラーを計算する方法は?

これは私があなたの問題を解決する方法を理解するのに役立ちました。これは、画像上で透明な単色だけかどうかによって異なります。グラデーションの場合はもっと難しいです。

<?php
//These colors here are the rgba values of the green transparency I used in my test image. You will need to know this to reverse the rgb blending.
$red = 44;
$green = 215;
$blue = 56;
$alpha = .45;

$img = imagecreatefrompng('test2.png');

for ($y = 0; $y < imagesy($img); $y++) {
    for ($x = 0; $x < imagesx($img); $x++) {
        $rgb = imagecolorat($img, $x, $y);
        $pixel_color = imagecolorsforindex($img, $rgb);
            //This is the algorithm from the link. But reordered to get the old color before the transparent color went over it.
        $oldR = ($pixel_color['red'] - $alpha * $red) /  (1 - $alpha);
        $oldG = ($pixel_color['green'] - $alpha * $green ) / (1 - $alpha);
        $oldB = ($pixel_color['blue'] - $alpha * $blue) / (1 - $alpha);

        $color = imagecolorallocate($img, $oldR, $oldG, $oldB);
        imagesetpixel($img, $x, $y, $color);
    }
}
imagesavealpha($img, true);            
imagepng($img, 'test_result.png');

ここに画像の説明を入力してください-開始画像

ここに画像の説明を入力してください-残像

上記のコードで使用されているrgb計算の説明は次のとおりです。リンクは基本的な式を示しています:

out = alpha * new + (1 - alpha) * old

out元の色と新しい色を混合した後の結果の色です。

したがって、古い色を取得するために数式を再配置する必要があります。これにより、次のようになります。

old = (out - alpha * new) / (1 - alpha)

古い答え:

この行が機能しない理由:

$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);

127は完全に透明であることを意味するため、見えないことを意味します。そのため、結果の画像は開始画像と同じになります。

この線が完全に白い画像を作成する理由:

$white_color = imagecolorallocatealpha($img, 255, 255, 255, 0); 

また

$white_color = imagecolorallocate($img, 255, 255, 255);

これは基本的に、選択したピクセルの上に白いピクセルを配置するだけです(0は透明度がないことを意味します)。そのため、選択したピクセルは完全に白になります。

ここで、次のことを行うと、次のようになります。

$white_color_semi_transparent = imagecolorallocatealpha($img, 255, 255, 255, 40); 

透明な緑を透明な白に置き換える代わりに、半透明の白ではなく明るい緑を取得することがわかります。

私のテスト例を参照してください:

開始画像-開始画像

ここに画像の説明を入力してください-色255,255,255,40の結果の画像

つまり、これは2つのことを示しています。

  1. 1つは、基本的に既存のピクセルの色の上に色が適用されるため、透明な白ではなく明るい透明な緑になります。
  2. 次に、茶色の部分は影響を受けないことに注意してください。茶色の部分は、実際には緑の不透明レイヤーの下にある不透明な赤い色でした。これは、画像がフォトショップのようなレイヤーを考慮しておらず、基本的に茶色を茶色として読み取り、緑色の透明色の背後にある赤色ではないことを示しています。PNGファイルにはレイヤー情報が含まれていないため、これは理にかなっています。

問題をどのように解決するかわかりません。それはあなたのイメージに依存します。思い通りのカラーリングは可能だと思いますが、画像が複雑になるほど難しくなります。たとえば、写真とは対照的に、2つの色が重なった2つの正方形です。

于 2012-05-25T18:18:15.293 に答える
0

Gohn67の画像を幅の作業に使用しました。

秘訣は、画像を変換する前にアルファブレンディングをオフにすることです。このようにimagesetpixel()して、ピクセルを希望どおりの値に設定するために使用できます。

のマニュアルからimagealphablending

非ブレンドモードでは、描画色が文字通りアルファチャネル情報とともにコピーされ、宛先ピクセルが置き換えられます。

これにより、次のコードが生成されました。

$img = imagecreatefrompng($path.$file);
imagealphablending($img, false); // Turn off blending
$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
for ($y = 0; $y < imagesy($img); $y++) {
    for ($x = 0; $x < imagesx($img); $x++) {
        $rgb = imagecolorat($img, $x, $y);
        $pixel_color = imagecolorsforindex($img, $rgb);
        if ($pixel_color['alpha'] != 0 && $pixel_color['alpha'] != 127){
            imagesetpixel($img, $x, $y, $white_color_transparent);
        }
    }
}
imagesavealpha($img, true);            
imagepng($img, $path.$file);

元の画像

元の画像

結果の画像

結果の画像
(背景は実際には透明ですが、ここでは見ることができません)

今のところ、すべての透明な色がこの完全に透明な白に置き換わっています。すべての色付きの透明度を同じアルファ値の透明な白に置き換えたい場合は、次のようにします。

imagesetpixel($img, $x, $y, imagecolorallocatealpha($img, 255, 255, 255, $pixel_color['alpha']));

また、緑色の透明なピクセルのみを選択するには、各ピクセルの色相を計算して、指定された範囲内にあるかどうかを確認します。

于 2012-05-25T20:49:30.663 に答える