0

PHP GDを使用して画像を台形に変換するこの関数があります:

 function perspective($i,$gradient=0.9,$rightdown=true,$background=0xFFFFFF) {
    $mult=3;
    $w=imagesx($i);
    $h=imagesy($i);
    $image=imagecreatetruecolor($w*$mult,$h*$mult);
    imagecopyresized($image,$i,0,0,0,0,$w*$mult,$h*$mult,$w,$h);
    imagedestroy($i);
    $w*=$mult;
    $h*=$mult;
    $im=imagecreatetruecolor($w,$h);
    $background=imagecolorallocate($im,($background>>16)&0xFF,($background>>8)&0xFF,$background&0xFF);
    imagefill($im,0,0,$background);
    imageantialias($im,true);
    $nh=$h-($h*$gradient);
    for ($x=0; $x<$w; $x++) {
        $ni=(($rightdown) ? $x : $w-$x);
        $p=intval($h-(($ni/$w)*$nh));
        if (($p%2)<>0)
        $p-=1;
        $nx=intval(($p-$h)/2);
        imagecopyresampled($im,$image,$x,0,$x,$nx,1,$p,1,$h-1);
        imageline($im,$x,$h-1,$x,$h+$nx,$background);
        imageline($im,$x,0,$x,-$nx-1,$background);
    }
    imagedestroy($image);
    imagefilter($im,IMG_FILTER_SMOOTH,10);
    $i=imagecreatetruecolor($w/$mult,$h/$mult);
    imageantialias($i,true);
    imagecopyresampled($i,$im,0,0,0,0,$w,$h,$w*$mult,$h*$mult);
    imagedestroy($im);
    return $i;
 }

しかし、それを変更して等脚台形を生成することはできません。小さな変更が1つだけ必要だと思いますが、それを理解することはできません(私は多くのことを試しました)。

誰か助けてくれませんか?

4

1 に答える 1

1

そうですね、基本的にそのコードは正しい値を生成するはずですが、バグにより、台形を取得するために多くのクラッジが配置されています。バグは、各行のコピーにdestination-yと のsource-y値が転置されていることです。はsource-y常に 0 であるdestination-y必要があり、変更する必要があります。

他にもいくつかの小さな数値上のバグと、不要なポイントでの二重の丸めがあり、結果が台無しになりました。

また、変数の命名がひどかったので、関数全体が明確になるように書き直しました。

次のことを試してください。

function makeTrapeziumImage($image, $gradient, $rightToLeft = false, $background = 0xFFFFFF, $supersampleScale = 3) {
  $originalWidth = imagesx($image);
  $originalHeight = imagesy($image);

  $supersampledWidth = $originalWidth * $supersampleScale;
  $supersampledHeight = $originalHeight * $supersampleScale;

  $supersampledImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);

  imagecopyresized($supersampledImage, $image,
                   0, 0, 0, 0,
                   $supersampledWidth, $supersampledHeight, $originalWidth, $originalHeight);

  $workingImage = imagecreatetruecolor($supersampledWidth, $supersampledHeight);

  $backgroundColour = imagecolorallocate($workingImage, ($background >> 16) & 0xFF, ($background >> 8) & 0xFF, $background & 0xFF);
  imagefill($workingImage, 0, 0, $backgroundColour);

  imageantialias($workingImage,true);

  $endHeight = $supersampledHeight - ($supersampledHeight * $gradient);

  for ($x = 0; $x < $supersampledWidth; $x++) {
    $cX = ($rightToLeft ? $supersampledWidth - $x : $x);

    $dstHeight = $supersampledHeight - ((($cX + 1) / $supersampledWidth) * $endHeight);

    $dstY = intval(($supersampledHeight - $dstHeight) / 2) - 1; // -1 required as zero-indexed
    $dstY = ($dstY < 0 ? 0 : $dstY); // Rounding can make $dstY = -1

    $dstHeight = intval($dstHeight); // Round the height after calculating $dstY

    imagecopyresampled($workingImage, $supersampledImage,
                       $cX, $dstY, $cX, 0,
                       1, $dstHeight, 1, $supersampledHeight);
  }

  imagedestroy($supersampledImage);
  imagefilter($workingImage, IMG_FILTER_SMOOTH, 10);

  $resizedImage = imagecreatetruecolor($originalWidth, $originalHeight);
  imageantialias($resizedImage, true);

  imagecopyresampled($resizedImage, $workingImage,
                     0, 0, 0, 0,
                     $originalWidth, $originalHeight, $supersampledWidth, $supersampledHeight);

  imagedestroy($workingImage);

  return $resizedImage;
}

前と同様に、内部ループの本質的なメカニズムは、x 軸に沿ってピクセルの各列を取得し、グラデーションでサイズを変更することです。自然に二等辺台形を作成します。非二等辺台形を作成するには、別のグラデーションを指定する必要があります。または、開始と終了のセットをy-values指定して、それらから勾配を計算することもできます。

この例は x 軸に沿って前と同じようにどちらの方向にも機能しますが、y 軸に沿って簡単に機能させることもできます (または、画像を 90 度回転させて処理し、元に戻すこともできます)。

于 2012-09-12T18:45:42.460 に答える