Skip to content

Instantly share code, notes, and snippets.

@pryley
Last active March 1, 2021 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pryley/277b4ab275cd538168fb759471ab7e2c to your computer and use it in GitHub Desktop.
Save pryley/277b4ab275cd538168fb759471ab7e2c to your computer and use it in GitHub Desktop.
ImageKit job for the Responsive Images Statamic addon (https://statamic.com/addons/spatie/responsive-images)
<?php
namespace App\Jobs;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Spatie\ResponsiveImages\Jobs\GenerateImageJob;
class GenerateImageKitJob extends GenerateImageJob
{
protected $image;
protected $height;
protected $width;
protected $transforms;
protected function crop(): void
{
$this->transforms['crop'] = [
'cm' => 'extract',
'h' => $this->resizedHeight(),
'w' => $this->resizedWidth(),
'x' => $this->resizedX() - $this->zoomedX(),
'y' => $this->resizedY() - $this->zoomedY(),
];
}
protected function cropResized(): void
{
$height = $this->resizedHeight();
$width = $this->resizedWidth();
$cx = ($this->image->get('width') * ($this->image->get('cx_percent') / 100)) - $this->zoomedX();
$cy = ($this->image->get('height') * ($this->image->get('cy_percent') / 100)) - $this->zoomedY();
$x = $cx - ($width / 2);
$y = $cy - ($height / 2);
$this->transforms['crop_resized'] = [
'cm' => 'extract',
'h' => $height,
'w' => $width,
'x' => $x,
'y' => $y,
];
}
protected function cropZoomed(): void
{
$this->transforms['crop_zoomed'] = [
'cm' => 'extract',
'h' => $this->zoomedHeight(),
'w' => $this->zoomedWidth(),
'x' => $this->zoomedX(),
'y' => $this->zoomedY(),
];
}
protected function generateUrl(): string
{
$parts = [
'domain' => config('imagekit.domain'),
'id' => config('imagekit.id'),
'identifier' => config('imagekit.identifier'),
'transformation' => $this->generateTransformation(),
'path' => trim(str_replace('assets/', 'photos/', $this->asset->url()), '/'),
];
return 'https://'.implode('/', array_filter($parts));
}
protected function generateTransformation(): string
{
$transforms = [];
foreach ($this->transforms as $params) {
array_walk($params, function (&$value, $key) {
if (is_numeric($value)) {
$value = intval(floor($value)); // round down
}
$value = $key.'-'.$value;
});
$transforms[] = 'tr:'.implode(',', $params);
}
return implode(':', $transforms);
}
protected function image(): Collection
{
$focus = explode('-', $this->asset->data()->get('focus', '50-50-1'));
$height = $this->asset->meta()['height'];
$width = $this->asset->meta()['width'];
$cx = Arr::get($focus, 0, 50);
$cy = Arr::get($focus, 1, 50);
$zoom = Arr::get($focus, 2, 1);
return collect([
'cx' => $cx,
'cy' => $cy,
'height' => $height,
'width' => $width,
'x' => $width * ($cx / 100),
'y' => $height * ($cy / 100),
'zoom' => $zoom,
]);
}
protected function imageUrl(): string
{
$this->image = $this->image();
$this->height = collect($this->params)->get('height');
$this->width = collect($this->params)->get('width');
if ($this->isZoomed()) {
$this->cropZoomed();
}
if ($this->isOversized()) {
$this->cropResized();
} else {
$this->crop();
}
$this->resize();
return $this->generateUrl();
}
protected function isHeightOversized(): bool
{
return $this->height > $this->image->get('height');
}
protected function isOversized(): bool
{
return $this->isHeightOversized() || $this->isWidthOversized();
}
protected function isWidthOversized(): bool
{
return $this->width > $this->image->get('width');
}
protected function isZoomed(): bool
{
return $this->image->get('zoom') > 1;
}
protected function ratio(int $number, int $a, int $b): int
{
return $number * ($a / $b);
}
protected function resize(): void
{
$this->transforms['resize'] = [
'h' => $this->height,
'w' => $this->width,
];
}
protected function resizedHeight(): int
{
$height = $this->zoomedHeight();
$width = $this->zoomedWidth();
$percentOfHeight = $height / $this->height;
$percentOfWidth = $width / $this->width;
return $percentOfHeight > $percentOfWidth
? $this->ratio($width, $this->height, $this->width)
: $height;
}
protected function resizedWidth(): int
{
$height = $this->zoomedHeight();
$width = $this->zoomedWidth();
$percentOfHeight = $height / $this->height;
$percentOfWidth = $width / $this->width;
return $percentOfWidth > $percentOfHeight
? $this->ratio($height, $this->width, $this->height)
: $width;
}
protected function resizedX(): int
{
$width = $this->resizedWidth();
$x = $this->image->get('x') - ($width / 2);
$adjustment = max(0, ($width - ($this->image->get('width') - $x)));
return intval($x - $adjustment);
}
protected function resizedY(): int
{
$height = $this->resizedHeight();
$y = $this->image->get('y') - ($height / 2);
$adjustment = max(0, ($height - ($this->image->get('height') - $y)));
return intval($y - $adjustment);
}
protected function zoomedHeight(): int
{
return $this->image->get('height') / $this->image->get('zoom');
}
protected function zoomedWidth(): int
{
return $this->image->get('width') / $this->image->get('zoom');
}
protected function zoomedX(): int
{
$width = $this->zoomedWidth();
$x = $this->image->get('x') - ($width / 2);
$adjustment = max(0, ($width - ($this->image->get('width') - $x)));
return intval($x - $adjustment);
}
protected function zoomedY(): int
{
$height = $this->zoomedHeight();
$y = $this->image->get('y') - ($height / 2);
$adjustment = max(0, ($height - ($this->image->get('height') - $y)));
return intval($y - $adjustment);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment