5

私はこの画像スケーリングの議論に興味をそそられ、その後、アップロードされた画像からサムネイルを作成するために使用しているPHPコードにも同じ問題があることがわかりました。下部に投稿されたPHP修正を試すことにしました(ガンマを2.2から1.0に変換し、画像のサイズを変更し、ガンマを1.0から2.2に戻します)。これは、記事に記載されている問題を解決するために機能しますが、コードに対するこの変更には、PNGアルファチャネルの透過性をノックアウトするという不幸な副作用があります。

これが、ガンマ補正を行った状態のコードです。

<?php
$image = imagecreatefrompng($source_file);
$resized_image = imagecreatetruecolor($new_width, $new_height);
imagealphablending($resized_image, false);
imagesavealpha($resized_image, true);
imagegammacorrect($image, 2.2, 1.0);
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height);
imagegammacorrect($resized_image, 1.0, 2.2);
imagepng($resized_image, $dest_file);
?>

元の画像のアルファチャネルの透明度を維持しながら、ガンマ補正のトリックを使用して画像のサイズを変更する方法を知っている人はいますか?

編集

サンプル画像:

  1. 元のファイル-アルファチャネル透過性のあるPNG
  2. 両方のimagegammacorrect()関数呼び出しがコメントアウトされたサイズ変更されたファイル
  3. 両方のimagegammacorrect()関数呼び出しが配置されたサイズ変更されたファイル

ガンマを修正しようとするまで、透明度は良好であることがわかります。(以下で透明度が機能していることを確認する最も簡単な方法は、画像にラップされている段落タグを調べて、FireBugなどを介してスタイル属性に黒の背景を追加することです。)

元の画像http://ender.hosting.emarketsouth.com/images/test-image.png ガンマ補正なしhttp://ender.hosting.emarketsouth.com/images/test-image-resized-no-gamma.png ガンマ修正済み-透明性なしhttp://ender.hosting.emarketsouth.com/images/test-image-resized.png

4

2 に答える 2

2

これが機能するコードです。基本的に、アルファチャネルを分離し、ガンマ補正を使用して画像のサイズを変更し、ガンマ補正なしでアルファチャネルのサイズを変更してから、アルファチャネルをガンマ補正で行われたサイズ変更された画像にコピーします。

私の推測では、imagegammacorrect()関数にはバグがあります。おそらくガンマはRGBにのみ適用され、GDはアルファチャネルにも同じ計算を行おうとしますか?色彩理論は私の得意ではありません。

とにかく、ここにコードがあります。残念ながら、ピクセルを1つずつループするよりも、チャネルを分離するためのより良い方法を見つけることができませんでした。しかたがない...

<?php
// Load image
$image = imagecreatefrompng('test-image.png');

// Create destination
$resized_image = imagecreatetruecolor(100, 100);
imagealphablending($resized_image, false); // Overwrite alpha
imagesavealpha($resized_image, true);

// Create a separate alpha channel
$alpha_image = imagecreatetruecolor(200, 200);
imagealphablending($alpha_image, false); // Overwrite alpha
imagesavealpha($alpha_image, true);

for ($x = 0; $x < 200; $x++) {
    for ($y = 0; $y < 200; $y++) {
        $alpha = (imagecolorat($image, $x, $y) >> 24) & 0xFF;
        $color = imagecolorallocatealpha($alpha_image, 0, 0, 0, $alpha);
        imagesetpixel($alpha_image, $x, $y, $color);
    }
}

// Resize image to destination, using gamma correction
imagegammacorrect($image, 2.2, 1.0);
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, 100, 100, 200, 200);
imagegammacorrect($resized_image, 1.0, 2.2);

// Resize alpha channel
$alpha_resized_image = imagecreatetruecolor(200, 200);
imagealphablending($alpha_resized_image, false);
imagesavealpha($alpha_resized_image, true);

imagecopyresampled($alpha_resized_image, $alpha_image, 0, 0, 0, 0, 100, 100, 200, 200);

// Copy alpha channel back to resized image
for ($x = 0; $x < 100; $x++) {
    for ($y = 0; $y < 100; $y++) {
        $alpha = (imagecolorat($alpha_resized_image, $x, $y) >> 24) & 0xFF;
        $rgb = imagecolorat($resized_image, $x, $y);
        $r = ($rgb >> 16 ) & 0xFF;
        $g = ($rgb >> 8 ) & 0xFF;
        $b = $rgb & 0xFF;
        $color = imagecolorallocatealpha($resized_image, $r, $g, $b, $alpha);
        imagesetpixel($resized_image, $x, $y, $color);
    }
}

imagepng($resized_image, 'test-image-scaled.png');
?>

もちろん、ハードコードされた値を変数に置き換えてください...そして、これがあなたの画像と私のコードを使って得た結果です:

サイズ変更された画像
(出典:jejik.com

于 2010-07-22T22:52:23.347 に答える
-1

imagecopyresampled()と透明度に問題があります。考えられる解決策については、 php.netのこのコメントをご覧ください

于 2010-07-21T21:21:14.413 に答える