php操作数据库读取出来的图片流并GD编辑图片


这个是切割裁切图片程序的主功能页面,里面主要是通过jcrop这个jq插件实现的核心功能。

大概的流程是,当选中一个图片的时候,先将图片直接upload上服务器,这个是原图,而当你需要裁切的时候,那么那个时候提交的仅仅是裁切的一些参数,比如坐标xy,宽高wh,然后通过这个参数,把从服务器取出来的原图进行GD2库的一些函数代码1:html端

<script type="text/javascript" src="__STATIC__/js/jquery.Jcrop.js">
</script>
<div style="padding:3px;align:center">
    <table width="370px">
        <tr>
            <td width="60%">
                原始图:
                <br/>
                <img src="<{:U('Avatar/getAvatar')}>?sid=<{$server_id}>&rid=<{$role_id}>&rand=xxxx"
                id="<{$prefix}>_roleHeadIconPrev" class="<{$prefix}>_roleHeadIconPrev"
                alt="avatar" style="width:200px;height:200px;" />
            </td>
            <td width="40%">
                <p style="padding-left:20px;">
                    <font color="#999999">
                        支持JPG图片格式,建议尺寸为90px*90px,大小500K以下;
                    </font>
                    <br/>
                    <br/>
                    预览图:
                    <br/>
                    <div style="width:90px;height:90px;overflow:hidden;">
                        <img src="<{:U('Avatar/getAvatar')}>?sid=<{$server_id}>&rid=<{$role_id}>&rand=xxxx"
                        id="<{$prefix}>_roleHeadIconTget" alt="<{$prefix}>_roleHeadIconTget">
                    </div>
                </p>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <form id="uploadAvatarForm" method="post" enctype="multipart/form-data">
                    <input type="hidden" name="info[server_id]" value="<{$server_id}>" />
                    <input type="hidden" name="info[role_id]" value="<{$role_id}>" />
                    <input type="file" name="upload_avatar" id="inputavatarfile" />
                </form>
                <p>
                    <span style="color:#FF0000" id="<{$prefix}>_roleHeadIconTips">
                        请选择图片后裁切,不裁切将保存原图
                    </span>
                </p>
            </td>
        </tr>
        <tr>
            <td colspan="2" align="center">
                <div>
                    <form id="resetAvatarForm" action="" method="post">
                        <input type="hidden" name="info[server_id]" value="<{$server_id}>" />
                        <input type="hidden" name="info[role_id]" value="<{$role_id}>" />
                        <input type="hidden" id="x" name="info[size][x]">
                        <input type="hidden" id="y" name="info[size][y]">
                        <input type="hidden" id="w" name="info[size][w]">
                        <input type="hidden" id="h" name="info[size][h]">
                        <button type="button" id="<{$prefix}>_btn_savecut" onclick="javascript:cutAvatarImages();">
                            保存裁切
                        </button>
                        <button type="button" id="<{$prefix}>_btn_close" onclick="javascript:close_avatar_upload();">
                            取消裁切并保存
                        </button>
                    </form>
                </div>
            </td>
        </tr>
    </table>
