Jak generować miniatury tylko wtedy, gdy są potrzebne?

18

Mam 1000 zdjęć. Jak sprawić, by Wordpress generował kciuk tylko w razie potrzeby. Na przykład suwak domowy używa tylko 10 obrazów. Nie chcę, aby pozostałe 1000 obrazów wygenerowało tę miniaturę, ponieważ jest to strata miejsca i zasobów.

Istnieje sposób na uruchomienie add_image_size tylko wtedy, gdy jest to potrzebne?

Dzięki

AKTUALIZACJA Jak już wspomniałeś, tak naprawdę nie dodajesz rozmiaru obrazu, co trzeba uruchomić. Byłoby wspaniale odpalić zmianę rozmiaru obrazu, gdy użyję_post_thumbnail ('slider-thumb'); Może to spowalnia pierwszy widok obrazu, ale ten widok jest zwykle generowany przeze mnie, gdy faktycznie przeglądam post, więc nie obchodzi mnie to.

Więc między moimi postami, suwakiem, blogami, miniaturami portfolio itp. Dostałem 1000 obrazów i chcę zmienić rozmiar 10 zdjęć dla suwaka. Widzę dużo zmarnowanych zasobów, aby wygenerować rozmiar miniatury dla pozostałych 990 obrazów.

Mam nadzieję, że teraz wszystko jest jasne, przepraszam za mój angielski

chifliiiii
źródło
2
W jaki sposób miniatury generowane z dodatkowych 990 obrazów są bardziej marnotrawstwem przestrzeni i zasobów niż 990 nieużywanych obrazów? Czy nie byłoby sensowniej przesyłać tylko te obrazy, których aktywnie używasz?
SickHippie
Chociaż bardziej wykwalifikowani programiści przedstawiają uzasadnione argumenty przeciwko Twojemu pomysłowi, uważam to za interesujące. Widziałem niektóre wtyczki i motywy, które przesyłają obrazy bez generowania kciuków (nie jestem pewien, które z nich teraz). Ale mam duże wątpliwości co do twojego pytania: kiedy będziesz go potrzebować? . Jaki będzie filtr?
brasofilo
1
Źle mnie zrozumiałeś. Używam 990 zdjęć w postach, po prostu nie używam suwaka domowego. Niektóre z nich potrzebuję kciuka do portfela, inne do kciuka na blogu itp.
chifliiiii

Odpowiedzi:

12

Spójrz na wtyczkę Dynamic Image Resizer firmy Otto

Ta wtyczka zmienia sposób, w jaki WordPress tworzy obrazy, aby generował obrazy tylko wtedy, gdy są one faktycznie używane gdzieś, w locie. Utworzone w ten sposób obrazy zostaną zapisane w normalnych katalogach przesyłania, do późniejszego szybkiego wysłania przez serwer WWW. W rezultacie oszczędzane jest miejsce (ponieważ obrazy są tworzone tylko w razie potrzeby), a przesyłanie zdjęć jest znacznie szybsze (ponieważ nie generuje już obrazów po przesłaniu).

Chris_O
źródło
2
Pamiętaj, że ta wtyczka ma problem z dodawaniem zdjęć do starych postów. Łatki mile widziane.
Otto
Właśnie tego szukałem. Spróbuję. Więc działa tylko na nowych postach?
chifliiiii
1
Dla osób, które napotykają ten post, oto podobna wtyczka, która wydaje się być aktywnie rozwijana: wordpress.org/plugins/fly-dynamic-image-resizer
Tim Malone
7

Umieść to w pliku funkcji motywu. Dzięki temu Wordpress nie będzie tworzył niczego poza 3 domyślnymi rozmiarami podczas przesyłania.

Gdy obraz zostanie następnie zażądany w określonym rozmiarze, który nie został jeszcze wygenerowany, zostanie utworzony tylko raz.

        add_filter('image_downsize', 'ml_media_downsize', 10, 3);
        function ml_media_downsize($out, $id, $size) {
            // If image size exists let WP serve it like normally
            $imagedata = wp_get_attachment_metadata($id);
            if (is_array($imagedata) && isset($imagedata['sizes'][$size]))
                return false;

            // Check that the requested size exists, or abort
            global $_wp_additional_image_sizes;
            if (!isset($_wp_additional_image_sizes[$size]))
                return false;

            // Make the new thumb
            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;

            // Save image meta, or WP can't see that the thumb exists now
            $imagedata['sizes'][$size] = $resized;
            wp_update_attachment_metadata($id, $imagedata);

            // Return the array for displaying the resized image
            $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) {
            // Removing these defaults might cause problems, so we don't
            return array(
                'thumbnail' => $sizes['thumbnail'],
                'medium' => $sizes['medium'],
                'large' => $sizes['large']
            );
        }
