Chrome תומך ב-createImageBitmap() ב-Chrome 50

פענוח תמונות לשימוש עם קנבס הוא די נפוץ, בין אם המטרה היא לאפשר למשתמשים להתאים אישית דמות, לחתוך תמונה או פשוט להגדיל את התצוגה. הבעיה בפענוח תמונות היא שהמעבד (CPU) עלול להיות אינטנסיבי, ולפעמים עלולות להתקבל שגיאות בממשק (jank) או בלוח מחיקות. החל מ-Chrome 50 (וב-Firefox 42 ואילך) יש לך עכשיו אפשרות נוספת: createImageBitmap(). הכלי הזה מאפשר לפענח תמונה ברקע ולקבל גישה לפרימיטיב חדש של ImageBitmap, שאותו אפשר לשרטט בקנבס כמו שעושים עם אלמנט <img>, על קנבס או על סרטון.

ציור blobs באמצעות createImageBitmap()

נניח שהורדתם תמונת blob באמצעות fetch() (או XHR), ואתם רוצים לשרטט אותה באזור העריכה. בלי createImageBitmap() צריך ליצור אלמנט תמונה וכתובת URL של Blob כדי להעלות את התמונה לפורמט שאפשר להשתמש בו. כך אפשר לקבל מסלול ישיר יותר לציור:

fetch(url)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => ctx.drawImage(imageBitmap, 0, 0));

גישה זו גם תעבוד עם תמונות שמאוחסנות כ-blobs ב-IndexedDB, כך שאובייקטים מסוג blobs יהיו פורמט ביניים נוח. במצב כזה, Chrome 50 תומך גם בשיטה .toBlob() באלמנטים של קנבס, כך שאפשר ליצור blobs מאלמנטים של קנבס, למשל.

שימוש ב-createImageBitmap() בעובדי אינטרנט

אחת מהתכונות הנחמדות ביותר של createImageBitmap() היא שהוא זמין גם ב-worker, כלומר עכשיו אפשר לפענח תמונות מכל מקום. אם יש לכם הרבה תמונות שלדעתכם לא חיוניות, תצטרכו לשלוח את כתובות ה-URL שלהן ל-Web Worker, שיוריד ויפענח אותן ככל שהזמן יאפשר. הם יועברו בחזרה לשרשור הראשי כדי לצייר על קנבס.

זרימת נתונים עם createImageBitmap ועובדי אינטרנט.

הקוד לביצוע הפעולה הזו עשוי להיראות כך:

// In the worker.
fetch(imageURL)
    .then(response => response.blob())
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => {
    // Transfer the imageBitmap back to main thread.
    self.postMessage({ imageBitmap }, [imageBitmap]);
    }, err => {
    self.postMessage({ err });
    });

// In the main thread.
worker.onmessage = (evt) => {
    if (evt.data.err)
    throw new Error(evt.data.err);

    canvasContext.drawImage(evt.data.imageBitmap, 0, 0);
}

היום, אם מתקשרים ל-createImageBitmap() ב-thread הראשי, זה בדיוק המקום שבו יתבצע הפענוח. עם זאת, אנחנו מתכננים לבצע את הפענוח של Chrome באופן אוטומטי בשרשור אחר, כדי שעומס העבודה ב-thread הראשי לא ייפגע. אבל בינתיים, חשוב לבצע פענוח ב-thread הראשי, כי מדובר בעבודה מאומצת שעלולה לחסום משימות חיוניות אחרות כמו JavaScript, חישובי סגנון, פריסה, ציור או קומפוזיציה.

ספרייה משנית

כדי שיהיה קצת יותר פשוט, יצרתי ספריית עזר שמטפלת בפענוח של ה-worker, שולחת חזרה את התמונה המפוענחת ל-thread הראשי ומושכת אותה לקנבס. תוכלו, כמובן, להנדס לאחור את המודל ולהחיל אותו על האפליקציות שלכם. היתרון העיקרי הוא שליטה רבה יותר, אבל (כמו תמיד) יש יותר קוד, יותר ניפוי באגים ויותר מקרים של קצה שכדאי להביא בחשבון בהשוואה לשימוש ברכיב <img>.

רוצה יותר שליטה בפענוח הקוד של תמונות? createImageBitmap() הוא החבר הכי טוב שלך. כדאי לך לנסות את Chrome 50 ולספר לנו איך הולך לך!