Skip to content

Commit 88e45ed

Browse files
committed
Fix Image::fromString to support PNG and WebP files
- Add missing fromString methods to PNG and WebP classes - Update Image::fromString to read image size and MIME type with getimagesizefromstring - Update and refactor related tests
1 parent 6e287e9 commit 88e45ed

File tree

7 files changed

+407
-131
lines changed

7 files changed

+407
-131
lines changed

src/Format/PNG.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ public static function fromFile($filename)
104104
return new self(file_get_contents($filename));
105105
}
106106

107+
/**
108+
* @param $string
109+
*
110+
* @return PNG
111+
*/
112+
public static function fromString($string)
113+
{
114+
return new self($string);
115+
}
116+
107117
/**
108118
* @param string $contents
109119
*

src/Format/WebP.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,19 @@ public function getIptc()
144144
*/
145145
public static function fromFile($filename)
146146
{
147-
// var_dump($filename);
148147
return new self(file_get_contents($filename));
149148
}
150149

150+
/**
151+
* @param $string
152+
*
153+
* @return PNG
154+
*/
155+
public static function fromString($string)
156+
{
157+
return new self($string);
158+
}
159+
151160
/**
152161
* @param string $contents
153162
*

src/Image.php

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -210,29 +210,31 @@ public static function fromFile($fileName)
210210
*
211211
* @return JPEG|WebP|PNG|false
212212
*/
213+
213214
public static function fromString($string)
214215
{
215-
$len = strlen($string);
216+
$imageInfo = getimagesizefromstring($string);
216217

217-
// try JPEG
218-
if ($len >= 2) {
219-
if (JPEG::SOI === substr($string, 0, 2)) {
220-
return JPEG::fromString($string);
221-
}
218+
if (!$imageInfo) {
219+
return false;
222220
}
223221

224-
// try WebP
225-
if ($len >= 4) {
226-
if ('RIFF' === substr($string, 0, 4) && 'WEBP' === substr($string, 8, 4)) {
227-
return WebP::fromString($string);
228-
}
229-
}
222+
$width = $imageInfo[0];
223+
$height = $imageInfo[1];
224+
$mime = $imageInfo['mime'];
230225

231-
// try PNG
232-
if ($len >= 8) {
233-
if (PNG::SIGNATURE === substr($string, 0, 8)) {
234-
return PNG::fromString($string);
235-
}
226+
$mimeToClass = [
227+
'image/jpeg' => JPEG::class,
228+
'image/png' => PNG::class,
229+
'image/webp' => WebP::class,
230+
];
231+
232+
if (isset($mimeToClass[$mime])) {
233+
$class = $mimeToClass[$mime];
234+
$image = $class::fromString($string);
235+
$image->width = $width;
236+
$image->height = $height;
237+
return $image;
236238
}
237239

238240
return false;

tests/Format/JPEGTest.php

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,58 @@
11
<?php
2-
32
namespace CSD\Image\Tests\Format;
43

54
use CSD\Image\Format\JPEG;
65
use CSD\Image\Metadata\Xmp;
76

87
/**
9-
* @author Daniel Chesterton <daniel@chestertondevelopment.com>
10-
*
118
* @coversDefaultClass \CSD\Image\Format\JPEG
129
*/
1310
class JPEGTest extends \PHPUnit\Framework\TestCase
1411
{
1512
/**
16-
* Test that JPEG can read XMP embedded with Photo Mechanic.
13+
* Data provider for testGetXmp method.
14+
*
15+
* @return array
1716
*/
18-
public function testGetXmpPhotoMechanic()
17+
public function providerTestGetXmp()
1918
{
20-
$jpeg = JPEG::fromFile(__DIR__ . '/../Fixtures/metapm.jpg');
21-
22-
$xmp = $jpeg->getXmp();
23-
24-
$this->assertInstanceOf(Xmp::class, $xmp);
25-
$this->assertSame('Headline', $xmp->getHeadline());
19+
return [
20+
// [method, filename, expectedHeadline]
21+
['fromFile', 'metapm.jpg', 'Headline'],
22+
['fromString', 'metapm.jpg', 'Headline'],
23+
['fromFile', 'metaphotoshop.jpg', 'Headline'],
24+
['fromString', 'metaphotoshop.jpg', 'Headline'],
25+
['fromFile', 'nometa.jpg', null],
26+
['fromString', 'nometa.jpg', null],
27+
];
2628
}
2729

2830
/**
29-
* Test that JPEG can read XMP embedded with Photoshop.
31+
* Test that JPEG can read XMP data using both fromFile and fromString methods.
32+
*
33+
* @dataProvider providerTestGetXmp
34+
*
35+
* @param string $method The method to use ('fromFile' or 'fromString')
36+
* @param string $filename The filename of the test image
37+
* @param string|null $expectedHeadline The expected headline in the XMP data
3038
*/
31-
public function testGetXmpPhotoshop()
39+
public function testGetXmp($method, $filename, $expectedHeadline)
3240
{
33-
$jpeg = JPEG::fromFile(__DIR__ . '/../Fixtures/metaphotoshop.jpg');
34-
35-
$xmp = $jpeg->getXmp();
41+
$filePath = __DIR__ . '/../Fixtures/' . $filename;
3642

37-
$this->assertInstanceOf(Xmp::class, $xmp);
38-
$this->assertSame('Headline', $xmp->getHeadline());
39-
}
40-
41-
/**
42-
* Test that JPEG class returns an empty XMP object when there is no XMP data.
43-
*/
44-
public function testGetXmpNoMeta()
45-
{
46-
$jpeg = JPEG::fromFile(__DIR__ . '/../Fixtures/nometa.jpg');
43+
if ($method === 'fromFile') {
44+
$jpeg = JPEG::fromFile($filePath);
45+
} elseif ($method === 'fromString') {
46+
$string = file_get_contents($filePath);
47+
$jpeg = JPEG::fromString($string);
48+
} else {
49+
throw new \InvalidArgumentException("Invalid method: $method");
50+
}
4751

4852
$xmp = $jpeg->getXmp();
4953

5054
$this->assertInstanceOf(Xmp::class, $xmp);
51-
$this->assertNull($xmp->getHeadline());
55+
$this->assertSame($expectedHeadline, $xmp->getHeadline());
5256
}
5357
}
58+

0 commit comments

Comments
 (0)