</div>
<script>
    //这里创建一个图像保存到内存,并没有添加到 HTML 中,只是个参考
    var avatarRateX, avatarRateY, avatarRateW, avatarRateH;
    //var avatarRateX=1,avatarRateY=1,avatarRateW=1,avatarRateH=1;
    function changePreviewSize() {
        $("<img/>").attr("src", "<{:U('Avatar/getAvatar')}>?sid=<{$server_id}>&rid=<{$role_id}>&rand=" + Math.random()).load(function() {
            var avatarRealSize = this;
            /*
$(".<{$prefix}>_roleHeadIconPrev").each(function(index,element){
avatarRateX = avatarRealSize.width/200;
avatarRateY = avatarRealSize.height/200;
//alert(element.style.height);
});*/
            avatarRateX = avatarRealSize.width / 200;
            avatarRateY = avatarRealSize.height / 200;
            //alert(avatarRateY);
        });
    }
    $(document).ready(function() {
        changePreviewSize(); //捣鼓一下预览区域的宽高率rate
        //2秒捣鼓一下预览区域的宽高率rate
        //setTimeout(changePreviewSize(), 2000);
        $("#inputavatarfile").change(function() {
            $("#<{$prefix}>_roleHeadIconTips").show(1000);
            $("#<{$prefix}>_roleHeadIconTips").html("正在上传请稍后...");
            //submit the form
            $('#uploadAvatarForm').submit();
        });

        //首次上传
        $('#uploadAvatarForm').form({
            url: "<{:U('Avatar/uploadImg')}>",
            onSubmit: function() {
                // do some check return false to prevent submit;
            },
            success: function(res) {
                //alert(res);
                if (res > 0) {
                    //$.messager.alert('提示信息', '操作成功', 'info');
                    //$("#roleHeadIconAvatarImg")[0].src="<{:U('Avatar/getAvatar')}>?sid=<{$server_id}>&rid=<{$role_id}>&rand="+Math.random();
                    $("#<{$prefix}>_roleHeadIconTips").html("已选择图片,请裁切!...");
                    $("#<{$prefix}>_roleHeadIconTips").fadeTo("slow", 0.6);
                    reloadImgResource(); //从服务器更新全部img资源
                    changePreviewSize(); //捣鼓一下预览区域的宽高率rate
                } else {
                    $.messager.alert('提示信息', '操作失败,请稍后再试', 'error');
                }
            },
            error: function() {
                alert('上传出错');
                //$(".loading").hide();
            }
        });

    });
    /*
*/
    //再次裁切form-裁切按钮
    $('#resetAvatarForm').form({
        url: "<{:U('Avatar/cropImg')}>",
        onSubmit: function() {
            changePreviewSize(); //捣鼓一下预览区域的宽高率rate
            // do some check return false to prevent submit;
        },
        success: function(res) {
            if (res > 0) {
                /**/
                $("#<{$prefix}>_roleHeadIconTget").css({
                    width: "100px",
                    height: "100px",
                    marginLeft: "0px",
                    marginTop: "0px"
                });
                $("#<{$prefix}>_roleHeadIconTips").html("已裁切成功!...");
                $("#<{$prefix}>_btn_savecut").hide("slow");
                $("#<{$prefix}>_btn_close").html("设置成功");
                $.messager.alert('提示信息', '操作成功', 'info');
                reloadImgResource(); //从服务器更新全部img资源
            } else {
                $.messager.alert('提示信息', '操作失败,请稍后再试', 'error');
            }
        },
        error: function() {
            alert('上传出错');
        }
    });
    jQuery(function($) {
        // Create variables (in this scope) to hold the API and image size
        var jcrop_api, boundx, boundy;

        $("#<{$prefix}>_roleHeadIconPrev").Jcrop({
            onChange: updatePreview,
            onSelect: updatePreview,
            aspectRatio: 1
        },
        function() {
            // Use the API to get the real image size
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];
            // Store the API in the jcrop_api variable
            jcrop_api = this;
        });

        function updatePreview(c) {
            $("#x").val(Math.round(c.x * avatarRateX));
            $("#y").val(Math.round(c.y * avatarRateY));
            $("#w").val(Math.round(c.w * avatarRateX));
            $("#h").val(Math.round(c.h * avatarRateY));

            if (parseInt(c.w) > 0) {
                var rx = 100 / c.w;
                var ry = 100 / c.h;

                $("#<{$prefix}>_roleHeadIconTget").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"
                });
            };
        };
    });
    function cutAvatarImages() {
        //alert('cutAvatarImages');
        if (!checkCoords()) return false;
        //submit the form
        $('#resetAvatarForm').submit();
    }
    function checkCoords() {
        if (parseInt($("#w").val())) return true;
        $.messager.alert('提示信息', '请在原图上拖出裁切的选区', 'error');
        return false;
    };
    function reloadImgResource() {
        $("img").each(function(index, element) {
            //$(this)[index].src = "bbbbbbaa2";
            element.src = element.src + "&rand=" + Math.random();
        });
        return;
    }
</script>

而在服务器端是通过php的GD2库进行图片裁切的:

代码2:php更新图片裁切的伪代码

<?php
/**
 * 重新设定图片大小
 * @param unknown $data 参数,不含二进制图片流
 * @return boolean 是否裁切成功
 */
function resetSize($data)
{
    $this->serverid = $data['server_id'];
    $this->change_game_db();

    $info = $data['size'];
    if (!empty($info)) {
        //print_r($info);die;
        //上传图片后切割的最大宽度和高度
        $width = 90;
        $height = 90;

        $imgStream = $this->showAvatarStream($data['server_id'], $data['role_id']);
        $temp = tempnam(sys_get_temp_dir(), 'Hsh');
        $handle = fopen($temp, 'w+');
        fwrite($handle, $imgStream);
        $handleSrc = imagecreatefromjpeg($temp);
        fclose($temp);

        //var_dump($im);exit();
        $handleNew = imagecreatetruecolor($width, $height);
        //var_dump($handleNew);exit();
        imagecopyresampled($handleNew, $handleSrc, 0, 0, $info['x'], $info['y'], $width, $height, $info['w'], $info['h']);

        $temp = tempnam(sys_get_temp_dir(), 'Hsh');
        imagejpeg($handleNew, $temp, 100);//
        $newStream = file_get_contents($temp);

        //header('Content-type: image/jpeg');
        //echo $imgStream;
        //echo imagejpeg($handleNew);
        //exit();

        $flag = $this->updateAvatar($data, $newStream);

        imagedestroy($handleNew);
        imagedestroy($handleSrc);

        return $flag;
        //header('Content-type: image/jpeg');
        //echo $imgStream;
        //echo imagejpeg($handleNew);
        //exit();
    }
    return false;
}

大致就是这样子了。主要的思路,就是首先file输入框change的时候就将图片丢到服务器,然后如果直接关闭就不进行裁切就这样子了,否则就需要裁切,但是裁切的时候传入的也仅仅是四个参数(当然还包括构成唯一对象的图片id等),然后服务器取出资源,用以下核心对象操作,最后保存新的资源对象:
boolean imagecopyresampled (resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
$dst_image:目标图片resource资源标识符
$src_image:源图片resource资源标识符
$dst_x:目标图片的int开始x坐标
$dst_y:目标图片的int开始y坐标
$src_x:源图片读取区域int的x坐标
$src_y:源图片读取区域int的y坐标
$dst_w:目标画布的int宽度
$dst_h:目标画布的int高度
$src_w:源画布读取的int宽度
$src_h:源画布读取的int高度
其次要注意的是:从数据库base64解压出来的是图片流,而不是图片资源标识符,需要将流保存到唯一的临时文件,然后获取图片标识符,然后进行gd库的操作。


原文链接:https://blog.yongit.com/note/94128.html