Как генерировать миниатюры только при необходимости?

26 мая 2012 г., 00:52:50
Просмотры: 28.3K
Голосов: 22

У меня есть 1000 изображений. Как сделать так, чтобы WordPress генерировал миниатюры только когда они действительно нужны? Например, для слайдера на главной странице используется только 10 изображений, и я не хочу, чтобы для остальных 1000 изображений создавались эти миниатюры, так как это пустая трата места и ресурсов.

Есть ли способ вызывать add_image_size только когда это действительно необходимо?

Спасибо

ОБНОВЛЕНИЕ Как вы упомянули, проблема не совсем в add_image_size. Было бы здорово иметь возможность запускать изменение размера изображения только когда я использую the_post_thumbnail('slider-thumb'); Возможно, это замедлит первый просмотр изображения, но этот просмотр обычно происходит, когда я просматриваю пост, так что меня это не беспокоит.

Так вот, среди моих постов, слайдера, миниатюр блога, миниатюр портфолио и т.д. у меня есть 1000 изображений, и я хочу, чтобы только 10 изображений были изменены в размере для слайдера. Я вижу много напрасно потраченных ресурсов на генерацию миниатюр для остальных 990 изображений.

Надеюсь, теперь понятно, извините за мой английский

3
Комментарии

Как создание миниатюр из дополнительных 990 изображений тратит больше места и ресурсов, чем 990 неиспользуемых изображений изначально? Не логичнее было бы загружать только те изображения, которые вы активно используете?

SickHippie SickHippie
26 мая 2012 г. 01:05:41

Хотя более опытные программисты приводят веские аргументы против вашей идеи, я нахожу её интересной. Я видел некоторые плагины и темы, которые загружают изображения без создания миниатюр (точно не помню какие). Но мой главный вопрос к вам: когда они вам понадобятся? Каким будет критерий отбора?

brasofilo brasofilo
26 мая 2012 г. 01:26:22

Вы меня неправильно поняли. Я использую эти 990 изображений в записях, просто не использую их в слайдере на главной. Для некоторых мне нужны миниатюры для портфолио, для других — миниатюры для блога и т.д.

chifliiiii chifliiiii
26 мая 2012 г. 01:55:53
Все ответы на вопрос 11
3
14

Ознакомьтесь с плагином Dynamic Image Resizer от Otto

Этот плагин изменяет способ, которым WordPress создаёт изображения, заставляя его генерировать изображения только тогда, когда они действительно где-то используются, на лету. Созданные таким образом изображения сохраняются в стандартных директориях загрузки для последующей быстрой отдачи веб-сервером. В результате экономится место (поскольку изображения создаются только по необходимости), а загрузка изображений становится намного быстрее (так как больше не происходит генерации изображений при загрузке).

26 мая 2012 г. 02:42:42
Комментарии

Обратите внимание, что у этого плагина есть проблема с добавлением изображений к старым записям. Патчи приветствуются.

Otto Otto
26 мая 2012 г. 05:18:42

Это именно то, что я искал. Я попробую его. Значит, он работает только с новыми записями?

chifliiiii chifliiiii
26 мая 2012 г. 19:04:34

Для тех, кто наткнулся на этот пост сейчас: вот похожий плагин, который, судя по всему, активно разрабатывается: https://wordpress.org/plugins/fly-dynamic-image-resizer/

Tim Malone Tim Malone
23 мар. 2016 г. 03:08:16
5

Поместите этот код в файл функций вашей темы. Это предотвратит создание WordPress любых размеров изображений, кроме 3 стандартных, при загрузке.

