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

ImageMedium#derivatives now works with image filters #1107

Merged
merged 10 commits into from
Oct 23, 2016
20 changes: 9 additions & 11 deletions system/src/Grav/Common/Page/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,13 @@ public function __construct($path)
}

// Create the base medium
if (!empty($types['base'])) {
if (empty($types['base'])) {
$max = max(array_keys($types['alternative']));
$medium = $types['alternative'][$max]['file'];
$medium = MediumFactory::scaledFromMedium($medium, $max, 1)['file'];
} else {
$medium = MediumFactory::fromFile($types['base']['file']);
$medium && $medium->set('size', $types['base']['size']);
} else if (!empty($types['alternative'])) {
$altMedium = reset($types['alternative']);
$ratio = key($types['alternative']);

$altMedium = $altMedium['file'];

$medium = MediumFactory::scaledFromMedium($altMedium, $ratio, 1)['file'];
}

if (empty($medium)) {
Expand All @@ -103,10 +100,9 @@ public function __construct($path)
// Build missing alternatives
if (!empty($types['alternative'])) {
$alternatives = $types['alternative'];

$max = max(array_keys($alternatives));

for ($i=2; $i < $max; $i++) {
for ($i=$max; $i > 1; $i--) {
if (isset($alternatives[$i])) {
continue;
}
Expand All @@ -115,7 +111,9 @@ public function __construct($path)
}

foreach ($types['alternative'] as $ratio => $altMedium) {
$medium->addAlternative($ratio, $altMedium['file']);
if ($altMedium['file'] != $medium) {
$medium->addAlternative($ratio, $altMedium['file']);
}
}
}

Expand Down
97 changes: 55 additions & 42 deletions system/src/Grav/Common/Page/Medium/ImageMedium.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ class ImageMedium extends Medium
'zoomCrop' => [0, 1]
];

/**
* @var array
*/
protected $derivatives = [];

/**
* @var string
*/
Expand Down Expand Up @@ -197,27 +192,19 @@ public function cache()
*/
public function srcset($reset = true)
{
if (empty($this->alternatives) && empty($this->derivatives)) {
if (empty($this->alternatives)) {
if ($reset) {
$this->reset();
}

return '';
}

if (!empty($this->derivatives)) {
asort($this->derivatives);

foreach ($this->derivatives as $url => $width) {
$srcset[] = $url . ' ' . $width . 'w';
}

$srcset[] = $this->url($reset) . ' ' . $this->get('width') . 'w';
} else {
$srcset = [$this->url($reset) . ' ' . $this->get('width') . 'w'];
foreach ($this->alternatives as $ratio => $medium) {
$srcset[] = $medium->url($reset) . ' ' . $medium->get('width') . 'w';
}
$srcset = [];
foreach ($this->alternatives as $ratio => $medium) {
$srcset[] = $medium->url($reset) . ' ' . $medium->get('width') . 'w';
}
$srcset[] = $this->url($reset) . ' ' . $this->get('width') . 'w';

return implode(', ', $srcset);
}
Expand Down Expand Up @@ -257,31 +244,53 @@ public function getImagePrettyName()
* @return $this
*/
public function derivatives($min_width, $max_width, $step = 200) {
$width = $min_width;

// Do not upscale images.
if ($max_width > $this->get('width')) {
$max_width = $this->get('width');
}

while ($width <= $max_width) {
$ratio = $width / $this->get('width');
$derivative = MediumFactory::scaledFromMedium($this, 1, $ratio);
if (is_array($derivative)) {
$this->addDerivative($derivative['file']);
if (!empty($this->alternatives)) {
$max = max(array_keys($this->alternatives));
$base = $this->alternatives[$max];
} else {
$base = $this;
}
$width += $step;
}
return $this;
}

/**
* Add a derivative
*
* @param ImageMedium $image
*/
public function addDerivative(ImageMedium $image) {
$this->derivatives[$image->url()] = $image->get('width');
// Do not upscale images.
$max_width = min($max_width, $base->get('width'));

for ($width = $min_width; $width < $max_width; $width = $width + $step) {
// Only generate image alternatives that don't already exist
if (array_key_exists((int) $width, $this->alternatives)) {
continue;
}

$derivative = MediumFactory::fromFile($base->get('filepath'));

// It's possible that MediumFactory::fromFile returns null if the
// original image file no longer exists and this class instance was
// retrieved from the page cache
if (isset($derivative)) {
$index = 2;
$widths = array_keys($this->alternatives);
sort($widths);

foreach ($widths as $i => $key) {
if ($width > $key) {
$index += max($i, 1);
}
}

$basename = preg_replace('/(@\d+x){0,1}$/', "@{$width}w", $base->get('basename'), 1);
$derivative->setImagePrettyName($basename);

$ratio = $base->get('width') / $width;
$height = $derivative->get('height') / $ratio;

$derivative->resize($width, $height);
$derivative->set('width', $width);
$derivative->set('height', $height);

$this->addAlternative($ratio, $derivative);
}
}

return $this;
}

/**
Expand Down Expand Up @@ -489,6 +498,10 @@ public function __call($method, $args)
call_user_func_array([$this->image, $method], $args);

foreach ($this->alternatives as $ratio => $medium) {
if (!$medium->image) {
$medium->image();
}

$args_copy = $args;

// regular image: resize 400x400 -> 200x200
Expand Down
4 changes: 3 additions & 1 deletion system/src/Grav/Common/Page/Medium/Medium.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ public function addAlternative($ratio, Medium $alternative)
}

$alternative->set('ratio', $ratio);
$this->alternatives[(float) $ratio] = $alternative;
$width = $alternative->get('width');

$this->alternatives[$width] = $alternative;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions system/src/Grav/Common/Page/Medium/MediumFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ public static function scaledFromMedium($medium, $from, $to)
}

$ratio = $to / $from;
$width = (int) ($medium->get('width') * $ratio);
$height = (int) ($medium->get('height') * $ratio);
$width = $medium->get('width') * $ratio;
$height = $medium->get('height') * $ratio;

$prev_basename = $medium->get('basename');
$basename = str_replace('@'.$from.'x', '@'.$to.'x', $prev_basename);
Expand Down