mirror of
https://github.com/getgrav/grav.git
synced 2026-05-06 20:15:54 +02:00
ImageMedium#derivatives now works with image filters (#1107)
* ImageMedium->derivatives now works with image filters Previously, using ImageMedium->derivatives would not work well in combination with image filters or the other method of generating srcset variants of images (by appending eg. "@2x" to their filenames). This commit hopefully fixes that. * Modified initialization of image alternatives The biggest alternative will now become the base medium, and alternatives will be filled out as necessary in a descending manner. * Fully reset image when derivatives method is called Otherwise we get some funky results, with the possibility of two different images being rendered between the full-width srcset version and the original src version. * Account for risk of original file not existing when generating image derivatives * Fixed an issue where too many alternatives would be generated When using naming conventions to generate image alternatives, this patch would previously generate a “@1x” alternative if one didn’t exist. That’s no longer the case * Add an "@1x" alternative when an image lacks a base medium When an image only has an alternative medium - ie. the only version of the image ends in eg. "@3x", then we construct the missing alternatives automatically. Previously, we would only do this down till "@2x", meaning that the image that would have been the base medium, had the image been manually resized, wasn't created. This has now been fixed. * Always make smallest image alternative the base medium When an image lacks a base medium on disk (eg. the only existing image is an @2x version), then we make a scaled down version the base medium, which ensures that the smaller version is served up in the src attribute in the HTML. Also, don't reset the image alternatives when calling ImageMedium#derivatives, instead only generate the image alternatives that are missing. * Set better prettynames for image derivatives * Changed image derivatives prettynames to be width based Instead of example2x.jpeg, we now have eg. example1280w.jpeg
This commit is contained in:
committed by
Andy Miller
parent
a96820af36
commit
db4c9c1844
@@ -74,16 +74,13 @@ class Media extends Getters
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
@@ -103,10 +100,9 @@ class Media extends Getters
|
||||
// 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;
|
||||
}
|
||||
@@ -115,7 +111,9 @@ class Media extends Getters
|
||||
}
|
||||
|
||||
foreach ($types['alternative'] as $ratio => $altMedium) {
|
||||
$medium->addAlternative($ratio, $altMedium['file']);
|
||||
if ($altMedium['file'] != $medium) {
|
||||
$medium->addAlternative($ratio, $altMedium['file']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +65,6 @@ class ImageMedium extends Medium
|
||||
'zoomCrop' => [0, 1]
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $derivatives = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -197,27 +192,19 @@ class ImageMedium extends Medium
|
||||
*/
|
||||
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);
|
||||
}
|
||||
@@ -257,31 +244,53 @@ class ImageMedium extends Medium
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,6 +498,10 @@ class ImageMedium extends Medium
|
||||
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
|
||||
|
||||
@@ -100,7 +100,9 @@ class Medium extends Data implements RenderableInterface
|
||||
}
|
||||
|
||||
$alternative->set('ratio', $ratio);
|
||||
$this->alternatives[(float) $ratio] = $alternative;
|
||||
$width = $alternative->get('width');
|
||||
|
||||
$this->alternatives[$width] = $alternative;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,8 +119,8 @@ class MediumFactory
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
Reference in New Issue
Block a user