Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable timeout setting for the optimize method #187

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 24 additions & 6 deletions docs/image-manipulations/optimizing-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ weight: 3

## Requirements

Optimization of images is done by the underlying [spatie/image-optimizer](https://github.com/spatie/image-optimizer). It assumes that there are a few optimization tools, such as [JpegOptim](http://freecode.com/projects/jpegoptim) an [Pngquant](https://pngquant.org/) present on your system. For more info, check out [the relevant docs](https://github.com/spatie/image-optimizer#optimization-tools).
Optimization of images is done by the underlying [spatie/image-optimizer](https://github.com/spatie/image-optimizer) package. It assumes that there are a few optimization tools, such as [JpegOptim](http://freecode.com/projects/jpegoptim) an [Pngquant](https://pngquant.org/) present on your system. For more info, check out [the relevant docs](https://github.com/spatie/image-optimizer#optimization-tools).

## How to use

Expand All @@ -28,17 +28,35 @@ No matter where or how many times you call `optimize` in you chain, it will alwa

## Customizing the optimization

To optimization of images is done by the underlying [spatie/image-optimizer](https://github.com/spatie/image-optimizer) package. You can pass your own customized chains as array. The keys should be fully qualified class names of optimizers and the values the options that they should get. Here's an example
You are able to customize the optimization by passing an options array to the `optimize` method. The `'optimizers'` settings key lets you to pass your own customized chain of optimizers as an array. The keys should be fully qualified class names of optimizers and the values should be the options that they should get.

```php
Image::load('example.jpg')
->optimize([Jpegoptim::class => [
'--all-progressive',
]])
->optimize([
'optimizers' => [
Jpegoptim::class => [
'--all-progressive',
],
],
])
->save();
```

If you need more control over the optimizer chain, you can still pass your own instance of `OptimizerChain`. It can be especially useful if you need to set a custom timeout or a custom binary path. You may not have enough privileges to install the necessary binaries on your server but you can still upload some [precompiled binaries](https://github.com/imagemin?q=bin&type=&language=).
Besides the options array you may pass the `$timeout` argument. It lets you to set a custom timeout in seconds other than the default 60s. Adjusting this setting may be inevitable while working with large images (see e.g. [#187](https://github.com/spatie/image/pull/187)).

```php
Image::load('example.jpg')
->optimize([
'optimizers' => [
Jpegoptim::class => [
'--all-progressive',
],
],
], timeout: 120)
->save();
```

If you need more control over the optimizer chain, you can still pass your own instance of `OptimizerChain`. It can be especially useful if you need to set a custom binary path. You may not have enough privileges to install the necessary binaries on your server but you can still upload some [precompiled binaries](https://github.com/imagemin?q=bin&type=&language=).

```php
$optimizer = new OptimizerChain();
Expand Down
13 changes: 11 additions & 2 deletions src/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,17 @@ protected function performOptimization($path, array $optimizerChainConfiguration
$optimizerChain = $this->optimizerChain ?? OptimizerChainFactory::create();

if (count($optimizerChainConfiguration)) {
if (isset($optimizerChainConfiguration['timeout'])) {
$optimizerChain->setTimeout($optimizerChainConfiguration['timeout']);
// unsetting the 'timeout' key for the backward compatibility for configuration arrays not having the 'optimizers' key
unset($optimizerChainConfiguration['timeout']);
}

$optimizersOptions = isset($optimizerChainConfiguration['optimizers'])
? $optimizerChainConfiguration['optimizers']
// backward compatibility for configuration arrays not having the 'optimizers' key
: $optimizerChainConfiguration;
$existingOptimizers = $optimizerChain->getOptimizers();

$optimizers = array_map(function (array $optimizerOptions, string $optimizerClassName) use ($existingOptimizers) {
$optimizer = array_values(array_filter($existingOptimizers, function ($optimizer) use ($optimizerClassName) {
return $optimizer::class === $optimizerClassName;
Expand All @@ -150,7 +159,7 @@ protected function performOptimization($path, array $optimizerChainConfiguration
$optimizer = isset($optimizer[0]) && $optimizer[0] instanceof BaseOptimizer ? $optimizer[0] : new $optimizerClassName();

return $optimizer->setOptions($optimizerOptions)->setBinaryPath($optimizer->binaryPath);
}, $optimizerChainConfiguration, array_keys($optimizerChainConfiguration));
}, $optimizersOptions, array_keys($optimizersOptions));

$optimizerChain->setOptimizers($optimizers);
}
Expand Down
6 changes: 5 additions & 1 deletion src/Manipulations.php
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,12 @@ public function watermarkOpacity(int $opacity): static
/**
* Shave off some kilobytes by optimizing the image.
*/
public function optimize(array $optimizationOptions = []): static
public function optimize(array $optimizationOptions = [], ?int $timeout = null): static
{
if ($timeout !== null) {
$optimizationOptions['timeout'] = $timeout;
}

return $this->addManipulation('optimize', json_encode($optimizationOptions));
}

Expand Down
79 changes: 72 additions & 7 deletions tests/Manipulations/OptimizeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,25 @@
it('can optimize an image with the given optimization options', function () {
$targetFile = $this->tempDir->path('optimized.jpg');

Image::load(getTestFile('test.jpg'))
->optimize([
'optimizers' => [
Jpegoptim::class => [
'--all-progressive',
],
],
])
->save($targetFile);

expect($targetFile)->toBeFile();
});

it('can optimize an image with options format backward compatibility', function () {
$targetFile = $this->tempDir->path('optimized.jpg');

Image::load(getTestFile('test.jpg'))
->optimize([Jpegoptim::class => [
'--all-progressive',
'--all-progressive',
]])
->save($targetFile);

Expand All @@ -46,14 +62,63 @@
Image::load(getTestFile('test.jpg'))
->setOptimizeChain(OptimizerChainFactory::create())
->optimize([
Pngquant::class => [
'--force',
],
Jpegoptim::class => [
'--all-progressive',
],
'optimizers' => [
Pngquant::class => [
'--force',
],
Jpegoptim::class => [
'--all-progressive',
],
],
])
->save($targetFile);

expect($targetFile)->toBeFile();
});

it('can optimize an image specifying a desired timeout with a configuration array key', function () {
$targetFile = $this->tempDir->path('optimized.jpg');

Image::load(getTestFile('test.jpg'))
->setOptimizeChain(OptimizerChainFactory::create())
->optimize([
'timeout' => 120,
'optimizers' => [
Jpegoptim::class => [
'--all-progressive',
],
],
])
->save($targetFile);

expect($targetFile)->toBeFile();
});

it('can optimize an image specifying a desired timeout with a method argument', function () {
$targetFile = $this->tempDir->path('optimized.jpg');

Image::load(getTestFile('test.jpg'))
->setOptimizeChain(OptimizerChainFactory::create())
->optimize([
'optimizers' => [
Jpegoptim::class => [
'--all-progressive',
],
],
], timeout: 120)
->save($targetFile);

expect($targetFile)->toBeFile();
});

it('can optimize an image with options format backward compatibility and timeout parameter', function () {
$targetFile = $this->tempDir->path('optimized.jpg');

Image::load(getTestFile('test.jpg'))
->optimize([Jpegoptim::class => [
'--all-progressive',
]], timeout: 120)
->save($targetFile);

expect($targetFile)->toBeFile();
});