emptygif
Ngôn ngữ: Tiếng Việt

GIF trong suốt nhỏ nhất chỉ có 43 byte.

Toàn bộ nó chỉ có vậy. Chọn một byte bất kỳ để xem nó làm gì, rồi sao chép tệp, tải xuống, hotlink hoặc phục vụ nó từ mã của bạn.

GIF 43 byte được phóng to: một điểm ảnh trong suốt
0000
0010
0020
Tải 1×1.gif

R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==

Mỗi byte làm gì

GIF là một chuỗi các khối. Tệp này có bảy khối, và mỗi màu trên trang này thuộc về một trong số đó. Chọn một byte hoặc một khối để xem giải thích. Số được lưu theo little-endian: byte thấp đứng trước, nên 01 00 nghĩa là 1.

ByteTrườngÝ nghĩa
Header Cho bộ giải mã biết đây là GIF và phiên bản định dạng nào cần dùng.
47 49 46Chữ kýCác chữ cái ASCII “GIF”. Mọi tệp GIF đều bắt đầu bằng chúng.
38 39 61Phiên bản“89a”. Cần 89a để có độ trong suốt; 87a không có phần mở rộng điều khiển đồ họa.
Mô tả màn hình logic Kích thước của canvas và cách thiết lập bảng màu của nó.
01 00Chiều rộng canvas1 px.
01 00Chiều cao canvas1 px.
80Cờ đóng góiBốn thiết lập được gói gọn trong một byte. Bit cao nhất cho biết theo sau là bảng màu toàn cục; ba bit cuối cho biết kích thước của nó.
00Chỉ số màu nềnMục 0 của bảng màu. Trình duyệt bỏ qua nó và hiển thị những gì nằm phía sau ảnh.
00Tỷ lệ khung hình điểm ảnh0 nghĩa là điểm ảnh vuông, không hiệu chỉnh.
Bảng màu toàn cục Bảng màu. Điểm ảnh lưu chỉ số trỏ vào danh sách này thay vì lưu màu.
FF FF FFMục bảng màuĐỏ, lục và lam, mỗi màu một byte: #ffffff. Hai mục là bảng màu nhỏ nhất mà GIF có thể có.
00 00 00Mục bảng màuĐỏ, lục và lam, mỗi màu một byte: #000000. Hai mục là bảng màu nhỏ nhất mà GIF có thể có.
Phần mở rộng điều khiển đồ họa Khối tùy chọn được thêm vào từ GIF89a. Ở đây nó làm mục 0 của bảng màu trở nên trong suốt.
21Byte mở đầu phần mở rộng0x21 (“!”) báo hiệu một khối mở rộng.
F9Nhãn điều khiển đồ họa0xF9 cho biết phần mở rộng này là phần mở rộng điều khiển đồ họa.
04Kích thước khốiTheo sau là 4 byte thiết lập.
01Cờ đóng góiBit thấp nhất là cờ trong suốt. Cờ đang bật, nên chỉ số trong suốt bên dưới được sử dụng.
00 00Độ trễ0 phần trăm giây. Chỉ có ý nghĩa với ảnh động.
00Chỉ số màu trong suốtMục 0 của bảng màu được vẽ hoàn toàn trong suốt.
00Byte kết thúc khốiMột khối con có độ dài bằng 0, dùng để đóng khối.
Mô tả ảnh Vị trí của ảnh trên canvas và kích thước của nó.
2CByte phân tách ảnh0x2C (“,”) bắt đầu một ảnh.
00 00TráiẢnh bắt đầu cách mép trái của canvas 0 px.
00 00TrênẢnh bắt đầu cách mép trên của canvas 0 px.
01 00Chiều rộng ảnh1 px.
01 00Chiều cao ảnh1 px.
00Cờ đóng góiKhông có bảng màu cục bộ, không xen kẽ. Ảnh dùng bảng màu toàn cục.
Dữ liệu ảnh Các điểm ảnh, được nén bằng LZW và chia thành các khối con tối đa 255 byte.
02Kích thước mã LZW tối thiểu2, nên các mã nén bắt đầu với độ rộng 3 bit.
02Kích thước khối conTheo sau là 2 byte dữ liệu nén.
44 01Điểm ảnh đã nénCác mã LZW được xếp từ bit thấp nhất trở lên. Xem cách chúng được giải mã ở bên dưới.
00Byte kết thúc khốiMột khối con có độ dài bằng 0, dùng để đóng khối.
Trailer Một byte đánh dấu điểm kết thúc tệp.
3BTrailer0x3B (“;”) kết thúc tệp.

Bên trong các byte đóng gói

Mỗi byte trong ba byte này chứa vài thiết lập nhỏ. Bit 7 nằm ngoài cùng bên trái.

Mô tả màn hình logic 0x80
1Có bảng màu toàn cục
000Độ phân giải màu
0Bảng màu sắp theo mức quan trọng
000Kích thước bảng: 2^(n+1) mục
Phần mở rộng điều khiển đồ họa 0x01
000Dành riêng
000Phương thức xử lý
0Chờ người dùng nhập
1Bật trong suốt
Mô tả ảnh 0x00
0Có bảng màu cục bộ
0Xen kẽ
0Bảng màu sắp theo mức quan trọng
00Dành riêng
000Kích thước bảng cục bộ

Hai byte chứa một điểm ảnh như thế nào

Với kích thước mã tối thiểu là 2, bộ giải mã đọc các mã 3 bit. Mã 4 xóa bảng, mã 5 kết thúc ảnh, và các mã từ 0 đến 3 là các mục trong bảng màu. Hai byte 44 01 được đọc từ bit thấp nhất trở lên:

0x44 010001000x01 00000001

  1. 001100 = 4Xóa: bắt đầu với bảng mới
  2. 000000 = 0Điểm ảnh: mục 0 của bảng màu
  3. 101101 = 5Kết thúc ảnh
  4. 0000000 Các bit đệm không dùng

Ảnh lớn hơn cũng dùng cùng mẹo đó: mỗi mã mới đại diện cho một dải dài hơn mã trước một điểm ảnh, nên một GIF trong suốt 1000×1000 chỉ tốn 1.743 byte.

Có thể nhỏ hơn không?

Có, nếu bỏ đi những phần mà bộ giải mã chấp nhận bị thiếu. Chúng tôi đưa từng biến thể vào ba engine trình duyệt và Pillow, rồi ghi lại những gì chúng vẽ ra.

Kích thướcBiến thểChromiumFirefoxWebKitPillow
43Tệp chuẩn trên trang này.Trong suốtTrong suốtTrong suốtTrong suốt
42Không có byte trailer. Dù sao bộ giải mã cũng dừng ở cuối dữ liệu.Trong suốtTrong suốtTrong suốtTrong suốt
37Hoàn toàn không có bảng màu. Vẫn hợp lệ: đặc tả cho phép bộ giải mã dùng bảng màu riêng, và dù sao chỉ số 0 cũng là trong suốt.Trong suốtTrong suốtTrong suốtTrong suốt
36Không có bảng màu và không có trailer.Trong suốtTrong suốtTrong suốtTrong suốt
35Không có khối trong suốt: điểm ảnh được vẽ bằng màu 0 của bảng màu, tức màu trắng.TrắngTrắngTrắngTrắng
35Định dạng năm 1987. Nó không có cách nào đánh dấu một màu là trong suốt.TrắngTrắngTrắngTrắng
34Có khối trong suốt nhưng không có điểm ảnh nén.Trong suốtTrong suốtTrong suốtLỗi
33Giống trên nhưng không có trailer.Trong suốtTrong suốtTrong suốtLỗi
29Không có bảng màu và không có độ trong suốt. Mỗi engine tự chọn màu.ĐenTrắngTrong suốtĐen
26Một ảnh hoàn toàn không có dữ liệu nén.Trong suốtTrong suốtTrong suốtLỗi
14Chỉ có header, kích thước canvas và trailer. Không có ảnh nào bên trong.Trong suốtLỗiTrong suốtLỗi

