From f080b755f81d5bcbb267984a371595947117c0f8 Mon Sep 17 00:00:00 2001 From: Tynan Beatty <38031130+tynanbe@users.noreply.github.com> Date: Mon, 9 Dec 2024 10:36:43 -0600 Subject: [PATCH] * **Image Optimization** Support AVIF replacement (#785) --- cli/image.cls.php | 2 +- src/htaccess.cls.php | 1 + src/media.cls.php | 72 +++++++++++++++++++++++++---------------- src/placeholder.cls.php | 8 ++--- src/utility.cls.php | 4 +-- 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/cli/image.cls.php b/cli/image.cls.php index 8e933b417..af594bdd1 100644 --- a/cli/image.cls.php +++ b/cli/image.cls.php @@ -118,7 +118,7 @@ public function status() } } - foreach (array('reduced', 'reduced_webp') as $v) { + foreach (array('reduced', 'reduced_webp', 'reduced_avif') as $v) { if (!empty($summary[$v])) { $summary[$v] = Utility::real_size($summary[$v]); } diff --git a/src/htaccess.cls.php b/src/htaccess.cls.php index 935db3b24..2115edc5c 100644 --- a/src/htaccess.cls.php +++ b/src/htaccess.cls.php @@ -441,6 +441,7 @@ private function _browser_cache_rules($cfg) 'ExpiresByType image/png A' . $ttl, 'ExpiresByType image/gif A' . $ttl, 'ExpiresByType image/webp A' . $ttl, + 'ExpiresByType image/avif A' . $ttl, '', 'ExpiresByType video/ogg A' . $ttl, 'ExpiresByType audio/ogg A' . $ttl, diff --git a/src/media.cls.php b/src/media.cls.php index 6871a33cb..19f273ffe 100644 --- a/src/media.cls.php +++ b/src/media.cls.php @@ -342,37 +342,52 @@ public function media_row_con($post_id) echo '

'; echo '

'; - // WebP info - if ($size_meta && !empty($size_meta['webp_saved'])) { - $percent = ceil(($size_meta['webp_saved'] * 100) / $size_meta['webp_total']); + // WebP/AVIF info + if ($size_meta && !empty($size_meta[$this->_format . '_saved'])) { + $is_avif = 'avif' === $this->_format; + $size_meta_saved = $size_meta[$this->_format . '_saved']; + $size_meta_total = $size_meta[$this->_format . '_total']; - $link = Utility::build_url(Router::ACTION_IMG_OPTM, 'webp' . $post_id); + $percent = ceil(($size_meta_saved * 100) / $size_meta_total); + + $link = Utility::build_url(Router::ACTION_IMG_OPTM, $this->_format . $post_id); $desc = false; $cls = ''; - if ($this->info($short_path . '.webp', $post_id)) { + if ($this->info($short_path . '.' . $this->_format, $post_id)) { $curr_status = __('(optm)', 'litespeed-cache'); - $desc = - __('Currently using optimized version of WebP file.', 'litespeed-cache') . - ' ' . - __('Click to switch to original (unoptimized) version.', 'litespeed-cache'); - } elseif ($this->info($short_path . '.optm.webp', $post_id)) { + $desc = $is_avif + ? __('Currently using optimized version of AVIF file.', 'litespeed-cache') + : __('Currently using optimized version of WebP file.', 'litespeed-cache'); + $desc .= ' ' . __('Click to switch to original (unoptimized) version.', 'litespeed-cache'); + } elseif ($this->info($short_path . '.optm.' . $this->_format, $post_id)) { $cls .= ' litespeed-warning'; $curr_status = __('(non-optm)', 'litespeed-cache'); - $desc = - __('Currently using original (unoptimized) version of WebP file.', 'litespeed-cache') . - ' ' . - __('Click to switch to optimized version.', 'litespeed-cache'); + $desc = $is_avif + ? __('Currently using original (unoptimized) version of AVIF file.', 'litespeed-cache') + : __('Currently using original (unoptimized) version of WebP file.', 'litespeed-cache'); + $desc .= ' ' . __('Click to switch to optimized version.', 'litespeed-cache'); } echo GUI::pie_tiny( $percent, 24, - sprintf(__('WebP file reduced by %1$s (%2$s)', 'litespeed-cache'), $percent . '%', Utility::real_size($size_meta['webp_saved'])), + sprintf( + $is_avif + ? __('AVIF file reduced by %1$s (%2$s)', 'litespeed-cache') + : __('WebP file reduced by %1$s (%2$s)', 'litespeed-cache'), + $percent . '%', + Utility::real_size($size_meta_saved) + ), 'left' ); - echo sprintf(__('WebP saved %s', 'litespeed-cache'), $percent . '%'); + echo sprintf( + $is_avif + ? __('AVIF saved %s', 'litespeed-cache') + : __('WebP saved %s', 'litespeed-cache'), + $percent . '%' + ); if ($desc) { echo sprintf( @@ -384,13 +399,16 @@ public function media_row_con($post_id) ); } else { echo sprintf( - ' %2$s', - __('Using optimized version of file. ', 'litespeed-cache') . ' ' . __('No backup of unoptimized WebP file exists.', 'litespeed-cache'), + ' %3$s', + __('Using optimized version of file. ', 'litespeed-cache'), + $is_avif + ? __('No backup of unoptimized AVIF file exists.', 'litespeed-cache') + : __('No backup of unoptimized WebP file exists.', 'litespeed-cache'), __('(optm)', 'litespeed-cache') ); } } else { - echo __('WebP', 'litespeed-cache') . ''; + echo __('WebP/AVIF', 'litespeed-cache') . ''; } echo '

'; @@ -956,7 +974,7 @@ private function _replace_buffer_img_webp($content) */ public function replace_background_webp($content) { - Debug2::debug2('[Media] Start replacing bakcground WebP.'); + Debug2::debug2('[Media] Start replacing background WebP/AVIF.'); // Handle Elementors data-settings json encode background-images $content = $this->replace_urls_in_json($content); @@ -1046,17 +1064,17 @@ public function replace_urls_in_json($content) } /** - * Replace internal image src to webp + * Replace internal image src to webp or avif * * @since 1.6.2 * @access public */ public function replace_webp($url) { - Debug2::debug2('[Media] webp replacing: ' . substr($url, 0, 200)); + Debug2::debug2('[Media] ' . $this->_format . ' replacing: ' . substr($url, 0, 200)); - if (substr($url, -5) == '.webp') { - Debug2::debug2('[Media] already webp'); + if (substr($url, -5) === '.' . $this->_format) { + Debug2::debug2('[Media] already ' . $this->_format); return false; } @@ -1068,10 +1086,10 @@ public function replace_webp($url) */ if (apply_filters('litespeed_media_check_ori', Utility::is_internal_file($url), $url)) { // check if has webp file - if (apply_filters('litespeed_media_check_webp', Utility::is_internal_file($url, 'webp'), $url)) { - $url .= '.webp'; + if (apply_filters('litespeed_media_check_webp', Utility::is_internal_file($url, $this->_format), $url)) { + $url .= '.' . $this->_format; } else { - Debug2::debug2('[Media] -no WebP file, bypassed'); + Debug2::debug2('[Media] -no WebP or AVIF file, bypassed'); return false; } } else { diff --git a/src/placeholder.cls.php b/src/placeholder.cls.php index e11a6f335..17238c3e3 100644 --- a/src/placeholder.cls.php +++ b/src/placeholder.cls.php @@ -290,10 +290,8 @@ private function _placeholder_realpath($src, $size) { // Use LQIP Cloud generator, each image placeholder will be separately stored - // Compatibility with WebP - if (substr($src, -5) === '.webp') { - $src = substr($src, 0, -5); - } + // Compatibility with WebP and AVIF + $src = Utility::drop_webp($src); $filepath_prefix = $this->_build_filepath_prefix('lqip'); @@ -414,7 +412,7 @@ private function _generate_placeholder($raw_size_and_src, $from_cron = false) $req_data = array( 'width' => $width, 'height' => $height, - 'url' => substr($src, -5) === '.webp' ? substr($src, 0, -5) : $src, + 'url' => Utility::drop_webp($src), 'quality' => $this->_conf_lqip_qual, ); diff --git a/src/utility.cls.php b/src/utility.cls.php index 622552ff9..536e55993 100644 --- a/src/utility.cls.php +++ b/src/utility.cls.php @@ -421,13 +421,13 @@ public static function basename($url) } /** - * Drop .webp if existed in filename + * Drop .webp and .avif if existed in filename * * @since 4.7 */ public static function drop_webp($filename) { - if (substr($filename, -5) === '.webp') { + if (in_array(substr($filename, -5), array('.webp', '.avif'))) { $filename = substr($filename, 0, -5); }