zoukankan      html  css  js  c++  java
  • php 图片生成器

    一.需求

      最近公司由于有大量的海报要做,而且海报的布局规模都是一样的,只是内容不同,所以老板想我开发一个图片的生成器。可以根据你输入的内容生成海报图片。

      具体有需求有以下的需求

      1.可以根据将每条数据都是独立的

      2.每条数据都必须居中,如果是数据很长的时候还要自动换行

        3.可以将一个二维码生成在海报中,二维码是自己手动上传的

      4.海报的长度是随着内容的大小而变化的

    二.分析

      因为目标文件为图片格式的,所以我想到的方法是使用php的gd库来生成图片。所以以上需求我是通过以下方式去解决的。

      需求1解决方法,因为数据是一次性数据的,这是为了方便市场工作这样子设置的。所以我只能通过添加标识符来切割数据

      需求2解决方法,通过设置每行最长宽度来分割每条数据,并计算每天数据的长度,然后计算出文字位置的偏移量,这里提示一下imagettfbbox()函数可以计算文字段落的长度

      需求3解决方法,通过上传文件然后将二维码转化为规定规格的图片,再定位到画布中即可

      需求4解决方法,通过计算数据的行数,标题以及二维码的总高度,然后设置画布的长度

    三.实现过程

      ----------------------------------------------html-------------------------------------------------------------------------------------------------------------------------------

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
        <title>海报自助生成器</title>
        <link rel="stylesheet" type="text/css" href="./css/zui.min.css">
        <script src="./jquery-3.2.1.min.js"></script>
        <style>
     p{
                text-align: center;
            }
            form{
                width: 90%;
                max-width: 500px;
                margin: 0 auto;
                line-height: 1.8;
            }
            input.form-control{
                border:1px solid #72a197;
                outline: none;
            }
            select.form-control{
                border-color:#72a197;
            }
            select.form-control:focus{
                outline: none;
                border-color:#72a197;
                box-shadow:0 0 0;
            }
            .radio_space input {
                width: 16px;
                line-height: 0px;
                text-align: initial;
                padding: 0;
            }
            .container{
                text-align: center;
                width: 100vw;
                height: 480px;
                overflow: hidden;
                margin: 0 auto;
            }
            .haibao{
                width:100vw;
            }
            .recruit-title{}
            .img-uploading{
                display:inline-block;
                width:100%;
                height:60px;
                line-height: 60px;
                margin-bottom:10px;
                border-radius: 3px;
                box-sizing: border-box;
                border:1px solid #72a197;
                position:relative;
                text-align: center;
                text-decoration: none !important;
            }
            .img-p{
               /* position:absolute;*/
                font-size:45px;
                height:60px;
                width:100%;
                font-weight:100;
                color:#72a197;
                /*left:calc(50% - 30px);*/
                text-align:center;
            }
            .uploading{
                width:100%;
                height:60px;
                opacity:0;
                position: absolute;
                top: 0px;
            }
            .create{
                border: none !important;
                background:#ea6b51;
                color:#fff;
                text-shadow: none !important;
            }
            .welfare-title .txta{
               margin:10px 0;
               width:100%;
               height:150px;
               border-radius: 8px;
               border:1px solid #72a197;
               outline: none;
               padding:10px;
            }
             .welfare-title  .img-uploading{
                border:1px solid #8d6e63;
             }
             .welfare-title .img-p{
                 color:#8d6e63;
             }
             .activity-title .txta{
               margin:10px 0;
               width:100%;
               height:150px;
               border-radius: 8px;
               border:1px solid #72a197;
               outline: none;
               padding:10px;
             }
             .activity-title  .img-uploading{
                border:1px solid #78909c;
             }
             .activity-title .img-p{
                 color:#78909c;
             }
    
        </style>
        <script type="text/javascript">
            function changeimg(imgvalue){
                document.getElementById('haibao').src = "./template/t"+imgvalue+".jpg";
            }
        </script>
    </head>
    <body>
    <p></p>
    <p>妈妈再也不担心我不会p图了</p>
    
    <form action="toImage.php"  id= "uploadForm" class="space form-horizontal" method="POST"  enctype="multipart/form-data" >
        <!-- 手机类型 1为安卓手机 2为苹果手机 -->
        <input type="hidden" name="phoneType"  id="phoneType">
        <div class="main" style="padding-top: 20px;">
            <div class="activity-title">
                <div class="form-group">
                    <label class="col-xs-2">标题:</label>
                    <div class="col-md-6 col-xs-10">
                        <input class="form-control" name="title" placeholder="" />
                    </div>
                </div>
                 <textarea class="txta" name="content"></textarea>
                 <p style="color: red;">请在每条数据后面添加*</p>
                 <p style="color: red;">同一条数据请不要手动换行*</p>
                
            </div>
            <a href="#" class="img-uploading">
                <i class="img-p"  id="symbol">+</i>
                <input type="file" name="file" class="uploading">
            </a>
             <a href="#haibao"  class="btn btn-block create"  value="生成"  onclick="doUpload();">
            生成
            </a>
        </div>
    </form>
    
    <p style="margin-top: 20px;">请长按保存,不要直接右上角转发</p>
    <p id="exp">参考海报</p>
    
    <div class="container">
        <img id="haibao" class="haibao" src="./template/t1.png"/>
    </div>
    <script>
        $(".uploading").on("change",function(){
    
            if($(".uploading").val() != ""){
                $("#symbol").text("二维码已上传");
                $("#symbol").css("fontSize","20px");
            } 
        });
    
        function doUpload() {  
            var formData = new FormData($( "#uploadForm" )[0]);  
            $.ajax({  
                url: 'toImage.php' ,  
                type: 'POST',  
                data: formData,  
                async: false,  
                cache: false,  
                contentType: false,  
                processData: false,  
                success: function (returndata) {  
                    $("#haibao").attr("src",returndata);
                    $("#exp").hide();
                },  
                error: function (returndata) {  
               
                }  
             });  
        }  
    </script>
    </body>
    </html>

    下面是php文件信息

    <?php /**
     * @param int  $fontSize 字体大小
     * @param resource  $ttf 字体文件路径
     * @param string $str 字符串
     * @param  array $data  数据数组容器
     * @param  int $textWidth 行宽
     * @param  int $textHeight  行高
     * @param  int $top  距离顶部距离
     */
    
    function toCenter($fontSize, $ttf, $str, &$data, $textWidth,$textHeight,&$top)
    {
        $length = mb_strlen($str,"utf-8");
        $rowNum = 0;
        $count = count($data);
        $index = 0;
        for($i = 1; $i <=  $length ; $i++ )
        {
            $substr = mb_substr($str , $index , $i-$index,"utf-8");
            // var_dump($substr);
            $width = getTextInfo($fontSize, $ttf, $substr)['width'];
            if($width >= $textWidth && $width <= ($textWidth + $fontSize*2))
            {
                $index = $i;
                $data[$count+$rowNum]['top'] = $top;
                $data[$count+$rowNum]['left'] = (1129-$width)/2;
                $data[$count+$rowNum]['str'] = $substr;    
                $data[$count+$rowNum]['fontSize'] = $fontSize;    
                $rowNum++;
                $top += $textHeight;
            }
        }
        if($index!=$length){
            $data[$count+$rowNum]['top'] = $top;
            $data[$count+$rowNum]['left'] = (1129-$width)/2;
            $data[$count+$rowNum]['str'] = $substr;    
            $data[$count+$rowNum]['fontSize'] = $fontSize;    
            $rowNum++;
            $top += $textHeight;
        }
    
        return $data;
    
    }
    
    function getTextInfo($fontSize, $ttf, $str)
    {
        $data = imagettfbbox($fontSize, 0, $ttf, $str);
        $width = $data[2]-$data[0];
        $height = $data[1]-$data[7];
        return [
            'width' => $width,
            'height' => $height 
        ];
    }
    
    
    
    /**
    * 制作略缩图方法
    * @param string $src  文件路径
    * @param int $width  生成略缩图的宽度(只设置高度是则为等比例缩放)
    * @param int $height  生成略缩图的高度(只设置宽度是则为等比例缩放)
    * @param string $filename 生成略缩图图片保存路径
    */
    function makeThumb($src, $width = null, $height = null, $filename)
    {
        $srcData = getimagesize($src);
        list($srcWidth, $srcHeight, $srcType) = $srcData;
        if (empty($width))  
            $width = $srcWidth * ($height / $srcHeight);  
        if (empty($height))  
            $height = $srcHeight * ($width / $srcWidth);  
        switch ($srcType) {
            case '1':
                $imgType = 'gif';
                break;
            case '2':
                $imgType = 'jpeg';
                break;
            case '3':
                $imgType = 'png';
                break;
        }
    
           $imageCreateFun = 'imagecreatefrom'.$imgType;
           $srcImg = $imageCreateFun($src);
           $destImg = imagecreatetruecolor(intval($width),intval($height));
           imagecopyresampled($destImg, $srcImg,0,0,0,0,$width,$height,$srcWidth,$srcHeight);
    
           $imagefunc = 'image'.$imgType;
    
           $imagefunc($destImg,$filename.'.'.$imgType);
           return $filename.'.'.$imgType;
    }
    
    // // /************************************************处理二维码开始**************************************************************************/
    $codePath = '';
    $codeImageType = '';
    if ((($_FILES["file"]["type"] == "image/jpeg")||($_FILES["file"]["type"] == "image/jpg")||($_FILES["file"]["type"] == "image/png"))&& ($_FILES["file"]["size"] < 2097152))
    {
        if($_FILES["file"]["error"] > 0)
        {
            echo "发生错误" . $_FILES["file"]["error"] . ",请找TzSteady<br />";
            exit;
        }else
        {
            move_uploaded_file($_FILES["file"]["tmp_name"],"./code/" . date("Ymd").$_FILES["file"]["name"]);
            $codePath = "./code/" . date("Ymd").$_FILES["file"]["name"];
            $codePath = makeThumb($codePath,300,false,'./code/'.date("YmdHis"));
            $codeImageType = $_FILES["file"]["type"];
        }
    }else
    {
        echo "<script>
        alert('请上传小于2M的jpg/png/jpeg格式的二维码');
        </script>";
        exit;
    }
    /******************************************************处理二维码结束********************************************************************/
    
    
    $data = [];
    $titleTop = 300;
    $ttf = './ttf/fangzhengqingkebenyuesongjianti.TTF';
    $titleData = [];
    $title = trim($_POST['title']);
    toCenter(65, $ttf, $title, $titleData, 700,100,$titleTop);
    $top =400;
    $str = trim($_POST['content']);
    $charArr = explode("*",$str); 
    foreach ($charArr as $key => &$value) {
        $value = trim($value);
        if(empty($value)) continue;
            toCenter(30, $ttf, $value, $data, 800,60,$top);
    }
    $count = count($data);
    $fillNum = ceil(($count-3)+6);
    
    // /******************************画图开始********************************************/
    $headerPath = './template/head.png';
    $fillPath = './template/fill1.png';
    $footerPath = './template/footer1.png';
    $ttf = './ttf/fangzhengqingkebenyuesongjianti.TTF';
    $header = imagecreatefrompng($headerPath);
    $fill = imagecreatefrompng($fillPath);
    $footer = imagecreatefrompng($footerPath);
    switch ($codeImageType) {
        case 'image/jpeg':
            $code = imagecreatefromjpeg($codePath);
            break;
        case 'image/jpg':
            $code = imagecreatefromjpeg($codePath);
            break;
        case 'image/png':
            $code = imagecreatefrompng($codePath);
            if(empty($code))
            {
                $code = imagecreatefromjpeg($codePath);
            }
            break;
    }
    
    list($headerWidth,$headerHeight,$headerType) = getimagesize($headerPath);
    list($fillWidth,$fillHeight,$fillType) = getimagesize($fillPath);
    list($footerWidth,$footerHeight,$footerType) = getimagesize($footerPath);
    list($codeWidth,$codeHeight,$codeType) = getimagesize($codePath);
    $img = imagecreatetruecolor($headerWidth,$headerHeight+$fillHeight*$fillNum+$footerHeight);
    
    $result = imagecopy($img , $header,0,0,0,0,$headerWidth,$headerHeight);
    for($i = 0; $i < $fillNum ; $i++)
    {
        $result = imagecopy($img , $fill,0,$headerHeight+$fillHeight*$i,0,0,$fillWidth,$fillHeight);
    }
    $result = imagecopy($img , $footer,0,$headerHeight+$fillHeight*$fillNum,0,0,$footerWidth,$footerHeight);
    
    $result = imagecopy($img , $code,420,$fillHeight*($fillNum-1)+$headerHeight-30,0,0,$codeWidth,$codeHeight);
    $orange = ImageColorAllocate($img, 249,135,0);
    $white = ImageColorAllocate($img, 0,0,0);
    $titlered = ImageColorAllocate($img, 163,0,14);
    
    if(isset($titleData) && !empty($titleData))
    {
        foreach ($titleData as $key => &$value) {
            imagettftext($img, $value['fontSize'], 0, $value['left'], $value['top'] , $titlered, $ttf,$value['str']);    
        }
    }
    
    foreach ($data as $key => &$value) {
        imagettftext($img, $value['fontSize'], 0, $value['left'], $value['top'] , $white, $ttf,$value['str']);    
    }
    imagettftext($img, 25, 0, 320 ,$headerHeight+$fillHeight*($fillNum-1)-50, $titlered, $ttf,'有兴趣的同学可以加微信咨询');
    $filename = './img/'.date("Ymd-H-i-s").'.png';
    imagepng($img,$filename);
    echo $filename;
    
    
    
    
    // /****************************画图结束**********************************************/
  • 相关阅读:
    开源:不断创新的动力
    Inkpad中文翻译已合并到官方项目
    Inkpad绘图原理浅析
    Vectoroid
    发布大幅重构优化的 TouchVG 1.0.2
    清理掉一直想研究的开源项目
    函数指针调用方式
    音视频直播优化
    std::unique_lock与std::lock_guard区别示例
    c++容器的操作方法总结
  • 原文地址:https://www.cnblogs.com/TzSteady/p/8182748.html
Copyright © 2011-2022 走看看