Client-side image resizer with HTML canvas

สรุปของสัปดาห์นี้ ได้โจทย์นึงเป็นเรื่อง Resize รูปก่อน Upload ขึ้นเว็บ คล้ายๆ กับ Facebook ที่ย่อรูปก่อนที่จะโพสขึ้น

วิธีการที่ใช้คือ HTML Canvas โดยผ่าน js ชื่อ canvasResize ครับ

canvasResizecanvasResize – Javascript Canvas Resize Plugin. It can work both with jQuery and Zepto. It’s compatible with iOS6 and Android 2.3+

Embedly Powered

via Github

ตามตัวอย่างที่มากับ Source จะพบว่าใช้วิธีสร้าง Form object ลอยๆ ขึ้นมา แล้วแปลงรูปจาก Canvas เป็น BLOB ก่อนจะเอาขึ้น Server ผ่าน AJAX แต่ตอนหยิบมาใช้เองดันส่งยังไงก็ไม่ผ่านซักที ในเมื่อเวลามีน้อยก็แก้ตามวิธีที่พอหาได้เพราะต้องไปปรับ code เก่าในโจทย์ด้วย

หลักการทำงาน

  1. ตอน Upload รูปผ่าน canvasResize เสร็จ แทนที่จะแปลง BLOB เปลี่ยนเป็น Base64 แล้วส่งผ่าน Input type hidden แทน
  2. ช่วง Submit form เปลี่ยนจาก Replace input file เป็น Reset value ออกไปเลย ให้ฝั่ง Server อ่านจาก Input hidden แทน
  3. ฝั่ง Server เปลี่ยนแค่ตัวแปร $_FILES ให้เป็น Wrapper function แทน (return $_FILES หรือรูปที่เซฟจาก Base64)
  4. ใน Code เดิมต้องการแค่ 2 อย่างคือ Path เก็บไฟล์ กับ file type, ของ $_FILES มีอยู่แล้ว, ของ Base64 ต้องเซฟไฟล์ลง tmp ซักที่ก่อนเพื่อให้ได้ Path อันนี้ให้เป็นหน้าที่ของ Wrapper

ปลีกย่อย

  1. ตอนแปลง base64 เป็นไฟล์รูปใช้ imagecreatefromstring() เพื่อสร้างรูปใหม่แทนของเดิม เลี่ยง code แฝงมากับรูป
  2. ข้อจำกัดของ Canvas คือคุณภาพรูปขึ้นอยู่กับ Browser และ Device ที่ใช้งาน ขนาดบน PC รูปออกมาเทียบโปรแกรมย่อรูปไม่ติด แค่พอดูได้, ลองดูเพิ่มแบบขำๆ มีบางคนพยายาม Optimize canvas อยู่ อาจจะพัฒนาต่อได้อีก

สรุปว่าการย่อรูปผ่าน Canvas เหมาะกับการทำให้ผู้ใช้ Upload รูปได้ แบบไม่ต้องซีเรียสเรื่องขนาด ไม่ต้องผ่านโปรแกรมย่อรูปมาก่อน โดยคุณภาพอยู่ในระดับที่พอรับได้


So, what do you think ?