Patrick
źródło
Ten filtr powinien być standardem w WordPress. Po co generować każdy rozmiar dla każdego obrazu? Dodaję ten kod do niestandardowych motywów. Dzięki
Michaelkay
2
Ładnie, ale teraz nadal będzie generować wszystkie obrazy, jeśli będę potrzebować tylko jednego niestandardowego rozmiaru.
Gijs
Zdarza się to, gdy używam obiektów graficznych z zaawansowanych pól niestandardowych
Gijs
Nie działa JEŚLI parametr add_image_size został wcześniej zdefiniowany, a wymiary obrazu zostały właśnie zmienione
Benjamin Intal
@Michaelkay w tym podejściu występuje kara wydajnościowa. Gdy obrazy są przesyłane, a następnie generowane dla każdego rozmiaru, oznacza to, że przesyłający jest cierpliwy. Ten kod sprawia, że ​​odwiedzający muszą mieć więcej cierpliwości, a Google udowodnił, że strony, których ładowanie trwa dłużej niż 2 sekundy, upuszcza 50% ludzi. Również jeśli Twoja witryna ma setki jednoczesnych odwiedzin, spowoduje to uszkodzenie serwerów.
Tom Roggero
2

Niestety odpowiedź @ Patrick przerywa funkcje srcset wprowadzone w WP 4.4. Na szczęście musimy tylko dodać dwie dodatkowe funkcje!

Najpierw musimy tymczasowo ponownie wprowadzić wszystkie zarejestrowane rozmiary miniatur do metadanych obrazu, aby można je było rozważyć:

function bi_wp_calculate_image_srcset_meta($image_meta, $size_array, $image_src, $attachment_id){
    //all registered sizes
    global $_wp_additional_image_sizes;

    //some source file specs we'll use a lot
    $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");

    //find what's missing
    foreach($_wp_additional_image_sizes AS $k=>$v)
    {
        if(!isset($image_meta['sizes'][$k]))
        {
            //first, let's find out how things would play out dimensionally
            $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];

            //bad values
            if(!$new_h || !$new_w)
                continue;

            //generate a filename the same way WP_Image_Editor would
            $new_f = wp_basename("{$src_root}{$src_base}-{$new_w}x{$new_h}." . strtolower($src_ext));

            //finally, add it!
            $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);

Następnie musimy przejrzeć dopasowania i wygenerować brakujące miniatury:

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

    //get some source info
    $src_path = get_attached_file($attachment_id);
    $src_root = trailingslashit(pathinfo($src_path, PATHINFO_DIRNAME));

    //the actual image metadata (which might be altered here)
    $src_meta = wp_get_attachment_metadata($attachment_id);

    //an array of possible sizes to search through
    $sizes = $image_meta['sizes'];
    unset($sizes['thumbnail']);
    unset($sizes['medium']);
    unset($sizes['large']);

    $new = false;

    //loop through sources
    foreach($sources AS $k=>$v)
    {
        $name = wp_basename($v['url']);
        if(!file_exists("{$src_root}{$name}"))
        {
            //find the corresponding size
            foreach($sizes AS $k2=>$v2)
            {
                //we have a match!
                if($v2['file'] === $name)
                {
                    //make it
                    if(!$resized = image_make_intermediate_size(
                        $src_path,
                        $v2['width'],
                        $v2['height'],
                        $v2['crop']
                    )){
                        //remove from sources on failure
                        unset($sources[$k]);
                    }
                    else
                    {
                        //add the new thumb to the true meta
                        $new = true;
                        $src_meta['sizes'][$k2] = $resized;
                    }

                    //remove from the sizes array so we have
                    //less to search next time
                    unset($sizes[$k2]);
                    break;
                }//match
            }//each size
        }//each 404
    }//each source

    //if we generated something, update the attachment meta
    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);
Josh
źródło
Tylko heads-up, aby poinformować cię, że to złamie trudne kadrowanie! Dopiero po kilku godzinach dowiedziałem się, że to był winowajca. Pracuję nad rozwiązaniem ...
Constantin Groß
1

W rzeczywistości add_image_size()nie generuje miniatury, po prostu rejestruje rozmiar obrazu jako dostępny dla WordPress.

Zazwyczaj miniatury są generowane przy pierwszym załadowaniu obrazu. Jest to proces automatyczny, więc nie musisz się martwić o wygenerowanie ich później. Pomyśl o tym w ten sposób - jeśli wygenerowanie miniatury na wolnym serwerze zajmuje 1-2 sekundy, a Ty czekasz, aż zostanie o to poproszony, zmuszasz osobę, która ją wyświetla, do oczekiwania na dodatkowe 1-2 sekundy na obraz, aby zobaczyć zawartość. O wiele łatwiej jest to zrobić z wyprzedzeniem - tj. Po przesłaniu obrazu.

Jednocześnie, jeśli absolutnie musisz przetwarzać miniatury w innym czasie, możesz zajrzeć do wtyczki Viper's Regenerate Thumbnails . Używa akcji na żądanie, aby zregenerować wszystkie miniatury obrazów ... ale możesz użyć podobnego kodu, aby wygenerować miniatury tylko w razie potrzeby.

