diff --git a/.github/workflows/tests-ffi-only.yml b/.github/workflows/tests-ffi-only.yml new file mode 100644 index 0000000..9af7a0e --- /dev/null +++ b/.github/workflows/tests-ffi-only.yml @@ -0,0 +1,48 @@ +name: Tests with ffi only (no vips-ext) + +on: + push: + branches: + - master + pull_request: + +jobs: + tests: + name: ${{ matrix.php }} ${{ matrix.env.COMPOSER_FLAGS }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - php: '7.4' + - php: '8.0' + env: + COMPOSER_FLAGS: "--prefer-lowest" + - php: '8.0' + - php: '8.1' + + env: + COMPOSER_FLAGS: ${{ matrix.env.COMPOSER_FLAGS }} + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install vips + run: sudo apt-get install -y libvips + + - name: Install composer dependencies + run: | + composer update --prefer-dist --no-interaction --no-progress --no-ansi ${COMPOSER_FLAGS} + + - name: PHPStan + run: composer phpstan + + - name: PHPUnit + run: composer phpunit diff --git a/.github/workflows/static.yml b/.github/workflows/tests-vips-only.yml similarity index 73% rename from .github/workflows/static.yml rename to .github/workflows/tests-vips-only.yml index fbe31a7..f945c87 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/tests-vips-only.yml @@ -1,4 +1,4 @@ -name: Static analysis +name: Tests with vips-ext only (no ffi) on: push: @@ -7,20 +7,21 @@ on: pull_request: jobs: - phpstan: - name: phpstan ${{ matrix.php }} + tests: + name: ${{ matrix.php }} ${{ matrix.env.COMPOSER_FLAGS }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - - php: '7.2' - - php: '7.3' - php: '7.4' + - php: '8.0' + env: + COMPOSER_FLAGS: "--prefer-lowest" - php: '8.0' - php: '8.1' - - + env: + COMPOSER_FLAGS: ${{ matrix.env.COMPOSER_FLAGS }} steps: - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -28,6 +29,7 @@ jobs: php-version: ${{ matrix.php }} tools: composer:v2 coverage: none + extensions: :ffi - name: Checkout code uses: actions/checkout@v2 @@ -47,3 +49,6 @@ jobs: - name: PHPStan run: composer phpstan + + - name: PHPUnit + run: composer phpunit diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..6f42b56 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,55 @@ +name: Tests with vips-ext and ffi + +on: + push: + branches: + - master + pull_request: + +jobs: + tests: + name: ${{ matrix.php }} ${{ matrix.env.COMPOSER_FLAGS }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - php: '7.2' #even though there's no ffi for 7.2, we leave it here for the "complete" coverage + - php: '7.3' #even though there's no ffi for 7.3, we leave it here for the "complete" coverage + - php: '7.4' + - php: '8.0' + env: + COMPOSER_FLAGS: "--prefer-lowest" + - php: '8.0' + - php: '8.1' + env: + COMPOSER_FLAGS: ${{ matrix.env.COMPOSER_FLAGS }} + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install vips + run: sudo apt-get install -y libvips-dev + + - name: Install vips extension + run: sudo pecl install vips + + - name: Install vips ext config + run: echo "extension=vips.so" >> $(php -i | grep /.+/php.ini -oE) + + - name: Install composer dependencies + run: | + composer update --prefer-dist --no-interaction --no-progress --no-ansi ${COMPOSER_FLAGS} + + - name: PHPStan + run: composer phpstan + + - name: PHPUnit + run: composer phpunit diff --git a/CHANGELOG.md b/CHANGELOG.md index 5703068..ac1d6f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +### 0.31.0 (2022-10-12) + * Make it compatible with jcupitt/vips 2.1 (and disable support for 2.0, 1.0.x is still supported) + * Add more phpstan tests for all the combinations + * Replace vips_version with Jcupitt\Vips\Config::version() for better support, when vips-ext is not available + * Add some simple PHPUnit tests + ### 0.30.1 (2022-10-04) * Fix issue with PHP < 8.0 diff --git a/README.md b/README.md index c1c1551..f8d0ee3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # libvips adapter for Imagine -[![Static analysis](https://github.com/rokka-io/imagine-vips/actions/workflows/static.yml/badge.svg)](https://github.com/rokka-io/imagine-vips/actions/workflows/static.yml) +[![Static analysis](https://github.com/rokka-io/imagine-vips/actions/workflows/tests.yml/badge.svg)](https://github.com/rokka-io/imagine-vips/actions/workflows/tests.yml) [![Latest Stable Version](https://poser.pugx.org/rokka/imagine-vips/version.png)](https://packagist.org/packages/rokka/imagine-vips) diff --git a/composer.json b/composer.json index 5f4925b..107e351 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "require": { "php": "^7.2 || ^8.0", "imagine/imagine": "^1.0", - "jcupitt/vips" : "^2.0.2 || ^1.0.3", + "jcupitt/vips" : "^2.1.0 || ^1.0.3", "phenx/php-font-lib": "^0.5.2" }, @@ -53,9 +53,11 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.8", - "phpstan/phpstan": "^1.8" + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^8 || ^9" }, "scripts": { - "phpstan": "phpstan analyze -l 3 lib/" + "phpstan": "phpstan analyze -l 3 lib/", + "phpunit": "phpunit tests" } } diff --git a/lib/Imagine/Vips/Image.php b/lib/Imagine/Vips/Image.php index 7d347b5..e3687ea 100644 --- a/lib/Imagine/Vips/Image.php +++ b/lib/Imagine/Vips/Image.php @@ -32,6 +32,7 @@ use Imagine\Image\VipsProfile; use Jcupitt\Vips\BandFormat; use Jcupitt\Vips\BlendMode; +use Jcupitt\Vips\Config; use Jcupitt\Vips\Direction; use Jcupitt\Vips\Exception; use Jcupitt\Vips\Exception as VipsException; @@ -271,7 +272,7 @@ public function strip() */ public function paste(ImageInterface $image, PointInterface $start, $alpha = 100) { - if (version_compare(vips_version(), '8.6', '<')) { + if (version_compare(Config::version(), '8.6', '<')) { throw new RuntimeException('The paste method needs at least vips 8.6'); } @@ -409,7 +410,7 @@ public function rotate($angle, ColorInterface $background = null) $vips = $vips->bandjoin(255); } } - if (version_compare(vips_version(), '8.6', '<')) { + if (version_compare(Config::version(), '8.6', '<')) { throw new RuntimeException('The rotate method for angles != 90, 180, 270 needs at least vips 8.6'); } $vips = $vips->similarity(['angle' => $angle, 'background' => self::getColorArrayAlpha($color, $vips->bands)]); @@ -1121,7 +1122,7 @@ private function getSaveMethodAndOptions($format, array $options): array 'Q' => $options[self::OPTION_WEBP_QUALITY], 'lossless' => $options[self::OPTION_WEBP_LOSSLESS], ], $options); - if (isset($options[self::OPTION_WEBP_REDUCTION_EFFORT]) && version_compare(vips_version(), '8.8', '>=')) { + if (isset($options[self::OPTION_WEBP_REDUCTION_EFFORT]) && version_compare(Config::version(), '8.8', '>=')) { $saveOptions['reduction_effort'] = $options[self::OPTION_WEBP_REDUCTION_EFFORT]; } @@ -1129,14 +1130,14 @@ private function getSaveMethodAndOptions($format, array $options): array } elseif ('tiff' == $format) { $saveOptions = $this->applySaveOptions([], $options); $method = 'tiffsave'; - } elseif (('heif' == $format || 'heic' == $format) && version_compare(vips_version(), '8.8.0', '>=')) { + } elseif (('heif' == $format || 'heic' == $format) && version_compare(Config::version(), '8.8.0', '>=')) { $saveOptions = $this->applySaveOptions(['Q' => $options[self::OPTION_HEIF_QUALITY], 'strip' => $this->strip], $options); $method = 'heifsave'; - } elseif (('avif' == $format) && version_compare(vips_version(), '8.9.0', '>=')) { + } elseif (('avif' == $format) && version_compare(Config::version(), '8.9.0', '>=')) { $saveOptions = $this->applySaveOptions(['Q' => $options[self::OPTION_AVIF_QUALITY], 'compression' => 'av1', 'strip' => $this->strip], $options); $method = 'heifsave'; } elseif ('gif' == $format) { - if (version_compare(vips_version(), '8.12.0', '>=') && !(isset($options['force_magick']) && true === $options['force_magick'])) { + if (version_compare(Config::version(), '8.12.0', '>=') && !(isset($options['force_magick']) && true === $options['force_magick'])) { $saveOptions = $this->applySaveOptions([], $options); $method = 'gifsave'; } else { @@ -1144,7 +1145,7 @@ private function getSaveMethodAndOptions($format, array $options): array $method = 'magicksave'; } $delayProperty = 'delay'; - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { $delayProperty = 'gif-delay'; } if (0 === $this->vips->typeof($delayProperty)) { @@ -1156,7 +1157,7 @@ private function getSaveMethodAndOptions($format, array $options): array } else { // use magicksave, if available and possible // ppm in vips has some strange issues, save in fallback... - if ('ppm' !== $format && version_compare(vips_version(), '8.7.0', '>=')) { + if ('ppm' !== $format && version_compare(Config::version(), '8.7.0', '>=')) { if ('heic' == $format || 'heif' === $format) { $saveOptions = ['quality' => $options[self::OPTION_HEIF_QUALITY], 'format' => $format]; $method = 'magicksave'; @@ -1198,7 +1199,7 @@ private function convertToAlternativeForSave(array $options, self $image, string private function joinMultilayer($format, self $image): VipsImage { $vips = $this->getVips(); - if ((('webp' === $format && version_compare(vips_version(), '8.8.0', '>=')) + if ((('webp' === $format && version_compare(Config::version(), '8.8.0', '>=')) || 'gif' === $format) && \count($image->layers()) > 1) { $vips = $vips->copy(); diff --git a/lib/Imagine/Vips/Imagine.php b/lib/Imagine/Vips/Imagine.php index 1a433b9..93af39b 100644 --- a/lib/Imagine/Vips/Imagine.php +++ b/lib/Imagine/Vips/Imagine.php @@ -23,6 +23,7 @@ use Imagine\Image\VipsProfile; use Jcupitt\Vips\Config; use Jcupitt\Vips\Exception; +use Jcupitt\Vips\FFI; use Jcupitt\Vips\Image as VipsImage; use Jcupitt\Vips\Interpretation; @@ -47,7 +48,7 @@ class Imagine extends AbstractImagine */ public function __construct(array $config = []) { - if (method_exists(Config::class, 'ffi')) { + if (\class_exists(FFI::class)) { if (!\extension_loaded('ffi')) { throw new RuntimeException('ffi extension not installed'); } @@ -202,7 +203,7 @@ public static function hasVipsInstalled() { try { // this method only exists in php-vips 2.0 - if (method_exists(Config::class, 'ffi')) { + if (\class_exists(FFI::class)) { // if ffi extension is not installed, we can't use php-vips if (!\extension_loaded('ffi')) { return false; diff --git a/lib/Imagine/Vips/Layers.php b/lib/Imagine/Vips/Layers.php index 5e90066..a4b0908 100644 --- a/lib/Imagine/Vips/Layers.php +++ b/lib/Imagine/Vips/Layers.php @@ -16,6 +16,7 @@ use Imagine\Image\AbstractLayers; use Imagine\Image\Metadata\MetadataBag; use Jcupitt\Vips\BlendMode; +use Jcupitt\Vips\Config; use Jcupitt\Vips\Exception; class Layers extends AbstractLayers @@ -89,7 +90,7 @@ public function merge() public function animate($format, $delay, $loops) { $vips = $this->image->vipsCopy(); - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { $vips->set('gif-delay', $delay / 10); } else { $vips->set('delay', array_fill(0, \count($this), $delay)); @@ -268,7 +269,7 @@ public function getResources() */ public function getDelays() { - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { throw new RuntimeException('This feature needs at least vips 8.9'); } $vips = $this->image->getVips(); @@ -288,7 +289,7 @@ public function getDelays() */ public function setDelays($delays) { - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { throw new RuntimeException('This feature needs at least vips 8.9'); } $vips = $this->image->vipsCopy(); @@ -306,7 +307,7 @@ public function setDelays($delays) */ public function getDelay($index) { - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { throw new RuntimeException('This feature needs at least vips 8.9'); } $vips = $this->image->getVips(); @@ -337,7 +338,7 @@ public function getDelay($index) */ public function setDelay($index, $delay) { - if (version_compare(vips_version(), '8.9', '<')) { + if (version_compare(Config::version(), '8.9', '<')) { throw new RuntimeException('This feature needs at least vips 8.9'); } $vips = $this->image->getVips(); diff --git a/tests/BasicImageTest.php b/tests/BasicImageTest.php new file mode 100644 index 0000000..0511888 --- /dev/null +++ b/tests/BasicImageTest.php @@ -0,0 +1,34 @@ +create(new Box(10,10)); + $this->assertInstanceOf(\Imagine\Vips\Image::class, $image); + $this->assertEquals($image->getSize()->getWidth(), 10); + } + + public function testResizeImage() { + $imagine = new \Imagine\Vips\Imagine(); + $image = $imagine->create(new Box(200,100)); + $image->resize(new Box(50,50)); + $this->assertEquals($image->getSize()->getWidth(), 50); + $this->assertEquals($image->getSize()->getHeight(), 50); + } + + public function testSaveImage() { + $imagine = new \Imagine\Vips\Imagine(); + $image = $imagine->create(new Box(200,100)); + $image->save("foo.jpg"); + $this->assertFileExists("foo.jpg"); + $loaded = $imagine->open("foo.jpg"); + $this->assertEquals($loaded->getSize()->getWidth(), 200); + $this->assertEquals($loaded->getSize()->getHeight(), 100); + unlink("foo.jpg"); + } +} \ No newline at end of file diff --git a/tests/EnabledTest.php b/tests/EnabledTest.php new file mode 100644 index 0000000..80e2091 --- /dev/null +++ b/tests/EnabledTest.php @@ -0,0 +1,10 @@ +assertTrue(\Imagine\Vips\Imagine::hasVipsInstalled()); + } +} \ No newline at end of file