Когда изображение будет запрошено в определенном размере, который еще не был сгенерирован, оно создастся только один раз.

        add_filter('image_downsize', 'ml_media_downsize', 10, 3);
        function ml_media_downsize($out, $id, $size) {
            // Если размер изображения существует, позволим WordPress обработать его как обычно
            $imagedata = wp_get_attachment_metadata($id);
            if (is_array($imagedata) && isset($imagedata['sizes'][$size]))
                return false;

            // Проверяем, существует ли запрашиваемый размер, иначе прерываем
            global $_wp_additional_image_sizes;
            if (!isset($_wp_additional_image_sizes[$size]))
                return false;

            // Создаем новый миниатюру
            if (!$resized = image_make_intermediate_size(
                get_attached_file($id),
                $_wp_additional_image_sizes[$size]['width'],
                $_wp_additional_image_sizes[$size]['height'],
                $_wp_additional_image_sizes[$size]['crop']
            ))
                return false;

            // Сохраняем метаданные изображения, иначе WordPress не увидит новую миниатюру
            $imagedata['sizes'][$size] = $resized;
            wp_update_attachment_metadata($id, $imagedata);

            // Возвращаем массив для отображения измененного изображения
            $att_url = wp_get_attachment_url($id);
            return array(dirname($att_url) . '/' . $resized['file'], $resized['width'], $resized['height'], true);
        }


        add_filter('intermediate_image_sizes_advanced', 'ml_media_prevent_resize_on_upload');
        function ml_media_prevent_resize_on_upload($sizes) {
            // Удаление этих стандартных размеров может вызвать проблемы, поэтому оставляем их
            return array(
                'thumbnail' => $sizes['thumbnail'],
                'medium' => $sizes['medium'],
                'large' => $sizes['large']
            );
        }
28 нояб. 2013 г. 17:40:30
Комментарии

Этот фильтр должен быть стандартным в WordPress. Зачем генерировать каждый размер для каждого изображения? Я добавляю этот код в свои пользовательские темы. Спасибо

Michaelkay Michaelkay
23 мая 2014 г. 20:19:51

Хорошо, но теперь все равно будут генерироваться все изображения, если мне нужен только один пользовательский размер...

Gijs Gijs
10 янв. 2015 г. 21:44:23

Это происходит, когда я использую объекты изображений из Advanced Custom Fields

Gijs Gijs
10 янв. 2015 г. 22:26:14

Не работает, если add_image_size был ранее определен с измененными размерами изображения

Benjamin Intal Benjamin Intal
21 янв. 2015 г. 12:19:09

@Michaelkay этот подход имеет недостаток в производительности. Когда изображения загружаются и затем генерируются для каждого размера, это означает, что загрузчик - это тот, у кого есть терпение. Этот код заставляет ваших посетителей быть более терпеливыми, а Google доказал, что сайты, которые загружаются дольше 2 секунд, теряют 50% пользователей. Также, если на вашем сайте сотни одновременных посещений, это может привести к падению ваших серверов.

Tom Roggero Tom Roggero
8 мар. 2019 г. 18:01:37
1

К сожалению, ответ @Patrick нарушает работу функций srcset, введенных в WordPress 4.4. К счастью, нам просто нужно добавить две дополнительные функции!

Сначала нам нужно временно вернуть все зарегистрированные размеры миниатюр в метаданные изображения, чтобы они могли быть учтены:

function bi_wp_calculate_image_srcset_meta($image_meta, $size_array, $image_src, $attachment_id){
    //все зарегистрированные размеры
    global $_wp_additional_image_sizes;

    //некоторые параметры исходного файла, которые будем часто использовать
    $src_path = get_attached_file($attachment_id);
    $src_info = pathinfo($src_path);
    $src_root = trailingslashit($src_info['dirname']);
    $src_ext = $src_info['extension'];
    $src_mime = wp_check_filetype($src_path);
    $src_mime = $src_mime['type'];
    $src_base = wp_basename($src_path, ".$src_ext");

    //находим отсутствующие размеры
    foreach($_wp_additional_image_sizes AS $k=>$v)
    {
        if(!isset($image_meta['sizes'][$k]))
        {
            //сначала определим новые размеры
            $new_size = image_resize_dimensions($image_meta['width'], $image_meta['height'], $v['width'], $v['height'], $v['crop']);
            if(!$new_size)
                continue;
            $new_w = (int) $new_size[4];
            $new_h = (int) $new_size[5];

            //пропускаем некорректные значения
            if(!$new_h || !$new_w)
                continue;

            //генерируем имя файла так же, как это делает WP_Image_Editor
            $new_f = wp_basename("{$src_root}{$src_base}-{$new_w}x{$new_h}." . strtolower($src_ext));

            //добавляем в метаданные
            $image_meta['sizes'][$k] = array(
                'file'      => $new_f,
                'width'     => $new_w,
                'height'    => $new_h,
                'mime-type' => $src_mime
            );
        }
    }

    return $image_meta;
}
add_filter('wp_calculate_image_srcset_meta', 'bi_wp_calculate_image_srcset_meta', 10, 4);

Затем нам нужно пройтись по найденным совпадениям и сгенерировать отсутствующие миниатюры:

function bi_wp_calculate_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id){

    //получаем информацию об исходном файле
    $src_path = get_attached_file($attachment_id);
    $src_root = trailingslashit(pathinfo($src_path, PATHINFO_DIRNAME));

    //актуальные метаданные изображения (которые могут быть изменены)
    $src_meta = wp_get_attachment_metadata($attachment_id);

    //массив возможных размеров для поиска
    $sizes = $image_meta['sizes'];
    unset($sizes['thumbnail']);
    unset($sizes['medium']);
    unset($sizes['large']);

    $new = false;

    //перебираем источники
    foreach($sources AS $k=>$v)
    {
        $name = wp_basename($v['url']);
        if(!file_exists("{$src_root}{$name}"))
        {
            //ищем соответствующий размер
            foreach($sizes AS $k2=>$v2)
            {
                //нашли совпадение!
                if($v2['file'] === $name)
                {
                    //создаем миниатюру
                    if(!$resized = image_make_intermediate_size(
                        $src_path,
                        $v2['width'],
                        $v2['height'],
                        $v2['crop']
                    )){
                        //удаляем из источников при ошибке
                        unset($sources[$k]);
                    }
                    else
                    {
                        //добавляем новую миниатюру в реальные метаданные
                        $new = true;
                        $src_meta['sizes'][$k2] = $resized;
                    }

                    //удаляем из массива размеров, чтобы уменьшить
                    //количество поисков в следующий раз
                    unset($sizes[$k2]);
                    break;
                }//совпадение
            }//каждый размер
        }//каждый 404
    }//каждый источник

    //если что-то сгенерировали, обновляем метаданные вложения
    if($new)
        wp_update_attachment_metadata($attachment_id, $src_meta);

    return $sources;
}
add_filter('wp_calculate_image_srcset', 'bi_wp_calculate_image_srcset', 10, 5);
16 апр. 2016 г. 08:08:38
Комментарии

Просто предупреждаю, что это сломает жесткое кадрирование! Мне потребовались часы, чтобы понять, что это было причиной. Я работаю над решением...

Sarah Groß Sarah Groß
22 февр. 2018 г. 09:25:46
2

На самом деле, add_image_size() не генерирует миниатюру, а только регистрирует размер изображения как доступный в WordPress.

Обычно миниатюры создаются при первой загрузке изображения. Это автоматический процесс, поэтому вам не нужно беспокоиться о их генерации позже. Думайте об этом так: если на медленном сервере генерация миниатюры занимает 1-2 секунды, и вы ждёте, пока она не будет запрошена, вы заставляете посетителя ждать дополнительные 1-2 секунды за каждое изображение, чтобы увидеть контент. Гораздо проще сделать это заранее - то есть при загрузке изображения.

