Vendor/phpspreadsheet/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php
private function buildWorkbookEscher()
    {
        $escher = null;

        // any drawings in this workbook?
        $found = false;
        foreach ($this->spreadsheet->getAllSheets() as $sheet) {
            if (count($sheet->getDrawingCollection()) > 0) {
                $found = true;

                break;
            }
        }

        // nothing to do if there are no drawings
        if (!$found) {
            return;
        }

        // if we reach here, then there are drawings in the workbook
        $escher = new Escher();

        // dggContainer
        $dggContainer = new DggContainer();
        $escher->setDggContainer($dggContainer);

        // set IDCLs (identifier clusters)
        $dggContainer->setIDCLs($this->IDCLs);

        // this loop is for determining maximum shape identifier of all drawing
        $spIdMax = 0;
        $totalCountShapes = 0;
        $countDrawings = 0;

        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
            $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet

            if (count($sheet->getDrawingCollection()) > 0) {
                ++$countDrawings;

                foreach ($sheet->getDrawingCollection() as $drawing) {
                    ++$sheetCountShapes;
                    ++$totalCountShapes;

                    $spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
                    $spIdMax = max($spId, $spIdMax);
                }
            }
        }

        $dggContainer->setSpIdMax($spIdMax + 1);
        $dggContainer->setCDgSaved($countDrawings);
        $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing

        // bstoreContainer
        $bstoreContainer = new BstoreContainer();
        $dggContainer->setBstoreContainer($bstoreContainer);

        // the BSE's (all the images)
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
            foreach ($sheet->getDrawingCollection() as $drawing) {
                if (!extension_loaded('gd')) {
                    throw new RuntimeException('Saving images in xls requires gd extension');
                }
                if ($drawing instanceof Drawing) {
                    $filename = $drawing->getPath();

                    list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);

                    switch ($imageFormat) {
                        case 1: // GIF, not supported by BIFF8, we convert to PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            ob_start();
                            imagepng(imagecreatefromgif($filename));
                            $blipData = ob_get_contents();
                            ob_end_clean();

                            break;
                        case 2: // JPEG
                            $blipType = BSE::BLIPTYPE_JPEG;
                            $blipData = file_get_contents($filename);

                            break;
                        case 3: // PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            $blipData = file_get_contents($filename);

                            break;
                        case 6: // Windows DIB (BMP), we convert to PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            ob_start();
                            imagepng(SharedDrawing::imagecreatefrombmp($filename));
                            $blipData = ob_get_contents();
                            ob_end_clean();

                            break;
                        default:
                            continue 2;
                    }

                    $blip = new Blip();
                    $blip->setData($blipData);

                    $BSE = new BSE();
                    $BSE->setBlipType($blipType);
                    $BSE->setBlip($blip);

                    $bstoreContainer->addBSE($BSE);
                } elseif ($drawing instanceof MemoryDrawing) {
                    switch ($drawing->getRenderingFunction()) {
                        case MemoryDrawing::RENDERING_JPEG:
                            $blipType = BSE::BLIPTYPE_JPEG;
                            $renderingFunction = 'imagejpeg';

                            break;
                        case MemoryDrawing::RENDERING_GIF:
                        case MemoryDrawing::RENDERING_PNG:
                        case MemoryDrawing::RENDERING_DEFAULT:
                            $blipType = BSE::BLIPTYPE_PNG;
                            $renderingFunction = 'imagepng';

                            break;
                    }

                    ob_start();
                    call_user_func($renderingFunction, $drawing->getImageResource());
                    $blipData = ob_get_contents();
                    ob_end_clean();

                    $blip = new Blip();
                    $blip->setData($blipData);

                    $BSE = new BSE();
                    $BSE->setBlipType($blipType);
                    $BSE->setBlip($blip);

                    $bstoreContainer->addBSE($BSE);
                }
            }
        }

        // Set the Escher object
        $this->writerWorkbook->setEscher($escher);
    }
