自由的风's Archivers

From 自由的风 on 2013-10-01 00:44:01

长微博生成(html to image)原理

在平时工作中有一些需求,简单而言就是需要将一些内容生成图片。简单的内容通过PhotoShop处理还行,但是类似于带表格等的内容,每次都通过PhotoShop进行处理太浪费时间。网上有很多类似于长微博等的生成工具,生成简单的图片还行,但是要使用富文本生成图片,则多需要money,于是便自己研究了一下基于PHP的实现。



首先展示一下演示效果http://loosky.cn/



需求及原理



基于PHP,将html内容生成图片(PNG,JPEG等)



实现方法



1. 直接通过图形函数生成

可以直接使用PHP中自带的GD库imagick,将文字内容转换成为图片。这在处理纯文字内容的时候是很给力的,但是对于富文本内容来说却很吃力了,很难处理好。目前开源的有painty等,可以支持p、img等几个简单的html标签。



2. html->pdf->png

该方式即首先将html内容生成pdf文档,再将pdf文档转换成为图片。



html to pdf:目前较为成熟的方案包括tcpdfHTML2PDF等,其实HTML2PDF也是使用的tcpdf的内核;



pdf to png:可以通过imagick php扩展。





目前基于该种方式的开源代码有html to image,其原理如下图所示。



<img src="http://loosky.net/Upload/2013/09/html-to-image-php-script.png" alt="html to image示意图" />



