Skip to content

Commit 91a5742

Browse files
authored
Merge pull request #3176 from michalsn/webp_support
Add webp support to Image class
2 parents 458e2d4 + a8f6c47 commit 91a5742

7 files changed

Lines changed: 125 additions & 38 deletions

File tree

system/Images/Handlers/GDHandler.php

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,17 @@ public function save(string $target = null, int $quality = 90): bool
325325
throw ImageException::forSaveFailed();
326326
}
327327
break;
328+
case IMAGETYPE_WEBP:
329+
if (! function_exists('imagewebp'))
330+
{
331+
throw ImageException::forInvalidImageCreate(lang('images.webpNotSupported'));
332+
}
333+
334+
if (! @imagewebp($this->resource, $target))
335+
{
336+
throw ImageException::forSaveFailed();
337+
}
338+
break;
328339
default:
329340
throw ImageException::forInvalidImageCreate();
330341
}
@@ -366,6 +377,38 @@ protected function createImage(string $path = '', string $imageType = '')
366377
$imageType = $this->image()->imageType;
367378
}
368379

380+
return $this->getImageResource($path, $imageType);
381+
}
382+
383+
//--------------------------------------------------------------------
384+
385+
/**
386+
* Make the image resource object if needed
387+
*/
388+
protected function ensureResource()
389+
{
390+
if ($this->resource === null)
391+
{
392+
// if valid image type, make corresponding image resource
393+
$this->resource = $this->getImageResource(
394+
$this->image()->getPathname(), $this->image()->imageType
395+
);
396+
}
397+
}
398+
399+
//--------------------------------------------------------------------
400+
401+
/**
402+
* Check if image type is supported and return image resource
403+
*
404+
* @param string $path Image path
405+
* @param integer $imageType Image type
406+
*
407+
* @return resource
408+
* @throws type ImageException
409+
*/
410+
protected function getImageResource(string $path, int $imageType)
411+
{
369412
switch ($imageType)
370413
{
371414
case IMAGETYPE_GIF:
@@ -389,39 +432,20 @@ protected function createImage(string $path = '', string $imageType = '')
389432
}
390433

391434
return imagecreatefrompng($path);
435+
case IMAGETYPE_WEBP:
436+
if (! function_exists('imagecreatefromwebp'))
437+
{
438+
throw ImageException::forInvalidImageCreate(lang('images.webpNotSupported'));
439+
}
440+
441+
return imagecreatefromwebp($path);
392442
default:
393443
throw ImageException::forInvalidImageCreate('Ima');
394444
}
395445
}
396446

397447
//--------------------------------------------------------------------
398448

399-
/**
400-
* Make the image resource object if needed
401-
*/
402-
protected function ensureResource()
403-
{
404-
if ($this->resource === null)
405-
{
406-
$path = $this->image()->getPathname();
407-
// if valid image type, make corresponding image resource
408-
switch ($this->image()->imageType)
409-
{
410-
case IMAGETYPE_GIF:
411-
$this->resource = imagecreatefromgif($path);
412-
break;
413-
case IMAGETYPE_JPEG:
414-
$this->resource = imagecreatefromjpeg($path);
415-
break;
416-
case IMAGETYPE_PNG:
417-
$this->resource = imagecreatefrompng($path);
418-
break;
419-
}
420-
}
421-
}
422-
423-
//--------------------------------------------------------------------
424-
425449
/**
426450
* Add text overlay to an image.
427451
*

system/Images/Handlers/ImageMagickHandler.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,11 @@ protected function process(string $action, int $quality = 100): array
252252
throw ImageException::forInvalidImageLibraryPath($this->config->libraryPath);
253253
}
254254

255+
if ($action !== '-version')
256+
{
257+
$this->supportedFormatCheck();
258+
}
259+
255260
if (! preg_match('/convert$/i', $this->config->libraryPath))
256261
{
257262
$this->config->libraryPath = rtrim($this->config->libraryPath, '/') . '/convert';
@@ -361,6 +366,26 @@ protected function getResourcePath()
361366
protected function ensureResource()
362367
{
363368
$this->getResourcePath();
369+
370+
$this->supportedFormatCheck();
371+
}
372+
373+
/**
374+
* Check if given image format is supported
375+
*
376+
* @throws ImageException
377+
*/
378+
protected function supportedFormatCheck()
379+
{
380+
switch ($this->image()->imageType)
381+
{
382+
case IMAGETYPE_WEBP:
383+
if (! in_array('WEBP', \Imagick::queryFormats()))
384+
{
385+
throw ImageException::forInvalidImageCreate(lang('images.webpNotSupported'));
386+
}
387+
break;
388+
}
364389
}
365390

366391
//--------------------------------------------------------------------
@@ -487,7 +512,7 @@ public function _getHeight()
487512
{
488513
return imagesy(imagecreatefromstring(file_get_contents($this->resource)));
489514
}
490-
515+
491516
//--------------------------------------------------------------------
492517

