博客已转移:PHP上传裁切

   发现经常有人在技术群里问要PHP图片上传裁切并且预览的例子。今天正好有时间,就亲自做了一个,同时把方法公布出来,让大家可以理解,学会如何用ThinkPHP+jcrop做这个例子。首先先下来jcrop,网址:http://deepliquid.com/content/Jcrop_Download.html

   下载完成后,里面有js,demo,css等文件夹.demo里是例子,建议大家先看一下源代码.剩下的,跟我一起来做这个例子:

   1.下载ThinkPHP,然后新建项目,生成项目目录

   2.在Tpl中新建Index/index.html

代码如下

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>上传图片</title>
 <script>
     function setFile(f1){
        document.frm.logoImg.value=f1;
     }
    </script>
</head>
<body>
<table border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td height="45" align="center" valign="middle">
        <form action="#" method="post"  name="frm"> 请选择上传的图片
              <input name="logoImg" id="logoImg"   type="text" size="30"/>
             <label style="cursor:hand" onClick="window.open('__URL__/upimg','上传图片','height=600,width=800,top=200,left=200')">上传图片</label><br/>
        </form>
    </td>
  </tr>
</table>
</body>
</html>


这是一个上传,在点击上传图片以后,会弹出一个窗口,专门用来上传图片裁切。在Tpl/Index/下新建upimg.html

代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>上传图片</title>
<script language="javascript">
    function $(id){
        return document.getElementById(id);
    }
    function ok(){
         $("logoimg").src = $("filename").value;
     }
</script>
</head>
<body>
<table border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td height="45" align="center" valign="middle">
        <form action="__URL__/uploadf?submit=1" method="post" enctype="multipart/form-data" name="form1"> 请选择上传的图片
            <input type="file" name="filename" id="filename" onchange="ok()">
            <!-- MAX_FILE_SIZE must precede the file input field -->
            <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
            <input type="submit" name="Submit" value="上传">
        </form>
    </td>
  </tr>
</table>
</body>
</html>


我没有用TP自带的文件上传类,如果大家需要,可以改下,以上主要就是弹出一个上传文件的窗口,在这个窗口中会完成文件上传,裁切等操作。点击提交到Index/uploadf

Index/uploadf代码如下:

$path = "uploadfiles/";         //图片上传地址
                if (! file_exists ( $path )) {
                    mkdir ( "$path", 0700 );
                }
                $tp = array (
                        "image/gif",
                        "image/jpeg",
                        "image/png",
                        "image/jpg"
                );
                                                                                                                                                                                                                                             
                if (! in_array ( $_FILES ["filename"] ["type"], $tp )) {
                    echo "格式不对";
                    exit ();
                } // END IF
                                                                                                                                                                                                                                             
                if ($_FILES ["filename"] ["name"]) {
                    $file1 = $_FILES ["filename"] ["name"];
                    $file2 = $path . time () . $file1;
                    $flag = 1;
                }
                                                                                                                                                                                                                                             
                if ($flag)
                    $result = move_uploaded_file ( $_FILES ["filename"] ["tmp_name"], $file2 );
                if ($result) {
                                                                                                                                                                                                                                         
                    $this->assign('filename',$file2);
                    $this->display();
                }



上传完成以后会直接跳转到uploadf.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<script src="__STYLE__/js/jquery.min.js"></script>
<script src="__STYLE__/js/jquery.Jcrop.js"></script>
<link rel="stylesheet" href="__STYLE__/css/main.css" type="text/css" />
<link rel="stylesheet" href="__STYLE__/css/demos.css" type="text/css" />
<link rel="stylesheet" href="__STYLE__/css/jquery.Jcrop.css" type="text/css" />
<script language='javascript'>
    jQuery(function($) {
        var jcrop_api, boundx, boundy,
        $preview = $('#preview-pane'), $pcnt = $('#preview-pane .preview-container'), $pimg = $('#preview-pane .preview-container img'),
        xsize = $pcnt.width(), ysize = $pcnt.height();
        console.log('init', [ xsize, ysize ]);
        $('#target').Jcrop({
            onChange : updatePreview,
            onSelect : updatePreview,
            aspectRatio : xsize / ysize
        }, function() {
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];
            jcrop_api = this;
            $preview.appendTo(jcrop_api.ui.holder);
        });
        function updatePreview(c) {
            if (parseInt(c.w) > 0) {
                var rx = xsize / c.w;
                var ry = ysize / c.h;
                $pimg.css({
                    width : Math.round(rx * boundx) + 'px',
                    height : Math.round(ry * boundy) + 'px',
                    marginLeft : '-' + Math.round(rx * c.x) + 'px',
                    marginTop : '-' + Math.round(ry * c.y) + 'px'
                });
                                                                                                                                                                                                                                   
                $('#x').val(c.x);
                $('#y').val(c.y);
                $('#w').val(c.w);
                $('#h').val(c.h);
            }
        }
        ;
        function updateCoords(c){
                                                                                                                                                                                                                                   
            };
                                                                                                                                                                                                                               
    });
