پردازش تصویر با کارایی بالا در سمت کلاینت
پردازش تصاویر در مرورگر اکنون به یک نیاز استاندارد تبدیل شده است. شما ممکن است ویرایشگرهای عکس، مجموعهابزارهای دارایی (asset toolkits) یا فیلترهای دسترسیپذیری بسازید. برای اینکه رابط کاربری (UI) خود را پاسخگو نگه دارید، به تأخیر (latency) کم نیاز دارید.
یک کار ساده، معکوس کردن رنگها (color inversion) است. این یعنی تبدیل مقادیر RGB به معکوس آنها. اگر از روش استاندارد برای تصاویر 4K استفاده کنید، با گلوگاههای سختافزاری مواجه خواهید شد.
مشکل: تکرار سادهلوحانه (Naive Iteration)
اکثر توسعهدهندگان از متد getImageData() استفاده میکنند. این متد یک Uint8ClampedArray برمیگرداند. این آرایه پیکسلها را به صورت کانالهای قرمز، سبز، آبی و آلفا (RGBA) ذخیره میکند.
یک حلقه استاندارد به این صورت است:
- تکرار روی تکتک بایتها.
- کم کردن هر مقدار رنگ از ۲۵۵.
- نادیده گرفتن کانال آلفا.
این روش برای تصاویر کوچک کار میکند، اما برای داراییهای 4K شکست میخورد. یک تصویر 4K بیش از ۸ میلیون پیکسل دارد. یک حلقه استاندارد بیش از ۳۳ میلیون عملیات نوشتن مجزا انجام میدهد. این کار باعث مسدود شدن رشته اصلی (main thread) میشود و منجر به لرزش مرورگر و افت فریم میگردد.
راه حل: دستکاری بافر ۳۲ بیتی
میتوانید از برخورد با پیکسلها به عنوان چهار کانال مجزا دست بکشید. در عوض، یک Uint32Array را روی بافر دادهها قرار دهید (overlay کنید).
با استفاده از یک نمای ۳۲ بیتی، شما R، G، B و A را در یک عدد صحیح واحد گروهبندی میکنید. اکنون حلقه شما به جای ۳۳ میلیون، تنها ۸.۲ میلیون تکرار انجام میدهد. شما به جای چهار عملیات، هر پیکسل را با یک عملیات پردازش میکنید.
معکوس کردن سریع رنگها از طریق XOR بیتی
برای معکوس کردن رنگها بدون دستکاری آلفا، از عملگر XOR بیتی (^) استفاده کنید. از ماسک 0x00FFFFFF استفاده کنید.
نحوه عملکرد:
- ماسک فقط بیتهای رنگ را هدف قرار میدهد.
- بیتهای آلفا بدون تغییر باقی میمانند.
- پردازنده (CPU) این کار را در یک چرخه (cycle) انجام میدهد.
نتایج:
- داراییهای 1080p: ۳.۸ برابر سریعتر.
- قالبهای 2K: ۴.۱ برابر سریعتر.
- والپیپرهای 4K: ۴.۴ برابر سریعتر.
نکته حرفهای: از Web Workers استفاده کنید اگر فایلهای با رزولوشن بالا را به تعداد زیاد پردازش میکنید، حتی عملیاتهای ۳۲ بیتی نیز میتوانند UI را کند کنند. منطق برنامه را به یک Web Worker منتقل کنید. از Transferable Objects برای انتقال بافر استفاده کنید. این کار از کپی کردن دادهها جلوگیری کرده و رشته اصلی شما را آزاد نگه میدارد.
استفاده از حلقههای سنگین را متوقف کنید. از کلمات ۳۲ بیتی و پرچمهای بیتی (bitwise flags) برای ساخت خط لولههای (pipelines) تصویر سبک و سریع استفاده کنید.