Web viewer này tôi viết 1 trang index tất cả các tập, 1 trang preview mỗi tập, 1 trang view từng trang, và bonus 1 trang xem 2 ảnh cùng lúc. Trình CSS tôi gà nên chỉ dám bảo đảm bấm fullscreen (bấm phím F) thì double page nó vừa đúng màn hình 1080p zoom 125%, khỏi kéo chuột. Xem trên điện thoại thì nhớ quay để chế độ phone nằm ngang mới đọc được đầy đủ trang, để đứng nó bị cắt mất bên trái hình.
Các trang ảnh được trích xuất từ file PDF (full) ở Voz, theo command này:
(0..($num_pages - 1)) | ForEach-Object {
$cmd = ".../magick '$infile[$_]' '$outpath/$_.png'"
iex $cmd
...
}
Hầu hết các trang có chiều cao 2400 pixels (px), tuy vậy có nhiều trang có chiều cao 2401px, sẽ được xóa bỏ 1 row ở top theo command này:
if ($h -eq 2401) {
$cmd = ".../magick '$outpath/$_.png' -chop 0x1 '$outpath/$_.png'"
iex $cmd
}
Với các trang có height bé hơn 2400px thì tôi xử lý thành 2400 theo 3 cách:
-unsharp nhiều hơn nên cũng không tồi lắm. Với 2 tập p01 và cl03 upscale từ 1800px lên 2400px tôi xài command:(0..187) | ForEach { iex "magick $_.png -filter Lanczos -resize 133.333333334% -unsharp 1.5x1.5+0.75+0.025 2400/$_.png" }
Các trang ảnh sẽ được chuyển lại thành định dạng AVIF, có chất lượng (quality) = 40 (0-100). Tuy quality chỉ là 40/100 nhưng không bị mờ như JPEG mà dung lượng file AVIF chỉ bằng có tầm 1/3 so với JPEG, và tầm 4% so với PNG. Ban đầu tôi chuyển PNG sang WEBP, tốc độ chuyển rất lẹ. Nhưng sau đó tầm vài ngày thì tôi đọc thấy AVIF mới hơn, nén dung lượng thấp hơn WEBP. Tôi xài thử thì thấy đúng thật như vậy, dung lượng bé hơn WEBP tầm 15-20%. Tôi còn thấy chất lượng nó nét hơn nữa, nên thử clone libavif về code cho quality thấp nữa, thì thấy ép xuống quality... 15 nó vẫn còn đọc được, tốt chán. Tôi tính ép xuống quality 30 thôi, 15 thấp quá, nhưng chuyển tập 1 xong nhân 84 tập thấy chỉ có 1.75 GiB thì lại nhắm với quality 40 tổng dung lượng 84 tập vừa đúng 2GB nên tôi đã chọn quality = 40. Vậy nhưng khi chuyển xong dung lượng nó lên hơn 2GB, lỡ ném lao rồi thôi theo lao luôn, vì chuyển PNG sang AVIF lâu quá.
Vì ImageMagick không cho chọn quality cho file AVIF nên tôi lại phải viết code C++ để vắt cổ chày AVIF hơn nữa. Hiện tại (tháng 1 năm 2023) libavif bản mới nhất 0.11.1 cũng chưa có, chỉ có cho chọn quality ở commit mới nhất.
encoder->speed = AVIF_SPEED_SLOWEST;
encoder->maxThreads = 4; // std::thread::hardware_concurrency()
encoder->quality = quality;
encoder->qualityAlpha = AVIF_QUALITY_LOSSLESS;
Tôi cho AVIF encoder chạy chế độ chậm nhất (chuyển ra file ảnh dung lượng nhỏ nhất), hint sử dụng 4 threads (vì nóng CPU quá), rồi chạy song song 2 chương trình chuyển 2 tập khác nhau:
./batch-img2avif s1 s1/avif 40
./batch-img2avif s2 s2/avif 40
Chuyển 2 tập ~190 trang mất gần 50 phút, sử dụng CPU AMD Ryzen 7 4800H (8 cores/16 threads), nhiệt độ core lúc chạy tầm 95-100°C. Được cái mỗi tập nén còn tầm 20 tới 30 MiB, mỗi trang tầm 100-150 KiB, load rất lẹ. Nhược điểm của AVIF là decode chậm, có lẽ chậm hơn WEBP... 30 lần, và ít có web browser / image viewer hỗ trợ nó vì nó khá mới: release năm 2019. So với WEBP release năm 2010 là tầm 12-13 năm về trước, hầu hết web browser nào cũng hỗ trợ, vậy mà người ta còn chưa chuyển hết PNG sang WEBP. AVIF tuy ít có hỗ trợ nhưng có 2 bé bự Firefox và Chrome hỗ trợ là đủ xài rồi.
Để cho trang index load một lúc 84 hình bìa lẹ tôi đã thu nhỏ ảnh bìa của mỗi tập còn width = 225px theo command này:
$cmd = ".../magick $_ -filter Lanczos -resize ${using:percentage}% -unsharp 0.5x0.5+0.5+0.008 $outfilepath"
iex $cmd
$percentage ở đây là (22500.0/1528). Vì $percentage cố định và cho là tất cả các trang đều có width = 1528px, mà điều này không đúng với 3 tập là cl01, cl02, cl03 nên 3 tập này có cover resize ra width không đúng 225px, nhưng đúng cái height = 353px, vì tất cả các trang đều có height 2400px.
Còn sử dụng -unsharp là để làm ảnh sắc nét hơn. Ở đây ảnh height 353px nhỏ xíu thì sắc nét hơn cũng chả quan trọng lắm. -unsharp quan trọng hơn khi cần làm sắc nét ảnh upscale từ 1800px lên 2400px.
Trang preview cho phép xem qua ảnh nhỏ của từng trang, mà mỗi tập gần 200 trang thì load 200 ảnh nhỏ tôi sợ lag nên gộp tất cả thành 1 ảnh lớn, dung lượng AVIF tầm 2.5 MiB mỗi trang theo command:
# 20 pages per row
convert +append $page1 $page2 ... $page20 r0.png
convert +append $page21 $page22 ... $page40 r1.png
...
convert +append $page181 $page182 ... $page191 r9.png
# Merge rows
convert -append -background white r0.png r1.png ... r9.png all.png
# Convert to AVIF
...
Cách load 1 trang bự này ai có tốc độ download yếu có thể chờ 5-10 giây mới hiện hình, đáng lẽ nên làm 1 cái icon quay vòng vòng cho "Click to preview" nhưng lười quá để từ từ tính...
- Ngày 13 Tháng 2 năm 2023
Updated: 2023/02/20