تغییر ابعاد تصویر با توجه به درخواست کاربر در لاراول (کتابخانه Intervention)

سلام ^_^

موضوع چیه ؟

یکی از نکاتی که می تونه سرعت لود سایت رو خیلی بهبود بده،‌ لود کردن تصاویر به صورت بهینه شده برای ابعاد مناسب در قالب HTML هست. یکی از روشهای ابتدایی برای این کار،‌ ذخیره کردن تصاویر کوچک شده، به همراه تصویر اصلی هست :| کاری که معمولا توی سی ام اس هایی مثل وردپرس مرسومه که به نظرم روش مزخرف و غیر هوشمندانه ایه ...

می خوام چی کار کنم ؟

معمولا همه جا، آدرس تصویر رو به صورت زیر بیان می کنن :

example.com / path-to-image / my-image.png

که این آدرس تصویر « my-image.png » رو با ابعاد اصلیش بارگذاری می کنه.

اما من دوست دارم یه آدرس دیگه هم داشته باشم به صورت زیر :

example.com / path-to-image / width / height / my-image.png

که توی این حالت عرض و ارتفاع دلخواه تصویر رو مشخص می کنم و باید تصویر با اون ابعاد لود بشه.

استفاده از کتابخانه اینتروِنشن

یکی از بهترین ابزارها برای ویرایش تصاویر در لاراول،‌ کتابخانه « Intervention Image » هست. بد نیست سری به مخزن گیتهاب و داکیومنت های کاملش بزنین.

Intervention Image is a PHP image handling and manipulation library providing an easier and expressive way to create, edit, and compose images. The package includes ServiceProviders and Facades for easy Laravel integration.

خب من چی کار کردم ؟

ابتدا توی کنترلر تصاویر یه متد برای دانلود قرار دادم.

متد دانلود
متد دانلود

این متد عرض و طول و نام فایل تصویر رو در ورودی می گیره و باید در نهایت تصویر با ابعاد جدید رو در خروجی برگردونه.


اولین کار توی این متد،‌ اینه که مطمئن شم فایل اصلی روی سرور وجود داره :


حالا فایل تصویر رو به کتابخانه اینترونشن تحویل میدم.

طول و عرض تصویر رو به کمک کتابخانه بدست می آرم. و بعد نسبت ابعاد تصویر رو برای تصویر اصلی و تصویر درخواستی محاسبه می کنم. اما نسبت ابعاد به چه دردم می خوره ؟

نقطه ی کلیدی در ریسایز دقیق تصویر همینجاست !

فرض کنیم تصویر با ابعاد ۱۰۸۰ × ۱۹۲۰ به صورت زیر باشه :

تصویر اصلی ۱۰۸۰ × ۱۹۲۰ (نسبت ابعاد : ۱/۷۷ )
تصویر اصلی ۱۰۸۰ × ۱۹۲۰ (نسبت ابعاد : ۱/۷۷ )

خب ممکنه تصویر درخواستی با ابعاد ۱۰۸۰ × ۱۳۰۰ باشه. در این صورت تصویر از ارتفاع برش نمیخوره و فقط از عرض برش می خوره. مثل تصویر زیر :

تصویر درخواستی با ابعاد ۱۰۸۰ × ۱۳۰۰ (نسبت ابعاد : ۱/۲۰ )
تصویر درخواستی با ابعاد ۱۰۸۰ × ۱۳۰۰ (نسبت ابعاد : ۱/۲۰ )

یا ممکنه تصویر درخواستی با ابعاد ۵۰۰ × ۱۹۲۰ باشه. اینجا تصویر از عرض برش نمیخوره و فقط از ارتفاع برش میخوره. مثل این :

تصویر درخواستی با ابعاد ۵۰۰ × ۱۹۲۰ (نسبت ابعاد :‌ ۳/۸۴ )
تصویر درخواستی با ابعاد ۵۰۰ × ۱۹۲۰ (نسبت ابعاد :‌ ۳/۸۴ )


توی کنترلر باید تصمیم بگیرم که تصویر رو از عرض برش بدم یا از ارتفاع و برای فهمیدن این موضوع،‌ بهترین راه مقایسه نسبت ابعاد تصویر درخواستی با نسبت ابعاد اصلیه.

تکنیک من برای حفظ کیفیت تصویر، ابتدا برش تصویر اصلی و سپس تغییر سایز هست. اینطوری من هر سایزی از تصویر رو میتونم داشته باشم بدون اینکه کیفیتش تکون بخوره ^_^

اگه نسبت ابعاد اصلی بزرگتر از مقدار درخواستی باشه ،‌ تصویر اصلی باید از عرض برش بخوره و بعد تغییر سایز داده بشه ،‌ و در حالت دیگه ، تصویر باید از ارتفاعش برش داده بشه و بعد سایزش تغییر کنه.

این طوری کیفیت تصویر حفظ میشه و کشیدگی یا فشردگی در تصویر دیده نخواهد شد.


خب اینم از کد من :


حالا باید تصمیم بگیرم که فایل جدید (ریسایز شده) کجا ذخیره بشه ؟

فایل رو توی آدرس همون فایل اصلی و با یک نام جدید ذخیره می کنم. به طوری که بعدا بشه پیداش کرد.

من میخوام برای تصاویر ریسایز شده از قاعده زیر برای نامگذاری استفاده کنم:

$resized_filename = $name . '_' . $width . 'x' . $height . '.' . $mime_type;

در این حالت اگر تصویر اصلی image.png باشه، تصویر با ابعاد درخواستی ۲۰۰×۳۰۰ رو به صورت زیر ذخیره می کنم :

image_300x200.png

دیگه وقتشه که تصویر جدید رو ذخیره کنم و اون رو برای کاربر بارگذاری کنم :

تامام !
تامام !

نکته اضافی ۱

تصویر ریسایز شده رو با یه اسم خاص ذخیره کردم تا بعدا بشه پیداش کرد. از این به بعد باید قبل از تبدیل تصویر بررسی کنم که آیا فایل درخواستی وجود داره یا نه. اگه وجود داشت که خوبه ! اگه نه تصویر رو ریسایز می کنم و برای درخواست های بعدی نگهش می دارم .

در نهایت متد دانلود به صورت زیر خواهد بود :

که داخل if هم کد های قبلی برای تغییر سایز تصویر رو قرار می دم.

با این روش، هر سایز درخواستی از تصویر در اولین درخواست ساخته میشه (یکم زمان بیشتری میبره) ولی در تمام درخواست های بعدی به سرعت از روی سرور لود میشه.

نکته اضافی ۲

کتابخونه ی اینترونشن، امکانات بسیار زیادی برای تغییر کیفیت تصاویر و کاهش حجمشون هم داره که میشه از اونها استفاده کنیم. البته در حوصله ی این متن و نبود :)