天天看點

用PHP+GD擴充實作圖像高斯模糊處理

很久以前寫的代碼了,現在才想起貼上來. 稍微更改并結合人臉識别可以實作自動模糊人物的臉部.

<?php
require_once 'RGB.php'; //這裡請看另一個 "PHP實作色彩空間轉換"
/**
 * 圖像資訊處理
 * @author shizhuolin
 */
class Image {

    /**
     * 位圖資源
     * @var resource 
     */
    protected $_image;

    /**
     * 使用指定檔案構造圖像操作執行個體
     * @param string $filename 
     */
    public function __construct($filename=null) {
        if ($filename)
            $this->open($filename);
    }

    /**
     * 讀取指定檔案明的圖像
     * @param string $filename
     * @return Image 
     */
    public function open($filename) {
        $handle = fopen($filename, "rb");
        $contents = stream_get_contents($handle);
        fclose($handle);
        $image = imagecreatefromstring($contents);
        $width = imagesx($image);
        $height = imagesy($image);
        $truecolorimage = imagecreatetruecolor($width, $height);
        imagefilledrectangle($truecolorimage, 0, 0, $width, $height, 0xFFFFFF);
        imagecopyresampled($truecolorimage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
        imagedestroy($image);
        $this->setImage($truecolorimage);
        return $this;
    }

    /**
     * 讀取指定資源的圖像
     * @param resource $image
     * @return Image 
     */
    public function load($image) {
        $width = imagesx($image);
        $height = imagesy($image);
        $truecolorimage = imagecreatetruecolor($width, $height);
        imagefilledrectangle($truecolorimage, 0, 0, $width, $height, 0xFFFFFF);
        imagecopyresampled($truecolorimage, $image, 0, 0, 0, 0, $width, $height, $width, $height);
        if ($this->getImage()) {
            imagedestroy($this->getImage());
        }
        $this->setImage($truecolorimage);
        return $this;
    }

    /**
     * 設定内部圖像資源描述符
     * @param resource $image 
     */
    protected function setImage($image) {
        $this->_image = $image;
    }

    /**
     * 擷取内部操作圖像資源
     * @return resource 
     */
    public function getImage() {
        return $this->_image;
    }

    /**
     * 擷取圖像寬度
     * @return int
     */
    public function getWidth() {
        return imagesx($this->getImage());
    }

    /**
     * 擷取圖像高度
     * @return int
     */
    public function getHeight() {
        return imagesy($this->getImage());
    }

    /**
     * 擷取指定坐标像素顔色
     * @param type $x
     * @param type $y
     * @return type 
     */
    public function getColorAt($x, $y) {
        $rgb = imageColorAt($this->getImage(), $x, $y);
        $r = ($rgb >> 16) & 0xFF;
        $g = ($rgb >> 8) & 0xFF;
        $b = $rgb & 0xFF;
        return array('red' => $r, 'green' => $g, 'blue' => $b);
    }

    /**
     * 高斯模糊(單緯度二次模糊)
     * @param float $radius 半徑
     */
    public function gaussianBlur($radius=1.0) {
        $width = $this->getWidth();
        $height = $this->getHeight();
        $sigma = $radius / 3;
        $sigma2 = 2 * pow($sigma, 2);
        $matrix = array();
        $newimage = imagecreatetruecolor($width, $height);
        /* 生成高斯矩陣(單緯度矩陣) */
        for ($x = -$radius; $x <= $radius; $x++) {
            $x2 = pow($x, 2) + pow($x, 2);
            $matrix[] = exp(-$x2 / $sigma2) / ($sigma2 * M_PI);
        }
        /* 構模組化糊圖像 */
        for ($y = 0; $y < $height; $y++) {
            for ($x = 0; $x < $width; $x++) {
                $bright = $red = $green = $blue = 0;
                /* 垂直模糊 */
                for ($yy = -$radius; $yy <= $radius; $yy++) {
                    $yyy = $y + $yy;
                    if ($yyy >= 0 && $yyy < $height) {
                        $weight = $matrix[$yy + $radius];
                        $bright += $weight;
                        $color = $this->getColorAt($x, $yyy);
                        $red += ($color['red'] * $weight);
                        $green += ($color['green'] * $weight);
                        $blue += ($color['blue'] * $weight);
                    }
                }
                /* 水準模糊 */
                for ($xx = -$radius; $xx <= $radius; $xx++) {
                    $xxx = $x + $xx;
                    if ($xxx >= 0 && $xxx < $width && $xx != 0) {
                        $weight = $matrix[$xx + $radius];
                        $bright+=$weight;
                        $color = $this->getColorAt($xxx, $y);
                        $red += ($color['red'] * $weight);
                        $green += ($color['green'] * $weight);
                        $blue += ($color['blue'] * $weight);
                    }
                }
                $z = 1 / $bright;
                imagesetpixel($newimage, $x, $y, ($red * $z << 16) | ($green * $z << 8) | $blue * $z);
            }
        }
        imagedestroy($this->getImage());
        $this->setImage($newimage);
    }

    /**
     * 析構 銷毀圖像占用記憶體
     */
    public function __destruct() {
        if ($this->getImage()) {
            imagedestroy($this->getImage());
        }
    }

}
           

調用代碼

<?php
require_once 'Image.php';
$image = new Image("http://www.u-cola.com/images/200809/1220676617582974754.jpg");
$image->gaussianBlur(10);
header("Content-type: image/png");
imagepng($image->getImage());