Chrome รองรับ createImageBitmap() ใน Chrome 50

การถอดรหัสรูปภาพเพื่อใช้กับ Canvas นั้นพบได้ทั่วไป ไม่ว่าจะเป็นการอนุญาตให้ผู้ใช้ปรับแต่งรูปโปรไฟล์ ครอบตัดรูปภาพ หรือเพียงแค่ซูมเข้ารูปภาพ ปัญหาในการถอดรหัสรูปภาพคืออาจใช้ CPU มาก ซึ่งบางครั้งอาจทำให้ภาพกระตุกหรือเป็นตารางกริด ตั้งแต่ Chrome เวอร์ชัน 50 (และใน Firefox เวอร์ชัน 42 ขึ้นไป) คุณจะมีตัวเลือกอื่นอีก นั่นคือ createImageBitmap() ซึ่งช่วยให้คุณถอดรหัสรูปภาพในเบื้องหลังและเข้าถึง ImageBitmap Primitive ใหม่ได้ ซึ่งคุณสามารถวาดลงใน Canvas ได้เช่นเดียวกับองค์ประกอบ <img>, Canvas อื่น หรือวิดีโอ

การวาดจุดด้วย createImageBitmap()

สมมติว่าคุณดาวน์โหลดรูปภาพ Blob ด้วย fetch() (หรือ XHR) และต้องการวาดรูปภาพนั้นลงใน Canvas หากไม่มี createImageBitmap() คุณจะต้องสร้างองค์ประกอบรูปภาพและ URL ของ Blob เพื่อเปลี่ยนรูปภาพให้อยู่ในรูปแบบที่คุณใช้ได้ ซึ่งจะช่วยให้คุณวาดภาพได้โดยตรงมากขึ้น

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

แนวทางนี้จะใช้ได้กับรูปภาพที่จัดเก็บเป็น Blob ใน IndexedDB ด้วย ซึ่งทำให้ Blob เป็นรูปแบบกลางที่สะดวก บังเอิญว่า Chrome 50 ยังรองรับเมธอด .toBlob() ในองค์ประกอบ Canvas ด้วย ซึ่งหมายความว่าคุณจะสร้าง Blob จากองค์ประกอบ Canvas ได้ เป็นต้น

การใช้ createImageBitmap() ในเว็บเวิร์กเกอร์

ฟีเจอร์ที่ยอดเยี่ยมอย่างหนึ่งของ createImageBitmap() คือมีให้บริการในอุปกรณ์ที่ทำงานด้วย ซึ่งหมายความว่าตอนนี้คุณถอดรหัสรูปภาพได้ทุกที่ที่ต้องการ หากมีรูปภาพจำนวนมากที่ต้องถอดรหัสซึ่งคุณคิดว่าไม่จำเป็น คุณจะต้องส่ง URL ของรูปภาพเหล่านั้นไปยัง Web Worker ซึ่งจะดาวน์โหลดและถอดรหัสรูปภาพดังกล่าวเมื่อมีโอกาส จากนั้นจะโอนกลับไปที่ชุดข้อความหลักเพื่อวาดลงในผืนผ้าใบ

การรับส่งข้อมูลด้วย createImageBitmap และ Web Worker

โค้ดสําหรับการดำเนินการนี้อาจมีลักษณะดังนี้

// 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() ในเธรดหลัก ระบบจะถอดรหัสในเธรดนั้น อย่างไรก็ตาม เรามีแผนที่จะให้ Chrome ทำการถอดรหัสในอีกเธรดโดยอัตโนมัติ ซึ่งจะช่วยลดความหนักหน่วงของเธรดหลัก อย่างไรก็ตาม ในระหว่างนี้ คุณควรระมัดระวังเกี่ยวกับการถอดรหัสในชุดข้อความหลัก เนื่องจากเป็นงานที่ต้องใช้ทรัพยากรมากซึ่งอาจบล็อกงานอื่นๆ ที่สำคัญ เช่น JavaScript, การคํานวณสไตล์, เลย์เอาต์, การวาดภาพ หรือการจัดวาง

ไลบรารีตัวช่วย

เราได้สร้างไลบรารีตัวช่วยที่จัดการการถอดรหัสในเวิร์กเกอร์ และส่งภาพที่มีการถอดรหัสกลับไปยังเธรดหลัก และวาดภาพนั้นลงในผืนผ้าใบ เพื่อให้ชีวิตง่ายขึ้น แน่นอนว่าคุณทำวิศวกรรมย้อนกลับและนำโมเดลไปใช้กับแอปของคุณเองได้ ประโยชน์หลักคือการควบคุมได้มากขึ้น แต่ (ตามปกติ) การใช้วิธีนี้จะมีโค้ดมากขึ้น มีการแก้ไขข้อบกพร่องมากขึ้น และกรณีขอบเขตที่ควรพิจารณามากกว่าการใช้องค์ประกอบ <img>

หากต้องการควบคุมการถอดรหัสรูปภาพได้มากขึ้น createImageBitmap() คือเพื่อนใหม่ของคุณ ลองใช้ฟีเจอร์นี้ใน Chrome 50 แล้วบอกให้เราทราบถึงประสบการณ์การใช้งานของคุณ