首页 > 编程语言 >PHP 合成gif 图片

PHP 合成gif 图片

时间:2023-11-02 13:56:46浏览次数:33  
标签:10 string 合成 frameSources gif frames PHP Locals

方法一:

<?php

namespace App\Services\Common;

//namespace gifCreator;

/**
 * Create an animated GIF from multiple images
 */
class Gifcreator
{
    /**
     * @var string The gif string source (old: this->GIF)
     */
    private $gif;

    /**
     * @var string Encoder version (old: this->VER)
     */
    private $version;

    /**
     * @var boolean Check the image is build or not (old: this->IMG)
     */
    private $imgBuilt;

    /**
     * @var array Frames string sources (old: this->BUF)
     */
    private $frameSources;

    /**
     * @var integer Gif loop (old: this->LOP)
     */
    private $loop;

    /**
     * @var integer Gif dis (old: this->DIS)
     */
    private $dis;

    /**
     * @var integer Gif color (old: this->COL)
     */
    private $colour;

    /**
     * @var array (old: this->ERR)
     */
    private $errors;

    // Methods
    // ===================================================================================

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->reset();

        // Static data
        $this->version = 'GifCreator: Under development';
        $this->errors = array(
            'ERR00' => 'Does not supported function for only one image.',
            'ERR01' => 'Source is not a GIF image.',
            'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.',
            'ERR03' => 'Does not make animation from animated GIF source.',
        );
    }

    /**
     * Create the GIF string (old: GIFEncoder)
     *
     * @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs
     * @param array $durations An array containing the duration of each frame
     * @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop)
     *
     * @return string The GIF string source
     */
    public function create($frames = array(), $durations = array(), $loop = 0)
    {
        if (!is_array($frames) && !is_array($durations)) {

            throw new \Exception($this->version.': '.$this->errors['ERR00']);
        }

        $this->loop = ($loop > -1) ? $loop : 0;
        $this->dis = 2;

        for ($i = 0; $i < count($frames); $i++) {

            if (is_resource($frames[$i])) { // Resource var

                $resourceImg = $frames[$i];

                ob_start();
                imagegif($frames[$i]);
                $this->frameSources[] = ob_get_contents();
                ob_end_clean();

            } elseif (is_string($frames[$i])) { // File path or URL or Binary source code

                if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path

                    $frames[$i] = file_get_contents($frames[$i]);
                }

                $resourceImg = imagecreatefromstring($frames[$i]);

                ob_start();
                imagegif($resourceImg);
                $this->frameSources[] = ob_get_contents();
                ob_end_clean();

            } else { // Fail

                throw new \Exception($this->version.': '.$this->errors['ERR02'].' ('.$mode.')');
            }

            if ($i == 0) {

                $colour = imagecolortransparent($resourceImg);
            }

            if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr($this->frameSources[$i], 0, 6) != 'GIF89a') {

                throw new \Exception($this->version.': '.$i.' '.$this->errors['ERR01']);
            }

            for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07))), $k = TRUE; $k; $j++) {

                switch ($this->frameSources[$i] { $j }) {

                    case '!':

                        if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') {

                            throw new \Exception($this->version.': '.$this->errors['ERR03'].' ('.($i + 1).' source).');
                        }

                        break;

                    case ';':

                        $k = false;
                        break;
                }
            }

            unset($resourceImg);
        }

        if (isset($colour)) {

            $this->colour = $colour;

        } else {

            $red = $green = $blue = 0;
            $this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1;
        }

        $this->gifAddHeader();
        //d(count($this->frameSources));
        for ($i = 0; $i < count($this->frameSources); $i++) {
            $this->addGifFrames($i, $durations[$i]);
        }

        $this->gifAddFooter();

        return $this->gif;
    }

    // Internals
    // ===================================================================================

    /**
     * Add the header gif string in its source (old: GIFAddHeader)
     */
    public function gifAddHeader()
    {
        $cmap = 0;

        if (ord($this->frameSources[0] { 10 }) & 0x80) {

            $cmap = 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07));

            $this->gif .= substr($this->frameSources[0], 6, 7);
            $this->gif .= substr($this->frameSources[0], 13, $cmap);
            $this->gif .= "!\377\13NETSCAPE2.0\3\1".$this->encodeAsciiToChar($this->loop)."\0";
        }
    }

    /**
     * Add the frame sources to the GIF string (old: GIFAddFrames)
     *
     * @param integer $i
     * @param integer $d
     */
    public function addGifFrames($i, $d)
    {

        $Locals_str = 13 + 3 * (2 << (ord($this->frameSources[ $i ] { 10 }) & 0x07));

        $Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1;
        $Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end);

        $Global_len = 2 << (ord($this->frameSources[0 ] { 10 }) & 0x07);
        $Locals_len = 2 << (ord($this->frameSources[$i] { 10 }) & 0x07);

        $Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] { 10 }) & 0x07)));
        $Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] { 10 }) & 0x07)));

        $Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 0).chr(($d >> 0 ) & 0xFF).chr(($d >> 8) & 0xFF)."\x0\x0";

        if ($this->colour > -1 && ord($this->frameSources[$i] { 10 }) & 0x80) {

            for ($j = 0; $j < (2 << (ord($this->frameSources[$i] { 10 } ) & 0x07)); $j++) {

                if (ord($Locals_rgb { 3 * $j + 0 }) == (($this->colour >> 16) & 0xFF) &&
                    ord($Locals_rgb { 3 * $j + 1 }) == (($this->colour >> 8) & 0xFF) &&
                    ord($Locals_rgb { 3 * $j + 2 }) == (($this->colour >> 0) & 0xFF)
                ) {
                    $Locals_ext = "!\xF9\x04".chr(($this->dis << 2) + 1).chr(($d >> 0) & 0xFF).chr(($d >> 8) & 0xFF).chr($j)."\x0";
                    break;
                }
            }
        }

        switch ($Locals_tmp { 0 }) {

            case '!':

                $Locals_img = substr($Locals_tmp, 8, 10);
                $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);

                break;

            case ',':

                $Locals_img = substr($Locals_tmp, 0, 10);
                $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);

                break;
        }

        if (ord($this->frameSources[$i] { 10 }) & 0x80 && $this->imgBuilt) {

            if ($Global_len == $Locals_len) {

                if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) {

                    $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp;

                } else {

                    $byte = ord($Locals_img { 9 });
                    $byte |= 0x80;
                    $byte &= 0xF8;
                    $byte |= (ord($this->frameSources[0] { 10 }) & 0x07);
                    $Locals_img { 9 } = chr($byte);
                    $this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
                }

            } else {

                $byte = ord($Locals_img { 9 });
                $byte |= 0x80;
                $byte &= 0xF8;
                $byte |= (ord($this->frameSources[$i] { 10 }) & 0x07);
                $Locals_img { 9 } = chr($byte);
                $this->gif .= $Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp;
            }

        } else {

            $this->gif .= $Locals_ext.$Locals_img.$Locals_tmp;
        }

        $this->imgBuilt = true;
    }

    /**
     * Add the gif string footer char (old: GIFAddFooter)
     */
    public function gifAddFooter()
    {
        $this->gif .= ';';
    }

    /**
     * Compare two block and return the version (old: GIFBlockCompare)
     *
     * @param string $globalBlock
     * @param string $localBlock
     * @param integer $length
     *
     * @return integer
     */
    public function gifBlockCompare($globalBlock, $localBlock, $length)
    {
        for ($i = 0; $i < $length; $i++) {

            if ($globalBlock { 3 * $i + 0 } != $localBlock { 3 * $i + 0 } ||
                $globalBlock { 3 * $i + 1 } != $localBlock { 3 * $i + 1 } ||
                $globalBlock { 3 * $i + 2 } != $localBlock { 3 * $i + 2 }) {

                return 0;
            }
        }

        return 1;
    }

    /**
     * Encode an ASCII char into a string char (old: GIFWord)
     *
     * $param integer $char ASCII char
     *
     * @return string
     */
    public function encodeAsciiToChar($char)
    {
        return (chr($char & 0xFF).chr(($char >> 8) & 0xFF));
    }

    /**
     * Reset and clean the current object
     */
    public function reset()
    {
        $this->frameSources;
        $this->gif = 'GIF89a'; // the GIF header
        $this->imgBuilt = false;
        $this->loop = 0;
        $this->dis = 2;
        $this->colour = -1;
    }

    // Getter / Setter
    // ===================================================================================

    /**
     * Get the final GIF image string (old: GetAnimation)
     *
     * @return string
     */
    public function getGif()
    {
        return $this->gif;
    }
}

