Định dạng hình ảnh: GIF

Mặc dù không đặc biệt hữu ích trên web hiện đại, nhưng GIF (Định dạng trao đổi đồ hoạ) cung cấp giới thiệu chắc chắn về các khái niệm cốt lõi về mã hoá hình ảnh.

Bạn có thể xem GIF là một trình bao bọc cho dữ liệu hình ảnh. Lớp này có một khung nhìn (được gọi là "màn hình logic") dùng để vẽ các khung dữ liệu hình ảnh riêng lẻ, gần giống với các lớp trong tài liệu Photoshop. Đó là cách GIF hỗ trợ ảnh động giống như cuốn sách lật: một khung hình duy nhất được vẽ trên màn hình logic, sau đó được thay thế bằng một khung khác rồi một khung khác. Tất nhiên, sự khác biệt này không quan trọng khi chúng ta xử lý GIF tĩnh, bao gồm một khung duy nhất được vẽ lên màn hình logic.

Nếu bạn tò mò muốn biết, GIF sử dụng phương thức nén dữ liệu không tổn hao. Đây là một biến thể của thuật toán "Lempel–Ziv–Welch". Thông tin chi tiết hơn về cách thức hoạt động của thuật toán này không cần chúng ta tìm hiểu, nhưng ở cấp độ cao: nó hoạt động hơi giống với JavaScript "Làm xấu", trong đó các chuỗi ký tự lặp lại trong tệp được lưu vào một loại từ điển nội bộ, để các chuỗi này có thể được tham chiếu thay vì lặp lại mỗi khi chúng xuất hiện.

Trực quan hoá tệp tham chiếu ảnh GIF bằng cách sử dụng lưới 4 x 4.

Dù sao thì thuật toán cũng không đơn giản như vẽ từng con số. Trình phân tích cú pháp sẽ thực hiện lại các bước qua bảng mã màu đã tạo để tìm các chuỗi màu pixel lặp lại rồi tạo bảng mã thứ hai gồm các mã tham chiếu. Tuy nhiên, mọi dữ liệu hình ảnh sẽ không bị mất, chỉ cần sắp xếp và sắp xếp lại theo cách có thể đọc được mà không cần thay đổi cơ bản dữ liệu đó.

Mặc dù về mặt kỹ thuật GIF sử dụng tính năng nén không tổn hao về mặt kỹ thuật, nhưng có một hạn chế lớn ảnh hưởng nghiêm trọng đến chất lượng hình ảnh: việc lưu hình ảnh dưới dạng GIF sẽ luôn làm giảm độ trung thực, trừ phi hình ảnh đã sử dụng 256 màu trở xuống.

Mỗi khung được vẽ vào màn hình logic của GIF chỉ có thể chứa tối đa 256 màu. GIF cũng hỗ trợ "độ trong suốt của chỉ mục", trong đó pixel trong suốt sẽ tham chiếu chỉ mục của một "màu" trong suốt trong bảng màu.

Việc giảm một khoảng giá trị thành một tập hợp giá trị đầu ra nhỏ hơn và gần đúng được gọi là lượng tử hoá. Đây là thuật ngữ bạn sẽ thấy rất nhiều khi tìm hiểu về mã hoá hình ảnh. Kết quả của việc định lượng bảng màu này thường rõ ràng:

Ví dụ về gif tĩnh

Để hiểu rõ hơn về quy trình này, hãy xem xét lưới hình ảnh đường quét mà bạn có thể tạo lại trong phần mô tả của tôi.

3 hộp màu xanh dương nằm ngang, theo sau là 1 hộp màu đỏ

Lần này, hãy thêm một chút chi tiết vào hình ảnh gốc đó: thêm một vài pixel, một trong số đó có màu xanh lam đậm hơn một chút:

Các hộp ngang màu xanh dương đến đỏ được chia thành 2 x 4, trong đó một hộp màu xanh dương được tô bóng đậm hơn các hộp khác.

Nếu không có bất kỳ sự nén nào, bạn có thể mô tả lưới này như sau:

Hàng một, cột một là #0000FF. Hàng một, cột hai là #0000FF. Hàng một, cột ba là #0000FF. Hàng một, cột bốn là #FF0000. Hàng hai, cột một là #0000FF. Hàng hai, cột hai là #000085. Hàng hai, cột ba là #0000FF. Hàng hai, cột bốn là #FF0000.

Khi sử dụng chức năng gần giống với tính năng nén dữ liệu không tổn hao và lập chỉ mục màu của GIF, bạn có thể mô tả chức năng này như sau:

A: #0000FF, B: #FF0000, C: #000085. Hàng một, các cột từ 1 đến 3 là A. Hàng một, cột bốn là B. Hàng hai, cột một là A. Hàng hai, cột hai là C. Hàng hai, cột ba là A. Hàng hai, cột bốn là B.

Bạn có thể thu gọn nội dung mô tả theo từng pixel vào một vài vị trí (“các cột từ 1 đến 3 là...”) và lưu một vài ký tự bằng cách xác định các màu lặp lại trong từ điển, theo loại màu, ở phía trước. Không có gì thay đổi về độ chân thực hình ảnh. Thông tin đã được nén mà không bị mất.

Các hộp nằm ngang từ màu xanh dương sang màu đỏ, có một pixel tối duy nhất có kích thước 2x2.

Tuy nhiên, như bạn có thể thấy, một pixel màu xanh dương đậm đang có tác động quá lớn đến kích thước mã hoá của chúng ta. Nếu tôi giới hạn bản thân trong một bảng màu lượng tử, thì con số này có thể được giảm nhiều hơn nữa:

A: #0000FF, B: #FF0000. Hàng một, các cột từ 1 đến 3 là A. Hàng một, cột bốn là B. Hàng hai, các cột từ 1 đến 3 là A. Hàng hai, cột bốn là B.

Kết quả cuối cùng không may là các byte đã lưu đó bị mất độ hoàn hảo của điểm ảnh.

Các hộp ngang màu xanh dương đến đỏ đồng nhất.

Tất nhiên, công cụ kết xuất bạn không biết điều đó—chi tiết của pixel màu xanh dương đậm hơn không nằm trong cách tôi mã hoá hình ảnh nguồn. Bạn đã kết xuất hình ảnh chính xác như tôi mã hoá, dựa trên hiểu biết chung của chúng ta về các màu hiện có.

Giờ đây, trong ví dụ phóng đại này, việc giảm ba màu xuống còn hai sẽ tạo ra sự khác biệt rõ ràng về chất lượng. Trên một hình ảnh lớn hơn và chi tiết hơn, hiệu ứng có thể không đáng chú ý, nhưng vẫn hiển thị.

Khi được mã hoá dưới dạng GIF, các màu chuyển tiếp tinh tế như bóng sẽ trở nên lem, với các pixel riêng lẻ nổi bật so với môi trường xung quanh:

Những bông hoa màu hồng trên nền xanh lục.

Trong thực tế, sự kết hợp giữa chức năng nén không mất dữ liệu và lượng tử bảng màu đồng nghĩa với việc GIF không còn hữu ích trong quá trình phát triển web hiện đại. Nén dữ liệu không tổn hao không đủ để giảm kích thước tệp và bảng màu giảm đồng nghĩa với việc chất lượng sẽ giảm rõ rệt.

Cuối cùng, GIF chỉ là một định dạng hiệu quả để mã hoá những hình ảnh đơn giản vốn đã sử dụng bảng màu hạn chế, các cạnh cứng thay vì khử răng cưa, và màu đồng nhất thay vì chuyển màu. Tất cả các trường hợp sử dụng đều được các định dạng khác phân phát hiệu quả hơn nhiều. Định dạng PNG nhỏ hơn và nổi bật hơn thường là lựa chọn tốt hơn cho hình ảnh đường quét, mặc dù cả hai đều kém hơn SVG về mặt kích thước tệp và độ trung thực hình ảnh đối với các trường hợp sử dụng như biểu tượng hoặc nghệ thuật đường kẻ, nơi vectơ toả sáng. Trường hợp sử dụng hiện đại phổ biến nhất cho GIF là ảnh động, nhưng có nhiều định dạng video hiện đại hiệu quả và dễ tiếp cận hơn để phục vụ mục đích đó.