Hãy dùng bản 43 byte khi nó phải chạy ở mọi nơi. Bản 37 byte vẫn là GIF hợp lệ và hiển thị trong suốt trên mọi engine chúng tôi đã thử. Nhỏ hơn nữa thì bạn phải trông vào sự dễ dãi của bộ giải mã, và tệp 29 byte cho thấy các engine bất đồng ra sao.

Kiểm tra ngày 23 tháng 9, 2026 với Chromium 153.0.8010.12, Firefox 155.0, WebKit 26.6, Pillow 12.2.0.

Tạo ở mọi kích thước

Trong suốt hoặc một màu đặc, từ 1×1 đến 65535×65535. Ảnh được tạo ngay trong trình duyệt; không có gì được tải lên.

Kích thước phổ biến

1×1 · 43 byte

Tải GIF

Phục vụ từ stack của bạn

173 đoạn mã chạy được ngay. Chọn cái của bạn: mỗi đoạn trả về phản hồi image/gif ở đường dẫn bạn chọn. Nếu bạn đã đổi kích thước hoặc màu ở trên, các đoạn mã sẽ dùng GIF đó.

Elixir, Erlang & Gleam

Express JavaScript

Cài đặt
npm i express
Tệp
server.mjs
Chạy
node server.mjs
import express from 'express';

const GIF = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', 'base64');

const app = express();

app.get('/pixel.gif', (req, res) => {
  res.set('Cache-Control', 'no-store');
  res.type('gif').send(GIF);
});

app.listen(8080);

Chúng tôi đã chạy đoạn mã này và so sánh các byte nó trả về. Mở trang

Dùng để làm gì

  • Tracking pixel và beacon: máy chủ ghi lại yêu cầu và trả về ảnh hợp lệ nhỏ nhất.
  • Placeholder cho ảnh lazy-load, để thẻ img hợp lệ trước khi nguồn ảnh thật được tải.
  • Khoảng đệm kích thước cố định trong email HTML, nơi CSS được hỗ trợ chắp vá.
  • Kiểm thử và mock cần một ảnh thật mà không phải kèm theo tệp ảnh.

Tracking pixel kém tin cậy hơn vẻ ngoài

Khi bật Bảo vệ quyền riêng tư trong Mail, Apple Mail tải trước ảnh từ xa qua một proxy, nên một lượt “mở” có thể chưa từng là của người thật. Gmail cũng tải ảnh qua proxy riêng và cache lại. Nhiều ứng dụng email chặn ảnh từ xa theo mặc định. Với phân tích trang, navigator.sendBeacon() hoặc phản hồi 204 No Content thường phù hợp hơn một ảnh.

Câu hỏi

Tại sao gọi là rỗng khi nó có một điểm ảnh?
Một GIF phải có ít nhất một điểm ảnh. Tệp này là 1×1 và màu duy nhất của nó được đánh dấu trong suốt, nên không có gì hiển thị.
Tệp 43 byte có hợp lệ không?
Có. Nó tuân thủ chính xác đặc tả GIF89a, và mọi engine trong bảng trên đều vẽ nó trong suốt.
Tại sao dùng GIF mà không phải PNG hay WebP?
Nó nhỏ hơn một PNG trong suốt tối giản, và mọi trình duyệt, ứng dụng email và thư viện ảnh trong 35 năm qua đều đọc được.
Nên dùng data URI hay tệp?
Data URI giúp bớt một yêu cầu, hợp với placeholder và CSS. Cần dùng tệp hoặc endpoint khi chính yêu cầu mới là mục đích, như với tracking pixel.
Nên gửi Content-Type nào?
image/gif. Thêm Cache-Control: no-store nếu mọi yêu cầu đều phải tới được máy chủ của bạn.