Skip to content

Commit c4c35dd

Browse files
authored
Merge pull request #937 from troosan/image_from_string
add support for Image creation from string image data
2 parents 60e7f53 + 204f0c3 commit c4c35dd

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

docs/elements.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ To add an image, use the ``addImage`` method to sections, headers, footers, text
232232
233233
$section->addImage($src, [$style]);
234234
235-
- ``$src``. String path to a local image or URL of a remote image.
235+
- ``$src``. String path to a local image, URL of a remote image or the image data, as a string.
236236
- ``$style``. See :ref:`image-style`.
237237

238238
Examples:
@@ -254,6 +254,8 @@ Examples:
254254
$footer->addImage('http://example.com/image.php');
255255
$textrun = $section->addTextRun();
256256
$textrun->addImage('http://php.net/logo.jpg');
257+
$source = file_get_contents('/path/to/my/images/earth.jpg');
258+
$textrun->addImage($source);
257259
258260
Watermarks
259261
~~~~~~~~~~

src/PhpWord/Element/Image.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Image extends AbstractElement
3535
const SOURCE_LOCAL = 'local'; // Local images
3636
const SOURCE_GD = 'gd'; // Generated using GD
3737
const SOURCE_ARCHIVE = 'archive'; // Image in archives zip://$archive#$image
38+
const SOURCE_STRING = 'string'; // Image from string
3839

3940
/**
4041
* Image source
@@ -379,6 +380,8 @@ private function checkImage($source)
379380
// Check image data
380381
if ($this->sourceType == self::SOURCE_ARCHIVE) {
381382
$imageData = $this->getArchiveImageSize($source);
383+
} else if ($this->sourceType == self::SOURCE_STRING) {
384+
$imageData = $this->getStringImageSize($source);
382385
} else {
383386
$imageData = @getimagesize($source);
384387
}
@@ -416,9 +419,15 @@ private function setSourceType($source)
416419
} elseif (strpos($source, 'zip://') !== false) {
417420
$this->memoryImage = false;
418421
$this->sourceType = self::SOURCE_ARCHIVE;
422+
} elseif (filter_var($source, FILTER_VALIDATE_URL) !== false) {
423+
$this->memoryImage = true;
424+
$this->sourceType = self::SOURCE_GD;
425+
} elseif (@file_exists($source)) {
426+
$this->memoryImage = false;
427+
$this->sourceType = self::SOURCE_LOCAL;
419428
} else {
420-
$this->memoryImage = (filter_var($source, FILTER_VALIDATE_URL) !== false);
421-
$this->sourceType = $this->memoryImage ? self::SOURCE_GD : self::SOURCE_LOCAL;
429+
$this->memoryImage = true;
430+
$this->sourceType = self::SOURCE_STRING;
422431
}
423432
}
424433

@@ -460,6 +469,24 @@ private function getArchiveImageSize($source)
460469
return $imageData;
461470
}
462471

472+
/**
473+
* get image size from string
474+
*
475+
* @param string $source
476+
*
477+
* @codeCoverageIgnore this method is just a replacement for getimagesizefromstring which exists only as of PHP 5.4
478+
*/
479+
private function getStringImageSize($source)
480+
{
481+
if (!function_exists('getimagesizefromstring')) {
482+
$uri = 'data://application/octet-stream;base64,' . base64_encode($source);
483+
return @getimagesize($uri);
484+
} else {
485+
return @getimagesizefromstring($source);
486+
}
487+
return false;
488+
}
489+
463490
/**
464491
* Set image functions and extensions.
465492
*

tests/PhpWord/Element/ImageTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,57 @@ public function testArchivedImage()
156156
$image = new Image("zip://{$archiveFile}#{$imageFile}");
157157
$this->assertEquals('image/jpeg', $image->getImageType());
158158
}
159+
160+
/**
161+
* Test getting image as string
162+
*/
163+
public function testImageAsStringFromFile()
164+
{
165+
$image = new Image(__DIR__ . '/../_files/images/earth.jpg');
166+
167+
$this->assertNotNull($image->getImageStringData());
168+
$this->assertNotNull($image->getImageStringData(true));
169+
}
170+
171+
/**
172+
* Test getting image from zip as string
173+
*/
174+
public function testImageAsStringFromZip()
175+
{
176+
$archiveFile = __DIR__ . '/../_files/documents/reader.docx';
177+
$imageFile = 'word/media/image1.jpeg';
178+
$image = new Image("zip://{$archiveFile}#{$imageFile}");
179+
180+
$this->assertNotNull($image->getImageStringData());
181+
$this->assertNotNull($image->getImageStringData(true));
182+
}
183+
184+
/**
185+
* Test construct from string
186+
*/
187+
public function testConstructFromString()
188+
{
189+
$source = file_get_contents(__DIR__ . '/../_files/images/earth.jpg');
190+
191+
$image = new Image($source);
192+
$this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image);
193+
$this->assertEquals($source, $image->getSource());
194+
$this->assertEquals(md5($source), $image->getMediaId());
195+
$this->assertEquals('image/jpeg', $image->getImageType());
196+
$this->assertEquals('jpg', $image->getImageExtension());
197+
$this->assertEquals('imagecreatefromjpeg', $image->getImageCreateFunction());
198+
$this->assertEquals('imagejpeg', $image->getImageFunction());
199+
$this->assertTrue($image->isMemImage());
200+
}
201+
202+
/**
203+
* Test invalid string image
204+
*
205+
* @expectedException \PhpOffice\PhpWord\Exception\InvalidImageException
206+
*/
207+
public function testInvalidImageString()
208+
{
209+
$object = new Image('this_is-a_non_valid_image');
210+
$object->getSource();
211+
}
159212
}

0 commit comments

Comments
 (0)