Làm thế nào là PNG lossless cho rằng nó có một tham số nén?


156

Các tệp PNG được cho là sử dụng nén không mất dữ liệu. Tuy nhiên, bất cứ khi nào tôi ở trong trình chỉnh sửa hình ảnh, chẳng hạn như GIMP và cố gắng lưu hình ảnh dưới dạng tệp PNG, nó sẽ yêu cầu tham số nén, nằm trong khoảng từ 0 đến 9. Nếu nó có tham số nén ảnh hưởng đến độ chính xác hình ảnh của hình ảnh nén, làm thế nào để làm cho PNG lossless?

Tôi có nhận được hành vi lossless chỉ khi tôi đặt tham số nén thành 9 không?


40
Hầu hết các thuật toán nén không mất dữ liệu đều có các nút điều chỉnh (như kích thước từ điển) được khái quát hóa trong một bộ điều chỉnh bao nhiêu nỗ lực để giảm thiểu thanh trượt kích thước đầu ra. Điều này hợp lệ cho ZIP, GZip, BZip2, LZMA, ...
Daniel B

20
Câu hỏi có thể được nêu khác nhau. Nếu không có chất lượng bị mất từ ​​quá trình nén, thì tại sao không luôn luôn sử dụng nén tạo ra kích thước nhỏ nhất? Câu trả lời sẽ là vì nó đòi hỏi nhiều RAM hơn và nhiều thời gian CPU hơn để nén và giải nén. Đôi khi bạn muốn nén nhanh hơn và không quan tâm nhiều đến tỷ lệ nén.
kasperd

14
Nén PNG gần giống với các tệp ZIPping. Bạn có thể nén chúng nhiều hơn hoặc ít hơn nhưng bạn sẽ lấy lại được tệp chính xác khi giải nén - đó là điều khiến nó không bị mất.
mikebabcock

13
Hầu hết các phần mềm nén như Zip và Rar cho phép bạn nhập "mức nén" cho phép bạn chọn giữa các tệp nhỏ hơn <-> thời gian ngắn hơn. Điều đó không có nghĩa là những phần mềm này sẽ loại bỏ dữ liệu trong quá trình nén. Cài đặt này (trong GIMP, pngcrush, v.v.) là tương tự.
Salman A

2
@naxa: Không có lời cảnh báo nào về việc png thực sự mất mát như thế nào. Nó luôn luôn mất 100%. Bài viết chỉ cảnh báo bạn về các lỗi mà một số trình duyệt cũ gặp phải khi triển khai PNG để xử lý hiệu chỉnh gamma. Và điều đó chỉ có ý nghĩa nếu bạn cần kết hợp màu với màu CSS (không được chỉnh sửa gamma).
Pauli L

Câu trả lời:


183

PNG là lossless. GIMP rất có thể chỉ là không sử dụng từ tốt nhất trong trường hợp này. Hãy coi nó là "chất lượng nén", hay nói cách khác là "mức độ nén". Với mức nén thấp hơn, bạn có được một tệp lớn hơn, nhưng sẽ mất ít thời gian hơn để sản xuất, trong khi với độ nén cao hơn, bạn sẽ có được một tệp nhỏ hơn mất nhiều thời gian hơn để sản xuất. Thông thường, bạn nhận được lợi nhuận giảm dần (nghĩa là không giảm nhiều kích thước so với mức tăng thời gian cần thiết) khi tăng đến mức nén cao nhất, nhưng tùy thuộc vào bạn.


42
Ngoài ra, nén PNG thực sự có nhiều tham số có thể điều chỉnh trong đó các điều chỉnh theo một trong hai hướng có thể thu nhỏ kích thước đầu ra tùy thuộc vào nội dung của nguồn - nó phức tạp hơn nhiều so với thanh trượt "tốt hơn" và "tệ hơn" đơn giản. Đối với mục đích chung, nó không quá quan trọng, nhưng nếu bạn muốn nhỏ nhất tuyệt đối thì hãy sử dụng một công cụ như thế pngcrushcó thể so sánh nhiều biến thể cho nhỏ nhất có thể.
Bob

4
Mức nén cao hơn làm tăng thời gian nén, nhưng nó cũng ảnh hưởng đến việc giải nén ?
Nolonar

10
@Nolonar Nói chung là không; nếu bất cứ điều gì mức nén cao hơn thường làm giảm thời gian giải nén vì có ít dữ liệu hơn để nó phải đọc và xử lý. Thời gian nén lâu hơn là do thực hiện một công việc kỹ lưỡng hơn là tìm các mẫu để nén (đơn giản hóa).
lông mịn

1
Câu trả lời của @fluffy LordNeckbeard có độ nén cao nhất mất 5 lần để giải mã hơn mức thấp nhất.
André Chalella

1
Đối với PNG, nó khá phổ biến để có thời gian nén lâu hơn cho các tập tin tốt hơn nén. Vấn đề là với PNG, một mẹo có thể là áp dụng thuật toán nén lặp đi lặp lại miễn là tệp nhỏ hơn. Một khi kích thước tăng lên, bạn ngừng áp dụng nó. Vì vậy, rất có thể bạn áp dụng thuật toán nén 5 hoặc 6 lần, điều đó có nghĩa là bạn phải giải nén tệp 5 hoặc 6 lần để hiển thị hình ảnh.
yo '

213

PNG được nén, nhưng lossless

Mức nén là sự đánh đổi giữa kích thước tệp và tốc độ mã hóa / giải mã. Để khái quát quá mức, ngay cả các định dạng không phải hình ảnh, chẳng hạn như FLAC, cũng có các khái niệm tương tự.

Mức nén khác nhau, cùng một đầu ra được giải mã

Mặc dù kích thước tệp là khác nhau, do các mức nén khác nhau, đầu ra được giải mã thực tế sẽ giống hệt nhau.

Bạn có thể so sánh các giá trị băm MD5 của các đầu ra được giải mã với ffmpegviệc sử dụng bộ trộn MD5 .

Điều này được hiển thị tốt nhất với một số ví dụ:

Tạo tập tin PNG:

$ ffmpeg -i input -vframes 1 -compression_level 0 0.png
$ ffmpeg -i input -vframes 1 -compression_level 100 100.png
  • Theo mặc định ffmpegsẽ sử dụng -compression_level 100cho đầu ra PNG.

So sánh kích thước tệp:

$ du -h *.png
  228K    0.png
  4.0K    100.png

Giải mã các tệp PNG và hiển thị băm MD5:

$ ffmpeg -loglevel error -i 0.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

$ ffmpeg -loglevel error -i 100.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

Vì cả hai giá trị băm đều giống nhau, bạn có thể yên tâm rằng các đầu ra được giải mã (video thô, không nén) hoàn toàn giống nhau.


26
+1 không biết rằng ffmpeg có thể xử lý pngs.
Lekensteyn

21
@Lekensteyn Thật tuyệt khi chụp ảnh màn hình . Ví dụ để bỏ qua 30 giây và chụp ảnh màn hình: ffmpeg -ss 30 -i input -vframes 1 output.pngCũng tốt để tạo video từ hình ảnh và ngược lại.
llogan

Điều đó có nghĩa là PNG cần được giải nén mỗi khi nó được hiển thị? Bởi vì nếu đó là sự thật, chúng ta phải
akshay2000

Nếu bạn đọc lại tệp từ đĩa hoặc bộ đệm, vâng, nó phải được giải nén. Trong cùng một trang, bộ đệm có thể sử dụng lại phiên bản giải nén.
David Mårtensson

1
@ akshay2000 Phụ thuộc vào cách chương trình hoạt động để hiển thị PNG. Thông thường tệp được đọc từ đĩa, giải nén và đệm trong RAM. Vì vậy, miễn là nó được đệm trong RAM, nó sẽ không cần phải giải nén hình ảnh một lần nữa.
xZise

24

Nén PNG xảy ra trong hai giai đoạn.

  1. Nén trước sắp xếp lại dữ liệu hình ảnh để nó có thể nén được nhiều hơn bằng thuật toán nén cho mục đích chung.
  2. Quá trình nén thực tế được thực hiện bởi DEFLATE, tìm kiếm và loại bỏ các chuỗi byte trùng lặp bằng cách thay thế chúng bằng các mã thông báo ngắn.

Vì bước 2 là một nhiệm vụ rất tốn thời gian / tài nguyên, thư viện zlib bên dưới (đóng gói DEFLATE thô) có tham số nén nằm trong khoảng từ 1 = Nén nhanh nhất, 9 = Nén tốt nhất, 0 = Không nén. Đó là nơi có phạm vi 0-9 và GIMP chỉ cần chuyển tham số đó xuống zlib. Quan sát rằng ở cấp 0, png của bạn sẽ thực sự lớn hơn một chút so với bitmap tương đương.

Tuy nhiên, cấp 9 chỉ là "tốt nhất" mà zlib sẽ cố gắng, và vẫn là một giải pháp thỏa hiệp .
Để thực sự cảm nhận được điều này, nếu bạn sẵn sàng dành 1000 lần sức mạnh xử lý cho một tìm kiếm toàn diện, bạn có thể đạt được mật độ dữ liệu cao hơn 3-8% bằng cách sử dụng zopfli thay vì zlib.
Việc nén vẫn không mất dữ liệu, đó chỉ là cách biểu thị dữ liệu DEFLATE tối ưu hơn. Điều này tiếp cận giới hạn của các thư viện tương thích với zlib và do đó, đây là cách nén "tốt nhất" thực sự có thể đạt được khi sử dụng PNG.


2
Lưu ý: Thời gian giải nén là như nhau bất kể mức độ nén hay số lần lặp khi sử dụng zopflipng.
Adria

16

Động lực chính cho định dạng PNG là tạo ra một sự thay thế cho GIF không chỉ miễn phí mà còn là một sự cải tiến về cơ bản trong tất cả các khía cạnh. Kết quả là, nén PNG hoàn toàn không mất dữ liệu - nghĩa là dữ liệu ảnh gốc có thể được xây dựng lại chính xác, từng bit một - giống như trong GIF và hầu hết các dạng TIFF.

PNG sử dụng quy trình nén 2 giai đoạn:

  1. Nén trước: lọc (dự đoán)
  2. Nén: DEFLATE (xem wikipedia )

Bước tiền nén được gọi là lọc, là phương pháp biến đổi ngược lại dữ liệu hình ảnh để động cơ nén chính có thể hoạt động hiệu quả hơn.

Ví dụ đơn giản, hãy xem xét một chuỗi các byte tăng đồng đều từ 1 đến 255:

1, 2, 3, 4, 5, .... 255

Vì không có sự lặp lại trong chuỗi, nó nén rất kém hoặc không tốt chút nào. Nhưng một sửa đổi nhỏ của chuỗi - cụ thể là để riêng byte đầu tiên nhưng thay thế từng byte tiếp theo bằng sự khác biệt giữa nó và tiền thân của nó - biến chuỗi thành một tập hợp cực kỳ nén:

1, 1, 1, 1, 1, .... 1

Việc chuyển đổi ở trên là lossless, vì không có byte nào bị bỏ qua và hoàn toàn có thể đảo ngược. Kích thước nén của loạt này sẽ giảm đi nhiều, nhưng loạt ban đầu vẫn có thể được phục hồi hoàn hảo.

Dữ liệu hình ảnh thực tế hiếm khi hoàn hảo, nhưng lọc không cải thiện khả năng nén trong các ảnh thang độ xám và truecolor, và nó cũng có thể giúp trên một số hình ảnh bảng màu. PNG hỗ trợ năm loại bộ lọc và bộ mã hóa có thể chọn sử dụng bộ lọc khác nhau cho mỗi hàng pixel trong ảnh:

Hình ảnh, tưởng tượng

Thuật toán hoạt động trên các byte, nhưng đối với các pixel lớn (ví dụ: RGB 24 bit hoặc 64 bit RGBA) chỉ các byte tương ứng được so sánh, có nghĩa là các thành phần màu đỏ của màu pixel được xử lý tách biệt với các thành phần pixel màu lục và màu xanh lam.

Để chọn bộ lọc tốt nhất cho mỗi hàng, một bộ mã hóa sẽ cần kiểm tra tất cả các kết hợp có thể. Điều này rõ ràng là không thể, vì ngay cả một hình ảnh 20 hàng sẽ yêu cầu thử nghiệm hơn 95 nghìn tỷ kết hợp, trong đó "thử nghiệm" sẽ liên quan đến việc lọc và nén toàn bộ hình ảnh.

Mức nén thường được định nghĩa là các số từ 0 (không có) và 9 (tốt nhất). Chúng đề cập đến sự đánh đổi giữa tốc độ và kích thước và liên quan đến số lượng kết hợp các bộ lọc hàng sẽ được thử. Không có tiêu chuẩn nào liên quan đến các mức nén này, vì vậy mọi trình chỉnh sửa hình ảnh có thể có thuật toán riêng về số lượng bộ lọc cần thử khi tối ưu hóa kích thước hình ảnh.

Mức nén 0 có nghĩa là các bộ lọc hoàn toàn không được sử dụng, điều này nhanh nhưng lãng phí. Các mức cao hơn có nghĩa là ngày càng có nhiều kết hợp được thử trên các hàng hình ảnh và chỉ những kết hợp tốt nhất được giữ lại.

Tôi đoán rằng cách tiếp cận đơn giản nhất để nén tốt nhất là tăng dần thử nghiệm nén từng hàng với từng bộ lọc, lưu kết quả nhỏ nhất và lặp lại cho hàng tiếp theo. Số tiền này để lọc và nén toàn bộ hình ảnh năm lần, đây có thể là sự đánh đổi hợp lý cho một hình ảnh sẽ được truyền và giải mã nhiều lần. Các giá trị nén thấp hơn sẽ làm ít hơn, theo quyết định của nhà phát triển công cụ.

Ngoài các bộ lọc, mức nén cũng có thể ảnh hưởng đến mức nén zlib là một số trong khoảng từ 0 (không có Độ lệch) và 9 (Độ lệch tối đa). Mức 0-9 được chỉ định ảnh hưởng đến việc sử dụng bộ lọc, tính năng tối ưu hóa chính của PNG, vẫn phụ thuộc vào nhà phát triển công cụ.

Kết luận là PNG có một tham số nén có thể làm giảm đáng kể kích thước tệp, tất cả mà không làm mất dù chỉ một pixel.

Nguồn:

Tài liệu libpng đồ họa mạng di động Wikipedia
Chương 9 - Nén và lọc


1
Tôi không nghĩ cài đặt mức nén thay đổi việc sử dụng các bộ lọc. Cài đặt cấp 1-9 có lẽ chỉ chọn mức nén zlib cấp 1-9 và cấp 0 có nghĩa là thuật toán khử nhiễu hoàn toàn không được sử dụng. Hầu hết các triển khai có thể không thay đổi các bộ lọc mỗi hàng, nhưng chỉ sử dụng bộ lọc Đường dẫn mọi lúc.
Pauli L

@PauliL: Tôi không đồng ý, vì trong tất cả các so sánh của phần mềm nén PNG, có sự khác biệt rất lớn giữa kích thước của hình ảnh được tạo. Nếu tất cả các sản phẩm sử dụng cùng một tham số cho cùng một thư viện, thì tất cả các kích thước phải giống nhau, cũng như tốc độ.
harrymc

Bạn có bất kỳ liên kết đến so sánh như vậy?
Pauli L

@PauliL: Một tìm kiếm nhanh đã đưa ra so sánh này .
harrymc

@PauliL: Có lẽ bạn đúng khi các mức nén zlib bị ảnh hưởng bởi các mức nén của PNG. Tôi đã sửa đổi câu trả lời của mình cho phù hợp, mặc dù không có công cụ nén nào ghi lại chính xác những gì họ làm. Có lẽ lời giải thích cho các công cụ có kết quả kích thước tồi tệ nhất là chúng không sử dụng bộ lọc nào cả, chỉ nén zlib.
harrymc

5

OK, tôi đã quá muộn cho tiền thưởng, nhưng dù sao đây cũng là câu trả lời của tôi.

PNG luôn luôn mất mát . Nó sử dụng thuật toán Deflate / Inflate, tương tự như thuật toán được sử dụng trong các chương trình zip.

Thuật toán Deflate tìm kiếm các chuỗi byte lặp lại và thay thế các chuỗi bằng các thẻ. Cài đặt mức nén xác định chương trình sử dụng bao nhiêu nỗ lực để tìm ra sự kết hợp tối ưu của các chuỗi byte và bao nhiêu bộ nhớ được dành riêng cho điều đó. Đó là sự thỏa hiệp giữa thời gian và việc sử dụng bộ nhớ so với kích thước tệp nén. Tuy nhiên, các máy tính hiện đại rất nhanh và có đủ bộ nhớ nên hiếm khi cần sử dụng ngoài cài đặt nén cao nhất.

Nhiều triển khai PNG sử dụng thư viện zlib để nén. Zlib có chín cấp độ nén, 1-9. Tôi không biết nội bộ của Gimp, nhưng vì nó có cài đặt mức nén 0-9 (0 = không nén), tôi sẽ giả sử cài đặt này chỉ đơn giản là chọn mức nén của zlib.

Thuật toán Deflate là một thuật toán nén cho mục đích chung , nó chưa được thiết kế để nén ảnh. Không giống như hầu hết các định dạng tệp hình ảnh lossless khác, định dạng PNG không giới hạn ở đó. Nén PNG tận dụng kiến ​​thức mà chúng tôi đang nén hình ảnh 2D . Điều này đạt được bằng cách gọi là bộ lọc .

(Bộ lọc thực sự là một thuật ngữ sai lệch một chút ở đây. Nó không thực sự thay đổi nội dung hình ảnh, nó chỉ mã hóa theo cách khác. Tên chính xác hơn sẽ là bộ mã hóa delta.)

Đặc tả PNG chỉ định 5 bộ lọc khác nhau (bao gồm 0 = none). Bộ lọc thay thế các giá trị pixel tuyệt đối bằng sự khác biệt từ pixel trước sang trái, lên, chéo hoặc kết hợp các giá trị pixel đó. Điều này có thể cải thiện đáng kể tỷ lệ nén. Mỗi dòng quét trên hình ảnh có thể sử dụng bộ lọc khác nhau. Bộ mã hóa có thể tối ưu hóa việc nén bằng cách chọn bộ lọc tốt nhất cho mỗi dòng.

Để biết chi tiết về định dạng tệp PNG, xem Đặc tả PNG .

Vì có số lượng kết hợp gần như vô hạn, nên không thể thử tất cả. Do đó, các loại chiến lược khác nhau đã được phát triển để tìm ra sự kết hợp hiệu quả. Hầu hết các trình chỉnh sửa hình ảnh có thể thậm chí không cố gắng tối ưu hóa các bộ lọc theo từng dòng mà thay vào đó chỉ sử dụng bộ lọc cố định (rất có thể là Paeth).

Một chương trình dòng lệnh pngcrush thử một số chiến lược để tìm ra kết quả tốt nhất. Nó có thể giảm đáng kể kích thước tệp PNG được tạo bởi các chương trình khác, nhưng có thể mất khá nhiều thời gian trên các hình ảnh lớn hơn. Xem Nguồn Forge - pngcrush .


