JPEG
lộ nhiều nhấtMột file JPEG cất siêu dữ liệu trong các segment APPn, nằm giữa phần đầu file và dữ liệu ảnh. Đây là thứ nằm ở đâu, và PicScrub làm gì với từng phần.
Những gì bị xóa
- EXIF tọa độ GPS, hãng và model máy ảnh, ngày giờ chụp, thông số phơi sáng
- XMP lịch sử chỉnh sửa, phần mềm đã dùng, điểm đánh giá
- IPTC / Photoshop chú thích, thông tin ghi công, từ khóa
- Chú thích và ảnh thu nhỏ nhúng sẵn một bản sao tí hon của ảnh gốc, có thể sống sót qua cả những lần bạn cắt cúp và chỉnh sửa
Những gì bạn có thể giữ
- Dữ liệu ảnh luôn nguyên vẹn, không bao giờ bị mã hóa lại
- Hồ sơ màu ICC tùy chọn, để màu sắc không bị lệch
- Hướng ảnh tùy chọn, để ảnh dọc không bị nằm ngang
- Thông báo bản quyền tùy chọn, cho ai muốn được ghi công mà không lộ tọa độ
Nhìn tổng quan cấu trúc file
Nếu từng mở một file JPEG bằng trình soạn thảo hex, bạn sẽ thấy nó gồm nhiều segment ngăn cách bởi các marker. Mọi marker đều bắt đầu bằng 0xFF, theo sau là một byte cho biết đó là loại segment nào. Thiết kế này khiến JPEG khá dễ đọc: chỉ cần dò tìm các byte FF rồi xem ngay sau nó là gì.
Điều đáng nói về quyền riêng tư là toàn bộ siêu dữ liệu (EXIF, GPS, ngày giờ chụp) đều nằm trong các segment đó, hoàn toàn tách khỏi dữ liệu ảnh thật. Nhờ vậy chúng tôi xóa được siêu dữ liệu mà không đụng tới pixel và cũng không phải nén lại thứ gì.
Cấu trúc file JPEG
Ví dụ phần đầu file JPEG
| Offset | Hex | ASCII | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | FFD8FFE000104A464946000101000048 | ......JFIF.....H | |||||||||||||||
| 0010 | 00480000FFE112344578696600000000 | .H.....4Exif.. | |||||||||||||||
Cấu trúc của một marker
FF xx:Marker (xx cho biết loại)LL LL:Độ dài (2 byte, big-endian, tính cả chính nó)Data...:Dữ liệu của segment (độ dài trừ 2 byte)
Bảng tra đầy đủ các marker JPEG
| Marker | Tên | Mô tả |
|---|---|---|
| FF D8 | SOI | Bắt đầu ảnh |
| FF D9 | EOI | Kết thúc ảnh |
| FF C0 | SOF0 | Bắt đầu khung ảnh (Baseline DCT) |
| FF C2 | SOF2 | Bắt đầu khung ảnh (Progressive DCT) |
| FF C4 | DHT | Khai báo bảng Huffman |
| FF DB | DQT | Khai báo bảng lượng tử hóa |
| FF DD | DRI | Khai báo khoảng restart |
| FF DA | SOS | Bắt đầu quét (dữ liệu ảnh nằm ngay sau) |
| FF FE | COM | Chú thích (siêu dữ liệu) |
| FF E0 | APP0 | Marker JFIF |
| FF E1 | APP1 | Marker EXIF / XMP |
| FF E2 | APP2 | Hồ sơ ICC / MPF |
| FF ED | APP13 | IPTC / Photoshop |
| FF EE | APP14 | Chuyển đổi màu của Adobe |
Màu vàng = siêu dữ liệu (bị xóa), không tô màu = cấu trúc được giữ nguyên
JFIF và EXIF
Có một chuyện làm khá nhiều người bối rối: file JPEG thường chứa cùng lúc hai chuẩn siêu dữ liệu khác nhau. JFIF ra đời trước và lo những thứ cơ bản như độ phân giải. Sau đó máy ảnh bắt đầu ghi thêm dữ liệu EXIF với đủ thông tin chi tiết về lần chụp. Đa số file JPEG hiện nay có cả hai, nên bạn sẽ thấy cả marker APP0 lẫn APP1 ở gần đầu file.
APP0:JFIF
JPEG File Interchange Format. Thông tin ảnh ở mức cơ bản.
- • Số phiên bản
- • Mật độ điểm ảnh (DPI)
- • Tỉ lệ khung hình
- • Ảnh thu nhỏ (tùy chọn)
APP1:EXIF
Exchangeable Image File Format. Siêu dữ liệu của máy ảnh.
- • Hãng và model máy ảnh
- • Tọa độ GPS
- • Ngày giờ chụp
- • Thông số phơi sáng
Mổ xẻ các marker APP
Chuẩn JPEG dành riêng 16 marker "ứng dụng" (APP0 tới APP15) để các hãng muốn dùng sao thì dùng. Qua nhiều năm, mỗi tổ chức lại chiếm lấy một marker cho định dạng siêu dữ liệu của mình. Kết quả là một mớ hơi lộn xộn, nhưng ít ra là mớ lộn xộn có tài liệu đầy đủ.
Chỗ khó là cùng một marker lại có thể mang ý nghĩa khác nhau tùy nội dung. Chẳng hạn APP1 có thể là dữ liệu EXIF hoặc XMP, nên bạn phải nhìn vào chuỗi định danh bên trong mới biết mình đang đụng tới cái nào.
APP0 (0xFFE0):JFIF
Định danh: JFIF\0. Chứa phiên bản, đơn vị mật độ, mật độ X/Y và ảnh thu nhỏ nhúng kèm (tùy chọn). Nhìn chung giữ lại là an toàn.
APP1 (0xFFE1):EXIF
Định danh: Exif\0\0. Chứa nguyên một cấu trúc TIFF với các mục IFD cho thông tin máy ảnh, dữ liệu GPS, ngày giờ chụp, ảnh thu nhỏ và maker note. Đây là mối lo lớn nhất về quyền riêng tư.
APP1 (0xFFE1):XMP
Định danh: http://ns.adobe.com/xap/1.0/\0. Chuẩn siêu dữ liệu dựa trên XML do Adobe đưa ra. Có thể chứa lịch sử chỉnh sửa, thông tin phần mềm và dữ liệu EXIF mở rộng.
Các namespace XMP
xmp: http://ns.adobe.com/xap/1.0/xmpMM: http://ns.adobe.com/xap/1.0/mm/dc: http://purl.org/dc/elements/1.1/photoshop: http://ns.adobe.com/photoshop/1.0/tiff: http://ns.adobe.com/tiff/1.0/exif: http://ns.adobe.com/exif/1.0/APP1 (0xFFE1):Extended XMP
Định danh: http://ns.adobe.com/xmp/extension/\0. Dành cho dữ liệu XMP vượt quá 65KB, được chia ra nhiều segment APP1.
APP2 (0xFFE2):MPF
Định danh: MPF\0. Multi-Picture Format, dùng cho ảnh nổi và ảnh toàn cảnh.
APP2 (0xFFE2):Hồ sơ ICC
Định danh: ICC_PROFILE\0. Dữ liệu quản lý màu. Có thể bị cắt nhỏ ra nhiều marker APP2. Thường thì giữ lại là an toàn.
APP13 (0xFFED):IPTC/Photoshop
Định danh: Photoshop 3.0\0. Chứa dữ liệu IPTC-IIM với chú thích, từ khóa, bản quyền, thông tin người tạo. Có thể chứa thông tin tác giả.
APP14 (0xFFEE):Adobe
Định danh: Adobe\0. Chứa các cờ chuyển đổi màu (RGB/CMYK). Quan trọng để màu hiển thị đúng.
Cấu trúc EXIF
Đây là chỗ thú vị (và hơi kỳ lạ). Dữ liệu EXIF thực chất là một file TIFF tí hon nằm gọn bên trong file JPEG của bạn. Đúng vậy đấy. Nó có phần đầu riêng, thứ tự byte riêng, và dùng cấu trúc IFD (Image File Directory) của TIFF để lưu các thẻ.
Thứ đầu tiên bạn thấy ngay sau định danh "Exif" là một header TIFF, cho biết dữ liệu là little-endian (Intel, "II") hay big-endian (Motorola, "MM"). Đọc sai chỗ này thì mọi con số đều thành rác, nên đây luôn là thứ đầu tiên mà mọi bộ đọc kiểm tra.
Header TIFF (8 byte)
| Offset | Hex | ASCII | |||||||
|---|---|---|---|---|---|---|---|---|---|
| 0000 | 49492A0008000000 | II*..... | |||||||
II = Intel (little-endian), MM = Motorola (big-endian)
Cấu trúc một mục IFD (12 byte)
Những mục IFD đáng chú ý
0x010F:Make0x0110:Model0x0132:DateTime0x8769:ExifIFDPointer0x8825:GPSInfoIFDPointer0x927C:MakerNotePicScrub xử lý JPEG như thế nào
Cách làm khá đơn giản: chúng tôi đọc lần lượt từng marker trong file, giữ lại những marker cần thiết để hiển thị ảnh, và bỏ qua những marker chứa siêu dữ liệu. Vì không bao giờ đụng vào phần dữ liệu ảnh đã nén, chất lượng không suy giảm chút nào.
Mấu chốt là cấu trúc dựa trên marker của JPEG khiến việc này rất dễ. Chúng tôi không cần hiểu hệ số DCT hay bảng Huffman. Chỉ cần biết segment nào là siêu dữ liệu và segment nào thì không.
Kiểm tra phần đầu file
Xác nhận có marker SOI (FF D8) ở đầu file
Đọc các marker
Đọc lần lượt từng marker, lấy ra loại và độ dài
Nhận diện siêu dữ liệu
Kiểm tra định danh trong các segment APP (EXIF, XMP, IPTC, v.v.)
Chép có chọn lọc
Chép các segment không phải siêu dữ liệu sang file mới, bỏ qua phần còn lại
Những gì được giữ lại
- • Marker SOI/EOI (bắt buộc)
- • DQT (bảng lượng tử hóa)
- • SOF (phần đầu khung ảnh)
- • DHT (bảng Huffman)
- • SOS và dữ liệu quét (chính là ảnh)
- • Tùy chọn: hồ sơ màu ICC (có thể bật tắt)
Những gì bị xóa
- • APP1 EXIF (máy ảnh, GPS, ngày giờ chụp)
- • APP1 XMP (siêu dữ liệu chỉnh sửa)
- • APP13 IPTC (chú thích, tác giả)
- • Marker COM (chú thích)
- • Ảnh thu nhỏ trong EXIF
Bảng tra thẻ EXIF
Xét về quyền riêng tư, không phải thẻ EXIF nào cũng như nhau. Một số thẻ, chẳng hạn thông số phơi sáng, khá vô hại. Số khác, như số sê-ri hay tên chủ sở hữu, có thể chỉ đích danh bạn hoặc thiết bị của bạn. Đây là những thẻ mà chúng tôi xếp vào loại rủi ro cao:
| ID thẻ | Tên | Rủi ro riêng tư |
|---|---|---|
| 0x9003 | DateTimeOriginal | Cao |
| 0x9004 | DateTimeDigitized | Cao |
| 0x9010 | OffsetTime | Trung bình |
| 0x9286 | UserComment | Cao |
| 0x927C | MakerNote | Cao |
| 0xA420 | ImageUniqueID | Cao |
| 0xA430 | CameraOwnerName | Cao |
| 0xA431 | BodySerialNumber | Cao |
| 0xA434 | LensModel | Trung bình |
| 0xA435 | LensSerialNumber | Cao |
| 0xFDE8 | OwnerName | Cao |
| 0xFDE9 | SerialNumber | Cao |
Xem tất cả các thẻ thông số máy ảnh (không nhận dạng được bạn)
0x829A ExposureTime0x829D FNumber0x8822 ExposureProgram0x8827 ISOSpeedRatings0x9201 ShutterSpeedValue0x9202 ApertureValue0x9203 BrightnessValue0x9204 ExposureBiasValue0x9207 MeteringMode0x9208 LightSource0x9209 Flash0x920A FocalLength0xA001 ColorSpace0xA002 PixelXDimension0xA003 PixelYDimension0xA402 ExposureMode0xA403 WhiteBalance0xA405 FocalLengthIn35mmFilm0xA406 SceneCaptureTypeBảng tra thẻ GPS
Dữ liệu GPS nằm trong một sub-IFD riêng, được thẻ 0x8825 trong IFD chính trỏ tới. Nếu con trỏ đó tồn tại thì ảnh của bạn có dữ liệu vị trí. Điện thoại thông minh đời mới đặc biệt hăng hái trong việc nhúng thứ này, thường là đủ chính xác để chỉ ra bạn đứng đúng ở chỗ nào.
| ID thẻ | Tên | Mô tả |
|---|---|---|
| 0x0000 | GPSVersionID | Phiên bản thẻ GPS |
| 0x0001 | GPSLatitudeRef | Bắc hay Nam |
| 0x0002 | GPSLatitude | Độ, phút, giây |
| 0x0003 | GPSLongitudeRef | Đông hay Tây |
| 0x0004 | GPSLongitude | Độ, phút, giây |
| 0x0005 | GPSAltitudeRef | Trên hay dưới mực nước biển |
| 0x0006 | GPSAltitude | Tính bằng mét |
| 0x0007 | GPSTimeStamp | Giờ UTC |
| 0x001D | GPSDateStamp | Ngày UTC |
| 0x0012 | GPSMapDatum | Hệ quy chiếu trắc địa |
| 0x001B | GPSProcessingMethod | GPS/CELLID/WLAN/MANUAL |
| 0x001C | GPSAreaInformation | Tên địa điểm |
Bảng tra thẻ IPTC
IPTC vốn được thiết kế cho các hãng tin, để nhúng chú thích, thông tin ghi công và bản quyền vào ảnh. Nó nằm trong APP13 với định danh "Photoshop 3.0" (đúng vậy, Adobe đã tiếp nhận chuẩn này). Nếu bạn từng thêm thông tin bản quyền hay từ khóa trong Lightroom hoặc Photoshop, đây chính là nơi chúng nằm lại.
0x0250 By-line (tác giả)0x0255 By-line Title0x025A City0x025C Sub-location0x025F Province/State0x0265 Country Name0x0274 Copyright Notice0x0276 Contact0x0237 Date Created0x023C Time Created0x0278 Caption/Abstract0x0219 Keywords