PHPPresentation
PHPPresentation copied to clipboard
Adding an Image to a Slide corrupts generated PowerPoint file
This is the code I've pieced together between the documentation, examples, and searching for solutions on github and stackoverflow to try to add an image to a slide:
$powerPoint = new PhpPresentation();
$masterSlide = $powerPoint->getAllMasterSlides()[0];
$slideLayout = $masterSlide->getAllSlideLayouts()[0];
$currentSlide = $powerPoint->getActiveSlide();
$currentSlide->setSlideLayout($slideLayout);
// using chromium to get base64 image stored in $image. confirmed this is correct.
$shape = (new Base64())->setData($image)->setHeight(500)->setWidth(500)->setOffsetX(50)->setOffsetY(50);
$currentSlide->addShape($shape);
// I also tried saving the image and inserting it that way
//$shape = $currentSlide->createDrawingShape('/path/to/my-image.png')->setHeight(500)->setWidth(500)->setOffsetX(50)->setOffsetY(50);
header('Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation');
header('Content-Disposition: attachment; filename="test.pptx"');
header('Cache-Control: max-age=0');
$writer = IOFactory::createWriter($powerPoint, 'PowerPoint2007');
$writer->save('php://output');
When the file downloads and I click on it, I get this message:
When I click "Repair", I get this message:
I'm using phpoffice/phppresentation dev-master with Microsoft PowerPoint for Mac Version 16.50.
Using jpeg looks like it doesn't corrupt the PowerPoint file but the image is still not visible. So the corrupt file may have something to do with png images. I'd prefer to use png but wouldn't mind using jpeg.
Try this...
$presentation = new PhpPresentation();
$presentation->getLayout()->setDocumentLayout(DocumentLayout::LAYOUT_A4, true);
// $slide = $presentation->createSlide();
$slide = $presentation->getSlide(0); // work with first slide of presentation
$file = './resources/presentation/left-side.png'; // relative path to the image
$shape = $slide->createDrawingShape();
$shape
->setPath($file)
->setOffsetX(Units::convert($x))
->setOffsetY(Units::convert($y));
Method Units::convert($mm) convert millimeters to pixels. ..class Units below
class Units
{
const UNIT_EMU = 'emu';
const UNIT_CENTIMETER = 'cm';
const UNIT_INCH = 'in';
const UNIT_MILLIMETER = 'mm';
const UNIT_PIXEL = 'px';
const UNIT_POINT = 'pt';
/**
* Convert specified value from one to another units
*
* @param mixed $value value at fromUnit units
* @param string $fromUnit units of value (from units)
* @param string $toUnit result units (to units)
*
* @return mixed value value at toUnit units
*/
public static function convert(
$value,
$fromUnit = self::UNIT_MILLIMETER,
$toUnit = self::UNIT_PIXEL
) {
if ($fromUnit === $toUnit) {
return $value;
}
// Convert from $fromUnit to EMU
switch ($fromUnit) {
case self::UNIT_MILLIMETER:
$value *= 36000;
break;
case self::UNIT_CENTIMETER:
$value *= 360000;
break;
case self::UNIT_INCH:
$value *= 914400;
break;
case self::UNIT_PIXEL:
$value = Drawing::pixelsToEmu($value);
break;
case self::UNIT_POINT:
$value *= 12700;
break;
case self::UNIT_EMU:
default:
// no changes
}
// Convert from EMU to $toUnit
switch ($toUnit) {
case self::UNIT_MILLIMETER:
$value /= 36000;
break;
case self::UNIT_CENTIMETER:
$value /= 360000;
break;
case self::UNIT_INCH:
$value /= 914400;
break;
case self::UNIT_PIXEL:
$value = Drawing::emuToPixels($value);
break;
case self::UNIT_POINT:
$value /= 12700;
break;
case self::UNIT_EMU:
default:
// no changes
}
return $value;
}
}
I wrote this method which add image to specified slide:
/**
* Add image to slide (from file)
*
* @param Slide $slide Slide
* @param string $file Image file name
* @param mixed $x Image x-position
* @param mixed $y Image y-position
* @param mixed $width Image width
* @param mixed $height Image height
*
* @return \PhpOffice\PhpPresentation\Shape\Drawing\File Image shape
*/
public function image(
Slide $slide,
string $file,
$x,
$y,
$width = null,
$height = null
) : \PhpOffice\PhpPresentation\Shape\Drawing\File {
$shape = $slide->createDrawingShape();
$shape
->setPath($file)
->setOffsetX(Units::convert($x))
->setOffsetY(Units::convert($y));
$uWidth = null;
$uHeight = null;
if ($width !== null) {
$uWidth = Units::convert($width);
$shape->setWidth($uWidth);
}
if ($height !== null) {
$uHeight = Units::convert($height);
$shape->setHeight($uHeight);
}
if ($shape->getWidth() > $uWidth) {
$shape->setWidth($uWidth);
}
return $shape;
}
Usage example:
$file = './resources/presentation/left-side.png';
$this->image($slide, $file, 10, 0, 70, 210);