¿Cómo generar miniaturas solo cuando sean necesarias?
Tengo 1000 imágenes. ¿Cómo puedo hacer que WordPress genere miniaturas solo cuando sean necesarias? Por ejemplo, el slider de la página principal solo usará 10 imágenes y no quiero que las otras 1000 imágenes tengan esa miniatura generada ya que es un desperdicio de espacio y recursos.
¿Existe alguna manera de ejecutar add_image_size solo cuando sea necesario?
Gracias
ACTUALIZACIÓN Como mencionan, no es realmente add_image_size lo que necesita ser ejecutado. Lo que sería genial es activar el redimensionamiento de la imagen cuando uso the_post_thumbnail('slider-thumb'); Tal vez esto ralentice la primera vista de la imagen, pero esa vista generalmente la genero yo cuando realmente reviso la entrada, así que no me importa.
Entonces, entre mis entradas, slider, miniaturas del blog, miniaturas del portafolio, etc., tengo 1000 imágenes y solo quiero que 10 imágenes sean redimensionadas para el slider. Veo muchos recursos desperdiciados al generar el tamaño de miniatura para las otras 990 imágenes.
Espero que ahora esté claro, disculpen mi inglés
Echa un vistazo al plugin Dynamic Image Resizer de Otto
Este plugin cambia la forma en que WordPress crea imágenes para que solo las genere cuando realmente se utilizan en algún lugar, al vuelo. Las imágenes creadas de esta manera se guardarán en los directorios normales de subida, para un envío rápido posterior por parte del servidor web. El resultado es que se ahorra espacio (ya que las imágenes solo se crean cuando se necesitan) y la subida de imágenes es mucho más rápida (ya que no genera las imágenes durante la subida).

Ten en cuenta que ese plugin tiene un problema al añadir imágenes a entradas antiguas. Se aceptan parches.

Eso es exactamente lo que estaba buscando. Lo probaré. ¿Entonces solo funciona en entradas nuevas?

Para aquellos que encuentren esta publicación ahora, aquí hay un plugin similar que parece estar en desarrollo activo: https://wordpress.org/plugins/fly-dynamic-image-resizer/

Coloca esto en el archivo de funciones de tu tema. Evitará que WordPress cree cualquier tamaño adicional a los 3 predeterminados al subir imágenes.
Cuando luego se solicite una imagen en un tamaño específico que aún no se ha generado, se creará solo esa una vez.
add_filter('image_downsize', 'ml_media_downsize', 10, 3);
function ml_media_downsize($out, $id, $size) {
// Si el tamaño de imagen existe, deja que WordPress lo sirva normalmente
$imagedata = wp_get_attachment_metadata($id);
if (is_array($imagedata) && isset($imagedata['sizes'][$size]))
return false;
// Verifica que el tamaño solicitado exista, o aborta
global $_wp_additional_image_sizes;
if (!isset($_wp_additional_image_sizes[$size]))
return false;
// Crea la nueva miniatura
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;
// Guarda los metadatos de la imagen, o WordPress no podrá ver que la miniatura existe ahora
$imagedata['sizes'][$size] = $resized;
wp_update_attachment_metadata($id, $imagedata);
// Devuelve el array para mostrar la imagen redimensionada
$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) {
// Eliminar estos valores predeterminados podría causar problemas, así que no lo hacemos
return array(
'thumbnail' => $sizes['thumbnail'],
'medium' => $sizes['medium'],
'large' => $sizes['large']
);
}

Este filtro debería ser estándar en WordPress. ¿Por qué generar cada tamaño para cada imagen? Estoy agregando este código a mis temas personalizados. Gracias

Bien, pero ahora aún generará todas las imágenes si solo necesito un tamaño personalizado...

No funciona SI add_image_size fue definido previamente con las dimensiones de la imagen que acaban de cambiar

@Michaelkay este enfoque tiene una penalización de rendimiento. Cuando las imágenes se suben y luego se generan para cada tamaño, significa que el que sube es el que tiene paciencia. Este código hace que tus visitantes tengan que tener más paciencia, y Google ha demostrado que los sitios que tardan más de 2 segundos en cargar, pierden el 50% de las personas. Además, si tu sitio tiene cientos de visitas concurrentes, esto derribará tus servidores.

Desafortunadamente, la respuesta de @Patrick rompe las funciones srcset introducidas en WP 4.4. Afortunadamente, ¡solo necesitamos agregar dos funciones adicionales!
Primero, necesitamos reintroducir temporalmente todos los tamaños de miniaturas registrados en los metadatos de la imagen para que puedan ser considerados:
function bi_wp_calculate_image_srcset_meta($image_meta, $size_array, $image_src, $attachment_id){
//todos los tamaños registrados
global $_wp_additional_image_sizes;
//algunas especificaciones del archivo fuente que usaremos mucho
$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");
//encontrar lo que falta
foreach($_wp_additional_image_sizes AS $k=>$v)
{
if(!isset($image_meta['sizes'][$k]))
{
//primero, averigüemos cómo funcionaría dimensionalmente
$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];
//valores incorrectos
if(!$new_h || !$new_w)
continue;
//generar un nombre de archivo de la misma manera que WP_Image_Editor
$new_f = wp_basename("{$src_root}{$src_base}-{$new_w}x{$new_h}." . strtolower($src_ext));
//finalmente, ¡agregarlo!
$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);
Luego necesitamos revisar las coincidencias y generar las miniaturas faltantes:
function bi_wp_calculate_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id){
//obtener información del archivo fuente
$src_path = get_attached_file($attachment_id);
$src_root = trailingslashit(pathinfo($src_path, PATHINFO_DIRNAME));
//los metadatos reales de la imagen (que podrían ser alterados aquí)
$src_meta = wp_get_attachment_metadata($attachment_id);
//un array de tamaños posibles para buscar
$sizes = $image_meta['sizes'];
unset($sizes['thumbnail']);
unset($sizes['medium']);
unset($sizes['large']);
$new = false;
//recorrer las fuentes
foreach($sources AS $k=>$v)
{
$name = wp_basename($v['url']);
if(!file_exists("{$src_root}{$name}"))
{
//encontrar el tamaño correspondiente
foreach($sizes AS $k2=>$v2)
{
//¡tenemos una coincidencia!
if($v2['file'] === $name)
{
//crearlo
if(!$resized = image_make_intermediate_size(
$src_path,
$v2['width'],
$v2['height'],
$v2['crop']
)){
//eliminar de las fuentes en caso de fallo
unset($sources[$k]);
}
else
{
//agregar la nueva miniatura a los metadatos reales
$new = true;
$src_meta['sizes'][$k2] = $resized;
}
//eliminar del array de tamaños para tener
//menos que buscar la próxima vez
unset($sizes[$k2]);
break;
}//coincidencia
}//cada tamaño
}//cada 404
}//cada fuente
//si generamos algo, actualizar los metadatos del adjunto
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);

En realidad, add_image_size()
no genera la miniatura, solo registra un tamaño de imagen como disponible para WordPress.
Normalmente, las miniaturas se generan cuando la imagen se sube por primera vez. Es un proceso automático, así que no tienes que preocuparte por generarlas más tarde. Piensa en ello así: si toma 1-2 segundos generar una miniatura en un servidor lento, y esperas hasta que se solicite, fuerzas al solicitante a esperar 1-2 segundos adicionales por imagen para ver el contenido. Es mucho más fácil hacer esto con anticipación, es decir, cuando se sube la imagen.
Al mismo tiempo, si absolutamente debes procesar las miniaturas en un momento diferente, quizás quieras echar un vistazo al plugin Viper's Regenerate Thumbnails. Utiliza una acción bajo demanda para regenerar todas tus miniaturas de imágenes... pero podrías usar un código similar para generar miniaturas solo cuando sea necesario.

Creo que no entendiste el punto. Él quiere controlar para qué imágenes se necesita una miniatura. Así que algunas imágenes no necesitan ser redimensionadas en absoluto.

La mayoría de las personas prueban las páginas cuando insertan fotos (me siento bastante seguro diciendo que todos). Esto generará los archivos necesarios una sola vez y ya está. En mi caso, tengo un tamaño de imagen de encabezado registrado. Aproximadamente 1 de cada 20 imágenes que subo son realmente para el encabezado. Así que 19 de cada 20 imágenes en mi biblioteca son un desperdicio de espacio.

