🖼️ Gestion de imagenes — ImageManager y rendimiento
Actualizado: 2024-12-01
Las imagenes suelen representar el 60-80% del peso de una pagina. PrestaShop proporciona ImageManager para redimensionar imagenes y un sistema de tipos de imagen configurable. WebP puede reducir el peso un 30-50%.
#ImageManager — generar thumbnails
Crear thumbnails con ImageManager
php
<?php
// ── Crear un thumbnail de un archivo de imagen ──
$sourcePath = _PS_IMG_DIR_ . 'mymodule/original.jpg';
$destPath = _PS_IMG_DIR_ . 'mymodule/thumb_400x300.jpg';
// Redimensionar manteniendo proporciones
$result = ImageManager::resize(
$sourcePath, // Origen
$destPath, // Destino
400, // Ancho deseado (null = proporcional)
300, // Alto deseado (null = proporcional)
'jpg', // Extension del destino
false, // Forzar tipo (false = auto)
ImageManager::REFIT_IMAGE, // Modo: REFIT, MIRROR, etc.
100 // Calidad JPEG (1-100)
);
// ── Modos de redimensionado ──
// ImageManager::REFIT_IMAGE = Mantiene proporciones, puede recortar
// ImageManager::MIRROR_IMAGE = Rellena con espacio blanco
// ── Crear directorio si no existe ──
$dir = _PS_IMG_DIR_ . 'mymodule/';
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
// Proteger contra listado de directorio
file_put_contents($dir . 'index.php', '<?php header("Location: ../../");');
}
// ── Verificar la imagen antes de procesar ──
if (!ImageManager::isRealImage($sourcePath, null, [IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF])) {
throw new \RuntimeException('Imagen invalida o corrupta');
}
// ── Detectar MIME type ──
$mime = ImageManager::getMimeType($sourcePath);
#Tipos de imagen del sistema
Tipos de imagen y como obtener sus dimensiones
php
<?php
// ── Obtener todos los tipos de imagen ──
$imageTypes = ImageType::getImagesTypes('products'); // 'products', 'categories', 'manufacturers'
// $imageTypes = [
// ['id_image_type' => 1, 'name' => 'cart_default', 'width' => 80, 'height' => 80, ...],
// ['id_image_type' => 2, 'name' => 'small_default', 'width' => 98, 'height' => 98, ...],
// ['id_image_type' => 3, 'name' => 'medium_default', 'width' => 452, 'height' => 452, ...],
// ['id_image_type' => 4, 'name' => 'large_default', 'width' => 800, 'height' => 800, ...],
// ['id_image_type' => 5, 'name' => 'home_default', 'width' => 250, 'height' => 250, ...],
// ['id_image_type' => 6, 'name' => 'category_default','width' => 141, 'height' => 141, ...],
// ]
// ── Obtener el tipo de imagen por nombre ──
$cartType = ImageType::getFormattedName('cart');
// $cartType = 'cart_default'
// ── URL de imagen de producto con tipo especifico ──
$link = Context::getContext()->link;
$imageUrl = $link->getImageLink(
$product['link_rewrite'], // Slug del producto
$product['id_image'], // ID de imagen
$cartType // Tipo de imagen
);
// URL resultante: https://tienda.com/80-cart_default/nombre-producto.jpg
#Obtener URL de imagen de producto
Obtener URLs de imagenes correctamente
php
<?php
$link = Context::getContext()->link;
// ── URL de imagen de producto ──
$imageUrl = $link->getImageLink(
$product['link_rewrite'], // Rewrite del nombre del producto
$product['id_image'], // ID de la imagen principal
'home_default' // Tipo de imagen
);
// ── Imagen con WebP (PS 1.7.7+) ──
// PrestaShop genera automaticamente versiones WebP si esta configurado
// La URL es la misma pero con .webp en lugar de .jpg/.png
$webpUrl = str_replace(['.jpg', '.png', '.gif'], '.webp', $imageUrl);
// ── Imagen de categoria ──
$categoryImageUrl = $link->getCatImageLink(
$category['link_rewrite'],
$category['id_image'],
'category_default'
);
// ── En Smarty — usar los helpers de PS ──
// $product.cover_image_url ya contiene la URL correcta (home_default)
// Para otros tamaños:
// {assign var='imageType' value={imageType name='cart' entity='products'}}
// {assign var='imageUrl' value={$urls.img_ps_url}}{$product.id_image|image_url:{$imageType}}
// ── Imagen placeholder cuando no hay imagen ──
$noImagePath = _PS_IMG_DIR_ . 'p/en-attente.jpg';
$imageUrl = $imageUrl ?: Tools::getNoImageURL();
#WebP y formatos modernos
Generar imagenes WebP en modulos
php
<?php
// ── PS 1.7.7+ genera WebP automaticamente si esta habilitado ──
// BO → Parametros Avanzados → Rendimiento → Imagenes → WebP: Si
// ── Verificar soporte de WebP en el servidor ──
if (function_exists('imagewebp')) {
echo 'WebP soportado';
}
// ── Generar WebP manualmente en un modulo ──
function convertToWebP(string $sourcePath, string $destPath, int $quality = 80): bool
{
$info = getimagesize($sourcePath);
if (!$info) return false;
switch ($info['mime']) {
case 'image/jpeg':
$image = imagecreatefromjpeg($sourcePath);
break;
case 'image/png':
$image = imagecreatefrompng($sourcePath);
// Mantener transparencia
imagealphablending($image, false);
imagesavealpha($image, true);
break;
default:
return false;
}
if (!$image) return false;
$result = imagewebp($image, $destPath, $quality);
imagedestroy($image);
return $result;
}
// ── Usar <picture> en HTML para WebP con fallback ──
// En Smarty:
// <picture>
// <source srcset="{$product.cover_image_url|str_replace:'.jpg':'.webp'}" type="image/webp">
// <img src="{$product.cover_image_url}" alt="{$product.name|escape:'html'}" loading="lazy">
// </picture>
#Lazy loading y optimizacion FO
Lazy loading de imagenes en Smarty
smarty
{* ── Lazy loading nativo (HTML5) ── *}
<img src="{$product.cover_image_url}"
alt="{$product.name|escape:'html':'UTF-8'}"
loading="lazy"
width="{$img_col_w}"
height="{$img_col_h}">
{* ── IMPORTANTE: Siempre especificar width y height ── *}
{* Para evitar el Cumulative Layout Shift (CLS) que penaliza en SEO *}
{* ── Eager loading para imagenes above-the-fold ── *}
{* La primera imagen del hero/banner NO debe ser lazy *}
<img src="{$banner.image}"
alt="{$banner.title|escape:'html'}"
loading="eager"
fetchpriority="high"
width="1920"
height="600">
{* ── srcset para imagenes responsivas ── *}
<img src="{$product.image_url_medium}"
srcset="{$product.image_url_small} 98w,
{$product.image_url_medium} 452w,
{$product.image_url_large} 800w"
sizes="(max-width: 768px) 98px, (max-width: 1200px) 452px, 800px"
alt="{$product.name|escape:'html'}"
loading="lazy">
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.