程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> php上傳圖片後,自動裁剪成縮略圖,寬不限高

php上傳圖片後,自動裁剪成縮略圖,寬不限高

編輯:關於PHP編程

php教程上傳圖片後,自動裁剪成縮略圖,寬不限高

<?php
// $Id: image.php 1937 2009-01-05 19:09:40Z dualface $

/**
* 定義 Helper_Image 類和 Helper_ImageGD 類
*
* @link http://qeephp.com/
* @copyright Copyright (c) 2006-2009 Qeeyuan Inc. {@link http://www.qeeyuan.com}
* @license New BSD License {@link http://qeephp.com/license/}
* @version $Id: image.php 1937 2009-01-05 19:09:40Z dualface $
* @package helper
*/

/**
* Helper_Image 類封裝了針對圖像的操作
*
* 開發者不能直接構造該類的實例,而是應該用 Helper_Image::createFromFile()
* 靜態方法創建一個 Image 類的實例。
*
* 操作大圖片時,請確保 php 能夠分配足夠的內存。
*
* @author YuLei Liao <[email protected]>
* @version $Id: image.php 1937 2009-01-05 19:09:40Z dualface $
* @package helper
*/
abstract class Helper_Image
{
    /**
     * 從指定文件創建 Helper_ImageGD 對象
     *
     * 用法:
     * @code php
     * $image = Helper_Image::createFromFile('1.jpg');
     * $image->resize($width, $height);
     * $image->saveAsJpeg('2.jpg');
     * @endcode
     *
     * 對於上傳的文件,由於其臨時文件名中並沒有包含擴展名。
     * 因此需要采用下面的方法創建 Image 對象:
     *
     * @code php
     * $ext = pathinfo($_FILES['postfile']['name'], PATHINFO_EXTENSION);
     * $image = Image::createFromFile($_FILES['postfile']['tmp_name'], $ext);
     * @endcode
     *
     * @param string $filename 圖像文件的完整路徑
     * @param string $fileext 指定擴展名
     *
     * @return Helper_ImageGD 從文件創建的 Helper_ImageGD 對象
     * @throw Q_NotImplementedException
     */
    static function createFromFile($filename, $fileext)
    {
        $fileext = trim(strtolower($fileext), '.');
        $ext2functions = array(
            'jpg'  => 'imagecreatefromjpeg',
            'jpeg' => 'imagecreatefromjpeg',
            'png'  => 'imagecreatefrompng',
            'gif'  => 'imagecreatefromgif'
        );

        if (!isset($ext2functions[$fileext]))
        {
                throw new Q_NotImplementedException(__('imagecreateform' . $fileext));
        }

        $handle = call_user_func($ext2functions[$fileext], $filename);
        return new Helper_ImageGD($handle);
    }

        /**
         * 將 16 進制顏色值轉換為 rgb 值
     *
     * 用法:
     * @code php
     * $color = '#369';
     * list($r, $g, $b) = Helper_Image::hex2rgb($color);
     * echo "red: {$r}, green: {$g}, blue: {$b}";
     * @endcode
     *
     * @param string $color 顏色值
     * @param string $default 使用無效顏色值時返回的默認顏色
         *
         * @return array 由 RGB 三色組成的數組
         */
        static function hex2rgb($color, $default = 'ffffff')
        {
        $hex = trim($color, '#&Hh');
        $len = strlen($hex);
        if ($len == 3)
        {
            $hex = "{$hex[0]}{$hex[0]}{$hex[1]}{$hex[1]}{$hex[2]}{$hex[2]}";
        }
        elseif ($len < 6)
        {
            $hex = $default;
        }
        $dec = hexdec($hex);
        return array(($dec >> 16) & 0xff, ($dec >> 8) & 0xff, $dec & 0xff);
        }
}

/**
* Helper_ImageGD 類封裝了一個 gd 句柄,用於對圖像進行操作
*
* @author YuLei Liao <[email protected]>
* @version $Id: image.php 1937 2009-01-05 19:09:40Z dualface $
* @package helper
*/
class Helper_ImageGD
{
    /**
     * GD 資源句柄
     *
     * @var resource
     */
    protected $_handle = null;

    /**
     * 構造函數
     *
     * @param resource $handle GD 資源句柄
     */
    function __construct($handle)
    {
        $this->_handle = $handle;
    }

    /**
     * 析構函數
     */
    function __destruct()
    {
            $this->destroy();
    }

