Ubah ukuran gambar dengan cepat menggunakan Nginx dan LuaJIT (OpenResty)

Untuk beberapa waktu sekarang, terinspirasi oleh artikel Mengubah Ukuran Gambar on the Fly , mengubah ukuran gambar dengan ngx_http_image_filter_module telah diatur dan semuanya berfungsi sebagaimana mestinya. Tetapi ada satu masalah ketika manajer perlu mendapatkan gambar dengan ukuran yang tepat untuk mengunggah ke beberapa layanan, karena ini adalah persyaratan teknis mereka. Sebagai contoh, jika kita memiliki gambar asli ukuran 1200x1200 , dan ketika mengubah ukuran kita menulis sesuatu seperti ? Ubah ukuran = 600x400 , kita akan mendapatkan gambar yang dikurangi secara proporsional di tepi terkecil, ukuran 400x400 . Juga tidak mungkin memperoleh gambar dengan resolusi yang lebih tinggi (kelas atas). Itu ? resize = 1500x1500 akan mengembalikan semua gambar yang sama1200x1200


Artikel OpenResty datang untuk menyelamatkan: kami mengubah NGINX menjadi server aplikasi lengkap untuk memahami bagaimana Nginx bekerja dengan Lua dan perpustakaan untuk Lua isage / lua-imagick sendiri - Lua murni-c binding menjadi ImageMagick. Mengapa solusi seperti itu dipilih, dan bukan, katakanlah, sesuatu dengan python - karena cepat dan nyaman. Anda bahkan tidak perlu membuat file apa pun, semuanya benar dalam konfigurasi Nginx (opsional).


Jadi apa yang kita butuhkan


Contoh akan diberikan berdasarkan Debian.


Instal nginx dan nginx-ekstra


apt-get update
apt-get install nginx-extras

Instal LuaJIT


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

Pasang imagemagick


apt-get -y install imagemagick

dan perpustakaan magickwand untuk itu, dalam kasus saya untuk versi 6


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

Lua-imagick build


Kami mengkloning repositori (well, atau mengambil zip dan membongkarnya)


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

Jika semuanya berjalan dengan baik, Anda dapat mengkonfigurasi 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 ()



Mengingat kekuatan dan kesederhanaan dari pendekatan ini, Anda dapat menerapkan hal-hal dengan logika yang agak rumit, misalnya, menambahkan tanda air atau menerapkan otorisasi dengan akses terbatas. Untuk mengetahui kemampuan API untuk bekerja dengan gambar, Anda dapat merujuk ke dokumentasi perpustakaan isage / lua-imagick


All Articles