การถอดรหัสรูปภาพเพื่อใช้กับ 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 ซึ่งจะดาวน์โหลดและถอดรหัสรูปภาพดังกล่าวเมื่อมีโอกาส จากนั้นจะโอนกลับไปที่ชุดข้อความหลักเพื่อวาดลงในผืนผ้าใบ

โค้ดสําหรับการดำเนินการนี้อาจมีลักษณะดังนี้
// 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 แล้วบอกให้เราทราบถึงประสบการณ์การใช้งานของคุณ