¿Existe alguna forma de activar add_image_size solo cuando sea necesario?
No exactamente. Pero puedes filtrar la lista de tamaños registrados justo antes de que se generen las miniaturas. La función wp_generate_attachment_metadata() (que llama a la función que genera las miniaturas) tiene un filtro llamado "intermediate_image_sizes_advanced", que te permite manipular el array de tamaños justo antes de que se generen los archivos. Podrías usar este filtro cada vez que agregues una imagen de cierto "tipo", y luego eliminarlo inmediatamente después.
Supongo que tu mayor desafío sería averiguar cómo diferenciar entre las imágenes que necesitan los tamaños adicionales y las que no.

Puedes utilizar mi plugin (no el de Ottos) "Dynamic Image Resize" 1).
"Dynamic Image Resize" es un plugin (MU) para WordPress que ofrece un shortcode y una etiqueta de plantilla para redimensionar imágenes "al vuelo" sin necesidad de TimThumb, utilizando las funciones principales de WordPress.
El plugin incluye tanto una etiqueta de plantilla como un shortcode.
1) Acabo de enterarme del plugin de Otto. La coincidencia de nombres no fue intencional.

Puedes probar este plugin: https://wordpress.org/plugins/optimize-images-resizing
Redimensiona imágenes basándose en los tamaños de imagen registrados, pero solo cuando es necesario. También puede limpiar los tamaños de imagen existentes para que puedan regenerarse.

El plugin WP Performance Pack ofrece un "manejo mejorado de imágenes", que se basa en Ottos Dynamic Image Resizer, pero incluye muchas mejoras, por ejemplo: En primer lugar, es compatible con la última versión de WordPress (3.9.1), utiliza WP_Image_Editor, se puede desactivar el guardado de miniaturas (pero se pueden almacenar en caché y el soporte para CDN está en camino), integración con Regenerate Thumbnails (para eliminar miniaturas existentes) y algunas más.

Aquí otro enfoque más: Se engancha al manejo de errores HTTP 404. Es decir, cuando la miniatura no está disponible, busca la imagen original y crea la miniatura. Ten en cuenta que esto no resuelve realmente tu problema, ya que no evita la generación de miniaturas durante la subida.
También ten en cuenta que este plugin podría ser utilizado por usuarios maliciosos para crear cualquier número de miniaturas y así agotar el espacio en tu disco.
Nota: Este plugin puede instalarse fácilmente usando Pluginception.
<?php
/*
Plugin Name: Crear miniaturas bajo demanda
Plugin URI:
Description: Crea miniaturas en lugar de mostrar error 404. Usa en combinación con "Broken Link Checker" para crear todas las miniaturas faltantes.
Version: 0.1
Author: Jack Miller
Author URI:
License:
License URI:
*/
add_filter('status_header', 'createThumbIf404');
function createThumbIf404($httpCodeString) //ej. 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);
}
}
}
}
}
//busca la imagen original dentro de $baseDir con $baseName.
//Devuelve el nombre del archivo incluyendo extensión de la imagen original o 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;
}
//Lee el archivo en $path desde el disco y lo devuelve como una petición HTTP de imagen JPG.
function ctod_sendImageAndExit($path)
{
$fp = fopen($path, 'rb');
header("Content-Type: image/jpeg");
header("Content-Length: " . filesize($path));
fpassthru($fp);
exit();
}

En otros lugares todos los tamaños creados funcionarán, pero solo en la subida de medios si deseas que se suba un tamaño específico, a continuación está el código para ello. Aquí está el enlace para más descripción - 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;
}

También puedes probar Aqua Resizer - https://github.com/syamilmj/Aqua-Resizer/
Es solo un archivo.
Puedes usarlo así:
$img_src = aq_resize( $img_src, $width = null, $height = null, $crop = null, $single = true, $upscale = false );
$img_src = aq_resize( $img_src, 150, 150); // redimensionado
$img_src = aq_resize( $img_src, 150, 150, true); // recortado
$img_src = aq_resize( $img_src, 150, 150, null, null, true); // una imagen de 120x120 por ejemplo será escalada hasta 150x150