493518
/**

system/Images/Image.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,10 @@ public function getProperties(bool $return = false)
143143
}
144144

145145
$types = [
146-
1 => 'gif',
147-
2 => 'jpeg',
148-
3 => 'png',
146+
IMAGETYPE_GIF => 'gif',
147+
IMAGETYPE_JPEG => 'jpeg',
148+
IMAGETYPE_PNG => 'png',
149+
IMAGETYPE_WEBP => 'webp',
149150
];
150151

151152
$mime = 'image/' . ($types[$vals[2]] ?? 'jpg');

system/Language/en/Images.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
'gifNotSupported' => 'GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.',
2222
'jpgNotSupported' => 'JPG images are not supported.',
2323
'pngNotSupported' => 'PNG images are not supported.',
24+
'webpNotSupported' => 'WEBP images are not supported.',
2425
'fileNotSupported' => 'The supplied file is not a supported image type.',
2526
'unsupportedImageCreate' => 'Your server does not support the GD function required to process this type of image.',
2627
'jpgOrPngRequired' => 'The image resize protocol specified in your preferences only works with JPEG or PNG image types.',

tests/_support/Images/ci-logo.webp

5.2 KB
Loading

tests/system/Images/GDHandlerTest.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,14 @@ public function testMoreText()
310310

311311
public function testImageCreation()
312312
{
313-
foreach (['gif', 'jpeg', 'png'] as $type)
313+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
314314
{
315+
if ($type === 'webp' && ! function_exists('imagecreatefromwebp'))
316+
{
317+
$this->expectException(ImageException::class);
318+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
319+
}
320+
315321
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
316322
$this->handler->text('vertical');
317323
$this->assertEquals(155, $this->handler->getWidth());
@@ -323,7 +329,7 @@ public function testImageCreation()
323329

324330
public function testImageCopy()
325331
{
326-
foreach (['gif', 'jpeg', 'png'] as $type)
332+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
327333
{
328334
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
329335
$this->handler->save($this->start . 'work/ci-logo.' . $type);
@@ -338,8 +344,14 @@ public function testImageCopy()
338344

339345
public function testImageCompressionGetResource()
340346
{
341-
foreach (['gif', 'jpeg', 'png'] as $type)
347+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
342348
{
349+
if ($type === 'webp' && ! function_exists('imagecreatefromwebp'))
350+
{
351+
$this->expectException(ImageException::class);
352+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
353+
}
354+
343355
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
344356
$this->handler->getResource(); // make sure resource is loaded
345357
$this->handler->save($this->start . 'work/ci-logo.' . $type);
@@ -354,8 +366,14 @@ public function testImageCompressionGetResource()
354366

355367
public function testImageCompressionWithResource()
356368
{
357-
foreach (['gif', 'jpeg', 'png'] as $type)
369+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
358370
{
371+
if ($type === 'webp' && ! function_exists('imagecreatefromwebp'))
372+
{
373+
$this->expectException(ImageException::class);
374+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
375+
}
376+
359377
$this->handler->withFile($this->origin . 'ci-logo.' . $type)
360378
->withResource() // make sure resource is loaded
361379
->save($this->start . 'work/ci-logo.' . $type);

tests/system/Images/ImageMagickHandlerTest.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,14 @@ public function testMoreText()
306306

307307
public function testImageCreation()
308308
{
309-
foreach (['gif', 'jpeg', 'png'] as $type)
309+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
310310
{
311+
if ($type === 'webp' && ! in_array('WEBP', \Imagick::queryFormats()))
312+
{
313+
$this->expectException(ImageException::class);
314+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
315+
}
316+
311317
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
312318
$this->handler->text('vertical');
313319
$this->assertEquals(155, $this->handler->getWidth());
@@ -319,7 +325,7 @@ public function testImageCreation()
319325

320326
public function testImageCopy()
321327
{
322-
foreach (['gif', 'jpeg', 'png'] as $type)
328+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
323329
{
324330
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
325331
$this->handler->save($this->root . 'ci-logo.' . $type);
@@ -334,8 +340,14 @@ public function testImageCopy()
334340

335341
public function testImageCompressionGetResource()
336342
{
337-
foreach (['gif', 'jpeg', 'png'] as $type)
343+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
338344
{
345+
if ($type === 'webp' && ! in_array('WEBP', \Imagick::queryFormats()))
346+
{
347+
$this->expectException(ImageException::class);
348+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
349+
}
350+
339351
$this->handler->withFile($this->origin . 'ci-logo.' . $type);
340352
$this->handler->getResource(); // make sure resource is loaded
341353
$this->handler->save($this->root . 'ci-logo.' . $type);
@@ -350,8 +362,14 @@ public function testImageCompressionGetResource()
350362

351363
public function testImageCompressionWithResource()
352364
{
353-
foreach (['gif', 'jpeg', 'png'] as $type)
365+
foreach (['gif', 'jpeg', 'png', 'webp'] as $type)
354366
{
367+
if ($type === 'webp' && ! in_array('WEBP', \Imagick::queryFormats()))
368+
{
369+
$this->expectException(ImageException::class);
370+
$this->expectExceptionMessage('Your server does not support the GD function required to process this type of image.');
371+
}
372+
355373
$this->handler->withFile($this->origin . 'ci-logo.' . $type)
356374
->withResource() // make sure resource is loaded
357375
->save($this->root . 'ci-logo.' . $type);

0 commit comments

Comments
 (0)