</script>
<style type="text/css">
.jcrop-holder #preview-pane {
    display: block;
    position: absolute;
    z-index: 2000;
    top: 10px;
    right: -240px;
    padding: 6px;
    border: 1px rgba(0, 0, 0, .4) solid;
    background-color: white;
    -webkit-border-radius: 6px;
    -moz-border-radius: 6px;
    border-radius: 6px;
    -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
}
#preview-pane .preview-container {
    width: 170px;
    height: 250px;
    overflow: hidden;
}
</style>
<body>
    <div class="container">
        <div class="row">
            <div class="span12">
                <div class="jc-demo-box">
                    <img src="__ROOT__/{$filename}" id="target" alt="[Jcrop Example]" />
                    <div id="preview-pane">
                        <div class="preview-container">
                            <img src="__ROOT__/{$filename}" class="jcrop-preview"
                                alt="Preview" />
                        </div>
                    </div>
                    <div class="clearfix"></div>
                </div>
            </div>
        </div>
    </div>
    <form action="__URL__/uploadf?submit=cut" method="post" onsubmit="return checkCoords();">
            <input type="hidden" id="x" name="x" />
            <input type="hidden" id="y" name="y" />
            <input type="hidden" id="w" name="w" />
            <input type="hidden" id="h" name="h" />
            <input type="hidden" name="filename" value="{$filename}">
            <input type="submit" value="Crop Image" />
        </form>
    <!--     <img src="__ROOT__/{$filename}" alt="" /> -->
</body>
</html>



这里的代码比较长,慢慢解释吧,我直接复制的jcrop demo里的tutorial3.html,加载他自己需要的js,css。其中

#preview-pane .preview-container {
    width: 170px;
    height: 250px;
    overflow: hidden;
}


这部分CSS会影响到出来的裁切框的比例。以及预览处的大小。

$('#target').Jcrop({
            onChange : updatePreview,
            onSelect : updatePreview,
            aspectRatio : xsize / ysize
        }, function() {
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];
            jcrop_api = this;
            $preview.appendTo(jcrop_api.ui.holder);
        });



onChange和onSelect处的意思是裁切的时候要执行的js代码,说实话,我js和jq的水平很垃圾。所以不管了。

function updatePreview(c) {
            if (parseInt(c.w) > 0) {
                var rx = xsize / c.w;
                var ry = ysize / c.h;
                $pimg.css({
                    width : Math.round(rx * boundx) + 'px',
                    height : Math.round(ry * boundy) + 'px',
                    marginLeft : '-' + Math.round(rx * c.x) + 'px',
                    marginTop : '-' + Math.round(ry * c.y) + 'px'
                });
                                                                                                                                                                
                $('#x').val(c.x);
                $('#y').val(c.y);
                $('#w').val(c.w);
                $('#h').val(c.h);
            }
        }
        ;


这个后面我自己加了一个赋值,赋值给form表单中。然后在提交到php完成裁切工作


点击提交到uploadf中,可以自己先写一个图片裁切的类:

