Saya melanjutkan dan mengulangi percobaan untuk melihat apakah saya bisa mengetahui apa yang sedang terjadi.
Prosedur
Saya menghasilkan gambar RGB 256-by-256 piksel acak menggunakan filter "Solid Noise" di GIMP (Filter> Render> Clouds> Solid Noise ...) menggunakan pengaturan default (ditunjukkan di bawah):
Dan hasilnya:
Lalu saya menyimpan gambar sebagai JPEG menggunakan pengaturan default:
Kemudian saya mentransfer gambar ke Windows dan membuka gambar dengan Windows Photo Viewer dengan mengklik kanan pada gambar di File Explorer dan memilih Preview dari menu. Lalu saya memutar gambar menggunakan tombol di bagian bawah, dan menyimpan gambar dengan menavigasi ke gambar berikutnya menggunakan tombol panah.
Untuk setiap tes di bawah ini saya mulai dengan salinan gambar asli, dan memutar (mengklik tombol putar) beberapa kali sebelum menyimpan. Berikut ini ukuran reslting ( ls -l -r
):
size in bytes last-modified date
VVVVV VVVVV
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:24 original.jpg
-rwxrwx--- 1 root vboxsf 23645 Nov 8 11:30 cw.jpg
-rwxrwx--- 1 root vboxsf 23636 Nov 8 11:30 cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:30 cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:27 cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:31 cw-cw-cw-cw-cw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:29 ccw.jpg
-rwxrwx--- 1 root vboxsf 23636 Nov 8 11:29 ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 23645 Nov 8 11:29 ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 6258 Nov 8 11:27 ccw-ccw-ccw-ccw.jpg
-rwxrwx--- 1 root vboxsf 23649 Nov 8 11:30 ccw-ccw-ccw-ccw-ccw.jpg
Pengamatan langsung
- Windows Photo Viewer (WPV) memang meningkatkan ukuran secara dramatis; jumlah kenaikan sekitar empat kali dalam tes ini!
- Semua gambar baru bertambah sekitar ukuran yang sama, tetapi mereka tidak identik.
- WPV tidak menyandikan ulang atau bahkan menyimpan kembali gambar ketika diputar dengan kelipatan 360 derajat. (Stempel waktu, 11:27, adalah saat file pertama kali disalin.)
Menggunakan cmp -l
pada file yang seharusnya memiliki konten yang identik memungkinkan kita untuk melihat di mana file berbeda.
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg ccw-ccw-ccw.jpg
2223 63 62
2224 60 71
2226 60 64
2227 60 66
robert@unity ../jpeg-rotate-test % cmp -l cw-cw.jpg ccw-ccw.jpg
2223 63 62
2224 60 71
2226 60 64
2227 62 64
robert@unity ..jpeg-rotate-test % cmp -l ccw.jpg cw-cw-cw.jpg
2223 62 63
2224 71 60
2226 64 60
2227 61 64
robert@unity ../jpeg-rotate-test % cmp -l cw.jpg cw-cw-cw-cw-cw.jpg
2221 60 61
2223 63 61
2224 60 66
2226 60 61
2227 60 61
robert@unity ../jpeg-rotate-test % cmp -l ccw.jpg ccw-ccw-ccw-ccw-ccw.jpg
2223 62 63
2224 71 60
2226 64 65
2227 61 64
File-file ini berbeda hanya dalam empat byte (sebenarnya dalam cap waktu), yang berarti bahwa WPV melakukan hal yang sama setiap kali; sekarang kita hanya perlu mencari tahu apa itu.
Pengamatan rinci
Untuk ini saya menggunakan JPEGsnoop untuk melihat apa sebenarnya yang ada di gambar.
Karena outputnya cukup panjang, saya menghubungkannya sebagai intisari . Berikut ringkasan perbedaan:
GIMP hanya menggunakan segmen APP0
(JFIF) dan COM
(komentar) untuk metadata. WPV membiarkan bagian tersebut APP0
tidak tersentuh, tetapi dengan anehnya menambahkan byte nol pada komentar (sehingga diakhiri null)
WPV menambahkan dua APP1
segmen, yaitu metadata Exif dan XMP. Segmen ini masing-masing adalah 4286 dan 12726 byte. Bersama-sama mereka menghitung hampir seluruh peningkatan dalam ukuran file.
GIMP menghasilkan JPEG progresif, sedangkan WPV menghasilkan JPEG dasar (non-progresif). Karena alasan ini gambar GIMP memiliki beberapa segmen pemindaian, sedangkan gambar WPV hanya memiliki satu segmen. Dalam pengalaman saya, gambar progresif kadang-kadang sedikit lebih kecil.
GIMP menggunakan 1 × 1 chroma subsampling, sedangkan WPV menggunakan 2 × 2 subsampling. Ini membuat saya percaya bahwa WPV tidak menggunakan rotasi lossless "benar", kecuali jika entah bagaimana dapat mendeteksi ini adalah gambar hitam-putih.
Untuk mengatasi masalah ini, saya menjalankan tes kedua.
Prosedur
Saya mengikuti langkah-langkah serupa pada tes pertama. Saya membuat gambar 256 × 256 RGB acak menggunakan filter Noise RGB (Filter> Nose> RGB Nose ...) dengan pengaturan berikut:
Inilah hasilnya:
Saya mengekspor file sebagai JPEG menggunakan pengaturan berikut:
Progresif telah dimatikan, tetapi Subsampling masih diatur ke 4: 4: 4 (yang merupakan nama lain untuk subsampling 1 × 1). Kualitasnya meningkat menjadi 98.
Saya menyalin gambar dan memutar salinan searah jarum jam; kemudian menyalin versi yang diputar dan memutar salinan itu berlawanan arah jarum jam, sehingga kita dapat langsung membandingkan kualitas antara yang asli dan salinan yang diproses WPV.
Hasil
-rwxrwx--- 1 root vboxsf 159774 Nov 8 16:21 original-random.jpg
-rwxrwx--- 1 root vboxsf 222404 Nov 8 16:24 cw-random.jpg
-rwxrwx--- 1 root vboxsf 222467 Nov 8 16:24 cw-ccw-random.jpg
Meskipun peningkatan kali ini relatif lebih kecil (sekitar 40%), peningkatan absolut bahkan lebih besar — sekitar 62 kB. Ini menunjukkan bahwa WMV menggunakan pengkodean yang kurang efisien.
Saya akan menggunakan ImageMagick untuk membandingkan dua gambar:
robert@unity ../jpeg-rotate-test % compare -verbose -metric AE original-random.jpg cw-ccw-random.jpg null:
original-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 160KB 0.000u 0:00.009
cw-ccw-random.jpg JPEG 256x256 256x256+0+0 8-bit sRGB 222KB 0.010u 0:00.010
Image: original-random.jpg
Channel distortion: AE
red: 0
green: 0
blue: 0
all: 0
original-random.jpg=> JPEG 256x256 256x256+0+0 8-bit sRGB 0.050u 0:00.020
Ada nol piksel yang berbeda antara salinan asli dan yang diputar. Jadi, bahkan jika WPV tidak menggunakan rotasi lossless "benar", itu melakukan pekerjaan yang cukup baik. Saya kira saya tahu apa yang sedang terjadi, dan untuk menjelaskan saya akan mengalihkan sedikit ke dalam matematika di balik kompresi JPEG.
Algoritma kompresi JPEG memecah gambar menjadi blok 8 × 8-piksel. Masing-masing dari blok ini kemudian mengalami Discrete Cosine Transform (DCT) . Koefisien DCT yang dihasilkan menggambarkan blok sebagai jumlah dari gelombang frekuensi-berbeda. Algoritma kemudian "membuang" beberapa informasi dalam gelombang frekuensi tinggi yang sesuai dengan kebisingan dan detail yang sangat kecil. Proses decoding membalikkan DCT, menambahkan gelombang yang tersimpan bersama untuk mendapatkan kembali blok.
Dimungkinkan untuk memutar "gelombang" DCT tanpa benar-benar membatalkan dan mengulangi transformasi (pada dasarnya Anda mengubah semua gelombang horizontal menjadi gelombang vertikal dan sebaliknya). Apa yang saya pikir terjadi dalam WPV adalah bahwa gambar tersebut benar-benar diterjemahkan, diputar, dan kemudian disandikan ulang. Selama proses pengkodean ulang, karena ukuran gambar kami adalah kelipatan 8 di kedua dimensi, masing-masing blok baru sesuai dengan salah satu blok asli. Yang penting, karena setiap blok tidak memiliki komponen frekuensi tinggi, algoritma tidak membuang informasi apa pun, dan menemukan komponen DCT yang tepat yang dimiliki oleh rotasi lossless "benar".
Terakhir, saya akan melihat komponen file JPEG lagi. Hasilnya dikaitkan kembali sebagai intisari . Membandingkan keduanya:
Gambar WPV berisi ekstra 4286 + 2 byte metadata Exif, 1 byte ekstra di komentar, dan 12.726 + 2 byte metadata XMP. Ini adalah total 17.017 byte metadata tambahan. Untuk apa semua data itu digunakan? Saya mengintip ke dalam file dengan hex editor terpercaya saya dan salinan standar yang relevan:
Exif metadata terstruktur seperti gambar TIFF, yang berisi sejumlah tag (ada cara yang lebih kompleksitas, tapi aku akan melewatkan hak di atasnya). Sebagian besar byte di segmen Exif terkandung dalam dua tag identik dengan nomor tag EA1C
(59.932 desimal). Nomor tag itu tidak didokumentasikan di mana pun saya dapat temukan. Kedua tag berisi 2060 byte tipe "tidak terdefinisi", yang semuanya byte nol kecuali untuk enam ( 1C EA 00 00 00 08
) pertama. Saya tidak tahu apa tag ini, mengapa ada dua, dan mengapa mereka harus masing-masing 2 kB.
Metadata XMP sebenarnya adalah seluruh dokumen XML yang disematkan dengan namespacing dan UUID yang panjang, yang hanya berisi string versi WPV (yang sudah ada dalam metadata Exif). Namun, itu hanya menyumbang sekitar 400 byte. Sisa dari segmen ini adalah 122 pengulangan dari 100 ruang diikuti oleh baris baru . Itu lebih dari 12.000 byte ruang yang benar-benar terbuang.
Seperti tes sebelumnya, baik GIMP dan WPV menggunakan tabel kuantisasi DCT yang sama. Ini berarti bahwa mereka harus menghitung koefisien DCT yang persis sama, itulah sebabnya gambarnya persis sama. Saya tidak yakin apakah WPV kebetulan menggunakan tabel kuantisasi yang sama atau jika menyalin tabel dari input.
Berbeda dengan tes sebelumnya, kali ini WPV menggunakan subsampling 1 × 1, jadi itu sebenarnya dapat mendeteksi bahwa ini adalah gambar berwarna (atau setidaknya sampel yang lebih tinggi diperlukan untuk menyandikan ulang gambar tanpa hilang).
GIMP dan WPV menggunakan tabel Huffman yang berbeda (bagian dari langkah pengkodean entropi). Tabel untuk WPV lebih besar dengan total 279 byte, dan dalam satu kasus mengandung 7 kali lebih banyak kode.
Melihat statistik JPEGsnoop, kita dapat melihat bahwa beberapa kode ini jarang digunakan. Misalnya, dalam ID: 1, Class: AC
tabel, dari 119 kode 16-bit yang ditentukan, hanya 23 yang benar-benar digunakan. Secara keseluruhan, segmen pemindaian yang sebenarnya adalah 28,5% lebih besar di versi WPV.
Ringkasan
WPV mungkin tidak melakukan rotasi lossless "benar", tetapi rotasi tampaknya praktis lossless.
Ukuran ekstra sebagian karena jumlah tetap metadata yang ditambahkan, dan sebagian karena pengkodean entropi yang kurang efisien.
Informasi Versi:
OS (Linux) ( uname -a
):
Linux unity 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u1 (2016-09-03) x86_64 GNU/Linux
OS (Windows):
GIMP (Linux): 2.8.14 (dari paket gimp
, versi 2.8.14-1+deb8u1
)
Window Photo Viewer (sesuai dengan metadata gambar):
Microsoft Windows Photo Viewer 10.0.10586.0