0

Xử lý hình ảnh Client-Side: Chuyển đổi định dạng HEIC sang PNG không cần Server dùng Web Worker

Chào anh em Viblo!

Nếu anh em từng làm các dự án liên quan đến upload hình ảnh từ người dùng iOS, chắc chắn đã từng gặp phải định dạng HEIC (High Efficiency Image Container). Đây là định dạng mặc định của Apple giúp tiết kiệm dung lượng nhưng lại là "cơn ác mộng" đối với các trình duyệt web thông thường vì chúng không thể hiển thị trực tiếp.

Thông thường, giải pháp dễ nhất là đẩy file lên Server (S3, Node.js backend...) rồi dùng các thư viện như imagemagick hoặc sharp để convert sang PNG/JPEG. Tuy nhiên, cách làm này có 2 nhược điểm rất lớn:

  1. Tốn chi phí Server & Băng thông: Người dùng upload ảnh gốc vài MB, server xử lý liên tục sẽ rất dễ nghẽn và tốn tiền RAM/CPU.
  2. Vấn đề bảo mật (Privacy): Người dùng ngày nay rất ngại việc upload ảnh cá nhân, tài liệu riêng tư lên server của một bên thứ ba.

Vì vậy, trong bài viết này, mình muốn chia sẻ cách mình tối ưu luồng chuyển đổi HEIC sang PNG 100% ngay tại Client-Side (Trình duyệt) để giải quyết triệt để hai bài toán trên.


1. Kiến trúc xử lý Client-Side: Tại sao lại chọn giải pháp này?

Ý tưởng cốt lõi của mình là biến trình duyệt của người dùng thành một "cỗ máy xử lý". Khi người dùng thả một hoặc nhiều file HEIC vào trang web, quá trình giải mã (decode) và mã hóa lại (re-encode) sang PNG sẽ diễn ra hoàn toàn bằng Javascript.

  • Không có Server Backend xử lý ảnh: Server chỉ đóng vai trò phân phối các file tĩnh (HTML, CSS, JS). Việc này giúp chi phí vận hành hệ thống gần như bằng 0.
  • Bảo mật tuyệt đối: Do ảnh không bao giờ rời khỏi máy của người dùng, họ có thể yên tâm convert các bức ảnh nhạy cảm hoặc quan trọng mà không sợ bị lộ dữ liệu.

Để thực hiện việc này một cách mượt mà, mình sử dụng tổ hợp: Next.js (React) + thư viện giải mã HEIC (như libheif thông qua WebAssembly) + Web Worker.


2. Giải quyết bài toán UI/UX đóng băng trình duyệt (Main Thread)

Một vấn đề kỹ thuật lớn khi xử lý file nặng trên trình duyệt là Đóng băng giao diện (UI Blocking). Việc giải mã một file ảnh HEIC dung lượng lớn đòi hỏi tính toán logic rất nặng. Nếu chạy trực tiếp trên Main Thread của Javascript, trình duyệt của người dùng sẽ bị đơ (lag), các hiệu ứng Loading dạng xoay vòng sẽ bị khựng lại, tạo ra trải nghiệm cực kỳ tệ.

Giải pháp: Đẩy logic vào Web Worker

Để giải quyết, mình đã tách biệt hoàn toàn luồng xử lý:

  1. Main Thread chỉ nhận file từ thẻ <input> hoặc sự kiện Drag & Drop, sau đó hiển thị UI trạng thái.
  2. File ảnh (dưới dạng Blob hoặc ArrayBuffer) sẽ được chuyển (transfer) vào một Web Worker chạy ngầm ở một thread riêng biệt.
  3. Web Worker đảm nhận việc giải mã dữ liệu HEIC và đóng gói lại thành file PNG, sau đó gửi trả kết quả về Main Thread để kích hoạt lệnh tải xuống (Download).

Nhờ kiến trúc này, người dùng có thể convert hàng loạt ảnh cùng lúc mà giao diện web vẫn mượt mà, không có bất kỳ hiện tượng giật lag nào xảy ra.


3. Demo sản phẩm thực tế: HEIC to PNG Converter

Để hiện thực hóa và kiểm chứng giải pháp kỹ thuật này, mình đã xây dựng một công cụ hoàn chỉnh có tên là HEIC to PNG Converter tại địa chỉ: heictopng.org.

Tại công cụ này, mình đã áp dụng toàn bộ các tối ưu hóa kể trên:

  • Tốc độ vượt trội: Quá trình chuyển đổi diễn ra trong vài giây nhờ tận dụng tối đa phần cứng máy tính của chính người dùng.
  • Hỗ trợ xử lý hàng loạt (Batch Processing): Người dùng có thể kéo thả nhiều file cùng lúc, các Web Worker sẽ xử lý song song để tiết kiệm thời gian.
  • Hoàn toàn miễn phí và không giới hạn: Vì không tốn tài nguyên server cho việc xử lý ảnh, mình có thể mở cấu hình cho phép convert thoải mái mà không cần giới hạn tính năng hay bắt đăng nhập.

Anh em có thể truy cập vào heictopng.org dùng thử, sau đó bật Tab Network trong DevTools lên để kiểm tra xem có bất kỳ file ảnh nào bị upload lên server không nhé. Mọi thứ đều diễn ra hoàn toàn cục bộ trên máy của anh em!


KẾT LUẬN

Xu hướng chuyển dịch logic từ Server về Client-side (nhờ sự phát triển của cấu hình thiết bị phần cứng và WebAssembly/Web Worker) đang giúp các lập trình viên độc lập tiết kiệm được rất nhiều chi phí vận hành, đồng thời nâng cao tính bảo mật cho sản phẩm.

Hy vọng bài chia sẻ này sẽ gợi mở thêm cho anh em một hướng đi khi xử lý các bài toán về tệp tin và hình ảnh trên Web. Anh em có kinh nghiệm gì hay về tối ưu hóa Web Worker hoặc thư viện xử lý ảnh Client-side thì cùng thảo luận ở phần bình luận bên dưới nhé!

Cảm ơn anh em đã dành thời gian đọc bài!


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.