private function buildWorkbookEscher()
    {
        $escher = null;

        // any drawings in this workbook?
        $found = false;
        foreach ($this->spreadsheet->getAllSheets() as $sheet) {
            if (count($sheet->getDrawingCollection()) > 0) {
                $found = true;

                break;
            }
        }

        // nothing to do if there are no drawings
        if (!$found) {
            return;
        }

        // if we reach here, then there are drawings in the workbook
        $escher = new Escher();

        // dggContainer
        $dggContainer = new DggContainer();
        $escher->setDggContainer($dggContainer);

        // set IDCLs (identifier clusters)
        $dggContainer->setIDCLs($this->IDCLs);

        // this loop is for determining maximum shape identifier of all drawing
        $spIdMax = 0;
        $totalCountShapes = 0;
        $countDrawings = 0;

        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
            $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet

            if (count($sheet->getDrawingCollection()) > 0) {
                ++$countDrawings;

                foreach ($sheet->getDrawingCollection() as $drawing) {
                    ++$sheetCountShapes;
                    ++$totalCountShapes;

                    $spId = $sheetCountShapes | ($this->spreadsheet->getIndex($sheet) + 1) << 10;
                    $spIdMax = max($spId, $spIdMax);
                }
            }
        }

        $dggContainer->setSpIdMax($spIdMax + 1);
        $dggContainer->setCDgSaved($countDrawings);
        $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing

        // bstoreContainer
        $bstoreContainer = new BstoreContainer();
        $dggContainer->setBstoreContainer($bstoreContainer);

        // the BSE's (all the images)
        foreach ($this->spreadsheet->getAllsheets() as $sheet) {
            foreach ($sheet->getDrawingCollection() as $drawing) {
                if (!extension_loaded('gd')) {
                    throw new RuntimeException('Saving images in xls requires gd extension');
                }
                if ($drawing instanceof Drawing) {
                    $filename = $drawing->getPath();

                    list($imagesx, $imagesy, $imageFormat) = getimagesize($filename);

                    switch ($imageFormat) {
                        case 1: // GIF, not supported by BIFF8, we convert to PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            ob_start();
                            imagepng(imagecreatefromgif($filename));
                            $blipData = ob_get_contents();
                            ob_end_clean();

                            break;
                        case 2: // JPEG
                            $blipType = BSE::BLIPTYPE_JPEG;
                            $blipData = file_get_contents($filename);

                            break;
                        case 3: // PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            $blipData = file_get_contents($filename);

                            break;
                        case 6: // Windows DIB (BMP), we convert to PNG
                            $blipType = BSE::BLIPTYPE_PNG;
                            ob_start();
                            imagepng(SharedDrawing::imagecreatefrombmp($filename));
                            $blipData = ob_get_contents();
                            ob_end_clean();

                            break;
                        default:
                            continue 2;
                    }

                    $blip = new Blip();
                    $blip->setData($blipData);

                    $BSE = new BSE();
                    $BSE->setBlipType($blipType);
                    $BSE->setBlip($blip);

                    $bstoreContainer->addBSE($BSE);
                } elseif ($drawing instanceof MemoryDrawing) {
                    switch ($drawing->getRenderingFunction()) {
                        case MemoryDrawing::RENDERING_JPEG:
                            $blipType = BSE::BLIPTYPE_JPEG;
                            $renderingFunction = 'imagejpeg';

                            break;
                        case MemoryDrawing::RENDERING_GIF:
                        case MemoryDrawing::RENDERING_PNG:
                        case MemoryDrawing::RENDERING_DEFAULT:
                            $blipType = BSE::BLIPTYPE_PNG;
                            $renderingFunction = 'imagepng';

                            break;
                    }

                    ob_start();
                    call_user_func($renderingFunction, $drawing->getImageResource());
                    $blipData = ob_get_contents();
                    ob_end_clean();

                    $blip = new Blip();
                    $blip->setData($blipData);

                    $BSE = new BSE();
                    $BSE->setBlipType($blipType);
                    $BSE->setBlip($blip);

                    $bstoreContainer->addBSE($BSE);
                }
            }
        }

        // Set the Escher object
        $this->writerWorkbook->setEscher($escher);
    }
Build the Escher object corresponding to the MSODRAWINGGROUP record.