PHP实现图片指定区域打印文字和图片

在一些通过模板制作效果图的需求中需要用到图片上加文字或者加图片。

下面这个类可以实现在某个区域内(通过left、top,width、height圈定区域)内居中打印文字和图片,文字可以自动换行,水平和垂直居中。

<?php

//拼图
class DrawText{
	
	private $sourceImg; //原图
	public  $sourceImgSize = [0,0]; //原图尺寸
	
	private $location_x = 0;
	private $location_y = 0;
	
	private $img_width = 300; //图片宽度
	private	$img_height = 300; //图片高度
	private	$img_padding = 0; //图片边距
	private	$font_size = 36; //图片字体大小
	private $font_color = [0,0,0];//文字rgb颜色
	const FONT_FILE = __DIR__ . '/msyh.ttf';
	
	//背景图
	function __construct($source_path,$pages=1){
		$this->sourceImg = imagecreatefrompng($source_path);
		list($width, $height, $type, $attr) = getimagesize($source_path);
		$this->sourceImgSize = [$width,$height];
	}
	
	public function move($x,$y){
		$this->location_x = $x;
		$this->location_y = $y;
	}
	
	public function draw($text,$width=300,$height=300,$fsize=36,$fontcolor=[0,0,0]){
		$this->font_color = $fontcolor;
		$this->__create($text,$width,$height,$fsize);
	}
	
	//画图片
	public function drawImage($img,$small_width,$small_height,$big_width,$big_height){
		if(function_exists("imagecopyresampled")){
			imagecopyresampled($this->sourceImg, $img, $this->location_x, $this->location_y, 0, 0, $big_width , $big_height,$small_width, $small_height);
		}else{
			imagecopyresized($this->sourceImg, $img, $this->location_x, $this->location_y, 0, 0, $big_width , $big_height,$small_width, $small_height);
		}
	}
	
	public function show(){
		header("Content-type: image/png");
		imagepng($this->sourceImg);
		imagedestroy($this->sourceImg);
	}
	
	public function getImage(){
		return $this->sourceImg;
	}
	
	public function destroy(){
		imagedestroy($this->sourceImg);
	}
	
	//根据文字绘图片
	private function __create($text,$width=300,$height=300,$fsize=36){
		$this->img_width = $width;
		$this->img_height = $height;
		$this->font_size = $fsize;

		$frontColor = imagecolorallocate($this->sourceImg, $this->font_color[0],$this->font_color[1],$this->font_color[2]);
		
		//行信息
		$line_arr = [];

		$this->text2line($text,$this->font_size,self::FONT_FILE,$line_arr);
		$tmp = array_column($line_arr,'height');
		$tmp = max($tmp);
		$line_height = $tmp * 1.2; //行间距
		
		$start_y = $this->img_padding;
		
		$total_height = $line_height * count($line_arr); //文字总高度
		
		$area_height = $this->img_height - $this->img_padding * 2;
		if($total_height < $area_height){
			$start_y = ($this->img_height - $total_height) / 2 + $line_height;
		}else if($total_height > $area_height){
			//文本高度大于图片高度,
		}
		
		for($i=0;$i<count($line_arr);$i++){
			$_y = $start_y + $i * $line_height;
			$_x = ($this->img_width - $line_arr[$i]['width']) / 2;
			
			//平移到目标位置
			$_x += $this->location_x;
			$_y += $this->location_y;
			
			imagefttext($this->sourceImg, $this->font_size, 0, $_x, $_y, $frontColor, self::FONT_FILE, $line_arr[$i]['text']);
		}
		//return null;
	}
	
	
	public function createbase64($text,$width=300,$height=300,$fsize=36){
		$path = $this->create($text,$width,$height,$fsize);
		$data = $this->imgToBase64($path);
		@unlink($path);
		return $data;
	}
	
	private function imgToBase64($img_file){
		$img_base64 = '';
		if (file_exists($img_file)) {
			$app_img_file = $img_file; // 图片路径
			$img_info = getimagesize($app_img_file); // 取得图片的大小,类型等
			$fp = fopen($app_img_file, "r"); // 图片是否可读权限
			if ($fp) {
				$filesize = filesize($app_img_file);
				$content = fread($fp, $filesize);
				$file_content = chunk_split(base64_encode($content)); // base64编码
				switch ($img_info[2]) {           //判读图片类型
					case 1: $img_type = "gif";
						break;
					case 2: $img_type = "jpg";
						break;
					case 3: $img_type = "png";
						break;
				}
				$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;//合成图片的base64编码
			}
			fclose($fp);
		}
		return $img_base64; //返回图片的base64
	}
	
	//文字分行
	public function text2line($text,$font_size,$font_file,&$line_arr){
		$index = 0;
		$count = 1;
		while(true){
			$line = $this->cnsubstr($text,$index,$count);
			if($line == '') break;
			
			//判断这一行的宽度
			$size = imagettfbbox($font_size,0,$font_file,$line);
			$xsize = abs($size[0]) + abs($size[2]);
			$ysize = abs($size[5]) + abs($size[1]);
			
			$all = implode('',array_column($line_arr,'text')) . $line;
			if(strlen($all) >= strlen($text)){
				//最后一行了
				$line_arr[] = [
					'text' => $line,
					'width' => $xsize,
					'height' => $ysize,
				];
				break;
			}
			
			if($xsize >= $this->img_width - 2 * $this->img_padding - 14){
				//这行到头了
				$line_arr[] = [
					'text' => $line,
					'width' => $xsize,
					'height' => $ysize,
				];
				$index += $count;
				$count = 1;
				continue;
			}
			$count++;
		}
	}
	
	public function cnsubstr($str,$start=0,$len=false) {
		if(function_exists('mb_substr')){
			if($len === false)
				return mb_substr($str,$start);
			else
				return mb_substr($str,$start,$len);
		}
		$res = array();
		for($i = 0; $i < strlen($str); $i++) {
			if(ord(substr($str, $i, 1)) > 0xa0) {
				$res[]= substr($str, $i, 3);//utf-8 -> 3,gbk -> 2
				$i+=2;
			}else{
				$res[]= substr($str, $i, 1);
			}
			if(count($res)>=$len) break;
		}
		
		if($len === false){
			$res = array_slice($res,$start);
		}else{
			$res = array_slice($res,$start,$len);
		}
		return implode('',$res);
	}
}

/*
$hp = new DrawText('bg.jpg');
$hp->move(164,194);
$hp->draw('钢筋混凝土用热轧带肋钢筋',210,36,10);
$hp->move(750,360);//移动到指定坐标
$hp->draw('595595595',32,47,9); //在指定宽度内以9号字体打印文字
$hp->show();
*/

相关字体文件自己下载了使用即可;

效果图.JPG