PHP里使用ImageMagick生成base64图片

> 个人博客 [https://duanruilong.github.io/blog/](https://duanruilong.github.io/blog/)

> 本文原地址[https://duanruilong.github.io/blog/2018/09/05/%E5%9C%A8PHP%E9%87%8C%E5%BE%88%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8ImageMagick/](https://duanruilong.github.io/blog/2018/09/05/%E5%9C%A8PHP%E9%87%8C%E5%BE%88%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8ImageMagick/)

最近的PHP项目中,需要用到画图和图片拼接效果,这里是一些开发过程里用到的一些点还有就是一些踩过的坑。通过ImageMagick生成base64图片格式,为前端所使用。

![PHP](http://upload-images.jianshu.io/upload_images/5412276-e805ee8d1d678a68?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-5940a11639adde0c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

> 一些需要的知识点

# PHP将图片转base64编码以及base64图片转换为图片并保存代码

## 图片转base64编码

```

/*图片转换为 base64格式编码*/

$img = 'uploads/about.png';

$base64_img = base64EncodeImage($img);

echo '<img src="' . $base64_img . '" />';

function base64EncodeImage ($image_file) {

    $base64_image = '';

    $image_info = getimagesize($image_file);

    $image_data = fread(fopen($image_file, 'r'), filesize($image_file));

    $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));

    return $base64_image;

}

```

## base64图片转换为图片并保存

```

/*  base64格式编码转换为图片并保存对应文件夹 */

function base64_image_content($base64_image_content,$path){

    //匹配出图片的格式

    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){

        $type = $result[2];

        $new_file = $path."/".date('Ymd',time())."/";

        if(!file_exists($new_file)){

            //检查是否有该文件夹,如果没有就创建,并给予最高权限

            mkdir($new_file, 0700);

        }

        $new_file = $new_file.time().".{$type}";

        if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){

            return '/'.$new_file;

        }else{

            return false;

        }

    }else{

        return false;

    }

}

echo base64_image_content($base64_img,"uploads/");

```

# base64

Base64是一种用64个字符来表示任意二进制数据的方法。

Base64的原理很简单,首先,准备一个包含64个字符的数组:

`['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']`

然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit,划为4组,每组正好6个bit

如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。

使用jpg图片体积要比png小

使用PHP的Imagick类进行图像的操作

# Imagick具体操作

## (1).创建一个底图,宽750px,高1046px,白色背景,格式为jpg的图片

```

// 初始化一个画板

        $img =new Imagick();

        $img->newImage(750,1046,'white','jpg') ;


```

## (2).在底图上添加需求图片

前提是我们已经知道了需要合并的图片链接地址

```

$item_img='https://img.alicdn.com/bao/uploaded/i1/1750208593/TB1rgM3hhtnkeRjSZSgXXXAuXXa_!!0-item_pic.jpg'

第一步:实例化图片

$imgtwo = new Imagick($item_img);

第二步:设置添加图片的大小

$imgtwo->resizeImage(750,764,Imagick::FILTER_LANCZOS,1);

关于resizeImage参数说明

    bool Imagick::resizeImage ( int $columns , int $rows , int $filter , float $blur [, bool $bestfit = false ] )

参数:

  ● columns 图片的宽度

  ● rows 图片高度

  ● filter 过滤器,用于过滤图片,有高斯filte根据情况而定

  ● blur blur=1 为虚化, blur =-1 为锐化

第三步:与底图合并

$img->compositeImage($imgtwo,$imgtwo->getImageCompose(),0,0);

使用compositeImage();

    bool Imagick::compositeImage ( Imagick $composite_object , int $composite , int $x , int $y [, int $channel = Imagick::CHANNEL_ALL ] )

参数:

  ● composite_object :用于合并的图片的Imagick对象

  ● composite:合并操作,定义操作常量。 具体请查看 合并操作常量列表

  ● x:相对图像顶点左上位置(0,0)的横坐标

  ● y:相对图像顶点左上位置(0,0)的纵坐标

  ● channel:通过传入一个通道常量,来开启通道模式。为了支持多个通道,可以通过二进制运算的操作来合并多个通道常量。

到这里就可以得到一个合并的图片了

1、加一个header信息,可以直接在网页上查看图片

    header("Content-Type: img/png");

    echo $img;

2、可以把图片在指定目录中生成,在指定目录下生成为img.png

$file="./img.png";

$img->writeImage($file);

我这里是这样处理:

    header ( 'Content-type: ' . strtolower ($img->getImageFormat ()) );

    $type = strtolower($img->getImageFormat());

    $dest_img='/data/tmp/' . md5(microtime(true)).'.'.$type;    //要生成的图片的路径,随机生成图片名称

```

## (3).图片上拼接文字

写入文字以添加店铺文字为例,逐步完成文字的写入。

```

    $shop_title='测试店铺';

    // 添加店铺文字

    $drawQr = new ImagickDraw(); // 实例化ImagickDraw

    $drawQr -> setFillColor(new ImagickPixel('#999999')); // 颜色

    $drawQr -> setFontSize('24'); // 大小

    $drawQr -> setFont('../../conf/Microsoftyahei.ttf'); // 字体

    $drawQr -> setTextAlignment(Imagick::ALIGN_LEFT); // 字体方向

    // ps: Imagick::ALIGN_RIGHT 朝右边    Imagick::ALIGN_LEFT 左边  Imagick::ALIGN_CENTER 中间

    $drawQr -> setTextEncoding("utf-8"); // 字体编码

    $drawQr -> annotation(114,990,$shop_title); // 画出文字

    $img -> drawImage($drawQr);  // 画在地板上

```

详细解读:

- 1、实例化ImagickDraw类:

    `$drawQr = new ImagickDraw(); `

- 2、设置字体颜色

`$drawQr -> setFillColor(new ImagickPixel('#999999')); `

- 3、设置字体大小

`$drawQr -> setFontSize('24'); `

- 4、设置字体格式

`$drawQr -> setFont('../../conf/Microsoftyahei.ttf');`

- 5、设置字体方向

`$draw->setTextAlignment(Imagick::ALIGN_RIGHT);`

> ps: Imagick::ALIGN_RIGHT 朝右边    Imagick::ALIGN_LEFT 左边  Imagick::ALIGN_CENTER 中间

- 6、设置字体编码

`$drawQr -> setTextEncoding("utf-8");`

- 7、画出文字

`$drawQr -> annotation(114,990,$shop_title); `

- 8、在底图上写入字体

`$img -> drawImage($drawQr);`

写入文字这个地方的一些坑:

没有设置字体格式时,中文字会解析错误

(英文没有问题)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-1ebdd91dd08d6bf4?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(汉字解析失败)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-8a18eb586fa58887?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(设置字体格式正常显示)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-d4a5388ce3e36fdb?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## (4).图片base64导出

最终得到的图片我们组要以base64的格式传递给前端,进行以下操作,把我们最后拼接的到的图片base64转换输出。

```

    $dest_img='/data/tmp/' . md5(microtime(true)).'.'.$type; //要生成的图片的路径

    $Return = array();

    // *图片转换为 base64格式编码*

    $base64_image = '';

    $image_info = getimagesize($dest_img);

    $image_data = fread(fopen($dest_img, 'r'), filesize($dest_img));

    $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));

    $Return['data']=$base64_image;

    return  $Return;

```

`$base64_image`就是base64格式的图片。

需要注意的是前端得到的额base64数据里包含有`'\r\n'`回车字符,需要特殊处理才可以正确显示图片。

![PHP](http://upload-images.jianshu.io/upload_images/5412276-1901352482215ddf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(最后得到的合并图片)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-eaefa07403444432?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(调整拼接图片大小得到不同的图片)

![PHP](http://upload-images.jianshu.io/upload_images/5412276-6d349e6b5d242161?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

最后来一组单打詹!!!

觉得喜欢欢迎关注,start

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容