-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement chunking of generating thumbnails
Closes #90
- Loading branch information
Showing
7 changed files
with
196 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
<?php | ||
|
||
namespace Biigle\Jobs; | ||
|
||
use Log; | ||
use File; | ||
use Biigle\Image; | ||
use InterventionImage as IImage; | ||
use Illuminate\Queue\SerializesModels; | ||
use Illuminate\Queue\InteractsWithQueue; | ||
use Illuminate\Contracts\Queue\ShouldQueue; | ||
use Intervention\Image\Exception\NotReadableException; | ||
|
||
class ProcessThumbnailChunkJob extends Job implements ShouldQueue | ||
{ | ||
use InteractsWithQueue, SerializesModels; | ||
|
||
/** | ||
* The images to generate thumbnails for. | ||
* | ||
* Public for testability. | ||
* | ||
* @var Collection | ||
*/ | ||
public $images; | ||
|
||
/** | ||
* The desired thumbnail width. | ||
* | ||
* @var int | ||
*/ | ||
protected $width; | ||
|
||
/** | ||
* The desired thumbnail height. | ||
* | ||
* @var int | ||
*/ | ||
protected $height; | ||
|
||
/** | ||
* The desired thumbnail file format. | ||
* | ||
* @var int | ||
*/ | ||
protected $format; | ||
|
||
/** | ||
* Create a new job instance. | ||
* | ||
* @param Collection $images The images to generate thumbnails for. | ||
* | ||
* @return void | ||
*/ | ||
public function __construct($images) | ||
{ | ||
$this->images = $images; | ||
} | ||
|
||
/** | ||
* Execute the job. | ||
* | ||
* @return void | ||
*/ | ||
public function handle() | ||
{ | ||
$this->width = config('thumbnails.width'); | ||
$this->height = config('thumbnails.height'); | ||
$this->format = config('thumbnails.format'); | ||
|
||
$memoryLimit = ini_get('memory_limit'); | ||
// increase memory limit for resizing large images | ||
ini_set('memory_limit', config('thumbnails.memory_limit')); | ||
|
||
foreach ($this->images as $image) { | ||
$this->makeThumbnail($image); | ||
} | ||
|
||
// restore default memory limit | ||
ini_set('memory_limit', $memoryLimit); | ||
} | ||
|
||
/** | ||
* Makes a thumbnail for a single image. | ||
* | ||
* @param Image $image | ||
*/ | ||
protected function makeThumbnail(Image $image) | ||
{ | ||
// Skip existing thumbnails. | ||
if (File::exists($image->thumbPath)) { | ||
return; | ||
} | ||
|
||
try { | ||
IImage::make($image->url) | ||
->resize($this->width, $this->height, function ($constraint) { | ||
// resize images proportionally | ||
$constraint->aspectRatio(); | ||
}) | ||
->encode($this->format) | ||
->save($image->thumbPath) | ||
// free memory; very important for scaling 1000s of images!! | ||
->destroy(); | ||
} catch (NotReadableException $e) { | ||
Log::error('Could not generate thumbnail for image '.$image->id.': '.$e->getMessage()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
namespace Biigle\Tests\Jobs; | ||
|
||
use Log; | ||
use File; | ||
use TestCase; | ||
use Biigle\Tests\ImageTest; | ||
use Biigle\Tests\VolumeTest; | ||
use InterventionImage as IImage; | ||
use Biigle\Jobs\ProcessThumbnailChunkJob; | ||
|
||
class ProcessThumbnailChunkJobTest extends TestCase | ||
{ | ||
public function testHandle() | ||
{ | ||
$volume = VolumeTest::create(); | ||
$image = ImageTest::create(['volume_id' => $volume->id]); | ||
File::delete($image->thumbPath); | ||
|
||
with(new ProcessThumbnailChunkJob([$image]))->handle(); | ||
|
||
$this->assertTrue(File::exists($image->thumbPath)); | ||
$size = getimagesize($image->thumbPath); | ||
$config = [config('thumbnails.width'), config('thumbnails.height')]; | ||
|
||
$this->assertTrue($size[0] <= $config[0]); | ||
$this->assertTrue($size[1] <= $config[1]); | ||
$this->assertTrue($size[0] == $config[0] || $size[1] == $config[1]); | ||
|
||
File::delete($image->thumbPath); | ||
} | ||
|
||
public function testHandleNotReadable() | ||
{ | ||
Log::shouldReceive('error')->once(); | ||
$image = ImageTest::create(['filename' => 'does_not_exist']); | ||
with(new ProcessThumbnailChunkJob([$image]))->handle(); | ||
} | ||
|
||
public function testSkipExisting() | ||
{ | ||
// This actually doesn't work and IImake::make() will throw an error afterwards. | ||
// But we want to test that make() isn't called anyway so if an error is thrown | ||
// this test fails as expected. | ||
IImage::shouldReceive('make')->never(); | ||
|
||
$image = ImageTest::create(['filename' => 'random']); | ||
touch($image->thumbPath); | ||
try { | ||
with(new ProcessThumbnailChunkJob([$image]))->handle(); | ||
} finally { | ||
File::delete($image->thumbPath); | ||
} | ||
} | ||
} |
Oops, something went wrong.