В то же время, если вам абсолютно необходимо обрабатывать миниатюры в другое время, вы можете взглянуть на плагин Viper's Regenerate Thumbnails. Он использует действие по запросу для повторной генерации всех ваших миниатюр изображений ... но вы можете использовать аналогичный код для генерации миниатюр только по необходимости.

26 мая 2012 г. 01:07:12
Комментарии

Думаю, вы не поняли суть. Он хочет контролировать, для каких изображений нужны миниатюры. То есть некоторые изображения вообще не нужно изменять в размере.

imrek imrek
21 мар. 2015 г. 18:55:30

Большинство людей тестируют страницы при добавлении фотографий (я уверен, что все так делают). Это приведет к однократному созданию нужных файлов, и на этом всё. В моем случае у меня зарегистрирован размер для шапки сайта. Примерно 1 из 20 загружаемых мной изображений действительно используется для шапки. Таким образом, 19 из 20 изображений в моей библиотеке занимают место впустую.

JpaytonWPD JpaytonWPD
5 дек. 2016 г. 02:55:09
1

Есть ли способ активировать add_image_size только при необходимости?

Не совсем. Но вы можете фильтровать список зарегистрированных размеров прямо перед генерацией миниатюр. Функция wp_generate_attachment_metadata() (которая вызывает функцию, генерирующую миниатюры) имеет фильтр под названием "intermediate_image_sizes_advanced", позволяющий манипулировать массивом размеров непосредственно перед созданием файлов. Вы можете использовать этот фильтр, когда добавляете изображение определённого "типа", а затем сразу же удалять его.

Полагаю, вашей основной сложностью будет определить, как отличать изображения, которым нужны дополнительные размеры, от тех, которым они не требуются.

26 мая 2012 г. 01:27:07
Комментарии

Мне нужно добавить опцию или чекбокс при загрузке медиафайлов, чтобы выбирать, какие миниатюры генерировать. Звучит хорошо, но я не знаю, как это сделать.

chifliiiii chifliiiii
26 мая 2012 г. 02:19:07
0

Вы можете использовать мой (не Ottos) "Dynamic Image Resize" 1) плагин.

“Dynamic Image Resize” — это WordPress (MU-)плагин, который предоставляет шорткод и тег шаблона для изменения размера изображений «на лету» без необходимости использования TimThumb, а с помощью встроенных функций WP.

Плагин включает в себя тег шаблона и шорткод.

1) Только что узнал о плагине Ottos. Совпадение названий не было преднамеренным.

29 июн. 2013 г. 14:03:01
0

Вы можете попробовать этот плагин: https://wordpress.org/plugins/optimize-images-resizing

Он изменяет размер изображений в соответствии с зарегистрированными размерами, но только когда это необходимо. Также может очистить существующие размеры изображений, чтобы их можно было перегенерировать.

30 июл. 2015 г. 03:27:09
0

WP Performance Pack — это плагин, предлагающий "усовершенствованную обработку изображений", основанную на Ottos Dynamic Image Resizer, но включающий множество улучшений. Например: прежде всего, он совместим с последней версией WordPress (3.9.1), использует WP_Image_Editor, позволяет отключить сохранение миниатюр (хотя их можно кэшировать, а поддержка CDN в разработке), интегрирован с плагином Regenerate Thumbnails (для удаления существующих миниатюр) и имеет ряд других преимуществ.

14 мая 2014 г. 13:02:21
1

Еще один подход: он подключается к обработке HTTP-ошибки 404. То есть, когда миниатюра недоступна, находим оригинальное изображение и создаем миниатюру. Обратите внимание, что это не решает вашу проблему полностью, так как не предотвращает генерацию миниатюр при загрузке.

Также учтите, что этот плагин может быть использован злоумышленниками для создания любого количества миниатюр и, следовательно, исчерпания дискового пространства.

Примечание: Этот плагин можно легко установить с помощью Pluginception.