<?php
class Imgshot {
    private $filename;
    private $ext;
    private $x;
    private $y;
    private $x1;
    private $y1;
    private $width = 170;
    private $height = 250;
    private $jpeg_quality = 90;
    /**
     * 构造器
     */
    public function __construct() {
//      log_message ( 'debug', "Img_shot Class Initialized" );
    }
    /**
     * 初始化截图对象
     *
     * @param
     *          filename 源文件路径全明
     * @param
     *          width 截图的宽
     * @param
     *          height 截图的高
     * @param
     *          x 横坐标1
     * @param
     *          y 纵坐标1
     * @param
     *          x1 横坐标1
     * @param
     *          y1 横坐标2
     *        
     */
    public function initialize($filename, $x, $y, $x1, $y1) {
        if (file_exists ( $filename )) {
            $this->filename = $filename;
            $pathinfo = pathinfo ( $filename );
            $this->ext = $pathinfo ['extension'];
        } else {
            $e = new Exception ( 'the file is not exists!', 1050 );
            throw $e;
        }
        $this->x = $x;
        $this->y = $y;
        $this->x1 = $x1;
        $this->y1 = $y1;
    }
    /**
     * 生成截图
     * 根据图片的格式,生成不同的截图
     */
    public function generate_shot() {
        switch ($this->ext) {
            case 'jpg' :
                return $this->generate_jpg ();
                break;
            case 'png' :
                return $this->generate_png ();
                break;
            case 'gif' :
                return $this->generate_gif ();
                break;
            default :
                return false;
        }
    }
    /**
     * 得到生成的截图的文件名
     */
    private function get_shot_name() {
        $pathinfo = pathinfo ( $this->filename );
        $fileinfo = explode ( '.', $pathinfo ['basename'] );
        $filename = $fileinfo [0] . '_small.' . $this->ext;
        return 'uploadfiles/'.$filename;
    }
    /**
     * 生成jpg格式的图片
     */
    private function generate_jpg() {
        $shot_name = $this->get_shot_name ();
        $img_r = imagecreatefromjpeg ( $this->filename );
        $dst_r = ImageCreateTrueColor ( $this->width, $this->height );
                                                                                                     
        imagecopyresampled ( $dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1 );
        imagejpeg ( $dst_r, $shot_name, $this->jpeg_quality );
        return $shot_name;
    }
    /**
     * 生成gif格式的图片
     */
    private function generate_gif() {
        $shot_name = $this->get_shot_name ();
        $img_r = imagecreatefromgif ( $this->filename );
        $dst_r = ImageCreateTrueColor ( $this->width, $this->height );
                                                                                                     
        imagecopyresampled ( $dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1 );
        imagegif ( $dst_r, $shot_name );
        return $shot_name;
    }
    /**
     * 生成png格式的图片
     */
    private function generate_png() {
        $shot_name = $this->get_shot_name ();
        $img_r = imagecreatefrompng ( $this->filename );
        $dst_r = ImageCreateTrueColor ( $this->width, $this->height );
                                                                                                     
        imagecopyresampled ( $dst_r, $img_r, 0, 0, $this->x, $this->y, $this->width, $this->height, $this->x1, $this->y1 );
        imagepng ( $dst_r, $shot_name );
        return $shot_name;
    }
}
?>



这个是我在网上down的.~没自己写,自己可以根据需求扩展一下.


裁切操作:

    $filename=$this->cut();
                echo "<script language='javascript'>";
                echo "alert(\"上传成功!\");";
                echo "</script>";
                echo ("<input type=\"button\" name=\"Submit\" value=\"确定\" onClick=\"window.opener.setFile('" .$filename. "');window.close();\">");
                echo '<img src="'.__ROOT__.'/'.$filename.'" alt="" />';
//裁切的方法
    function cut(){
        import('ORG.Net.Imgshot');
        $imgshot=new Imgshot();
        $imgshot->initialize(SITE_PATH.'/'.$_REQUEST['filename'], $_REQUEST['x'], $_REQUEST['y'], $_REQUEST['x']+$_REQUEST['w'], $_REQUEST['y']+$_REQUEST['h']);
        $filename=$imgshot->generate_shot();
        return $filename;
    }



完成以后会直接echo出最后裁切的图片,并且还有一个确定按钮,点击确定以后,则会把裁切后图像的地址返回到最一开始的input[type="text"]。整个例子我还没有完善,大家可以根据需要自己去理解和完善。好了,如果不会的朋友可以加群:252799167问我。整个例子我已经发布到ThinkPHP的官网,大家可以下载。

http://www.thinkphp.cn/topic/9154.html


footer.jpg