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

Sudah cukup lama, terinspirasi oleh artikel tersebut Mengubah ukuran gambar dengan cepat pengubahan ukuran gambar dikonfigurasi menggunakan ngx_http_image_filter_module dan semuanya berjalan sebagaimana mestinya. Namun satu masalah muncul ketika pengelola perlu menerima gambar dengan dimensi yang tepat untuk diunggah ke beberapa layanan, karena... ini adalah persyaratan teknis mereka. Misalnya, jika kita memiliki gambar asli berukuran 1200x1200, dan saat mengubah ukuran kami menulis sesuatu seperti ?ubah ukuran=600Γ—400, lalu kita mendapatkan gambar yang diperkecil secara proporsional di sepanjang tepi terkecil, berukuran 400x400. Juga tidak mungkin mendapatkan gambar dengan resolusi lebih tinggi (kelas atas). Itu. ?ubah ukuran=1500Γ—1500 akan mengembalikan gambar yang sama 1200x1200

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

Jadi apa yang kita butuhkan

Contoh akan diberikan berdasarkan Debian.

Menginstal nginx dan nginx-extra

apt-get update
apt-get install nginx-extras

Menginstal LuaJIT

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

Menginstal imagemagick

apt-get -y install imagemagick

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

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

Membangun lua-imagick

Kami mengkloning repositori (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.

Saya akan memberikan contoh konfigurasi host backend, yang sebenarnya bertanggung jawab untuk mengubah ukuran. Diproxy oleh server depan, juga dengan Nginx, dimana caching terjadi untuk jangka waktu tertentu (hari) dan lain-lain.

konfigurasi 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
    }
}

Apa yang diperlukan (memperluas gambar di sekitar tepinya) terjadi menggunakan img:extent() dan ditentukan menggunakan parameter resize dengan tanda + pada akhirnya.

Opsi berikut tersedia:

  • WxH (Pertahankan rasio aspek, gunakan dimensi yang lebih tinggi)
  • LxT^ (Pertahankan rasio aspek, gunakan dimensi yang lebih rendah (pangkas))
  • WxH! (Abaikan rasio aspek)
  • WxH+ (Pertahankan rasio aspek, tambahkan batas samping)

Tabel ringkasan dengan hasil pengubahan ukuran

Minta parameter uri
Ukuran Gambar Keluaran

?ubah ukuran=400Γ—200
200x200

?ubah ukuran=400Γ—200^
400x400

?ubah ukuran=400Γ—200!
400Γ—200 (Tidak proporsional)

?ubah ukuran=400Γ—200+
400Γ—200 (Proporsional)

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

Total

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

Sumber: www.habr.com

Tambah komentar