<?php
/*
Plugin Name: Создание миниатюр по требованию
Plugin URI: 
Description: Создает миниатюры вместо отображения 404. Используйте в сочетании с "Broken Link Checker" для создания всех отсутствующих миниатюр.
Version: 0.1
Author: Jack Miller
Author URI: 
License: 
License URI: 
*/
add_filter('status_header', 'createThumbIf404');
function createThumbIf404($httpCodeString) //например, HTTP/1.1 200 OK 
{
    global $wp_query;
    error_reporting(E_ALL);
    ini_set('display_errors', 1);

    $httpCode = explode(" ", $httpCodeString);
    $httpCode = $httpCode[1];
    if ($httpCode == "404") {
        $requestUri = $_SERVER["REQUEST_URI"];
        $regex = '/^\/(wp-content\/uploads\/(?:[a-zA-Z0-9]*\/){2})(.*)-(.*)x(.*)\.jpg$/';
        preg_match($regex, $requestUri, $groups);
        if (sizeof($groups) === 5) {
            $baseDir  = $groups[1];
            $baseName = $groups[2];
            $sizeX    = $groups[3];
            $sizeY    = $groups[4];

            $oriImg = ctod_checkFile($baseDir, $baseName);
            if ($oriImg != null) {

                $image = wp_get_image_editor($baseDir . $oriImg);
                if (!is_wp_error($image)) {
                    $image->resize($sizeX, $sizeY, true);
                    $thumb = $baseDir . $baseName . '-' . $sizeX . 'x' . $sizeY . '.jpg';
                    $image->save($thumb);
                    ctod_sendImageAndExit($thumb);
                }
            }
        }
    }
}
//находит оригинальное изображение в $baseDir с $baseName.
//Возвращает имя файла с расширением оригинального изображения или null.
function ctod_checkFile($baseDir, $baseName)
{
    $arr = array(
        ".jpg",
        ".JPG",
        ".jpeg",
        ".JPEG"
    );
    foreach ($arr as &$ext) {
        if (file_exists($baseDir . $baseName . $ext)) {
            return $baseName . $ext;
        }
    }
    return null;
}
//Читает файл по пути $path с диска и возвращает его как HTTP-запрос изображения JPG.
function ctod_sendImageAndExit($path)
{
    $fp = fopen($path, 'rb');
    header("Content-Type: image/jpeg");
    header("Content-Length: " . filesize($path));
    fpassthru($fp);
    exit();
}
22 мая 2016 г. 08:16:30
Комментарии

Мне нравится это решение. Вы когда-нибудь адаптировали его для работы с большим количеством типов изображений?

kalligator kalligator
8 мая 2021 г. 13:53:14
0

На других местах все созданные размеры будут работать, но только при загрузке медиафайлов, если вы хотите загружать конкретный размер, то ниже приведен код для этого. Вот ссылка для более подробного описания - https://developer.wordpress.org/reference/hooks/wp_handle_upload_prefilter/

add_filter('wp_handle_upload_prefilter', 'custom_upload_filter' );
 
function custom_upload_filter( $file ) {
   foreach ( get_intermediate_image_sizes() as $size ) {
        if ( !in_array( $size, array( 'thumbnail', 'medium', 'medium_large', 'large' ) ) ) {
            remove_image_size( $size );
        }
    }
    return $file;
}
8 дек. 2020 г. 13:11:21
0
-1

Вы также можете попробовать Aqua Resizer - https://github.com/syamilmj/Aqua-Resizer/

Это всего лишь один файл.

Использовать его можно следующим образом:

$img_src = aq_resize( $img_src, $width = null, $height = null, $crop = null, $single = true, $upscale = false );

$img_src = aq_resize( $img_src, 150, 150); // изменённый размер
$img_src = aq_resize( $img_src, 150, 150, true); // обрезанное изображение
$img_src = aq_resize( $img_src, 150, 150, null, null, true); // изображение размером 120x120, например, будет увеличено до 150x150
17 мар. 2014 г. 13:30:52