Αλλαγή μεγέθους εικόνων εν κινήσει χρησιμοποιώντας Nginx και LuaJIT (OpenResty)

Εδώ και αρκετό καιρό, εμπνευσμένη από το άρθρο Αλλαγή μεγέθους εικόνας εν κινήσει Η αλλαγή μεγέθους εικόνας διαμορφώθηκε χρησιμοποιώντας ngx_http_image_filter_module και όλα λειτούργησαν όπως έπρεπε. Αλλά ένα πρόβλημα προέκυψε όταν ο διαχειριστής χρειάστηκε να λάβει εικόνες με ακριβείς διαστάσεις για μεταφόρτωση σε ορισμένες υπηρεσίες, επειδή... αυτές ήταν οι τεχνικές τους απαιτήσεις. Για παράδειγμα, εάν έχουμε μια πρωτότυπη εικόνα μεγέθους 1200 × 1200, και κατά την αλλαγή μεγέθους γράφουμε κάτι σαν ?resize=600×400, τότε παίρνουμε μια αναλογικά μειωμένη εικόνα κατά μήκος της μικρότερης άκρης, μεγέθους 400 × 400. Είναι επίσης αδύνατο να αποκτήσετε μια εικόνα με υψηλότερη ανάλυση (upscale). Εκείνοι. ?resize=1500×1500 θα επιστρέψει την ίδια εικόνα 1200 × 1200

Αυτό το άρθρο ήρθε στη διάσωση OpenResty: μετατροπή του NGINX σε έναν ολοκληρωμένο διακομιστή εφαρμογών για να κατανοήσετε πώς λειτουργεί το Nginx με τον Lua και την ίδια τη βιβλιοθήκη για τον Lua isage/lua-imagick - Lua pure-c δεσμεύσεις στο ImageMagick. Γιατί επιλέχθηκε αυτή η λύση και όχι, ας πούμε, κάτι σε python - γιατί είναι γρήγορη και βολική. Δεν χρειάζεται καν να δημιουργήσετε αρχεία, όλα είναι σωστά στη διαμόρφωση Nginx (προαιρετικά).

Τι χρειαζόμαστε λοιπόν

Θα δοθούν παραδείγματα με βάση το Debian.

Εγκατάσταση nginx και nginx-extras

apt-get update
apt-get install nginx-extras

Εγκατάσταση LuaJIT

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

Εγκατάσταση του imagemagick

apt-get -y install imagemagick

και βιβλιοθήκες μαγικό ραβδί σε αυτό, στην περίπτωσή μου για την έκδοση 6

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

Κτίριο lua-imagick

Κλωνοποιούμε το αποθετήριο (ή παίρνουμε το φερμουάρ και το αποσυσκευάζουμε)

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

Εάν όλα πήγαν καλά, μπορείτε να διαμορφώσετε το Nginx.

Θα δώσω ένα παράδειγμα της διαμόρφωσης του κεντρικού υπολογιστή υποστήριξης, ο οποίος, στην πραγματικότητα, είναι υπεύθυνος για την αλλαγή μεγέθους. Γίνεται μεσολάβηση από τον μπροστινό διακομιστή, επίσης με το Nginx, όπου η προσωρινή αποθήκευση λαμβάνει χώρα για μια συγκεκριμένη χρονική περίοδο (ημέρες) και άλλα πράγματα.

διαμόρφωση backend nginx

# 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 (Διατήρηση αναλογίας διαστάσεων, χρήση υψηλότερης διάστασης)
  • WxH^ (Διατήρηση αναλογίας διαστάσεων, χρήση χαμηλότερης διάστασης (περικοπή))
  • WxH! (Παράβλεψη αναλογίας διαστάσεων)
  • WxH+ (Διατήρηση αναλογίας διαστάσεων, προσθήκη πλευρικών περιγραμμάτων)

Συνοπτικός πίνακας με αποτελέσματα αλλαγής μεγέθους

Αίτημα παραμέτρου uri
Μέγεθος εικόνας εξόδου

?resize=400×200
200 × 200

?resize=400×200^
400 × 400

?resize=400×200!
400×200 (Μη αναλογικό)

?resize=400×200+
400×200 (Αναλογικά)

Αλλαγή μεγέθους εικόνων εν κινήσει χρησιμοποιώντας Nginx και LuaJIT (OpenResty)

Σύνολο

Λαμβάνοντας υπόψη τη δύναμη και την απλότητα αυτής της προσέγγισης, μπορείτε να εφαρμόσετε πράγματα με αρκετά περίπλοκη λογική, για παράδειγμα, προσθέτοντας υδατογραφήματα ή εφαρμόζοντας εξουσιοδότηση με περιορισμένη πρόσβαση. Για να μάθετε τις δυνατότητες του API για εργασία με εικόνες, μπορείτε να ανατρέξετε στην τεκμηρίωση της βιβλιοθήκης isage/lua-imagick

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο