เมื่อแบ็กเอนด์รับการอัปโหลดรูปภาพจากผู้ใช้ มักมีปัญหาที่ติดมาด้วยแบบเงียบ ๆ

  • ใน JPEG อาจมีพิกัด GPS, ชื่อรุ่นอุปกรณ์, เวลาที่ถ่าย เก็บอยู่ใน EXIF
  • เมทาดาทาสีอย่าง ICC profile ก็อาจถูกเก็บและแจกจ่ายต่อไปทั้งอย่างนั้น
  • ถ้ามีทั้ง JPEG, PNG, GIF, WebP ปะปนกันเข้ามา pipeline ของการจัดเก็บ/CDN/การเรนเดอร์จะซับซ้อนขึ้น
  • แค่จัดการ EXIF orientation ผิด รูปก็อาจถูกบันทึกโดยหมุนไป 90°

smol-image-processor คือไมโครเซอร์วิสแบบหน้าที่เดียวที่จัดการปัญหาเหล่านี้แบบรวดเดียว

วิธีการทำงาน

เมื่ออัปโหลดรูปไปที่ POST /process ด้วย multipart/form-data จะได้ผลลัพธ์กลับมาเป็น WebP เสมอ
ใช้คุณสมบัติของพฤติกรรมการส่งออกเริ่มต้นของ Sharp ที่ทิ้งเมทาดาทาอย่าง source EXIF และ ICC profile ไปโดยตรง แต่สำหรับ EXIF orientation จะใช้ .rotate() กับพิกเซลก่อนลบเมทาดาทา เพื่อคงทิศทางของภาพไว้

ชั้นการป้องกันมีสองอย่าง

  • จำกัดจำนวนพิกเซล (MAX_PIXELS): แม้ขนาดไฟล์จะเล็ก แต่ถ้าถอดรหัสแล้วขยายเป็นภาพระดับหลายร้อยล้านพิกเซล ก็จะถูกบล็อกด้วย limitInputPixels ของ Sharp เพื่อป้องกันภาพแบบ decompression bomb
  • จำกัดจำนวนเฟรม (MAX_PAGES): ป้องกัน DoS ที่ทำให้หน่วยความจำและ CPU หมดจาก GIF/WebP แบบแอนิเมชันที่มีหลายร้อยถึงหลายพันเฟรม

GIF/WebP แบบแอนิเมชันจะถูกแปลงเป็น animated WebP โดยคงค่า frame delay และจำนวนรอบการลูปไว้
ส่วน alpha channel ของ PNG ก็ยังคงอยู่เหมือนเดิม

ใน response header จะมี width, height, size, สถานะว่าเป็น animated หรือไม่, และจำนวนหน้า ของภาพที่ประมวลผลแล้ว ทำให้สามารถบันทึกลง DB ได้ทันทีโดยไม่ต้องมีขั้นตอนดึงเมทาดาทาแยกต่างหาก

สแตก

  • Runtime: Bun, HTTP framework: Elysia
  • การประมวลผลภาพ: Sharp (wrapper ของ libvips)
  • มี Docker image ให้ใช้งาน (GHCR)

เริ่มต้นอย่างรวดเร็ว

docker run --rm -p 6701:6701 ghcr.io/levish0/smol-image-processor
curl -F file=@photo.jpg http://localhost:6701/process -o clean.webp

https://github.com/levish0/smol-image-processor

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น