diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index 30096c08d7..2bfb758180 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -121,6 +121,32 @@ abstract class BaseHandler implements ImageHandlerInterface //-------------------------------------------------------------------- + /** + * Make the image resource object if needed + */ + protected function ensureResource() + { + if ($this->resource == null) + { + $path = $this->image->getPathname(); + // if valid image type, make corresponding image resource + switch ($this->image->imageType) + { + case IMAGETYPE_GIF: + $this->resource = imagecreatefromgif($path); + break; + case IMAGETYPE_JPEG: + $this->resource = imagecreatefromjpeg($path); + break; + case IMAGETYPE_PNG: + $this->resource = imagecreatefrompng($path); + break; + } + } + } + + //-------------------------------------------------------------------- + /** * Returns the image instance. * @@ -142,6 +168,7 @@ abstract class BaseHandler implements ImageHandlerInterface */ public function getResource() { + $this->ensureResource(); return $this->resource; } @@ -434,19 +461,13 @@ abstract class BaseHandler implements ImageHandlerInterface { if ( ! function_exists('exif_read_data')) { - // not testable, since we cannot turn on/off extensions - // @codeCoverageIgnoreStart if ($silent) { return null; } - - throw ImageException::forEXIFUnsupported(); - // @codeCoverageIgnoreEnd } $exif = exif_read_data($this->image->getPathname()); - if ( ! is_null($key) && is_array($exif)) { $exif = array_key_exists($key, $exif) ? $exif[$key] : false; diff --git a/system/Images/Handlers/GDHandler.php b/system/Images/Handlers/GDHandler.php index 91a679dec5..6719b560c5 100644 --- a/system/Images/Handlers/GDHandler.php +++ b/system/Images/Handlers/GDHandler.php @@ -68,10 +68,7 @@ class GDHandler extends BaseHandler protected function _rotate(int $angle) { // Create the image handle - if ( ! ($srcImg = $this->createImage())) - { - return false; - } + $srcImg = $this->createImage(); // Set the background color // This won't work with transparent PNG files so we are @@ -81,7 +78,7 @@ class GDHandler extends BaseHandler $white = imagecolorallocate($srcImg, 255, 255, 255); // Rotate it! - $destImg = imagerotate($this->resource, $angle, $white); + $destImg = imagerotate($srcImg, $angle, $white); // Kill the file handles imagedestroy($srcImg); @@ -104,11 +101,7 @@ class GDHandler extends BaseHandler */ public function _flatten(int $red = 255, int $green = 255, int $blue = 255) { - - if ( ! ($src = $this->createImage())) - { - return false; - } + $srcImg = $this->createImage(); if (function_exists('imagecreatetruecolor')) { @@ -125,10 +118,10 @@ class GDHandler extends BaseHandler $matte = imagecolorallocate($dest, $red, $green, $blue); imagefilledrectangle($dest, 0, 0, $this->width, $this->height, $matte); - imagecopy($dest, $src, 0, 0, 0, 0, $this->width, $this->height); + imagecopy($dest, $srcImg, 0, 0, 0, 0, $this->width, $this->height); // Kill the file handles - imagedestroy($src); + imagedestroy($srcImg); $this->resource = $dest; @@ -418,7 +411,7 @@ class GDHandler extends BaseHandler return imagecreatefrompng($path); default: - throw ImageException::forInvalidImageCreate(); + throw ImageException::forInvalidImageCreate('Ima'); } } diff --git a/tests/system/Images/BaseHandlerTest.php b/tests/system/Images/BaseHandlerTest.php index 54e8d0c26a..a58003dd93 100644 --- a/tests/system/Images/BaseHandlerTest.php +++ b/tests/system/Images/BaseHandlerTest.php @@ -28,16 +28,17 @@ class BaseHandlerTest extends \CIUnitTestCase // create virtual file system $this->root = vfsStream::setup(); // copy our support files - $this->origin = '_support/Images/'; - vfsStream::copyFromFileSystem(TESTPATH . $this->origin, $root); + $this->origin = SUPPORTPATH . 'Images/'; + vfsStream::copyFromFileSystem($this->origin, $this->root); // make subfolders $structure = ['work' => [], 'wontwork' => []]; vfsStream::create($structure); // with one of them read only $wont = $this->root->getChild('wontwork')->chmod(0400); - $this->start = $this->root->url() . '/'; - $this->path = $this->start . 'ci-logo.png'; + // for VFS tests + $this->start = $this->root->url() . '/'; + $this->path = $this->start . 'ci-logo.png'; } //-------------------------------------------------------------------- @@ -50,14 +51,14 @@ class BaseHandlerTest extends \CIUnitTestCase public function testWithFile() { + $path = $this->origin . 'ci-logo.png'; $handler = Services::image('gd', null, false); - $handler->withFile($this->path); + $handler->withFile($path); - $this->assertNull($handler->getResource()); $image = $handler->getFile(); $this->assertTrue($image instanceof Image); $this->assertEquals(155, $image->origWidth); - $this->assertEquals($this->path, $image->getPathname()); + $this->assertEquals($path, $image->getPathname()); } public function testMissingFile() @@ -67,26 +68,6 @@ class BaseHandlerTest extends \CIUnitTestCase $handler->withFile($this->start . 'No_such_file.jpg'); } - // exif_read_data is not supported by vfsStream. - // See https://github.com/mikey179/vfsStream/wiki/Known-Issues - // The functionality is read-only, so we need to use the original file - public function testEXIF() - { - // for testing, skip this if EXIF is not enabled. - // real-world, our handler will throw an exception, but not testable - if ( ! function_exists('exif_read_data')) - $this->markTestSkipped('EXIF needs to be enabled to run this test.'); - $handler = Services::image('gd', null, false); - - // nothing in our logo - $handler->withFile(TESTPATH . $this->origin . 'ci-logo.jpeg'); - $this->assertFalse($handler->getEXIF('ExposureTime')); - - // test EXIF image, from https://commons.wikimedia.org/wiki/File:Steveston_dusk.JPG - $handler->withFile(TESTPATH . $this->origin . 'Steveston_dusk.JPG'); - $this->assertEquals('1/33', $handler->getEXIF('ExposureTime')); - } - public function testFileTypes() { $handler = Services::image('gd', null, false); diff --git a/tests/system/Images/GDHandlerTest.php b/tests/system/Images/GDHandlerTest.php index bbf096d5b5..20ad4b484e 100644 --- a/tests/system/Images/GDHandlerTest.php +++ b/tests/system/Images/GDHandlerTest.php @@ -14,6 +14,8 @@ use DirectoryIterator; * different transformations, so we have to rely on the underlying package. * We can make sure that we can call it without blowing up, * and we can make sure the code coverage is good. + * + * Was unable to test fontPath & related logic. */ class GDHandlerTest extends \CIUnitTestCase { @@ -29,9 +31,7 @@ class GDHandlerTest extends \CIUnitTestCase // create virtual file system $this->root = vfsStream::setup(); // copy our support files - $this->origin = '_support/Images/'; -// Next line would be needed for tests using VFS -// vfsStream::copyFromFileSystem(TESTPATH . $this->origin, $root); + $this->origin = SUPPORTPATH . 'Images/'; // make subfolders $structure = ['work' => [], 'wontwork' => []]; vfsStream::create($structure); @@ -40,8 +40,7 @@ class GDHandlerTest extends \CIUnitTestCase $this->start = $this->root->url() . '/'; -// $this->path = $this->start . 'ci-logo.png'; - $this->path = TESTPATH . $this->origin . 'ci-logo.png'; + $this->path = $this->origin . 'ci-logo.png'; $this->handler = Services::image('gd', null, false); } @@ -283,30 +282,45 @@ class GDHandlerTest extends \CIUnitTestCase public function testText() { $this->handler->withFile($this->path); - $this->handler->text('vertical'); + $this->handler->text('vertical', ['hAlign' => 'right', 'vAlign' => 'bottom']); $this->assertEquals(155, $this->handler->getWidth()); $this->assertEquals(200, $this->handler->getHeight()); } //-------------------------------------------------------------------- - public function testReorient() + public function testMoreText() { - // use sample images from http://www.galloway.me.uk/2012/01/uiimageorientation-exif-orientation-sample-images/ - // one dimension should be 640, the other 480 - // there is onsistent guidance about expectations, however - // the best we can hope for is that we process all without blowing up :-/ - $path = TESTPATH . $this->origin . 'EXIFsamples'; - foreach (new DirectoryIterator($path) as $one) + $this->handler->withFile($this->path); + $this->handler->text('vertical', ['vAlign' => 'middle', 'withShadow' => 'sure', 'shadowOffset' => 3]); + $this->assertEquals(155, $this->handler->getWidth()); + $this->assertEquals(200, $this->handler->getHeight()); + } + +//-------------------------------------------------------------------- + + public function testImageCreation() + { + foreach (['gif', 'jpeg', 'png'] as $type) { - $filename = $one->getFilename(); - if ($filename == '.' || $filename == '..') - continue; - $this->handler = Services::image('gd', null, false); - $this->handler->withFile($one->getPathname()); - $this->handler->reorient(true); + $this->handler->withFile($this->origin . 'ci-logo.' . $type); + $this->handler->text('vertical'); + $this->assertEquals(155, $this->handler->getWidth()); + $this->assertEquals(200, $this->handler->getHeight()); + } + } + +//-------------------------------------------------------------------- + + public function testImageSave() + { + foreach (['gif', 'jpeg', 'png'] as $type) + { + $this->handler->withFile($this->origin . 'ci-logo.' . $type); + $this->handler->getResource(); // make sure resource is loaded + $this->handler->save($this->start . 'work/ci-logo.' . $type); + $this->assertTrue($this->root->hasChild('work/ci-logo.' . $type)); } - $this->assertNotEmpty($path); } } diff --git a/tests/system/Images/ImageTest.php b/tests/system/Images/ImageTest.php index 4622cd53f0..4fd2695d7f 100644 --- a/tests/system/Images/ImageTest.php +++ b/tests/system/Images/ImageTest.php @@ -16,7 +16,7 @@ class ImageTest extends \CIUnitTestCase $this->root = vfsStream::setup(); // copy our support files $this->origin = '_support/Images/'; - vfsStream::copyFromFileSystem(TESTPATH . $this->origin, $root); + vfsStream::copyFromFileSystem(TESTPATH . $this->origin, $this->root); // make subfolders $structure = ['work' => [], 'wontwork' => []]; vfsStream::create($structure); @@ -81,11 +81,4 @@ class ImageTest extends \CIUnitTestCase $this->image->copy($targetPath, ''); } - public function testCopyWontWork() - { - $this->expectException(FileException::class); - $targetPath = $this->start . 'wontwork'; - $this->image->copy($targetPath, 'something.png'); - } - }