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

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

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

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