Grafika\Gd\Helper\GifHelper::decodeToBlocks PHP Method

decodeToBlocks() public method

Decompose GIF into its block components. The GIF blocks are in the order that they appear in the byte stream.
public decodeToBlocks ( GifByteStream $bytes ) : array
$bytes GifByteStream
return array
    public function decodeToBlocks($bytes)
    {
        $bytes->setPosition(0);
        $blocks = array();
        // Header block
        $blocks['header'] = $bytes->bite(6);
        // Logical screen descriptor block
        $part = $bytes->bite(2);
        // canvass w
        $hex = $part;
        $part = $bytes->bite(2);
        // canvass h
        $hex .= $part;
        $part = $bytes->bite(1);
        // packed field
        $hex .= $part;
        $bin = $this->_fixSize($this->_hexToBin($part), 8);
        $globalColorTableFlag = bindec(substr($bin, 0, 1));
        $sizeOfGlobalColorTable = bindec(substr($bin, 5, 3));
        $part = $bytes->bite(1);
        // backgroundColorIndex
        $hex .= $part;
        $part = $bytes->bite(1);
        // pixelAspectRatio
        $hex .= $part;
        $blocks['logicalScreenDescriptor'] = $hex;
        // Global color table is optional so check its existence
        if ($globalColorTableFlag > 0) {
            // Formula: 3 * (2^(N+1))
            $colorTableLength = 3 * pow(2, $sizeOfGlobalColorTable + 1);
            $part = $bytes->bite($colorTableLength);
            $blocks['globalColorTable'] = $part;
        }
        $commentC = $plainTextC = $appCount = $gce = $dc = 0;
        // index count
        while (!$bytes->isEnd()) {
            $part = $bytes->bite(1);
            if ('21' === $part) {
                // block tests
                $hex = $part;
                $part = $bytes->bite(1);
                if ('ff' === $part) {
                    // App extension block
                    $hex .= $part;
                    $part = $bytes->bite(1);
                    // app name length should be 0x0b or int 11 but we check anyways
                    $size = hexdec($part);
                    // turn it to int
                    $hex .= $part;
                    $part = $bytes->bite($size);
                    // app name
                    $hex .= $part;
                    while (!$bytes->isEnd()) {
                        // loop thru all app sub blocks
                        $nextSize = $bytes->bite(1);
                        if ($nextSize !== '00') {
                            $hex .= $nextSize;
                            $size = hexdec($nextSize);
                            $part = $bytes->bite($size);
                            $hex .= $part;
                        } else {
                            $hex .= $nextSize;
                            $blocks['applicationExtension-' . $appCount] = $hex;
                            break;
                        }
                    }
                    $appCount++;
                } else {
                    if ('f9' === $part) {
                        // graphic
                        $hex .= $part;
                        $part = $bytes->bite(1);
                        // size
                        $hex .= $part;
                        $part = $bytes->bite(1);
                        // packed field
                        $hex .= $part;
                        $part = $bytes->bite(2);
                        // delay time
                        $hex .= $part;
                        $part = $bytes->bite(1);
                        // trans color index
                        $hex .= $part;
                        $part = $bytes->bite(1);
                        // terminator
                        $hex .= $part;
                        $blocks['graphicControlExtension-' . $gce] = $hex;
                        $gce++;
                    } else {
                        if ('01' === $part) {
                            // plain text ext
                            $hex .= $part;
                            while (!$bytes->isEnd()) {
                                // loop thru all app sub blocks
                                $nextSize = $bytes->bite(1);
                                if ($nextSize !== '00') {
                                    $hex .= $nextSize;
                                    $size = hexdec($nextSize);
                                    $part = $bytes->bite($size);
                                    $hex .= $part;
                                } else {
                                    $hex .= $nextSize;
                                    $blocks['plainTextExtension-' . $plainTextC] = $hex;
                                    break;
                                }
                            }
                            $plainTextC++;
                        } else {
                            if ('fe' === $part) {
                                // comment ext
                                $hex .= $part;
                                while (!$bytes->isEnd()) {
                                    // loop thru all app sub blocks
                                    $nextSize = $bytes->bite(1);
                                    if ($nextSize !== '00') {
                                        $hex .= $nextSize;
                                        $size = hexdec($nextSize);
                                        $part = $bytes->bite($size);
                                        $hex .= $part;
                                    } else {
                                        $hex .= $nextSize;
                                        $blocks['commentExtension-' . $commentC] = $hex;
                                        break;
                                    }
                                }
                                $commentC++;
                            }
                        }
                    }
                }
            } else {
                if ('2c' === $part) {
                    // image descriptors
                    $hex = $part;
                    $part = $bytes->bite(2);
                    // imageLeft
                    $hex .= $part;
                    $part = $bytes->bite(2);
                    // imageTop
                    $hex .= $part;
                    $part = $bytes->bite(2);
                    // imageWidth
                    $hex .= $part;
                    $part = $bytes->bite(2);
                    // imageHeight
                    $hex .= $part;
                    $part = $bytes->bite(1);
                    // packed field
                    $hex .= $part;
                    $blocks['imageDescriptor-' . $dc] = $hex;
                    $bin = $this->_fixSize($this->_hexToBin($part), 8);
                    $localColorTableFlag = bindec(substr($bin, 0, 1));
                    $sizeOfLocalColorTable = bindec(substr($bin, 5, 3));
                    //LC
                    if ($localColorTableFlag) {
                        // Formula: 3 * (2^(N+1))
                        $localColorTableLen = 3 * pow(2, $sizeOfLocalColorTable + 1);
                        $part = $bytes->bite($localColorTableLen);
                        $blocks['localColorTable-' . $dc] = $part;
                    }
                    // Image data
                    $part = $bytes->bite(1);
                    // LZW code
                    $hex = $part;
                    while ($bytes->isEnd() === false) {
                        $nextSize = $bytes->bite(1);
                        $hex .= $nextSize;
                        if ($nextSize !== '00') {
                            $subBlockLen = hexdec($nextSize);
                            $subBlock = $bytes->bite($subBlockLen);
                            $hex .= $subBlock;
                        } else {
                            $blocks['imageData-' . $dc] = $hex;
                            break;
                        }
                    }
                    $dc++;
                } else {
                    $blocks['trailer'] = $part;
                    break;
                }
            }
        }
        if ($blocks['trailer'] !== '3b') {
            throw new \Exception('Error decoding GIF. Stopped at ' . $bytes->getPosition() . '. Length is ' . $bytes->length() . '.');
        }
        return $blocks;
    }