2012-09-12 88 views
0

我有這個功能變換圖像使用PHP GD到梯形:圖片爲等腰梯形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

大概你不知道如何在當前的代碼中創建梯形? – Orbling

+0

嗯,我可以理解它是如何創建的,但我沒有足夠的PHP(gd)知識使其以另一種方式工作。 – SomeoneS

回答

1

沒錯,基本上這個代碼應該能夠生成正確的值,但是由於bug有很多瑕疵來形成梯形。錯誤在於每行的副本有destination-ysource-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度,被處理,然後被旋轉回來)。

+0

哇,真是太棒了,我不能夠感謝你。在PHP GD中沒有創建等腰梯形的功能。現在更容易理解。 Tnx再次:) – SomeoneS

+1

很好。這是對圖像的專業轉變,所以不太可能內置在悲哀之中。如果你使用了像Image Magick這樣更強大的圖像庫,那麼也許。 – Orbling

+1

請注意,原始圖像損壞了傳入圖像,我的圖像沒有。所以如果你不再需要原始圖像,你將不得不''imagedestroy()'它。 – Orbling