调用方法:参考来源

            //图片资源写入数组,支持如下图片资源。
            $frames = array(
                imagecreatefrompng("./static/wx-images/ICE.png"),
                "./static/wx-images/DFI.png",
                //file_get_contents("./static/image/left_top.jpg"),
                "./static/image/left_top.jpg",
                //'https://img.php.cn/upload/article/000/079/647/1c9e6b85e03d3c1219c51e2eaef37444-0.jpg',
                './static/wx-images/02-ICE/ICE-42.jpg'
            );

            // 设置图片转换快慢,数值越小越快,数组个数和frames对应。
            $durations = array(40, 80, 40, 20);

            $gc = new Gifcreator();
            $gifBinary = $gc->create($frames, $durations, 0);

            //输出方式  浏览器输出
            header('Content-type: image/gif');
            header('Content-Disposition: filename="butterfly.gif"');
            echo $gifBinary;
            exit;

            //或者 保存gif图片。
//            file_put_contents('1animated_picture.gif', $gifBinary);

  

标签:10,string,合成,frameSources,gif,frames,PHP,Locals
From: https://www.cnblogs.com/andydao/p/17805217.html

相关文章

  • php: ajax请求,在返回信息前面出现ufeff红点,导致解析错误
    问题:ajax请求,在返回信息前面出现ufeff红点,导致解析错误原因:PHP文件格式编码位utf-8bom  文件编码是含BOM的会导致出现这种情况解决:  第一种方法:PHP文件格式编码转化为utf-8  第二种方法:在接口echo输出前面,添加一个ob_clean()函数           ......
  • PHP大文件分割上传详解
    这篇文章主要为大家详细介绍了PHP大文件分割上传,PHP分片上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关upload_max_filesize=2M //PHP最大能接受的文件大小post_max_size=8M //PHP能收到的最大POST值'me......
  • PHP语言特性
    1.弱类型''==0==false'123'==123'abc'==0'0x01'==1'0e123456789'=='0e987654321'[false]==[0]==[NULL]==['']NULL==false==0true==1php中'=='和'===......
  • php安装ffmpeg扩展
    如何安装php-ffmpeg删除putenv涵数首先项目根目录运行composerrequirephp-ffmpeg/php-ffmpeg然后系统安装ffmpeg宝塔安装wgethttp://download.bt.cn/install/ext/ffmpeg.sh&&shffmpeg.sh需要很久......
  • 使用phpQuery库采集平安健康代码示例
    大家好,今天给大家分享的内容是使用phpQuery库采集平安健康相关视频,内容非常简单,篇幅也很短,但是确实很实用,一起学习一下吧。```php<?php//引入phpQuery库require_once'phpQuery/phpQuery.php';//创建一个phpQuery对象$jq=phpQuery::newDocument();//使用配置p......
  • php:bcrypt加密和验证(php 8.1)
    一,相关文档:https://www.php.net/manual/zh/function.password-hash.php二,php代码:12345678910111213141516171819202122232425/* *测试用bcrypt方式验证密码 *用password_hash和password_verify一对函数实现 **/publicfunct......
  • 【Azure App Service】为部署在App Service上的PHP应用开启JIT编译器
    问题描述在AppServiceforlinux上创建一个PHP应用,通过phpinfo()查看PHP的扩展设置,发现JIT没有被开启, jit_buffer_size大小为0.那么,在AppService的环境中,如何开启JIT呢? 问题解答PHP8在PHP的内核中添加了JIT编译器,可以极大地提高性能。首先,仅在启用opcache的情况下,JIT才有效......
  • 大模型训练中的AI合成数据应用
    随着人工智能技术的飞速发展,数据成为了训练高级模型的关键因素。然而,很多时候,真实的数据并不总是能够满足模型训练的需求。为了解决这个问题,一些开发者开始尝试使用AI合成数据来训练模型。这种现象近年来逐渐引起人们的关注,但同时也充满了争议。使用AI合成数据训练模型具有很多优势......
  • [极客大挑战 2019]PHP
    打开靶机页面后发现有提示:因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯。结合常用的备份字典,直接扫到存在www.zip文件,下载后解压打开,发现源码。在index.php中,关键代码如下:<?phpinclude'class.php';$select=$_GET['select'];$res=unserialize......
  • [极客大挑战 2019]PHP
    打开靶机页面后发现有提示:因为每次猫猫都在我键盘上乱跳,所以我有一个良好的备份网站的习惯。结合常用的备份字典,直接扫到存在www.zip文件,下载后解压打开,发现源码。在index.php中,关键代码如下:<?phpinclude'class.php';$select=$_GET['select'];$res=unseria......