核心代码为(摘自:http://buffernow.com/html-to-image-php-script/):



//获取某个URL地址的内容
echo file_get_contents('http://loosky.net/');

//将内容转换成pdf文档
$html2pdf = new HTML2PDF('P', 'A4');
$html2pdf->writeHTML($html_content);
$file = $html2pdf->Output('temp.pdf','F');

//将pdf文档转换成图片
$im = new imagick('temp.pdf');
$im->setImageFormat( "jpg" );
$img_name = time().'.jpg';
$im->setSize(800,600);
$im->writeImage($img_name);
$im->clear();
$im->destroy();


这里使用了HTML2PDF的代码,其实个人建议使用tcpdf的,毕竟tcpdf的版本更新,功能更为强大。经过实际测试,tcpdf对中文、html格式等的支持更好,相对而言,HTML2PDF有点惨不忍睹,较长的中文会出现无法自动换行等基本错误。



但同时,这种方法存在一个较大的缺陷,当插入了图片等媒体后,经常会出现一页内无法放进去需要重新在另外一页进行排版的问题,从而生成的图片就会有较大的空白区域;同时每页的内容如果没有完全排满的话,生成的图片同样存在较大的空白区域,十分不美观。



因此,并不推荐这种方式。



3. 通过截图

该种方式类似于采用浏览器的截图功能,直接将某个URL地址的内容进行截图。相对前面两种方式而言:第一,对于富文本的html内容渲染更为方便、简单,直接生成html代码即可;第二,内容排版更为合理,不会出现pdf文档中存在的空白区域等问题;第三,对于中文的支持更为友好。



目前主要的开源项目包括:



khtml2png:基于Linux平台,可以将html转成图片格式,有如下要求:



g++
KDE 3.x
kdelibs for KDE 3.x (kdelibs4-dev)
zlib (zlib1g-dev)
cmake


对于服务器而言,尤其是资源比较吃紧的VPS而言,安装一个KED有点花销太大。



CutyCapt及其兄弟版本IECapt:其中CutyCapt是基于Linux、Windows平台,IECapt基于Windows平台,支持svg,ps,pdf,itext,html,rtree,png,jpeg,mng,tiff,gif,bmp,ppm,xbm,xpm等多种格式,使用均较为简单,直接使用如下命令。



注意:CutyCapt的可执行命令在Windows平台和Linux平台下的大小写不太一致。



./CutyCapt --url=http://www.example.org --out=example.png

IECapt --url=http://www.example.org/ --out=localfile.png


它的部署要求是:



CutyCapt depends on Qt 4.4.0+.


但是它比khtml2png好的一点是它可以不用装X server,可以用Xvfb这种轻量级的东西,然后可以这样使用:



xvfb-run --server-args="-screen 0, 1024x768x24" ./CutyCapt --url=... --out=...


通过对各种实现方式进行实际的对比,本人倾向于采用CutyCapt的方式。



具体实现过程



1、如http://loosky.cn/首页所示,通过嵌入富文本编辑器,提供富文本编辑功能,同时可以提供对作者信息、版权标记、图片大小格式等的定制。



2、将提交的内容进行过滤,并生成htm/html文档,通过CSS对生成的文档内容进行格式渲染。



3、通过PHP执行CutyCapt命令,对生成的网页文件进行截图。




到这一步已经完全可以实现html内容生成图片的功能了,但CutyCapt生成的图片相对而言会比较大,因此还可以进一步进行优化。




4、通过imagick对生成的图片进行优化



imagick具有强大的图片处理功能,可以优化CutyCapt生成的图片的质量及大小,同时还可以方便地进行加水印等操作。



开发经验分享



在实际开发过程中碰到了各种问题,进行一些分享。



1、操作系统选择

CutyCapt及imagick都有Linux和Windows的版本,在Windows下面的开发、运行不存在较大的问题,按照正常步骤进行安装配置即可。



在Linux平台下,CutyCapt的安装教程可参考http://www.cszhi.com/20130305/cutycapt.html



centos下安装cutycapt:



(1)安装qt47



增加qt47的源



vim /etc/yum.repos.d/atrpms.repo

//加入如下内容
[atrpms]
name=CentOS $releasever – $basearch – ATrpms
baseurl=http://dl.atrpms.net/el$releasever-$basearch/atrpms/stable
gpgkey=http://ATrpms.net/RPM-GPG-KEY.atrpms
gpgcheck=1
enabled=1

[atrpms-testing]
name=CentOS $releasever – $basearch - ATrpms testing
baseurl=http://dl.atrpms.net/el$releasever-$basearch/atrpms/testing
gpgkey=http://ATrpms.net/RPM-GPG-KEY.atrpms
gpgcheck=1
enabled=1

//进行安装
yum update
yum install qt47
yum install qt47-devel
yum install qt47-webkit
yum install qt47-webkit-devel


2、安装cutycapt



yum install svn
svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
mv cutycapt/CutyCapt /usr/local/cutycapt
cd /usr/local/cutycapt
qmake
qmake-qt47


3、安装xvfb



yum install Xvfb


4、测试cutycapt截图



xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url=http://www.baidu.com --out=baidu.png


5、将xvfb置入后台运行



Xvfb -fp /usr/share/fonts :0 -screen 0 1024x768x24 &
DISPLAY=:0 ./CutyCapt --url=http://www.baidu.com --out=baidu.png


ubuntu下安装cutycapt



1、两条命令搞定



apt-get install cutycapt
apt-get install xvfb


2、测试截图



xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url=http://www.baidu.com --out=baidu.png


中文乱码问题:



将windows下的中文字体上传至/usr/share/fonts目录,执行下命令fc-cache即可。



在这里,作者想说的是,尽量选择Ubuntu吧,安装方便;更重要的是,CentOS下面会出现各种问题,如CutyCapt: cannot connect to X server :99等,会让你非常郁闷,我甚至安装了新的包含Gnome、KDE桌面环境的操作系统仍无法解决,而在Ubuntu下面几乎不存在任何问题。



2、Web服务器的选择

因为截图功能涉及到PHP需要执行操作系统的CutyCapt命令,可以通过system()或者exec()函数。



作者分别使用了apache和Nginx两种Web服务器,在Nginx下会出现执行调用CutyCapt的PHP脚本无法运行的情况,会遇到比较麻烦的权限问题,http://alfred-long.iteye.com/blog/1578904中提供了一种解决方案,但作者没有测试成功。使用apache服务器则是一路畅通,不存在这个问题。



因此,作者建议选择Ubuntu+apache的组合,千万不要选择CentOS+Nginx,需要解决的麻烦问题太多,从而也容易造成一些不安全的因素。



安装代码如下:



apt-get install apache2
apt-get install php5 libapache2-mod-php5


3、Ubuntu中安装imagick

apt-get install php5-dev php5-cli php-pear //安装支持环境
apt-get install imagemagick //有可能不是最新版本,需要通过源代码安装最新版本

//源代码方式安装http://www.imagemagick.org/script/download.php
cd /usr/local/src
wget ftp://ftp.kddlabs.co.jp/graphics/ImageMagick/ImageMagick-6.8.7-0.tar.gz
tar xzvf ImageMagick-6.8.7-0.tar.gz
cd ImageMagick-6.8.7-0/
./configure && make && make install

apt-get install graphicsmagick-libmagick-dev-compat
pecl install imagick

echo extension=imagick.so >>/etc/php5/conf.d/imagick.ini

service apache2 restart


常见错误:



在运行pecl install imagick 时有以下出错提示:



checking if ImageMagick version is at least 6.2.4... configure: error: no. You need at least Imagemagick version 6.2.4 to use Imagick.
ERROR: `/tmp/pear/temp/imagick/configure --with-imagick=hjw' failed


根据提示是没有安装Imagemagick或者Imagemagick版本不够,可以通过源代码的方式安装最新版本的Imagemagick。



4、Linux平台下的字体渲染

可以将Windows平台下的雅黑、宋体、楷体、黑体等常用中文字体安装到Ubuntu系统中,避免出现截图中的字体不好看的情况,同时也满足对富文本编辑中支持的字体进行渲染。


查看完整版本: 长微博生成(html to image)原理

From 为爱久留吧 on 2013-11-24 22:02:05

win 5.26下要安装什么Fatal error: Class 'imagick' not found

From 自由的风 on 2013-11-25 12:18:28

还需要在PHP中加载imagick,你可以到网上搜一下教程。

From 为爱久留吧 on 2013-11-25 20:22:14

找到了。可是为什么我用你的那个项目之后生成的图片带了很多空白,你的那个测试站却没有。。QQ:251743870

From 为爱久留吧 on 2013-11-25 20:23:39

为什么你的没有大片的空白。。我用你的项目生成。有太多的空白。。QQ:251743870 加下

From 为爱久留吧 on 2013-11-25 20:24:57

我想把一篇文章,自己用正则分成几块,生成几个图片。怎么做呢?

From 自由的风 on 2013-11-26 15:53:32

那需要自己修改一下程序了。

From 石头 on 2014-02-04 02:43:41

请问博主CutyCapt 截图不显示网页里面的图片是怎么回事,是命令的问题吗

From 自由的风 on 2014-02-07 21:37:16

不一定,也有可能是Web服务器设置了拒绝程序访问

From openbilly on 2014-03-23 11:17:57

如果能在windows桌面下做个工具就好。

From 自由的风 on 2014-03-23 22:07:53

呵呵,那还不如直接用ps之类的喔。

From openbilly on 2014-03-24 16:04:59

PS太重啦,打开都半天,有个专业小工具,相信是不少人期待的。

From on 2014-05-08 11:57:46

win7 64 文字正常显示,图片怎么不可以,请问博主 是怎么回事?

From Vans爱好者 on 2014-10-29 16:55:23

cutycapt 现在仓库变了,而且貌似不能 qmake 。测试也出问题。怎么办?

From Vans爱好者 on 2014-10-29 17:00:23

按照你那个测试输入之后 /usr/bin/xvfb-run: line 166: CutyCapt: command not found 貌似新的CutyCapt不能你文章那样编译。

From 落风 on 2015-12-10 11:42:16

为啥我用cutycapt生成的图片样式变了,变的很难看,我在win7下运行的

From xuzhuzhuzi on 2016-07-17 19:32:34

你好,为什么现在连qt47都没办法下载了?已经整了一天了,在window上可以实现了,但是linux上根本没办法下载。。。有什么解决办法吗?

From AKG on 2016-08-04 09:37:45

中文乱码问题: 将windows下的中文字体上传至/usr/share/fonts目录 控制面板\外观和个性化\字体 win下有很多中文字体呀,全部都上传至/usr/share/fonts目录??? 谢谢

From AKG on 2016-08-05 12:06:57

能够正常截图 可惜截图时间实在是慢. 大概需要4秒左右.

From 自由的风 on 2016-08-08 10:45:37

不是,需要的字体,比如宋体等

From 自由的风 on 2016-08-08 10:46:14

我感觉还挺快的,不需要那么久

Tags: Apache, CutyCapt, Linux, Nginx, PHP, TCPDF


©自由的风