Redimensionado de imágenes según la resolución del cliente
Tags: php, optimizacion, castellano, spanish
Published: 2019-03-27 19:20:19

---
title: Redimensionado de imágenes según la resolución del cliente
published: true
description: Como realizar redimensionado de imagen de una manera inteligente según la resolución del dispositivo del cliente
tags: PHP, Optimizacion, Castellano, Spanish
---

Una vez tenemos claro como utilizar una herramienta como [Packer](https://github.com/eusonlito/laravel-Packer) para el redimensionado de imágenes en tiempo de ejecución:

{% link https://dev.to/lito_ordes/redimensionando-imgenes-en-tiempo-de-ejecucin-con-packer-57c6 %}

Vamos a dar un paso más aplicando la redimensión según la resolución del dispositivo del cliente.

Esta mejora permitirá enviar fotos posiblemente mucho más reducidas en tamaño para optimizar sobre todo la navegación móvil en, como mínimo, cuatro puntos:

* el cliente usa menos ancho de banda con lo cual la descarga será más rápida y la web se visualizará antes
* el uso de CPU del dispositivo será menor al tener que renderizar imágenes más ligeras
* evitamos guardar en la caché de disco del cliente imágenes a alta resolución
* el feeling en el scroll mejorará cuanto más reducidas sean las imágenes

Lo primero es añadir un trozo de código javascript en el HTML:

```javascript
(function() {
    function setCookie(value) {
        document.cookie = value
            + '; path=/'
            + '; max-age=' + (3600 * 24 * 30 * 12)
            + '; SameSite=Strict'
            + '; secure';
    }

    function setResolution() {
        var width = document.documentElement.clientWidth || window.innerWidth,
            height = document.documentElement.clientHeight || window.innerHeight,
            dpr = window.devicePixelRatio || 1;

        setCookie('resolution=' + width + ',' + height + ',' + dpr);
    }

    setResolution();

    window.addEventListener('resize', function() {
        setResolution();
    });
})();
```

Con esto ya tenemos una cookie que registra la resolución del dispositivo conectado.

Ahora vamos por la parte de backend.

Primero creamos un servicio que nos permita realizar las transformaciones desde las plantillas de manera sencilla:

```php
<?php declare(strict_types=1);

namespace App\Services\Html;

class Html
{
    /**
     * @param string $image
     * @param string $options = ''
     *
     * @return string
     */
    public static function img(string $image, string $options = ''): string
    {
        return Image::transform($image, $options);
    }
}

```

Y lo añadimos como alias en `app/config.php`:

```php
    'aliases' => [
        ...,
        'Html' => App\Services\Html\Html::class,
    ],
```

Ahora preparamos el servicio de procesado de imágenes:

```php
<?php declare(strict_types=1);

namespace App\Services\Html;

use Packer;

class Image
{
    /**
     * @param string $image
     * @param string $options
     *
     * @return string
     */
    public static function transform(string $image, string $options): string
    {
        if ($options = static::options($options)) {
            return (string)Packer::img($image, $options);
        }

        return $image;
    }

    /**
     * @param string $options
     *
     * @return string
     */
    protected static function options(string $options): string
    {
        if (empty($resolution = $_COOKIE['resolution'])) {
            return $options;
        }

        list($widthMax, $heightMax, $dpr) = array_pad(array_map('intval', explode(',', $resolution, 3)), 3, 1);

        if (empty($widthMax) || empty($heightMax)) {
            return $options;
        }

        $options = $options ?: 'resize,0,0,center,middle';

        $widthMax *= ($dpr ?: 1);
        $heightMax *= ($dpr ?: 1);

        list($action, $width, $height, $horizontal, $vertical) = array_pad(explode(',', $options, 5), 5, null);

        if ($width > $widthMax) {
            $height = intval(($widthMax * $height) / $width);
            $width = $widthMax;
        } elseif ($height > $heightMax) {
            $width = intval(($heightMax * $width) / $height);
            $height = $heightMax;
        }

        return $action.','.$width
            .($height ? (','.$height) : '')
            .($horizontal ? (','.$horizontal) : '')
            .($vertical ? (','.$vertical) : '');
    }
}
```

Ahora sólo queda usarlo en las plantillas y comparar las imágenes generadas según el dispositivo con el que nos conectemos:

```html
<img src="{{ Html::img('/storage/images/background.jpg') }}" />
<img src="{{ Html::img('/storage/images/slider.jpg', 'resize,1920') }}" />
```

Eso es todo amigos!