本来是想用ImageMagick来实现这个功能,但是ImageMagick 的环境搭建了半天没搞定,就换成了GD库。等有时间再去研究ImageMagick吧。
为了简化业务人员的工作流程,需要在系统上开发一个小功能,用于拼接图片。原先的工作,需要业务人员通过ps去拼接一个长图。需求是省去ps的环节,业务人员只需上传图片,并制定每个图片的title。就能自动生成一张长图。
以下开发步骤,为个人开发过程处理思路。

分析需求目标

通过分析得知。一份长图可以大致分为四个部分。
一个大标题图。
一个logo图
一个图片小标题图。
一张内容图。
当然,除了大标题外,其他的图肯定不止一个。只是相同点是这些。剩下的是如何去拼接这个循环体。

需求拆分

清楚需求后,就可以开始动手去实现。但是一个整体功能,无法下手。这时候,需要将大功能拆分成一个个小功能去实现。

等比例压缩图片
因为上传的图片并非同一大小,而拼接的长图需要一个统一的宽度。所以需要将不同尺寸的图片转换成相同的宽度。

public function PicCompress($src,$out_with=468){// 获取图片基本信息list($width, $height, $type, $attr) = getimagesize($src);// 获取图片后缀名$pictype = image_type_to_extension($type,false);// 拼接方法$imagecreatefrom = "imagecreatefrom".$pictype;// 打开传入的图片$in_pic = $imagecreatefrom($src);// 压缩后的图片长宽$new_width = $out_with;$new_height = $out_with/$width*$height;// 生成中间图片$temp = imagecreatetruecolor($new_width,$new_height);// 图片按比例合并在一起。imagecopyresampled($temp,$in_pic,0,0,0,0,$new_width,$new_height,$width,$height);// 销毁输入图片imagedestroy($in_pic);  return array($temp,$new_width,$new_height);}

思路是这样,首先获取传入图片的信息。获取图片的宽高。等比例转换宽高后,使用压缩后的宽高创建一张空白图片。再将两张图片合并。结果就是一张等比例缩放的图片。

计算拼图的高
因为gd库拼图的原理是先生成一张长图,再把每一个图片拼到长图上。因此我们需要先知道这张长图的高是多少(宽为确定值)。

public function PicALLHeight($arr,$width){$height = 0;if(count($arr) == count($arr,1)){  //一位数组的计算foreach ($arr as $key => $value) {$info = getimagesize($value);$height += $width/$info[0]*$info[1];}}else{foreach ($arr as $key => $value) {  //二维数组的计算foreach ($value as $k => $v) {$info = getimagesize($v);$height += $width/$info[0]*$info[1];}}}return $height;}

这里我直接根据我的业务,写了一个。函数中的判断为一维数组还是二维数组。思路是先获取传入图的宽高,通过确定的宽度,求缩放后的高度。再将每个高求和返回。即为内容图的高度。
将文字转换成图片
这一步比较复杂,我使用了一个简单的算法去解决。
对于文字部分的需求是这样的。要求文字必须居中处理。因为gd库并不支持html标签生成。所以需要计算来确定文字是否居中。
这是我第一版本解决方法

public function Fonttopic(){// header("Content-type: image/jpeg");// 给文字指定一个编码,避免乱码mb_internal_encoding("UTF-8");  $im =imagecreate(468,100);  $background_color = ImageColorAllocate ($im, 255, 255, 255);  $col = imagecolorallocate($im, 0, 0, 0);  $font="fonts/WRYH.ttf"; //字体所放目录  $come="凤的天啊!-年舍得离开-阿斯蒂了空间发拉克丝敦伦尽分拉看似简单法兰克圣诞节放按时交电费的李开复加速离开的减肥拉数据东风逻辑了"; $txt_max_width = intval(0.8*468);$content = "";for ($i=0;$i<mb_strlen($come);$i++) {$letter[] = mb_substr($come, $i, 1);}foreach ($letter as $l) {$teststr = $content." ".$l;$testbox = imagettfbbox(10,0,$font,$teststr);// 判断拼接后的字符串是否超过预设的宽度。超出宽度添加换行if (($testbox[2] > $txt_max_width) && ($content !== "")) {$content .= "\n";}$content .= $l;}$txt_width = $testbox[2]-$testbox[0];$y = 100 * 0.5; // 文字从何处的高度开始$x = (468 - $txt_width) / 2; //文字居中// echo $x;die;imagettftext($im,10,0,$x,$y,$col,$font,$content); //写 TTF 文字到图中  // die;// imagejpeg($im);return $im;}

思路。将文字字符串,拆分成单个字。存到数组中。再通过遍历数组。不断增加字,去判断这行字是否超出所设定的宽度。如果超出则换行。
执行结果
执行之后发现,忽略了一个问题。这种做法最后一行没法居中。

第二个解决方法
为了解决这个问题,我把加了换行符的字符串。又拆分成一个数组。再去遍历这个数组,一行一行的网图片上拼。

public function FontToPic($text,$font_size=10,$pic_hight=100,$pic_width=468){// header("Content-type: image/jpeg");  mb_internal_encoding("UTF-8");  $im =imagecreate($pic_width,$pic_hight);  $background_color = ImageColorAllocate ($im, 255, 255, 255);  $col = imagecolorallocate($im, 0, 0, 0);  $font="fonts/WRYH.ttf"; //字体所放目录  $come=$text;   /*水平居中(换行),固定字号*/$txt_max_width = intval(0.8*$pic_width);$content = "";for ($i=0;$i<mb_strlen($come);$i++) {$letter[] = mb_substr($come, $i, 1);}// var_dump($letter);die;foreach ($letter as $l) {$teststr = $content." ".$l;$testbox = imagettfbbox($font_size,0,$font,$teststr);// var_dump($testbox);die;// 判断拼接后的字符串是否超过预设的宽度if (($testbox[2] > $txt_max_width) && ($content !== "")) {$content .= "\n";}$content .= $l;}$test = explode("\n",$content);// var_dump($test);die;// $fbox = imagettfbbox(10,0,$font,$come);// echo  1;die;$txt_width = $testbox[2]-$testbox[0];$txt_height = $testbox[0]-$testbox[7];$y = ($pic_hight * 0.8)-((count($test)-1)*$txt_height); // baseline of text at 90% of $img_height// var_dump($txt_height);die;// imagettftext($im,$font_size,0,$x,$y,$col,$font,$content); //写 TTF 文字到图中  foreach ($test as $key => $value) {$textbox = imagettfbbox($font_size,0,$font,$value);$txt_height = $textbox[0]-$textbox[7];$text_width = $textbox[2]-$textbox[0];$x = ($pic_width - $text_width) / 2;imagettftext($im,$font_size,0,$x,$y,$col,$font,$value);$y = $y+$txt_height+2; // 加2为调整行距}return $im;}


这里需要说明一下代码中的字体,因为gd库生成文字图片时需要指定一种字体。所有想要什么字体,需要到网上下载才能使用。
到此小功能都已解决。接下来就是如何去拼接这个数组,如何去遍历这个数组,生成想要的结果图片。

功能实现

懒得再去写代码,这里从项目和中拷贝生成图片部分的代码。

try {/** 计算长图高* $this->PicALLHeight($for_length,468) => 点位图总高(468为图片压缩后宽度);* (count($for_length,1)-count($for_length))*100  =>点位图数量乘于100;100为点位文字图高,相减为只求二维的数量。* count($image_arr)*100  =>排期数量乘于100;100为排期文字图高.* PicALLHeight($media_for_length,234)  =>媒体图总高(234为图片压缩后宽度) ;*/$pic_tall = Common::PicALLHeight($for_length,468)+(count($for_length,1)-count($for_length))*100+count($image_arr)*100+Common::PicALLHeight($media_for_length,234);// 创建长图 $temp = imagecreatetruecolor(468,$pic_tall);$color = imagecolorAllocate($temp,255,255,255);   //分配一个白色底色imagefill($temp,0,0,$color);$add_tall = 0;// $ymd = date('-Ymd',time()); //排期命名+日期// var_dump($image_arr);die;foreach ($image_arr as $k => $v) {// 创建排期名称文字图片// $schedule_info=Schedule::CheckSchedule($k);// var_dump($schedule_info);die;$font_pic=Common::FontToPic($copy_schedule_name[$k],18);// header('Content-Type: image/jpeg');// imagejpeg($font_pic);die;imagecopymerge($temp,$font_pic,0,$add_tall,0,0,468,100,100);$add_tall += 100; foreach ($v as $ke => $val) {// 创建大媒体图片list($open_pic,$width,$height) = Common::PicCompress($all_media_arr[$ke],234);imagecopymerge($temp,$open_pic,117,$add_tall,0,0,$width,$height,100);$add_tall += $height;foreach ($val as $key => $value) {$font_pic=Common::FontToPic($key,10.5);imagecopymerge($temp,$font_pic,0,$add_tall,0,0,468,100,100);$add_tall += 100; list($open_pic,$width,$height) = Common::PicCompress($value,468);imagecopymerge($temp,$open_pic,0,$add_tall,0,0,$width,$height,100);// echo $width.'|||||';$add_tall += $height;}}}  // header("Content-type: image/jpeg");  // imagejpeg($temp);// die;$savepath=Yii::$app->basePath.'/uploads/longpic/'.date('Ym',time()).'/';if(!is_dir($savepath)){mkdir($savepath,0777,true);}$savafile = $savepath.$pic_schedule_id.time().'.jpg';// echo $savepath;die;imagejpeg($temp,$savafile,100);}catch(\Exception $e) {   //捕获生成长图时的任意异常,异步返回标识。$this->returnJson(false,'图片生成出错','2');}

到此拼接图片功能就完成了。需要注意imagecopymerge这个函数。这是一个合并图片的函数,需要指定原图的宽高和结果图的宽高,复制的起始坐标。函数的必须参数比较多。需要弄懂每个参数的用法。
imagejpeg函数用于生成图片。有三个参数,第一个参数为图片对象,第二个参数为生成的图片名称,第三个参数为图片的质量。0–100,值越大质量越高。
在开发工程中,可能思路不会那么清晰。这需要不断的取验证自己的想法。整体流程没问题,但是在这个过程中,可能需要反复的去调整。
效果图如下
文章没有很详细的去介绍用到的每个函数。但是对gd库这几个函数有研究,加上代码中的注释应该都可以看懂。主要还是思路,思路正确了,实现的方法有很多种。

使用php的GD库拼接图片相关推荐

  1. PHP用gd库给图片添加水印,php用GD库给图片添加水印

    php用GD库给图片添加文字水印,整个代码比较简单,DEMO如下: /*打开图片*/ //1.配置图片路径 $src = "aeroplane.jpg"; //2.获取图片信息 $ ...

  2. php 图片上加文字,php使用GD库实现图片上添加文字的方法(代码)

    本篇文章给大家带来的内容是关于php使用GD库实现图片上添加文字的方法(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 我们可以利用php的gd库扩展来对我们的图片进行处理,例 ...

  3. php颜色底色,PHP GD 库自定义图片背景颜色

    缘起 开发"微信推广海报"的时, 背景图片未覆盖的地方默认会被黑色填充. 而我希望改成白色背景, 以对用户更友好一些. 但是无论设置成什么颜色, 图片的背景颜色一直都是黑色, 无法 ...

  4. php 用gd库在图片上写文字,并处理文字糊模问题

    今天有个需求,用php在一张图片上写文字. 这个不是挺简单的嘛?我在一个test.php文件上,敲出6行代码,搞定 img=imagecreatefrompng("C:\Users\Admi ...

  5. PHP面向对象——GD库实现图片水印和缩略图

    今天的实现目标就是使用GD库完成对图片加水印和图 片缩略图两个功能 动身前逻辑准备 属性:路径功能:构造方法生成水印的方法获取图片信息获取位置信息(123 456 789)创建图片资源合并图片资源重新 ...

  6. 使用GD库为图片打水印

    一.文字水印 文字水印就是在图片上加上文字,主要使用gd库的imagefttext方法,并且需要字体文件. 代码如下: $dst_path = 'dst.jpg'; //创建图片的实例 $dst = ...

  7. php获取微信素材图片乱码,如何解决在php用gd库输出图片到微信浏览器出现乱码...

    如何解决在php用gd输出图片到微信浏览器出现乱码? 程序如下:<?php $im = imagecreate(200, 300); $white = imagecolorallocate($i ...

  8. php GD库实现图片合并、文本居中 案例:生成分享海报

    因有需求要做到用php服务端去生成分享海报,并要求把头像.文字.以及二维码跟海报背景图合并,所以研究了一下php的GD库来实现该需求 本次用到的函数介绍 getimagesize 获取图片的宽高 im ...

  9. php gd库合成图片并在图片上加文字

    背景图 图1 图2 /*** 将图1和图2画在背景图bgimg上*/$bgimg = "bgimg.jpg"; $bg_info = getimagesize($bgimg);// ...

最新文章

  1. 石川es6课程---4、箭头函数
  2. Install vsftpd on centos
  3. 【easysnmp】python snmp IF-MIB::ifPhysAddress messy code,解析mac地址乱码
  4. 微软认证及课程简写含义
  5. Stats mac免费版 2.4.9(支持M1驱动器的mac,最新macOS系统)
  6. 【华为云技术分享】前端工程师必备:从浏览器的渲染到性能优化
  7. [原创]商品条码管理与条码打印管理软件的实现
  8. package.json作用
  9. hibernate 之HQL查询实例
  10. java 多线程任务队列_精简的java 线程池与任务队列
  11. python web 模版引擎集合
  12. 国产各数据库厂商数据库梳理
  13. vscode node 乱码 非中文乱码
  14. 2021年高压电工模拟考试系统及高压电工考试试题
  15. 清明上河图对计算机技术的启发,风俗画的定义与《清明上河图》的启示
  16. ThreadPoolExecutor(一)——简介
  17. goahead移植和使用
  18. mysql _数据库表的创建
  19. 神经网络参数量和计算量,神经网络是参数模型吗
  20. RT-thread应用讲解——U盘(usb host)

热门文章

  1. Android用Canvas画钟表仪
  2. 人脸识别门禁在安防弱电系统中的具体方案
  3. springboo集成bboss-elasticsearch实现elasticsearch客户端
  4. 怎样写出优秀的的研究计划 (Research Proposal) ?
  5. 开关电源MOS管选型500V、600V、650V参数
  6. 腾讯收购Foxmail的意图
  7. 【电路补习笔记】8、稳压电路 —— 线性电源及LDO
  8. 第四章 Pandas统计分析基础
  9. 计算机专业学微积分有什么用,学微积分有什么用啊?
  10. 毕设之基金定投小程序