    /**
     * 快速縮放圖像到指定大小(質量較差)
     *
     * @param int $width 新的寬度
     * @param int $height 新的高度
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function resize($width, $height)
    {
        if (is_null($this->_handle)) return $this;

        $dest = imagecreatetruecolor($width, $height);
        imagecopyresized($dest, $this->_handle, 0, 0, 0, 0,
            $width, $height,
            imagesx($this->_handle), imagesy($this->_handle));
        imagedestroy($this->_handle);
        $this->_handle = $dest;
        return $this;
    }

    /**
     * 縮放圖像到指定大小(質量較好,速度比 resize() 慢)
     *
     * @param int $width 新的寬度
     * @param int $height 新的高度
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function resampled($width, $height)
    {
        if (is_null($this->_handle)) return $this;
        $dest = imagecreatetruecolor($width, $height);
        imagecopyresampled($dest, $this->_handle, 0, 0, 0, 0,
            $width, $height,
            imagesx($this->_handle), imagesy($this->_handle));
        imagedestroy($this->_handle);
        $this->_handle = $dest;
        return $this;
    }

    /**
     * 調整圖像大小,但不進行縮放操作
     *
     * 用法:
     * @code php
     * $image->resizeCanvas($width, $height, 'top-left');
     * @endcode
     *
     * $pos 參數指定了調整圖像大小時,圖像內容按照什麼位置對齊。
     * $pos 參數的可用值有:
     *
     * -   left: 左對齊
     * -   right: 右對齊
     * -   center: 中心對齊
     * -   top: 頂部對齊
     * -   bottom: 底部對齊
     * -   top-left, left-top: 左上角對齊
     * -   top-right, right-top: 右上角對齊
     * -   bottom-left, left-bottom: 左下角對齊
     * -   bottom-right, right-bottom: 右下角對齊
     *
     * 如果指定了無效的 $pos 參數,則等同於指定 center。
     *
     * @param int $width 新的高度
     * @param int $height 新的寬度
     * @param string $pos 調整時圖像位置的變化
     * @param string $bgcolor 空白部分的默認顏色
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function resizeCanvas($width, $height, $pos = 'center', $bgcolor = '0xffffff')
    {
        if (is_null($this->_handle)) return $this;

        $dest = imagecreatetruecolor($width, $height);
        $sx = imagesx($this->_handle);
        $sy = imagesy($this->_handle);

        // 根據 pos 屬性來決定如何定位原始圖片
        switch (strtolower($pos))
        {
        case 'left':
            $ox = 0;
            $oy = ($height - $sy) / 2;
            break;
        case 'right':
            $ox = $width - $sx;
            $oy = ($height - $sy) / 2;
            break;
        case 'top':
            $ox = ($width - $sx) / 2;
            $oy = 0;
            break;
        case 'bottom':
            $ox = ($width - $sx) / 2;
            $oy = $height - $sy;
            break;
        case 'top-left':
        case 'left-top':
            $ox = $oy = 0;
            break;
        case 'top-right':
        case 'right-top':
            $ox = $width - $sx;
            $oy = 0;
            break;
        case 'bottom-left':
        case 'left-bottom':
            $ox = 0;
            $oy = $height - $sy;
            break;
        case 'bottom-right':
        case 'right-bottom':
            $ox = $width - $sx;
            $oy = $height - $sy;
            break;
        default:
            $ox = ($width - $sx) / 2;
            $oy = ($height - $sy) / 2;
        }

        list ($r, $g, $b) = Helper_Image::hex2rgb($bgcolor, '0xffffff');
        $bgcolor = imagecolorallocate($dest, $r, $g, $b);
        imagefilledrectangle($dest, 0, 0, $width, $height, $bgcolor);
        imagecolordeallocate($dest, $bgcolor);

        imagecopy($dest, $this->_handle, $ox, $oy, 0, 0, $sx, $sy);
        imagedestroy($this->_handle);
        $this->_handle = $dest;

        return $this;
    }

    /**
     * 在保持圖像長寬比的情況下將圖像裁減到指定大小
     *
     * crop() 在縮放圖像時,可以保持圖像的長寬比,從而保證圖像不會拉高或壓扁。
     *
     * crop() 默認情況下會按照 $width 和 $height 參數計算出最大縮放比例,
     * 保持裁減後的圖像能夠最大程度的充滿圖片。
     *
     * 例如源圖的大小是 800 x 600,而指定的 $width 和 $height 是 200 和 100。
     * 那麼源圖會被首先縮小為 200 x 150 尺寸,然後裁減掉多余的 50 像素高度。
     *
     * 用法:
     * @code php
     * $image->crop($width, $height);
     * @endcode
     *
     * 如果希望最終生成圖片始終包含完整圖像內容,那麼應該指定 $options 參數。
     * 該參數可用值有:
     *
     * -   fullimage: 是否保持完整圖像
     * -   pos: 縮放時的對齊方式
     * -   bgcolor: 縮放時多余部分的背景色
     * -   enlarge: 是否允許放大
     * -   reduce: 是否允許縮小
     *
     * 其中 $options['pos'] 參數的可用值有:
     *
     * -   left: 左對齊
     * -   right: 右對齊
     * -   center: 中心對齊
     * -   top: 頂部對齊
     * -   bottom: 底部對齊
     * -   top-left, left-top: 左上角對齊
     * -   top-right, right-top: 右上角對齊
     * -   bottom-left, left-bottom: 左下角對齊
     * -   bottom-right, right-bottom: 右下角對齊
     *
     * 如果指定了無效的 $pos 參數,則等同於指定 center。
     *
     * $options 中的每一個選項都可以單獨指定,例如在允許裁減的情況下將圖像放到新圖片的右下角。
     *
     * @code php
     * $image->crop($width, $height, array('pos' => 'right-bottom'));
     * @endcode
     *
     * @param int $width 新的寬度
     * @param int $height 新的高度
     * @param array $options 裁減選項
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function crop($width, $height, $options = array())
    {
        if (is_null($this->_handle)) return $this;

        $default_options = array(
            'fullimage' => false,
            'pos'       => 'center',
            'bgcolor'   => '0xfff',
            'enlarge'   => false,
            'reduce'    => true,
        );
        $options = array_merge($default_options, $options);

        // 創建目標圖像
        $dest = imagecreatetruecolor($width, $height);
        // 填充背景色
        list ($r, $g, $b) = Helper_Image::hex2rgb($options['bgcolor'], '0xffffff');
        $bgcolor = imagecolorallocate($dest, $r, $g, $b);
        imagefilledrectangle($dest, 0, 0, $width, $height, $bgcolor);
        imagecolordeallocate($dest, $bgcolor);

        // 根據源圖計算長寬比
        $full_w = imagesx($this->_handle);
        $full_h = imagesy($this->_handle);
        $ratio_w = doubleval($width) / doubleval($full_w);
        $ratio_h = doubleval($height) / doubleval($full_h);

        if ($options['fullimage'])
        {
            // 如果要保持完整圖像,則選擇最小的比率
            $ratio = $ratio_w < $ratio_h ? $ratio_w : $ratio_h;
        }
        else
        {
            // 否則選擇最大的比率
            $ratio = $ratio_w > $ratio_h ? $ratio_w : $ratio_h;
        }

        if (!$options['enlarge'] && $ratio > 1) $ratio = 1;
        if (!$options['reduce'] && $ratio < 1) $ratio = 1;

        // 計算目標區域的寬高、位置
        $dst_w = $full_w * $ratio;
        $dst_h = $full_h * $ratio;

        // 根據 pos 屬性來決定如何定位
        switch (strtolower($options['pos']))
        {
        case 'left':
            $dst_x = 0;
            $dst_y = ($height - $dst_h) / 2;
            break;
        case 'right':
            $dst_x = $width - $dst_w;
            $dst_y = ($height - $dst_h) / 2;
            break;
        case 'top':
            $dst_x = ($width - $dst_w) / 2;
            $dst_y = 0;
            break;
        case 'bottom':
            $dst_x = ($width - $dst_w) / 2;
            $dst_y = $height - $dst_h;
            break;
        case 'top-left':
        case 'left-top':
            $dst_x = $dst_y = 0;
            break;
        case 'top-right':
        case 'right-top':
            $dst_x = $width - $dst_w;
            $dst_y = 0;
            break;
        case 'bottom-left':
        case 'left-bottom':
            $dst_x = 0;
            $dst_y = $height - $dst_h;
            break;
        case 'bottom-right':
        case 'right-bottom':
            $dst_x = $width - $dst_w;
            $dst_y = $height - $dst_h;
            break;
        case 'center':
        default:
            $dst_x = ($width - $dst_w) / 2;
            $dst_y = ($height - $dst_h) / 2;
        }

        imagecopyresampled($dest,  $this->_handle, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $full_w, $full_h);
        imagedestroy($this->_handle);
        $this->_handle = $dest;

        return $this;
    }

    /**
     * 保存為 JPEG 文件
     *
     * @param string $filename 保存文件名
     * @param int $quality 品質參數,默認為 80
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function saveAsJpeg($filename, $quality = 80)
    {
        imagejpeg($this->_handle, $filename, $quality);
    }

    /**
     * 保存為 PNG 文件
     *
     * @param string $filename 保存文件名
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function saveAsPng($filename)
    {
        imagepng($this->_handle, $filename);
    }

    /**
     * 保存為 GIF 文件
     *
     * @param string $filename 保存文件名
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function saveAsGif($filename)
    {
        imagegif($this->_handle, $filename);
    }

    /**
     * 銷毀內存中的圖像
     *
     * @return Helper_ImageGD 返回 Helper_ImageGD 對象本身,實現連貫接口
     */
    function destroy()
    {
            if (!$this->_handle)
            {
            @imagedestroy($this->_handle);
            }
        $this->_handle = null;
        return $this;
    }
}

調用方法

<?php
$image = Helper_Image::createFromFile('c:a.jpg','jpg');
$image->resampled(100, 100);  //縮放到100px * 100PX
$image->saveAsJpeg('c:a_output.jpg', 100);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved