Tại sao các phương pháp nén (lossless) của nhiều hình ảnh png tương tự không hiệu quả?


21

Tôi chỉ bắt gặp điều sau đây: Tôi đặt nhiều bản sao giống hệt của hình ảnh png vào một thư mục và sau đó thử nén thư mục đó bằng các phương pháp sau:

  • tar czf folder.tar.gz folder/
  • tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz (cái này hoạt động tốt cho các hình ảnh giống hệt nhau, tuy nhiên đối với các hình ảnh tương tự thì mức tăng bằng không)
  • zip -r folder.zip folder/

Khi tôi kiểm tra kích thước của .tar.gz, .tar.xz, .ziptôi nhận ra rằng nó gần như là giống như một trong folder/.
Tôi hiểu rằng một hình ảnh png có thể có mức độ nén cao và do đó không thể nén thêm được nữa. Tuy nhiên, khi hợp nhất nhiều hình ảnh png tương tự (trong trường hợp này thậm chí giống hệt nhau) vào một kho lưu trữ và sau đó nén tệp lưu trữ, tôi sẽ hy vọng kích thước yêu cầu sẽ giảm rõ rệt. Trong trường hợp hình ảnh giống hệt nhau, tôi sẽ mong đợi một kích thước gần bằng kích thước của một hình ảnh.


2
Hành vi này chỉ hiện diện với các tập tin png?
pdexter

7
Không đưa ra câu trả lời này vì nó trả lời một câu hỏi không có nội dung, nhưng nếu bạn biết bạn sẽ nén rất nhiều hình ảnh gần giống nhau, bạn luôn có thể thay thế tất cả các hình ảnh ngoại trừ hình ảnh đầu tiên bằng hình ảnh nhị phân so với hình ảnh đầu tiên. Giả sử hình ảnh không ồn ào, bạn sẽ có kết quả đầu ra rất nén và hình ảnh gốc sẽ vẫn có thể tái tạo.
Baldrickk

Nếu bạn sử dụng các tệp không nén (ví dụ .bmp), tệp tar.gz sẽ có thể tận dụng sự tương tự. (Ít nhất là nếu sự giống nhau là rất nhiều pixel giống hệt nhau)
CodeInChaos

1
Tôi không biết gì về nó, nhưng theo Wikipedia, định dạng lưu trữ "ZPAQ" hỗ trợ chống trùng lặp, mà tôi tin là những gì bạn đang theo đuổi. vi.wikipedia.org/wiki/ZPAQ#Ded
repeatation

Bạn đang cố gắng nén một cái gì đó đã được nén. Xem tại đây
Kyle Khalaf

Câu trả lời:


34

Có một cái nhìn về cách các thuật toán nén hoạt động. Ít nhất là những người trong gia đình Lempel-Ziv ( gzip sử dụng LZ77 , zipdường như cũng làm như vậyxz sử dụng LZMA ) nén một phần cục bộ : Không thể xác định được những điểm tương đồng cách xa nhau.

Các chi tiết khác nhau giữa các phương thức, nhưng điểm mấu chốt là vào thời điểm thuật toán đạt đến hình ảnh thứ hai, nó đã "quên" sự bắt đầu của lần đầu tiên. Và như vậy.

Bạn có thể thử và thay đổi thủ công các tham số của phương thức nén; nếu kích thước cửa sổ (LZ77) resp. kích thước khối / khối (các phương thức sau) ít nhất bằng hai hình ảnh, bạn có thể sẽ thấy nén thêm.


Lưu ý rằng những điều trên chỉ thực sự áp dụng nếu bạn có hình ảnh giống hệt hoặc hình ảnh không nén gần như giống hệt nhau . Nếu có sự khác biệt, hình ảnh nén có thể trông không giống bất cứ thứ gì trong bộ nhớ. Tôi không biết cách nén PNG hoạt động; bạn có thể muốn kiểm tra các biểu diễn hex của hình ảnh bạn có để chia sẻ thủ công.

Cũng lưu ý rằng ngay cả khi đã thay đổi các tham số và dự phòng để khai thác, bạn sẽ không giảm kích thước của một hình ảnh. Từ điển lớn hơn có nghĩa là kích thước từ mã lớn hơn và ngay cả khi hai hình ảnh giống hệt nhau, bạn có thể phải mã hóa cái thứ hai bằng nhiều từ mã (chỉ vào cái đầu tiên).


3
Một câu trả lời chính xác hơn: gzip và zip sử dụng cùng một codec DEFLATE cơ bản, dựa trên lý thuyết LZ77 + Huffman.
Nayuki

Vâng Đó là một nửa câu chuyện; xem câu trả lời của tôi cho nửa kia, hoặc câu trả lời tuyệt vời của Nayuki .
DW

1
cho hậu thế: định dạng lưu trữ khai thác dư thừa giữa các tập tin bằng cách kết hợp các tập tin vào một blob đơn và nén được gọi là rắn . không chắc chắn nếu có các điều khoản khác cho các cấp độ trung gian của 'độ rắn', v.v.
underscore_d

22

Tại sao điều này xảy ra. Thực tế có hai hiệu ứng khác nhau xảy ra ở đây:

  • Mỗi tập tin được nén độc lập. Một số chương trình lưu trữ - bao gồm zip - nén từng tệp một cách độc lập, không có bộ nhớ từ tệp này sang tệp khác. Nói cách khác, mỗi tệp được nén riêng biệt, sau đó các tệp nén được nối vào một kho lưu trữ.

  • Trí nhớ ngắn hạn. Một số chương trình lưu trữ có thể sử dụng thông tin về một tệp để giúp nén tệp tiếp theo tốt hơn. Họ nối các tệp một cách hiệu quả, sau đó nén kết quả. Đây là một cải tiến.

    Xem thêm câu trả lời của Nayuki để biết thêm thảo luận về điều này.

    Tuy nhiên, có một vấn đề thứ hai. Một số lược đồ nén - bao gồm zip, gzip và bzip2 - có bộ nhớ hạn chế. Họ nén dữ liệu nhanh chóng và ghi nhớ 32KB dữ liệu trước đó, nhưng họ không nhớ bất cứ điều gì về dữ liệu xảy ra trước đó trong tệp. Nói cách khác, họ không thể tìm thấy dữ liệu trùng lặp nếu các bản sao xảy ra cách xa nhau hơn 32KB. Kết quả là, nếu các tệp giống hệt nhau ngắn (ngắn hơn khoảng 32KB), thuật toán nén có thể xóa dữ liệu trùng lặp, nhưng nếu các tệp giống nhau dài, thuật toán nén bị hoen rỉ và trở nên vô giá trị: nó không thể phát hiện bất kỳ trùng lặp trong dữ liệu của bạn. (Bzip ghi nhớ 900KB hoặc hơn dữ liệu trước đó, thay vì 32KB.)

    Tất cả các thuật toán nén tiêu chuẩn có một số kích thước bộ nhớ tối đa, ngoài ra chúng không phát hiện được các mẫu ... nhưng đối với một số, con số này lớn hơn nhiều so với các thuật toán khác. Đối với Bzip, nó giống như 900KB. Đối với xz, nó giống như 8MB (với cài đặt mặc định). Đối với 7z, nó giống như 2GB. 2GB là quá đủ lớn để nhận ra các bản sao của các tệp PNG (thường nhỏ hơn 2GB). Ngoài ra, 7z cũng cố gắng khéo léo trong việc đặt các tệp có khả năng tương tự nhau cạnh nhau trong kho lưu trữ, để giúp máy nén hoạt động tốt hơn; tar không biết gì về điều đó.

    Xem thêm câu trả lời của Raphaelcâu trả lời của Nayuki để được giải thích thêm về hiệu ứng này.

Làm thế nào điều này áp dụng cho thiết lập của bạn. Ví dụ cụ thể của bạn, bạn đang làm việc với hình ảnh PNG. Hình ảnh PNG tự nén, vì vậy bạn có thể nghĩ về mỗi tệp PNG về cơ bản là một chuỗi các byte trông ngẫu nhiên, không có mẫu hoặc trùng lặp trong tệp. Không có gì để máy nén khai thác, nếu nó nhìn vào một hình ảnh PNG. Do đó, nếu bạn cố nén một tệp PNG (hoặc tạo tệp lưu trữ zip / tar / ... chỉ chứa một tệp PNG), bạn sẽ không nhận được bất kỳ nén nào.

Bây giờ hãy xem điều gì xảy ra nếu bạn cố lưu trữ nhiều bản sao của cùng một tệp PNG:

  • Tập tin nhỏ. Nếu tệp PNG rất nhỏ, thì mọi thứ ngoại trừ zip sẽ hoạt động tốt. Zip sẽ thất bại một cách ngoạn mục: nó nén từng tệp một cách độc lập, do đó nó không có cơ hội phát hiện sự dư thừa / trùng lặp giữa các tệp. Hơn nữa, khi nó cố nén từng tệp PNG, nó không đạt được nén; kích thước của một kho lưu trữ zip sẽ rất lớn. Ngược lại, kích thước của kho lưu trữ tar (cho dù được nén bằng gzip, bzip2 hoặc xz) và lưu trữ 7z sẽ nhỏ, vì về cơ bản, nó lưu trữ một bản sao của tệp và sau đó thông báo rằng những cái khác đều giống hệt nhau - chúng có lợi từ việc giữ lại bộ nhớ từ tệp này sang tệp khác.

  • Tập tin lớn. Nếu tệp PNG lớn, thì chỉ có 7z hoạt động tốt. Đặc biệt, zip tiếp tục thất bại một cách ngoạn mục. Ngoài ra, tar.zip và tar.bzip2 thất bại nặng nề, vì kích thước của tệp lớn hơn cửa sổ bộ nhớ của máy nén: vì trình nén nhìn thấy bản sao đầu tiên của tệp, nó không thể co lại được (vì nó đã được nén ); tại thời điểm nó bắt đầu thấy phần đầu của bản sao thứ hai của tệp, nó đã quên các chuỗi byte được nhìn thấy ở phần đầu của tệp đầu tiên và không thể tạo ra kết nối rằng dữ liệu này thực sự là một bản sao.

    Ngược lại, tar.xz và 7z tiếp tục làm rất tốt với nhiều bản sao của một tệp PNG lớn. Họ không có giới hạn "kích thước bộ nhớ nhỏ" và có thể nhận thấy rằng bản sao thứ hai của tệp giống hệt với bản sao đầu tiên, do đó không cần lưu trữ lần thứ hai.

Những gì bạn có thể làm về điều này. Sử dụng 7z. Nó có một loạt các heuristic sẽ giúp phát hiện các tệp giống hệt hoặc tương tự và nén thực sự tốt trong trường hợp đó. Bạn cũng có thể xem lrzip với nén lzop.

Làm sao tôi biết? Tôi đã có thể xác minh điều này bằng cách thử một số thử nghiệm với 100 bản sao của tệp chứa byte ngẫu nhiên. Tôi đã thử 100 bản sao của tệp 4KB, 100 bản sao của tệp 1 MB và 100 bản sao của tệp 16 MB. Đây là những gì tôi tìm thấy:

Size of file      Size of compressed archive (with 100 copies)
                  zip  tar.gz  tar.bz2  tar.xz    7z
         4KB    414KB     8KB     10KB     5KB    5KB
         1MB    101MB   101MB    101MB     1MB    2MB
        16MB    1.6G    1.6GB    1.6GB   1.6GB  401MB

Như bạn có thể thấy, zip là khủng khiếp cho dù tập tin của bạn nhỏ như thế nào. 7z và xz đều tốt nếu hình ảnh của bạn không quá lớn (nhưng xz sẽ dễ vỡ và phụ thuộc vào thứ tự hình ảnh được đặt trong kho lưu trữ, nếu bạn có một số trùng lặp và một số không trùng lặp với nhau). 7z là khá tốt, ngay cả đối với các tệp lớn.

Tài liệu tham khảo. Điều này cũng được giải thích tốt trong một loạt các bài đăng tại Super User. Hãy xem:


5
Có thể đáng lưu ý rằng định dạng ZIP được thiết kế vào khoảng năm 1990 (PKZIP đã giới thiệu định dạng ZIP vào năm 1989 cho biết Wikipedia và DEFLATE đã được giới thiệu vào năm 1993). Trong khoảng thời gian này, một PC khá phổ biến có thể là 286 hoặc 386 (486 được giới thiệu vào năm 1989, nhưng như mọi khi, phải mất một thời gian để bắt kịp) chạy DOS với RAM 2-4 MB, chỉ có thể 400- MB 500 KB trong số đó có thể sử dụng trực tiếp mà không cần hỗ trợ lập trình thông minh (EMS, XMS) mà không được đảm bảo có sẵn. Trong môi trường đó, một kích thước cửa sổ nén nhỏ là yêu cầu khá nhiều.
một CVn

"Mỗi tệp được nén độc lập" - Điều này dường như rất khác nhau giữa các tiêu chuẩn và công cụ. Kinh nghiệm của tôi với phần mềm đóng gói mặc định của Ubuntu là nó dường như giải nén mọi thứ khi mở kho lưu trữ. Tôi thường nghĩ rằng nó nên nén mọi tệp một cách độc lập, vì mức tăng khả năng sử dụng thường vượt trội hơn các nhược điểm nén.
Raphael

"100 bản sao của tệp chứa byte ngẫu nhiên" - còn tệp "tương tự" thì sao? (Hướng tới câu hỏi thực tế, làm thế nào tương tự PNG các hình ảnh tương tự?)
Raphael

Raphael đã đưa ra một quan điểm tốt về điều này trong câu trả lời của mình. Thật ra tôi có nhiều hình ảnh tương tự (không giống hệt nhau) mà tôi muốn lưu trữ. Tương tự về mặt chúng cho thấy cấu trúc tương tự với các biến thể nhẹ (cũng liên quan đến cường độ và nền). Tuy nhiên, sự khác biệt rất nhỏ đến mức chúng khó có thể nhìn thấy. Tôi đã thử với tarchúng và sau đó nén bằng xz(hoạt động rất tốt cho các hình ảnh giống hệt nhau) tuy nhiên trong trường hợp hình ảnh tương tự thì mức tăng bằng không. Tôi đã thử với 71 ảnh mỗi ảnh có kích thước ~ 831KB.
a_guest 16/07/2016

2
@a_guest - điều đó sẽ không diễn ra tốt đẹp. Hình ảnh PNG trông tương tự sẽ có nội dung byte rất khác nhau (do nén PNG). Xem thêm superuser.com/q/730592/93541 , superuser.com/q/418286/93541 , superuser.com/q/893206/93541 , superuser.com/q/921140/93541 - về cơ bản, không có giải pháp tốt.
DW

10

Đầu tiên, lưu ý rằng định dạng hình ảnh PNG về cơ bản là các pixel RGB thô (với một số bộ lọc ánh sáng) được đẩy qua định dạng nén DEFLATE. Nói chung, các tệp nén (PNG, JPEG, MP3, v.v.) sẽ không có lợi ích gì khi được nén lại. Vì vậy, đối với các ý định thực tế, chúng tôi có thể coi tệp PNG của bạn là dữ liệu ngẫu nhiên không thể nén được cho phần còn lại của thử nghiệm.

Thứ hai, lưu ý rằng các định dạng ZIP và gzip cũng sử dụng codec DEFLATE. (Điều này sẽ giải thích lý do tại sao nén so với gzipping một tệp sẽ tạo ra kích thước đầu ra cơ bản giống nhau.)


Bây giờ cho phép tôi nhận xét về từng trường hợp thử nghiệm riêng lẻ:

  • tar czf folder.tar.gz folder/

    Điều này tạo ra một tệp TAR (không nén) kết hợp tất cả các tệp PNG giống hệt của bạn (với một lượng siêu dữ liệu và phần đệm được thêm vào). Sau đó, tệp duy nhất này được gửi qua máy nén gzip để tạo một tệp đầu ra được nén.

    Thật không may, định dạng DEFLATE chỉ hỗ trợ cửa sổ từ điển LZ77 có 32768 byte. Vì vậy, mặc dù TAR chứa dữ liệu lặp đi lặp lại, nếu tệp PNG của bạn lớn hơn 32 KiB thì chắc chắn máy nén DEFLATE không thể nhớ dữ liệu đủ xa để tận dụng thực tế là dữ liệu giống hệt đang lặp lại.

    Mặt khác, nếu bạn thử lại thử nghiệm này với một tệp PNG 20 KB được nhân đôi 10 lần, thì rất có khả năng bạn sẽ nhận được một tệp gzip chỉ lớn hơn một chút so với 20 KB.

  • tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xz

    Điều này tạo ra một tệp TAR giống như trước đây và sau đó sử dụng định dạng xz và máy nén LZMA / LZMA2. Tôi không thể tìm thấy thông tin về LZMA trong tình huống này, nhưng từ 7-Zip cho Windows tôi biết nó có thể hỗ trợ kích thước cửa sổ từ điển lớn (ví dụ 64 MiB). Vì vậy, có thể bạn đang sử dụng các cài đặt dưới mức tối ưu và codec LZMA có thể đã giảm tệp TAR xuống chỉ bằng kích thước của một tệp PNG.

  • zip -r folder.zip folder/

    Định dạng ZIP không hỗ trợ lưu trữ "rắn"; có nghĩa là, mọi tập tin được nén độc lập. Chúng tôi giả định mọi tập tin là không thể nén được. Do đó, thực tế là mọi tệp giống hệt nhau đều không thể được khai thác và tệp ZIP sẽ lớn bằng phép nối thẳng của tất cả các tệp.


xztheo mặc định chạy trong xz -6chế độ, sử dụng từ điển 8 MiB LZMA2 . Tôi không thể tìm thấy ngay trong trang man có sẵn trên hệ thống Debian của mình kích thước cửa sổ mặc định cho máy nén là gì.
một CVn

Câu trả lời tốt! Đối với trường hợp thứ hai tôi thực sự đã làm như sau: tar czf folder.tar.gz folder/ && xz --stdout folder.tar.gz > folder.tar.gz.xzkhông có bất kỳ ảnh hưởng nào (điều này có ý nghĩa theo những gì bạn đã giải thích). Tôi đoán rằng tôi đã bị mất một chút trong tất cả các công cụ nén này: D Khi sử dụng tar cf folder.tar folder/ && xz --stdout folder.tar > folder.tar.xztôi thực sự kết thúc với một chút nhiều hơn kích thước của một hình ảnh (điều này cũng có ý nghĩa theo kích thước cửa sổ chính tả mặc định là 64 MiB). Tôi cập nhật câu hỏi của tôi cho phù hợp. Cảm ơn!
a_guest 16/07/2016

@a_guest Được rồi, nhận xét của bạn mô tả trường hợp thứ hai khác. Vấn đề ở đây là tar -> gzip -> xz, DEFLATE gzip có thể nén từng bản sao của dữ liệu PNG theo một cách khác nhau, vì vậy xz sẽ không thể phát hiện các dự phòng.
Nayuki

6

Vấn đề là, (hầu hết) các lược đồ nén thiếu kiến ​​thức về dữ liệu bạn có. Ngay cả khi bạn giải nén PNG của mình thành bitmap và nén chúng trong tarball, bạn sẽ không nhận được (đáng kể) kết quả nhỏ hơn.

Trong trường hợp có nhiều hình ảnh tương tự, sơ đồ nén phù hợp sẽ là codec video.

Sử dụng mã hóa lossless, bạn sẽ đạt được kết quả nén gần như hoàn hảo mà bạn đang mong đợi.

Nếu bạn muốn kiểm tra nó, hãy sử dụng một cái gì đó như thế này:

ffmpeg -i img%03d.png -c:v libx264 -c:v libx264 -profile:v high444 -crf 0 out.mp4

https://trac.ffmpeg.org/wiki/Create%20a%20video%20slIDIA%20from%20images


Điểm tốt khi sử dụng bộ mã hóa video! Tôi sẽ thử điều đó khi tôi nâng cấp Ubuntu vì 14.04 không bao gồm ffmpeg theo mặc định. Tôi đoán bộ mã hóa video này đang sử dụng nén không mất dữ liệu hoặc ít nhất có một công tắc cho điều đó? Bạn có biết?
a_guest 16/07/2016

Có, -crf 0 làm cho nó không bị mất (hoặc giống như được đề cập trong các tài liệu -qp 0 cũng làm như vậy (-qp 0 được ưu tiên)). trac.ffmpeg.org/wiki/Encode/H.264
Jonas

4

PNG là sự kết hợp của Bộ lọc + LZ77 + Huffman (sự kết hợp của LZ77 + Huffman được gọi là Deflate) theo thứ tự đó:

bước 1) nếu bộ lọc khác với Không có, giá trị của các pixel được thay thế bằng chênh lệch so với các pixel liền kề (để biết thêm chi tiết, hãy xem http://www.libpng.org/pub/png/book/ch CHƯƠNG09.html ) . Điều đó làm tăng khả năng nén hình ảnh với độ dốc (vì vậy ... 4 5 6 7 trở thành ... 1 1 1 1) và nó có thể giúp trong các khu vực có cùng màu (... 3 3 3 5 5 5 5 5 trở thành 0 0 0 2 0 0 0 0 0). Theo mặc định, các bộ lọc được bật trong hình ảnh 24 bit và bị vô hiệu hóa trong hình ảnh 8 bit với bảng màu.

bước 2) dữ liệu được nén bằng LZ77 thay thế các chuỗi byte lặp lại (khớp) bằng một tuple chứa khoảng cách đến khớp và độ dài của khớp.

bước 3) kết quả của bước 2 được mã hóa bằng mã Huffman thay thế các ký hiệu có độ dài cố định bằng mã có độ dài thay đổi, ký hiệu càng thường xuyên thì mã càng ngắn.

Có nhiều vấn đề:

Một thay đổi nhỏ ảnh hưởng đến một vài pixel sẽ dẫn đến thay đổi kết quả từ 3 bước nén png:

1) Giá trị được lọc của các pixel liền kề sẽ thay đổi (tùy thuộc vào bộ lọc được sử dụng). Điều đó sẽ khuếch đại tác động của những thay đổi nhỏ.

2) Thay đổi sẽ có nghĩa là phù hợp với khu vực đó sẽ khác nhau. Ví dụ: thay đổi 333333 thành 333533 vì một lần xuất hiện khác của 333333 sẽ không còn khớp nữa nên nó sẽ chọn một kết quả khác thành 333333 với một khoảng cách khác hoặc nó sẽ chọn cùng một trận đấu nhưng với độ dài ngắn hơn và sau đó là một trận đấu khác cho 3 byte cuối cùng. Tự nó sẽ thay đổi kết quả rất nhiều.

3) Vấn đề lớn nhất là ở bước 3. Mã huffman sử dụng số bit thay đổi, do đó, ngay cả một thay đổi nhỏ cũng sẽ dẫn đến việc mọi thứ tiếp theo không được căn chỉnh nữa. AFAIK Hầu hết các thuật toán nén không thể phát hiện các kết quả khớp không phải là byte do đó sẽ ngăn chặn (hoặc ít nhất là giảm rất nhiều) việc nén dữ liệu đã theo sau thay đổi trừ khi máy nén có thể phát hiện các kết quả khớp không được căn chỉnh byte.

Các vấn đề khác đã được trả lời bởi các trả lời khác:

4) Gzip sử dụng cùng một thuật toán Deflate với từ điển 32KB, vì vậy nếu các tệp png lớn hơn 32KB, các kết quả trùng khớp sẽ không được phát hiện ngay cả khi chúng giống hệt nhau. Bzip2 tốt hơn ở khía cạnh đó vì nó sử dụng khối 900 KB. XZ sử dụng LZMA, IIRC có từ điển 4 MB ở mức nén mặc định. 5) Định dạng Zip không sử dụng nén rắn nên sẽ không nén các tệp tương tự hoặc giống hệt nhau.

Có lẽ máy nén từ họ PAQ hoặc PPMD ​​sẽ nén tốt hơn nhưng nếu bạn cần nén nhiều tệp hình ảnh tương tự thì bạn có thể xem xét 3 cách tiếp cận:

1) Lưu trữ hình ảnh không nén (với PNG -0 hoặc ở định dạng không nén) và nén bằng máy nén có từ điển lớn hoặc kích thước khối. (LZMA sẽ hoạt động tốt)

2) Một tùy chọn khác sẽ là giữ các bộ lọc nhưng loại bỏ nén Deflate khỏi các PNG. Điều đó có thể được thực hiện ví dụ với tiện ích ( AdvDef ). Sau đó, bạn nén các PNG không nén kết quả. Sau khi giải nén, bạn có thể giữ PNG không nén hoặc nén chúng lại bằng AdvDef (nhưng sẽ mất thời gian).

Bạn cần kiểm tra cả hai cách tiếp cận để xem nén nào nhiều nhất.

3) Tùy chọn cuối cùng sẽ là chuyển đổi hình ảnh png trong video, nén nó bằng máy nén video lossless như x264 lossless (đặc biệt chú ý sử dụng định dạng màu phù hợp) và sau đó trích xuất trích xuất các khung hình thành từng hình ảnh png riêng lẻ. Điều đó có thể được thực hiện với ffmpeg. Bạn cũng cần giữ ánh xạ giữa số khung và tên gốc.

Đó sẽ là cách tiếp cận phức tạp nhất nhưng nếu pngs là một phần của hoạt hình thì nó có thể hiệu quả nhất. Tuy nhiên, bạn sẽ cần một định dạng video hỗ trợ tính minh bạch nếu bạn cần.

Chỉnh sửa: Cũng có định dạng MNG nên nó không được sử dụng thường xuyên.


2

Khi bạn có bộ dữ liệu đặc biệt, bạn sử dụng các thuật toán đặc biệt, không phải các công cụ đa năng.

Câu trả lời là việc nén không mất lựa chọn của bạn không được thực hiện cho những gì bạn làm. Không ai mong bạn nén cùng một hình ảnh hai lần và ngay cả khi bạn thực hiện việc đó (tình cờ) kiểm tra tất cả các đầu vào trước đó sẽ làm cho thuật toán của bạn O (n ^ 2) (có thể tốt hơn một chút, nhưng cách tiếp cận naiv ít nhất sẽ là n ^ 2).

Hầu hết các chương trình nén của bạn mà bạn đã thử khi chạy trong O (n), chúng đều tăng tốc độ trên tỷ lệ nén tối ưu. Không ai muốn chạy máy tính của mình trong 5 giờ chỉ để dành vài mb, đặc biệt là những ngày này. Đối với đầu vào lớn hơn, bất cứ điều gì ở trên O (n) đều trở thành vấn đề của thời gian chạy.

Một vấn đề khác là ram. Bạn không thể truy cập mọi phần của đầu vào của mình tại bất kỳ thời điểm nào, khi đầu vào đủ lớn. Ngay cả khi không quan tâm đến điều này, hầu hết mọi người không muốn từ bỏ toàn bộ ram hoặc cpu của họ chỉ để nén một cái gì đó.

Nếu bạn có các mẫu trong các tệp mà bạn muốn nén, bạn sẽ phải thực hiện các thao tác manuel trên chúng, viết nén của riêng bạn hoặc có khả năng sử dụng "nén" -type-nén (nano). Một nén để lưu trữ dài hạn, quá chậm để sử dụng hàng ngày.

Một tùy chọn khác có khả năng sẽ là nén video lossless.


1
Do các cấu trúc thư mục chứa nhiều tệp giống nhau ở các vị trí khác nhau, có vẻ như một tiện ích kiểu zip tốt sẽ cung cấp tùy chọn để kiểm tra xem một tệp được thêm vào kho lưu trữ có nén và kích thước giá trị băm không nén phù hợp với những tập tin hiện có. Nếu cả hai giá trị băm và cả hai kích thước khớp nhau, có vẻ đáng để đính kèm tên thứ hai vào khối dữ liệu được liên kết với tệp đầu tiên. Ngay cả khi ZIP không thể đáp ứng điều đó, nó dường như là một tính năng hữu ích trong bất kỳ định dạng nào trong tương lai.
supercat

1
Câu trả lời của bạn ngụ ý thuật toán nén của tar là tốt cho việc nén một số loại dư thừa, nhưng không phải cho loại xảy ra trong kịch bản của OP. Bạn có thể muốn mô tả loại dự phòng nào bạn nghĩ tốt, vì điều đó không rõ ràng. Đối với một người có lẽ chưa bao giờ sử dụng máy nén này thành công, tất cả những gì họ đang thấy là họ đã thử nó trên một thứ khá nén về mặt lý thuyết, nó không hoạt động, vậy thì cái máy nén này tốt cho cái gì vậy?
Don nở

1
@leftaroundabout: Không có cách nào trong bất kỳ Unix nào tôi biết để sử dụng ngữ nghĩa "copy-on-write" với các tệp phù hợp. Trong nhiều trường hợp, các bản sao dư thừa tồn tại để đối phó với thực tế là những thứ có thể giống ngày hôm nay, có thể không giống nhau vào ngày mai và không liên kết tượng trưng hoặc liên kết cứng nào có vẻ phù hợp trong những trường hợp như vậy.
supercat

1
@supercat: với nhiều tệp như vậy, đây là một giải pháp hoàn toàn tốt để sử dụng một liên kết tượng trưng đến một phiên bản chính thức, một phiên bản chỉ đọc. Nếu sau đó bạn muốn thay đổi bản sao của mình, hãy thay thế symlink bằng một bản sao vật lý.
rẽ trái

1
@leftaroundabout: Một điều mà đôi khi tôi nghĩ sẽ rất thú vị nếu người ta có thể giảm nguy cơ va chạm băm được thiết kế đến mức chấp nhận được là có một định danh tham chiếu phổ quát dựa trên hàm băm, thay vì liên kết với một tên tệp "logic" người ta sẽ tạo ra một liên kết dựa trên hàm băm. Lưu trữ sau đó sẽ lưu trữ 256 byte hoặc hơn băm thay vì lưu trữ các tệp thực sự lớn. Một biến thể của cách tiếp cận như vậy cũng có thể được sử dụng để cho phép lưu vào bộ đệm của các tệp cần được bảo vệ chống lại sự thay đổi.
supercat

2

Định dạng tệp PNG đã sử dụng thuật toán nén DEFLATE trong nội bộ. Đây là thuật toán tương tự như được sử dụng bởi xz, gzip và zip - chỉ trong một số biến thể. tar.gztar.xztận dụng sự tương tự giữa các tập tin, điều zipnày không.

Vì vậy, trên thực tế, bạn thực hiện nén DEFLATE trên các tệp nén DEFLATE - đây là lý do tại sao các tệp giữ gần như kích thước ban đầu.

Các bzip2chương trình (cũng là một thuật toán có liên quan) là tốt hơn khi nói đến (gần) các tập tin giống hệt nhau.

# for i in $(seq 4); do cp test.png test$i.png; done
# tar -cjf archive.tar.bz2 *.png
# ls -l
-rw-r--r-- 1 abcde users  43813 15. Jul 08:45 test.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:45 test1.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test2.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test3.png
-rw-r--r-- 1 abcde users  43813 15. Jul 08:46 test4.png
-rw-r--r-- 1 abcde users  68115 15. Jul 08:47 archive.tar.bz2

PNG - xin lưu ý rằng có các bộ lọc được sử dụng, loại bỏ khử không chuẩn (dù sao cái nào cũng là tiêu chuẩn?) Và bạn có đúng rằng việc chạy cùng một thuật toán hai lần không mang lại điều gì (hoặc ít nhất là nó không có lợi), nhưng chạy cùng một thuật toán với các cài đặt khác nhau không được đảm bảo để thất bại. Ngoài ra, có sự khác biệt giữa deflate32, deflate64, LZW, LZMA, bạn không thể chỉ nói rằng tất cả chúng đều sử dụng cùng một def def.
Ác

Đó là lý do tại sao tôi nói "trong một số biến thể". Tất nhiên, DEFLATE đề cập đến một loại thuật toán chứ không phải là một triển khai nhất định.
rexkogitans

3
Điều này bỏ lỡ điểm khi tôi hiểu nó. Có, chỉ một tệp PNG đã được nén, vì vậy tôi không mong đợi việc nén thêm bất kỳ loại nào có hiệu quả. Nhưng một sự kết hợp của một số tệp PNG giống hệt nhau (về cơ bản là tình huống ở đây) có thể được dự kiến ​​sẽ nén xuống không quá nhiều so với kích thước của một trong số chúng.
Don nở

Rõ ràng, các thuật toán nén bỏ lỡ điểm đó. bzip2bắt nó : tar -cjf archive.tar.bz2 *.png. Cập nhật trong câu trả lời của tôi.
rexkogitans
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.