EAMann
źródło
Myślę, że nie rozumiesz. Chce kontrolować, dla których obrazów potrzebne są miniatury. Dlatego niektórych obrazów nie trzeba wcale zmieniać.
Drunken Master
Większość osób testuje strony, gdy wstawiają zdjęcia (wydaje mi się, że oszczędzam mówiąc wszystko). Spowoduje to wygenerowanie potrzebnych plików, które będą gotowe. W moim przypadku mam zarejestrowany rozmiar obrazu nagłówka. Około 1 na 20 zdjęć, które przesyłam, to tak naprawdę nagłówek. Tak więc 19 na 20 zdjęć w mojej bibliotece to marnowanie miejsca.
JpaytonWPD,
1

Istnieje sposób na uruchomienie add_image_size tylko wtedy, gdy jest to potrzebne?

Nie dokładnie. Ale możesz filtrować listę zarejestrowanych rozmiarów tuż przed wygenerowaniem miniatur. Funkcja wp_generate_attachment_metadata () (która wywołuje funkcję, która generuje miniatury) ma filtr o nazwie „intermediate_image_sizes_advanced”, który pozwala manipulować tablicą rozmiarów tuż przed wygenerowaniem plików. Możesz użyć tego filtra za każdym razem, gdy dodajesz obraz określonego „typu”, a następnie usuń go natychmiast po.

Wydaje mi się, że twoim największym wyzwaniem byłoby dowiedzieć się, jak odróżnić obrazy wymagające dodatkowych rozmiarów od tych, które tego nie potrzebują.

MathSmath
źródło
musiałbym dodać opcję lub pole wyboru, gdy przesyłam media, aby wybrać, które kciuki chcę na przykład wygenerować. Brzmi nieźle, ale nie mam pojęcia, jak to zrobić
chifliiiii,
1

Możesz użyć mojej wtyczki (nie Ottos) „Dynamic Image Resize” 1) .

„Dynamic Image Resize” to wtyczka WordPress (MU-), która oferuje krótki kod i znacznik szablonu do zmiany rozmiaru obrazów „w locie” bez potrzeby korzystania z TimThumb, ale z podstawowymi funkcjami WP.

Wtyczka posiada również tag szablonu i krótki kod .

1) Właśnie dowiedziałem się o wtyczce Ottos. Nazewnictwo kolizji nie było zamierzone.

kajzer
źródło
0

Wtyczka WP Performance Pack oferuje „ulepszoną obsługę obrazów”, która jest oparta na Ottos Dynamic Image Resizer, ale zawiera wiele ulepszeń, np .: przede wszystkim jest kompatybilna z najnowszą wersją WordPress (3.9.1), wykorzystuje WP_Image_Editor, zapisywanie miniatur może być wyłączone (ale można je buforować, a obsługa CDN jest w drodze), integracja Regenerate Thumbails (aby usunąć istniejące miniatury) i jeszcze więcej.

Björn
źródło
-1

Możesz spróbować również Aqua Resizer - https://github.com/syamilmj/Aqua-Resizer/

To tylko jeden plik.

Możesz użyć tego w następujący sposób:

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

$img_src = aq_resize( $img_src, 150, 150); // resized
$img_src = aq_resize( $img_src, 150, 150, true); // cropped
$img_src = aq_resize( $img_src, 150, 150, null, null, true); // image with 120x120 for example will be upscaled up to 150x150
antongorodezkiy
źródło
-1

Oto jeszcze jedno podejście: łączy się z obsługą błędów 404 HTTP. Oznacza to, że gdy miniatura nie jest dostępna, znajdź oryginalny obraz i utwórz miniaturę. Pamiętaj, że tak naprawdę nie rozwiązuje to problemu, ponieważ nie zapobiega generowaniu miniatur podczas przesyłania.

Pamiętaj również, że ta wtyczka może być wykorzystywana przez złośliwych użytkowników do tworzenia dowolnej liczby miniatur, a tym samym do wyczerpania miejsca na dysku.

Uwaga: tę wtyczkę można łatwo zainstalować przy użyciu wtyczki .

<?php
/*
Plugin Name: Create thumbnails on demand
Plugin URI: 
Description: Create thumbnails instead of showing 404. Use in combination with "Broken Link Checker" to create all missing thumbnails.
Version: 0.1
Author: Jack Miller
Author URI: 
License: 
License URI: 
*/
add_filter('status_header', 'createThumbIf404');
function createThumbIf404($httpCodeString) //e.g. 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);
                }
            }
        }
    }
}
//finds original image within $baseDir with $baseName.
//Returns file name including extension of original image or 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;
}
//Read file at $path from disk and return it as HTTP JPG image request.
function ctod_sendImageAndExit($path)
{
    $fp = fopen($path, 'rb');
    header("Content-Type: image/jpeg");
    header("Content-Length: " . filesize($path));
    fpassthru($fp);
    exit();
}
Jack Miller
źródło