https://segmentfault.com/a/1190000016384960
    原文地址:https://duanruilong.github.io/blog/2018/09/05/在PHP里很好的使用ImageMagick/
    最近的PHP项目中,需要用到画图和图片拼接效果,这里是一些开发过程里用到的一些点还有就是一些踩过的坑。通过ImageMagick生成base64图片格式,为前端所使用。

    PHP对Base64的支持非常好,有内置的base64_encode与base64_decode负责图片的Base64编码与解码。
    编码上,只要将图片流读取到,而后使用base64_encode进行进行编码即可得到。

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

    1. /*图片转换为 base64格式编码*/
    2. $img = 'uploads/about.png';
    3. $base64_img = base64EncodeImage($img);
    4. echo '<img src="' . $base64_img . '" />';
    5. function base64EncodeImage ($image_file) {
    6. $base64_image = '';
    7. $image_info = getimagesize($image_file);
    8. $image_data = fread(fopen($image_file, 'r'), filesize($image_file));
    9. //chunk_split() 函数把字符串分割为一连串更小的部分,默认76个字符添加一个 \r\n。这里不设置这个也可以,设置之后可以多行显示base64编码后的字符,不设置的话一行显示
    10. $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));
    11. return $base64_image;
    12. }



    base64图片转换为图片并保存

    1. <?php
    2. /* base64格式编码转换为图片并保存对应文件夹 */
    3. function base64_image_content($base64_image_content,$path){
    4. //匹配出图片的格式
    5. if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
    6. $type = $result[2];
    7. $new_file = $path."/".date('Ymd',time())."/";
    8. if(!file_exists($new_file)){
    9. //检查是否有该文件夹,如果没有就创建,并给予最高权限
    10. mkdir($new_file, 0700);
    11. }
    12. $new_file = $new_file.time().".{$type}";
    13. if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){
    14. return '/'.$new_file;
    15. }else{
    16. return false;
    17. }
    18. }else{
    19. return false;
    20. }
    21. }
    22. 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的图片

    1. // 初始化一个画板
    2. $img =new Imagick();
    3. $img->newImage(750,1046,'white','jpg') ;

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

    1. <?php
    2. //前提是我们已经知道了需要合并的图片链接地址
    3. $item_img='https://img.alicdn.com/bao/uploaded/i1/1750208593/TB1rgM3hhtnkeRjSZSgXXXAuXXa_!!0-item_pic.jpg'
    4. //第一步:实例化图片
    5. $imgtwo = new Imagick($item_img);
    6. //第二步:设置添加图片的大小
    7. $imgtwo->resizeImage(750,764,Imagick::FILTER_LANCZOS,1);
    8. //关于resizeImage参数说明
    9. bool Imagick::resizeImage ( int $columns , int $rows , int $filter , float $blur [, bool $bestfit = false ] )
    10. 参数:
    11. columns 图片的宽度
    12. rows 图片高度
    13. filter 过滤器,用于过滤图片,有高斯filte根据情况而定
    14. blur blur=1 为虚化, blur =-1 为锐化
    15. //第三步:与底图合并
    16. $img->compositeImage($imgtwo,$imgtwo->getImageCompose(),0,0);
    17. 使用compositeImage();
    18. bool Imagick::compositeImage ( Imagick $composite_object , int $composite , int $x , int $y [, int $channel = Imagick::CHANNEL_ALL ] )
    19. 参数:
    20. composite_object :用于合并的图片的Imagick对象
    21. composite:合并操作,定义操作常量。 具体请查看 合并操作常量列表
    22. x:相对图像顶点左上位置(0,0)的横坐标
    23. y:相对图像顶点左上位置(0,0)的纵坐标
    24. channel:通过传入一个通道常量,来开启通道模式。为了支持多个通道,可以通过二进制运算的操作来合并多个通道常量。
    25. //到这里就可以得到一个合并的图片了
    26. //1、加一个header信息,可以直接在网页上查看图片
    27. header("Content-Type: img/png");
    28. echo $img;
    29. //2、可以把图片在指定目录中生成,在指定目录下生成为img.png
    30. $file="./img.png";
    31. $img->writeImage($file);
    32. //我这里是这样处理:
    33. header ( 'Content-type: ' . strtolower ($img->getImageFormat ()) );
    34. $type = strtolower($img->getImageFormat());
    35. $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);  // 画在地板上
    

    详细解读:
    l 1、实例化ImagickDraw类:
    $drawQr = new ImagickDraw();
    l 2、设置字体颜色
    $drawQr -> setFillColor(new ImagickPixel(‘#999999’));
    l 3、设置字体大小
    $drawQr -> setFontSize(‘24’);
    l 4、设置字体格式
    $drawQr -> setFont(‘../../conf/Microsoftyahei.ttf’);
    l 5、设置字体方向
    $draw->setTextAlignment(Imagick::ALIGN_RIGHT);
    ps: Imagick::ALIGN_RIGHT 朝右边 Imagick::ALIGN_LEFT 左边 Imagick::ALIGN_CENTER 中间
    l 6、设置字体编码
    $drawQr -> setTextEncoding(“utf-8”);
    l 7、画出文字
    $drawQr -> annotation(114,990,$shop_title);
    l 8、在底图上写入字体
    $img -> drawImage($drawQr);
    写入文字这个地方的一些坑:
    没有设置字体格式时,中文字会解析错误
    (英文没有问题)
    (汉字解析失败)
    (设置字体格式正常显示)
    ImageMagick生成base64图片 - 图1


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

    <?php
    $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’回车字符,需要特殊处理才可以正确显示图片。