3

Mức nén trong công cụ lossless luôn chỉ là giao dịch tài nguyên mã hóa (thường là thời gian, đôi khi cũng là RAM) so với bitrate. Chất lượng luôn luôn là 100%.

Tất nhiên, máy nén không tổn hao KHÔNG BAO GIỜ đảm bảo bất kỳ nén thực tế nào. Dữ liệu ngẫu nhiên là không thể nén được, không có mẫu nào để tìm và không có sự tương đồng. Lý thuyết thông tin Shannon và tất cả những thứ đó. Điểm chung của việc nén dữ liệu không mất dữ liệu là con người thường làm việc với dữ liệu không ngẫu nhiên cao, nhưng để truyền và lưu trữ, chúng ta có thể nén nó xuống càng ít bit càng tốt. Hy vọng xuống càng gần càng tốt với sự phức tạp Kolmogorov của bản gốc.

Cho dù đó là dữ liệu chung zip hay 7z, hình ảnh png, âm thanh flac hoặc video h.264 (ở chế độ không mất dữ liệu), điều đó đều giống nhau. Với một số thuật toán nén, như lzma (7zip) và bzip2, việc tăng tốc độ cài đặt nén sẽ tăng thời gian CPU của DECODER (bzip2) hoặc thường xuyên hơn chỉ là dung lượng RAM cần thiết (lzma và bzip2 và h.264 với nhiều khung tham chiếu hơn) . Thông thường bộ giải mã phải lưu nhiều đầu ra được giải mã hơn trong RAM vì giải mã byte tiếp theo có thể đề cập đến một byte được giải mã nhiều megabyte trước đây (ví dụ: một khung hình video giống với một nửa giây trước sẽ được mã hóa với các tham chiếu đến 12 khung hình trở lại ). Điều tương tự với bzip2 và chọn kích thước khối lớn, nhưng điều đó cũng giải nén chậm hơn. lzma có một từ điển kích thước thay đổi và bạn có thể tạo các tệp yêu cầu 1.


Hmmm Tôi đã thấy một triển khai để kiểm soát động cơ bước ổ đĩa và trực tiếp đi đầu để cung cấp nén không mất mát được đảm bảo. Mã hóa Manchester dễ dàng bị đánh bại nếu bạn có nguồn đồng hồ độ phân giải cao.
Joshua

@Joshua: Sử dụng định dạng lưu trữ vật lý mật độ cao hơn không giống như nén dữ liệu ...
SamB

0

Thứ nhất, PNG luôn luôn mất mát. Nghịch lý rõ ràng là do có hai loại nén khác nhau có thể (đối với bất kỳ loại dữ liệu nào): mất mát và mất mát.

Nén không mất dữ liệu nén dữ liệu (tức là kích thước tệp) bằng nhiều thủ thuật khác nhau, giữ mọi thứ và không thực hiện bất kỳ phép tính gần đúng nào. Kết quả là, có thể nén không mất dữ liệu sẽ không thực sự có thể nén mọi thứ. (Dữ liệu kỹ thuật với entropy cao có thể rất khó hoặc thậm chí không thể nén được đối với các phương pháp không mất dữ liệu.) Nén tổn thất xấp xỉ dữ liệu thực, nhưng phép tính gần đúng là không hoàn hảo, nhưng việc "vứt bỏ" độ chính xác này cho phép nén tốt hơn.

Dưới đây là một ví dụ tầm thường về nén không mất dữ liệu: nếu bạn có một hình ảnh được tạo từ 1.000 pixel đen, thay vì lưu trữ giá trị cho 1000 lần màu đen, bạn có thể lưu trữ số đếm (1000) và giá trị (màu đen) do đó nén 1000 pixel " hình ảnh "thành hai số. (Đây là một dạng thô của phương pháp nén không mất dữ liệu được gọi là mã hóa độ dài chạy).

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.