ในการพัฒนาแอปพลิเคชันเว็บสมัยใหม่อย่าง Look Scanned การเพิ่มประสิทธิภาพเป็นสิ่งที่สำคัญที่สุด โดยเฉพาะในส่วนของการประมวลผลภาพ แม้ว่าอินเทอร์เฟซ ImageBitmap จะยังไม่เป็นที่แพร่หลาย แต่เป็นเครื่องมือที่ทรงประสิทธิภาพในการเพิ่มความเร็วในการทำงาน บทความนี้จะแนะนำคุณสมบัติหลักของ ImageBitmap ข้อดีต่างๆ และประสบการณ์การนำไปใช้งานจริงที่ Look Scanned

ImageBitmap คืออะไร?

ImageBitmap คืออินเทอร์เฟซ HTML5 ที่ถูกออกแบบมาเพื่อการประมวลผลภาพที่มีประสิทธิภาพสูง จุดเด่นสำคัญคือความสามารถในการถอดรหัสและประมวลผลภาพนอกเธรดหลัก ซึ่งช่วยลดภาระการเรนเดอร์และเพิ่มความเร็วในการตอบสนองของแอปพลิเคชัน เมื่อสร้างออบเจกต์ ImageBitmap แล้ว สามารถใช้งานได้ทันทีในการเรนเดอร์ผ่าน Canvas 2D หรือ WebGL ทำให้เหมาะอย่างยิ่งสำหรับแอปพลิเคชันที่ต้องจัดการภาพจำนวนมาก

ทำไมเราจึงเลือก ImageBitmap?

แต่เดิม Look Scanned ใช้ Blob ในการส่งข้อมูลภาพระหว่างฟังก์ชันประมวลผล แต่ Blob จำเป็นต้องเข้าและถอดรหัสทุกครั้งที่ใช้งาน ซึ่งส่งผลให้ประสิทธิภาพลดลง ในทางกลับกัน ImageBitmap สามารถเข้าถึงข้อมูลภาพได้โดยตรง ตัดขั้นตอนที่ไม่จำเป็นออกไป ทำให้การเรนเดอร์เร็วขึ้นอย่างเห็นได้ชัด

รายละเอียดการนำไปใช้

เนื่องจากต้องรักษาความเข้ากันได้กับเบราว์เซอร์รุ่นเก่า การเปลี่ยนไปใช้ ImageBitmap ทั้งหมดจึงไม่ใช่ทางเลือกที่เป็นไปได้ เราจึงพัฒนาวิธีแบบผสมผสานเพื่อให้ใช้งานได้กับเบราว์เซอร์ที่หลากหลาย สามารถดูรายละเอียดการรองรับได้ที่ caniuse.com นอกจากนี้ เนื่องจาก Safari มีข้อจำกัดเกี่ยวกับ Canvas เราจึงใช้ WebAssembly (WASM) ในการประมวลผลภาพ ซึ่งต้องใช้ Blob เป็นข้อมูลนำเข้า

จากปัจจัยข้างต้น เราได้พัฒนาโซลูชันแบบผสมที่รองรับทั้ง Blob และ ImageBitmap โดยมีรายละเอียดการใช้งานที่สำคัญดังนี้:

การโหลดและถอดรหัสภาพ

async function loadImage(url): Promise<ImageBitmap | Blob> {
  const response = await fetch(url);
  const blob = await response.blob();
  if (window.createImageBitmap) {
    return createImageBitmap(blob);
  }
  // ใช้ Blob เป็นทางเลือกสำรอง
  return blob;
}

การทำงานร่วมกับ WebAssembly

สำหรับการประมวลผลขั้นสูง เราส่ง Blob ไปยังโมดูล WASM เพื่อให้แอปทำงานได้บนเบราว์เซอร์ที่ไม่รองรับ ImageBitmap โดยเราจะเรนเดอร์ภาพลงบน Canvas ก่อน แล้วจึงใช้ canvas.toBlob สร้างออบเจกต์ Blob ที่ต้องการ

ระบบเรนเดอร์สำรอง

async function renderImage(canvas, imageUrl) {
  const ctx = canvas.getContext("2d");
  const image = await loadImage(imageUrl);
  if (image instanceof ImageBitmap) {
    ctx.drawImage(image, 0, 0);
  } else {
    const img = new Image();
    img.src = URL.createObjectURL(image);
    img.onload = () => ctx.drawImage(img, 0, 0);
  }
}

ผลลัพธ์ที่ได้

การนำ ImageBitmap มาใช้ช่วยลดเวลาประมวลผลภาพใน Look Scanned จาก 50 มิลลิวินาทีเหลือเพียง 20 มิลลิวินาทีต่อภาพ การปรับปรุงนี้เห็นผลชัดเจนโดยเฉพาะเมื่อประมวลผลเอกสารที่สแกน ทำให้ผู้ใช้งานได้รับประสบการณ์ที่ราบรื่นและรวดเร็วยิ่งขึ้น

สิ่งที่ค้นพบ

ระหว่างการพัฒนา เราพบข้อสังเกตที่น่าสนใจ: การสร้างสำเนาใหม่ของ ImageBitmap ก่อนส่งไปยัง Web Worker ให้ประสิทธิภาพดีกว่าการส่งออบเจกต์ต้นฉบับโดยตรง ซึ่งอาจเป็นผลมาจากการเพิ่มประสิทธิภาพภายในของเบราว์เซอร์สำหรับออบเจกต์ที่สามารถโอนย้ายได้

การรองรับของเบราว์เซอร์

ปัจจุบัน ImageBitmap ได้รับการรองรับอย่างกว้างขวางในเบราว์เซอร์หลักทุกตัว รวมถึงเวอร์ชันล่าสุดของ Chrome, Firefox, Edge และ Safari ดูรายละเอียดเพิ่มเติมเกี่ยวกับความเข้ากันได้ได้ที่เอกสาร createImageBitmap บน caniuse.com

สรุปและแนวโน้มในอนาคต

การนำ ImageBitmap มาใช้ใน Look Scanned ไม่เพียงช่วยเพิ่มประสิทธิภาพอย่างมาก แต่ยังเปิดทางให้สามารถถอดรหัสแบบอะซิงโครนัส เรนเดอร์ได้เร็วขึ้น และทำงานร่วมกับ Web Workers ได้ดียิ่งขึ้น แม้ว่าจะยังต้องคงการรองรับ Blob สำหรับเบราว์เซอร์รุ่นเก่า แต่การทยอยเปลี่ยนไปใช้ ImageBitmap จะยังคงสร้างประโยชน์สำคัญในระยะยาว

ลองสัมผัสประสิทธิภาพที่เพิ่มขึ้นได้ที่ Look Scanned!