Redimensionner les images à la volée à l'aide de Nginx et LuaJIT (OpenResty)

Depuis un certain temps maintenant, inspiré par l'article Redimensionner les images à la volée , le redimensionnement d'image avec ngx_http_image_filter_module a été configuré et tout a fonctionné comme il se doit. Mais il y avait un problème lorsque le gestionnaire devait obtenir des images de tailles exactes pour les télécharger sur certains services, car c'étaient leurs exigences techniques. Par exemple, si nous avons une image originale de taille 1200x1200 , et lors du redimensionnement, nous écrivons quelque chose comme ? Resize = 600x400 , nous obtiendrons une image proportionnellement réduite au plus petit bord, taille 400x400 . Il est également impossible d'obtenir une image avec une résolution plus élevée (haut de gamme). Ceux. ? resize = 1500x1500 renverra tout de même la même image1200x1200


Un article d' OpenResty est venu à la rescousse: nous transformons NGINX en un serveur d'applications à part entière pour comprendre comment Nginx fonctionne avec Lua et la bibliothèque pour Lua isage / lua-imagick elle-même - Lia pure-c bindings à ImageMagick. Pourquoi une telle solution a été choisie, et non, disons, quelque chose en python - parce qu'elle est rapide et pratique. Vous n'avez même pas besoin de créer de fichiers, tout se passe bien dans la configuration Nginx (facultatif).


Alors de quoi avons-nous besoin


Des exemples seront donnés sur la base de Debian.


Installer nginx et nginx-extras


apt-get update
apt-get install nginx-extras

Installer LuaJIT


apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-dev

Installer imagemagick


apt-get -y install imagemagick

et les bibliothèques magickwand , dans mon cas pour la version 6


apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-dev

Construction Lua-imagick


Nous clonons le référentiel (enfin, ou prenons le zip et le déballons)


cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make install

Si tout s'est bien passé, vous pouvez configurer Nginx.


backend , , , . Nginx, () . .


nginx backend config
# Backend image server
server {
    listen       8082;
    listen [::]:8082;
    set $files_root /var/www/example.lh/frontend/web;
    root $files_root;
    access_log off;
    expires 1d;

    location /files {
        #   
        set $w 700;
        set $h 700;
        set $q 89;

        #1-89 allowed
        if ($arg_q ~ "^([1-9]|[1-8][0-9])$") {
            set $q $arg_q;
        }

        if ($arg_resize ~ "([\d\-]+)x([\d\+\!\^]+)") {  
            set $w $1;
            set $h $2;
            rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
        }

        rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
    }

    location ~* ^/resize/([\d]+)/([\d\+\!\^]+)/([\d]+)/files/(.+)$ {
        default_type 'text/plain';

        set $w $1;
        set $h $2;
        set $q $3;
        set $fname $4;

        #     Lua    
        # content_by_lua_file /var/www/some.lua;
        # lua_code_cache off; #dev
        content_by_lua '
        local magick = require "imagick"
        local img = magick.open(ngx.var.files_root .. "/files/" .. ngx.var.fname)
        if not img then ngx.exit(ngx.HTTP_NOT_FOUND) end
        img:set_gravity(magick.gravity["CenterGravity"])

        if string.match(ngx.var.h, "%d+%+") then
            local h = string.gsub(ngx.var.h, "(%+)", "")
            resize = ngx.var.w .. "x" .. h
            --  png   
            img:set_bg_color(img:has_alphachannel() and "none" or img:get_bg_color())
            img:smart_resize(resize)
            img:extent(ngx.var.w, h)
        else
                img:smart_resize(ngx.var.w .. "x" .. ngx.var.h)
        end

        if ngx.var.arg_q then img:set_quality(ngx.var.q) end

        ngx.say(img:blob())
        ';
    }
}

# Upstream
upstream imageserver {
    server localhost:8082;
}

server {
    listen 80;
    server_name examaple.lh;

    #   jpg  png   imageserver
    location ~* ^/files/.+\.(jpg|png) {
        proxy_buffers 8 2m;
        proxy_buffer_size 10m;
        proxy_busy_buffers_size 10m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass     http://imageserver;  # Backend image server
    }
}

, ( ) img:extent() resize + .


:


  • WxH (Keep aspect-ratio, use higher dimension)
  • WxH^ (Keep aspect-ratio, use lower dimension (crop))
  • WxH! (Ignore aspect-ratio)
  • WxH+ (Keep aspect-ratio, add side borders)


uri
?resize=400x200200x200
?resize=400x200^400x400
?resize=400x200!400x200 ( )
?resize=400x200+400x200 ()



Étant donné la puissance et la simplicité de cette approche, vous pouvez implémenter des choses avec une logique plutôt complexe, par exemple, ajouter watermark'i ou implémenter une autorisation avec un accès limité. Afin de découvrir les capacités de l'API pour travailler avec des images, vous pouvez vous référer à la documentation de la bibliothèque isage / lua-imagick


All Articles