Nếu một hình ảnh được xoay một cách dễ dàng, tại sao kích thước tệp thay đổi?


37

Tôi đã tìm kiếm các phương pháp xoay hình ảnh lossless và tình cờ thấy câu hỏi này giải thích nó khá độc đáo:

Các phép quay "Windows Photo Viewer" có bị mất không?

Vì vậy, tôi đã tạo ra một JPEG 256 × 256 với các pixel ngẫu nhiên (bộ lọc đám mây Photoshop) và sau đó xoay nó bằng Windows Picture Viewer. Sau khi xoay, kích thước tệp thực sự tăng lên, nhưng chỉ ở lần xoay đầu tiên. Mỗi lần quay tiếp theo sau đó, kích thước tệp vẫn tĩnh. Tôi biết rằng nó xoay một cách dễ dàng bởi vì tôi đã xoay nó nhiều lần mà không giảm chất lượng đáng chú ý trong khi hình ảnh 256 × 257 được xoay 20 lần trở nên rất mất mát.


8
Kích thước tệp đã tăng lên bao nhiêu trong các thử nghiệm của bạn?
James Snell

3
@JamesSnell Tôi biết tôi nên bao gồm điều đó. Công cụ tôi vừa thực hiện bằng bộ lọc phân biệt khác nhau của GIMP ban đầu là 14,583 byte, nhưng đã thay đổi thành 23,638 byte sau khi chuyển vùng. Đó là sự khác biệt của hơn 9000 byte, có vẻ như có rất nhiều dữ liệu bổ sung nếu chúng ta chỉ nói về siêu dữ liệu.
oscilatingcretin

4
Có vẻ như rất nhiều siêu dữ liệu bổ sung. Tôi sẽ không quá nhanh để cho rằng tất cả dữ liệu bổ sung đó là siêu dữ liệu. Dường như với tôi rằng sự khác biệt về kích thước do siêu dữ liệu gần như là một hằng số (trong một vài byte để tính đại diện chuỗi của một số số).
scottbb

4
Khi cung cấp thêm thông tin phù hợp với câu hỏi, vui lòng chỉnh sửa thành câu hỏi thay vì trong các bình luận. Bình luận là phù du và đôi khi có thể được làm sạch.
scottbb

2
Tải lên phiên bản gốc của hình ảnh thử nghiệm của bạn sẽ hữu ích.
CodeInChaos

Câu trả lời:


36

Điều này rất có thể gây ra bởi mã hóa entropy , đây là giai đoạn nén lossless cuối cùng, sau khi dữ liệu hình ảnh đã được lượng tử hóa để giảm kích thước của nó.

Khi một hình ảnh JPEG được quay một cách dễ dàng, lớp mã hóa không mất dữ liệu cuối cùng này phải được hoàn tác, các hệ số DCT đã giải nén được xáo trộn xung quanh, và sau đó các hệ số được xáo trộn cần được mã hóa lại. Do hiệu quả của lớp mã hóa entropy phụ thuộc vào thứ tự các hệ số DCT trong mỗi khối, khi xoay hình ảnh sẽ thay đổi, không có gì đáng ngạc nhiên khi tệp hình ảnh được xoay có thể nhỏ hơn hoặc lớn hơn vài phần trăm so với ban đầu.

Ngoài ra còn có một số cách khác nhau để thực hiện bước mã hóa entropy, do đó, có thể kích thước tệp của cùng một hình ảnh JPEG chính xác có thể khác nhau tùy thuộc vào phần mềm thực hiện mã hóa. Một số khác biệt tiềm năng giữa các bộ mã hóa bao gồm:

  • lựa chọn mã hóa số học (hiếm nhưng có khả năng hiệu quả hơn, được sử dụng để được cấp bằng sáng chế) so với mã hóa Huffman (đơn giản hơn, tiêu chuẩn);
  • sự lựa chọn tuần tự (mỗi khối 8 x 8 pixel được mã hóa một lần) so với lũy tiến (các thành phần tần số thấp của tất cả các khối được mã hóa trước các thành phần tần số cao hơn, thường nhỏ gọn hơn một chút);
  • lựa chọn sử dụng các bảng biểu tượng Huffman tiêu chuẩn (nhanh hơn, đơn giản hơn, có thể hiệu quả hơn đối với các hình ảnh rất nhỏ) so với các bảng tùy chỉnh được tối ưu hóa cho mỗi hình ảnh (thường hiệu quả hơn đối với hình ảnh lớn, chậm hơn và phức tạp hơn để mã hóa);
  • nếu các bảng Huffman tùy chỉnh được sử dụng, các bộ mã hóa khác nhau có thể có khả năng tạo các bảng khác nhau cho cùng một dữ liệu hình ảnh;
  • các chi tiết cấp thấp khác nhau của chính quá trình mã hóa, chẳng hạn như liệu và khi nào nên bao gồm các dấu khởi động lại trong luồng dữ liệu, cũng có thể khác nhau giữa các bộ mã hóa.

Ngoài ra, những người "tệp JPEG" thường làm việc với thực sự chứa dữ liệu hình ảnh được nén JPEG được bọc trong một thùng chứa JFIF hoặc Exif , kết hợp dữ liệu hình ảnh với một hoặc nhiều khối siêu dữ liệu và đưa ra các biến chứng riêng. Ngay cả khi phần mềm xoay hình ảnh không thực sự có bất kỳ thay đổi đáng kể nào đối với siêu dữ liệu JFIF / Exif, chỉ cần sắp xếp lại dữ liệu có thể ảnh hưởng đến kích thước tệp theo một vài byte.

Cụ thể, siêu dữ liệu JFIF / Exif có thể chứa một hoặc nhiều hình thu nhỏ của hình ảnh kích thước đầy đủ và phần mềm xoay hình ảnh thực sự sẽ tái tạo (hoặc cũng có thể xoay một cách dễ dàng!) Để chúng phù hợp với hướng mới của toàn bộ kích thước hình ảnh. Điều này một mình có thể dễ dàng chiếm sự khác biệt kích thước quan sát.


4
Đối với chênh lệch 9KB (60%), dự đoán của tôi sẽ là hình thu nhỏ.
BlueRaja - Daniel Pflughoeft

JPEG có thể quá đơn giản để điều này trở thành bộ mã hóa đáng làm, nhưng bộ mã hóa video như x264 thực sự có thể xem xét khả năng của bộ mã hóa đầu vào để mã hóa những gì họ sắp xuất ra tiếp theo, khi đưa ra quyết định so với quyết định đánh đổi méo mó. (tức là quyết định mỗi giải pháp thay thế có thể tốn bao nhiêu bit và cân nhắc điều đó với lỗi mất mát). Điều này được gọi là lượng tử hóa trellis. Xem Ghi chú về việc thực hiện lượng tử hóa trong H.264 từ tác giả của x264 (Loren Merritt); ông bắt đầu với một lời giải thích khá cơ bản về mục đích.
Peter Cordes

Dù sao đi nữa, bộ mã hóa JPEG có thể đã chọn các hệ số DCT sao cho chúng nén tốt với bộ mã hóa entropy, do đó, ngay cả một máy nén tối ưu cũng không thể tạo ra một phiên bản xoay nhỏ. . (Khung hình I trong h.264 sử dụng dự đoán nội bộ, dự đoán từ các khối khác trong cùng khung hình, làm cho chúng nhỏ hơn JPEG với cùng chất lượng hình ảnh.)
Peter Cordes

24

Tôi đã tiếp tục và lặp lại thí nghiệm để xem liệu tôi có thể biết chuyện gì đang xảy ra không.

Thủ tục

Tôi đã tạo một hình ảnh RGB 256 x 256 pixel ngẫu nhiên bằng bộ lọc "Solid noise" trong GIMP (Bộ lọc> Kết xuất> Đám mây> Nhiễu rắn ...) bằng cách sử dụng cài đặt mặc định (hiển thị bên dưới):

nhập mô tả hình ảnh ở đây

Và kết quả:

nhập mô tả hình ảnh ở đây

Sau đó, tôi đã lưu hình ảnh dưới dạng JPEG bằng cách sử dụng các cài đặt mặc định:

nhập mô tả hình ảnh ở đây

Sau đó, tôi chuyển hình ảnh sang Windows và mở hình ảnh bằng Windows Photo Viewer bằng cách nhấp chuột phải vào hình ảnh trong File Explorer và chọn Xem trước từ menu. Sau đó, tôi xoay hình ảnh bằng cách sử dụng các nút ở phía dưới và lưu hình ảnh bằng cách điều hướng đến hình ảnh tiếp theo bằng các phím mũi tên.

Đối với mỗi thử nghiệm bên dưới, tôi bắt đầu với một bản sao của hình ảnh gốc và được xoay (nhấp vào nút xoay) số lần tương ứng trước khi lưu. Dưới đây là các kích thước thay đổi ( 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

Quan sát ngay lập tức

  • Windows Photo Viewer (WPV) tăng kích thước đáng kể; số lượng tăng khoảng bốn lần trong thử nghiệm này!
  • Tất cả các hình ảnh mới tăng lên cùng kích thước, nhưng chúng không giống nhau.
  • WPV không mã hóa lại hoặc thậm chí lưu lại hình ảnh khi nó được xoay bởi bội số 360 độ. (Dấu thời gian, 11:27, là khi các tệp được sao chép lần đầu tiên.)

Sử dụng cmp -ltrên các tệp nên có nội dung giống hệt nhau cho phép chúng tôi xem các tệp khác nhau ở đâu.

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

Các tệp này chỉ khác nhau ở bốn byte (thực tế là trong dấu thời gian), có nghĩa là WPV luôn làm điều tương tự; bây giờ chúng ta chỉ cần tìm ra đó là gì.

Quan sát chi tiết

Đối với điều này, tôi đã sử dụng JPEGsnoop để xem chính xác những gì trong hình ảnh.

Vì các đầu ra khá dài nên tôi đã liên kết với chúng như một ý chính . Dưới đây là tóm tắt về sự khác biệt:

  • GIMP chỉ sử dụng phân đoạn APP0(JFIF) và COM(bình luận) cho siêu dữ liệu. WPV để APP0phân đoạn không bị ảnh hưởng, nhưng tò mò thêm một byte null vào bình luận (để nó bị chấm dứt null).

  • WPV thêm hai APP1phân đoạn, đó là siêu dữ liệu Exif và XMP. Các phân đoạn này lần lượt là 4286 và 12726 byte. Họ cùng nhau chiếm gần như toàn bộ sự gia tăng của tập tin.

  • GIMP tạo ra một JPEG lũy tiến, trong khi WPV tạo ra một JPEG cơ bản (không tiến bộ). Vì lý do này, hình ảnh của GIMP có nhiều phân đoạn quét, trong khi hình ảnh WPV chỉ có một. Theo kinh nghiệm của tôi, hình ảnh tiến bộ đôi khi hơi nhỏ hơn.

  • GIMP đã sử dụng mẫu phụ sắc độ 1 × 1, trong khi WPV sử dụng mẫu phụ 2 × 2. Điều này khiến tôi tin rằng WPV không sử dụng phép quay "lossless" thực sự, trừ khi bằng cách nào đó có thể phát hiện ra đây là hình ảnh đen trắng.

Để giải quyết những vấn đề này, tôi đã chạy thử nghiệm thứ hai.

Thủ tục

Tôi đã làm theo các bước tương tự để thử nghiệm đầu tiên. Tôi đã tạo một hình ảnh RGB 256 × 256 ngẫu nhiên bằng bộ lọc nhiễu RGB (Bộ lọc> Mũi> Mũi RGB ...) với các cài đặt sau:

nhập mô tả hình ảnh ở đây

Đây là kết quả:

nhập mô tả hình ảnh ở đây

Tôi đã xuất tệp dưới dạng JPEG bằng các cài đặt sau:

nhập mô tả hình ảnh ở đây

Tiến trình đã bị tắt, nhưng Lấy mẫu con vẫn được đặt thành 4: 4: 4 (tên gọi khác của mẫu phụ 1 × 1). Chất lượng được tăng lên 98.

Tôi đã sao chép hình ảnh và xoay bản sao theo chiều kim đồng hồ; sau đó sao chép phiên bản xoay và xoay bản sao đó ngược chiều kim đồng hồ, để chúng ta có thể so sánh trực tiếp chất lượng giữa bản gốc và bản sao được xử lý WPV.

Các kết quả

-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

Mặc dù mức tăng lần này nhỏ hơn về mặt tương đối (khoảng 40%), mức tăng tuyệt đối thậm chí còn lớn hơn khoảng 62 kB. Điều này cho thấy WMV đang sử dụng mã hóa kém hiệu quả hơn.

Tôi sẽ sử dụng ImageMagick để so sánh hai hình ảnh:

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

Không có pixel nào khác nhau giữa bản gốc và bản sao xoay. Vì vậy, ngay cả khi WPV không sử dụng vòng quay "lossless" thực sự, nó vẫn đang làm một công việc đủ tốt. Tôi nghi ngờ tôi biết những gì đang xảy ra, và để giải thích tôi sẽ chuyển hướng một chút vào toán học đằng sau việc nén JPEG.

Thuật toán nén JPEG chia hình ảnh thành các khối 8 × 8 pixel. Mỗi một trong số các khối này sau đó phải chịu Biến đổi Cosine rời rạc (DCT) . Các hệ số DCT kết quả mô tả khối là tổng của các sóng tần số khác nhau. Thuật toán sau đó "vứt bỏ" một số thông tin trong sóng tần số cao tương ứng với nhiễu và chi tiết rất nhỏ. Quá trình giải mã đảo ngược DCT, cộng các sóng được lưu trữ lại với nhau để lấy lại khối.

Có thể xoay "sóng" DCT mà không thực sự hoàn tác và làm lại biến đổi (về cơ bản, bạn biến tất cả các sóng ngang thành sóng dọc và ngược lại). Những gì tôi nghĩ xảy ra trong WPV là hình ảnh thực sự được giải mã, xoay và sau đó được mã hóa lại. Trong quá trình mã hóa lại, vì kích thước hình ảnh của chúng tôi là bội số của cả hai chiều, mỗi khối mới tương ứng với một trong các khối ban đầu. Điều quan trọng là, vì mỗi khối không có các thành phần tần số cao, thuật toán sẽ không loại bỏ bất kỳ thông tin nào và tìm thấy chính xác các thành phần DCT đúng mà một phép quay không mất "thực" sẽ có.

Cuối cùng, tôi sẽ xem lại các thành phần của các tệp JPEG. Các kết quả được liên kết lại như là ý chính . So sánh hai:

  • Hình ảnh WPV chứa thêm siêu dữ liệu Exif có thêm 4286 + 2 byte, thêm 1 byte trong nhận xét và 12.726 + 2 byte siêu dữ liệu XMP. Đây là tổng số 17.017 byte siêu dữ liệu bổ sung. Tất cả những gì dữ liệu được sử dụng cho? Tôi nhìn vào tập tin với trình soạn thảo hex đáng tin cậy của tôi và một bản sao của các tiêu chuẩn có liên quan:

    • Exif siêu dữ liệu có cấu trúc giống như một hình ảnh TIFF, trong đó có một số thẻ (có cách phức tạp hơn, nhưng tôi sẽ bỏ qua ngay nó). Hầu hết các byte trong phân đoạn Exif được chứa trong hai thẻ giống hệt nhau với số thẻ EA1C(59.932 thập phân). Số thẻ đó không được ghi lại ở bất cứ đâu tôi có thể tìm thấy. Cả hai thẻ chứa 2060 byte của kiểu "không xác định", mà tất cả đều rỗng byte trừ trong sáu đầu tiên ( 1C EA 00 00 00 08). Tôi không biết những thẻ này là gì, tại sao có hai trong số chúng, và tại sao chúng cần có 2 kB mỗi thẻ.

    • Siêu dữ liệu XMP thực sự là toàn bộ tài liệu XML được nhúng với không gian tên và UUID dài, chỉ chứa chuỗi phiên bản WPV (đã có trong siêu dữ liệu Exif). Tuy nhiên, điều đó chỉ chiếm khoảng 400 byte. Phần còn lại của phân khúc là 122 lần lặp lại của 100 khoảng trắng theo sau là một dòng mới . Đó là hơn 12.000 byte không gian lãng phí hoàn toàn.

  • Giống như thử nghiệm trước đó, cả GIMP và WPV đều sử dụng các bảng lượng tử hóa DCT giống nhau. Điều này có nghĩa là họ nên tính toán chính xác các hệ số DCT, đó là lý do tại sao các hình ảnh giống hệt nhau. Tôi không chắc chắn nếu WPV chỉ sử dụng các bảng lượng tử hóa tương tự hoặc nếu nó sao chép các bảng từ đầu vào.

  • Không giống như thử nghiệm trước, lần này WPV sử dụng mẫu phụ 1 × 1, do đó, thực tế có thể phát hiện ra rằng đây là hình ảnh màu (hoặc ít nhất là các mẫu cao hơn là cần thiết để mã hóa lại hình ảnh một cách dễ dàng).

  • GIMP và WPV sử dụng các bảng Huffman khác nhau (một phần của bước mã hóa entropy). Các bảng cho WPV lớn hơn tổng cộng 279 byte và trong một trường hợp chứa gấp 7 lần số mã.

    Nhìn vào số liệu thống kê của JPEGsnoop, chúng ta có thể thấy rằng một số mã này hiếm khi được sử dụng. Ví dụ, trong ID: 1, Class: ACbảng, trong số 119 mã 16 bit được xác định, chỉ có 23 mã thực sự được sử dụng. Nhìn chung, phân khúc quét thực tế lớn hơn 28,5% trong phiên bản WPV.

Tóm lược

  • WPV có thể không thực hiện các phép quay "lossless" thực sự, nhưng các phép quay dường như không thực sự mất.

  • Kích thước bổ sung một phần là do một lượng siêu dữ liệu được thêm vào cố định và một phần do mã hóa entropy kém hiệu quả hơn.

Thông tin phiên bản:

  • Hệ điều hành (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
    
  • HĐH (Windows):

    nhập mô tả hình ảnh ở đây

  • GIMP (Linux): 2.8,14 (từ gói gimp, phiên bản 2.8.14-1+deb8u1)

    nhập mô tả hình ảnh ở đây

  • Window Photo Viewer (theo siêu dữ liệu hình ảnh):

    Microsoft Windows Photo Viewer 10.0.10586.0
    

20

EDIT : Câu trả lời này đã được đăng trước khi tôi biết rằng các tệp đã tăng kích thước khoảng 9 KiB (9055 byte cho hình ảnh 256 × 256, 9612 KiB cho hình ảnh 512 × 512).

Trong tất cả khả năng, khi bạn lần đầu tiên xoay hình ảnh, Windows Picture Viewer đã thực hiện một (hoặc cả hai) việc sau:

  1. Đã thêm thẻ EXIF ​​không có trong hình ảnh JPEG gốc (có lẽ là thẻ Định hướng);
  2. Thông tin được sửa đổi / thêm vào thẻ đã tồn tại (có thể là thẻ Phần mềm xử lý hoặc Phần mềm hình ảnh).

Điều này làm tăng kích thước tệp vì thẻ EXIF ​​bổ sung (và / hoặc dữ liệu bổ sung cho các thẻ hiện có).

Các lần quay tiếp theo không làm tăng kích thước tệp vì tất cả các thẻ và / hoặc dữ liệu thẻ mà WPV sẽ thêm / sửa đổi đã có sẵn. Chỉ giá trị Thẻ Định hướng thay đổi (và có lẽ cả giá trị thẻ ngày / giờ).


EDIT : Gần như chắc chắn rằng lời giải thích này không thể chiếm khoảng 9 KiB dữ liệu bổ sung trong tệp. Hơn nữa, không có bất kỳ lý do nào khác cho việc tăng kích thước, giải thích này sẽ cho rằng việc tăng kích thước sẽ ít nhiều không đổi (modulo một số khác biệt về độ dài giữa các biểu diễn chuỗi của dữ liệu số, có thể là một vài byte). Đó rõ ràng không phải là những gì đang xảy ra ở đây, ít nhất là không phải là lời giải thích hoàn chỉnh.


1
Và một thẻ EXIF ​​sẽ chiếm 9kB? Chà, điều này ít nhất là dễ kiểm tra - yêu cầu OP xóa EXIF ​​hoặc các thẻ khác khỏi hình ảnh được xoay và xem kích thước tệp thay đổi như thế nào.
Carl Witthoft

2
@CarlWitthoft 9kB là thông tin mới. Chỉnh sửa để đề cập đến điều đó.
scottbb

3

Nếu không có kỹ thuật đảo ngược, bộ giải mã jpeg không thể nói chắc chắn được. Thực tế có một số tiêu chuẩn jpeg và trái với niềm tin phổ biến, không phải tất cả chúng đều có thể được sửa đổi mà không cần mã hóa lại.

Có thể lần lưu đầu tiên ghi lại mất mát vào hương vị jpeg ưa thích của nó và các lần quay tiếp theo là một chỉnh sửa siêu dữ liệu đơn giản hoặc một thao tác trực tiếp trên bảng DCT (có thể cho một số lược đồ mã hóa).

Việc tăng kích thước tệp cũng có thể bao gồm một số siêu dữ liệu bổ sung, mặc dù 9k có vẻ rất nhiều, điều đó là có thể. Sự gia tăng cũng có thể được tính bằng việc thêm hình thu nhỏ có thể không có trong đầu ra từ GIMP. Chúng tôi có thể lấy thêm thông tin từ các tệp trực tiếp (trước WPV và sau).

Trong mọi trường hợp, cố gắng làm việc không mệt mỏi với jpeg thực sự là một việc vặt vì nó chỉ hữu ích với một số kích thước hình ảnh nhất định, không phải tất cả các bộ giải mã và mã hóa đều giống hệt nhau và nó yêu cầu các trình soạn thảo đó phải làm việc trực tiếp với nội dung jpeg mà bạn không thể dựa vào trường hợp ... Chỉ vì nó làm như vậy bây giờ không có nghĩa là nó sẽ tiếp tục trong tương lai.

Đặt cược tốt hơn của bạn là làm việc với một định dạng lossless và tránh hoàn toàn nỗi đau.


2
Tôi hoàn toàn không tin rằng xoay dữ liệu jpeg sẽ gây ra mã hóa lại ở vị trí đầu tiên.
Carl Witthoft

Phụ thuộc vào việc bạn có phải là lập trình viên hay không ... Tôi đoán là bạn không. Bạn phải đặc biệt tìm kiếm sự tối ưu hóa đó để thực hiện thay đổi tối thiểu đó nếu không một thao tác lưu sẽ bắt đầu từ bitmap không nén.
James Snell

3
Từ câu hỏi được liên kết, rõ ràng Windows Photo Viewer không thể xoay JPEG một cách dễ dàng.
vclaw

2
@James Tôi không phải là lập trình viên cấp thấp, tho 'Tôi chơi trên TV :-). OP đã cung cấp một liên kết đến một mô tả chính xác về thời điểm sẽ được mã hóa lại và khi nào thì không. Tôi đã suy luận từ cuộc thảo luận rằng anh ta chỉ được xoay vòng bởi $ \ frac {\ pi} {2} $. Tôi đồng ý rằng xoay góc tùy ý gây ra mã hóa lại và vì vấn đề đó sẽ gây mất thông tin trừ khi hình ảnh X-by-Y được nhúng vào một vùng ít nhất là cạnh huyền.
Carl Witthoft

1
Chúng tôi khá chắc chắn rằng chúng tôi biết rằng WPV đang quay ngược chiều cho hình ảnh với bội số kích thước là 8/16. Xem bình luận của @ Tristan cho câu trả lời của Matt Grum cho câu hỏi liên quan đến OP. Tristan làm việc trong nhóm WPV tại Microsoft và về cơ bản xác nhận.
scottbb

1

Chỉ có thể xoay JPEG không mất dữ liệu mà không cần giới thiệu các tạo phẩm biên nếu kích thước hình ảnh là bội số của kích thước khối (thường là [/ luôn luôn?] 8). Xem trang người dùng jpegtran (xin lỗi tôi không có liên kết chính tắc tốt cho nó; vui lòng chỉnh sửa nếu bạn tìm thấy) để biết chi tiết về những gì liên quan:

Việc chuyển đổi chuyển vị không có hạn chế về
kích thước hình ảnh . Các biến đổi khác hoạt động khá kỳ quặc nếu kích thước hình ảnh không phải là bội số của kích thước iMCU (thường là 8 hoặc 16 pixel), vì chúng chỉ có thể chuyển đổi các khối dữ liệu hệ số DCT hoàn chỉnh theo cách mong muốn.

hành vi mặc định của jpegtran khi chuyển đổi hình ảnh có kích thước lẻ
được thiết kế để duy trì tính thuận nghịch chính xác và tính
nhất quán toán học của bộ chuyển đổi. Như đã nêu, transpose
có thể lật toàn bộ khu vực hình ảnh. Phản chiếu ngang để lại bất kỳ cột iMCU nào ở cạnh phải không bị ảnh hưởng, nhưng có thể lật tất cả các hàng của hình ảnh. Tương tự, phản chiếu dọc để lại bất kỳ hàng iMCU một phần nào ở cạnh dưới cùng không bị ảnh hưởng, nhưng có thể lật tất cả các cột. Các biến đổi khác có thể được xây dựng thành chuỗi các hoạt động chuyển vị và lật; để thống nhất, các hành động của chúng trên các pixel cạnh được xác định giống như kết quả cuối cùng của chuỗi chuyển đổi và lật tương ứng.

Để sử dụng thực tế, bạn có thể muốn loại bỏ bất kỳ
pixel cạnh không thể chuyển đổi hơn là có một dải trông lạ dọc theo cạnh
phải và / hoặc cạnh dưới của hình ảnh được chuyển đổi. Để làm điều này, thêm công tắc -trim:

Tôi nghi ngờ Windows Photo Viewer đang tránh vấn đề này bằng cách thực hiện giải nén và giải nén chất lượng cực cao để mô phỏng hành vi mất dữ liệu khi kích thước hình ảnh không phải là bội số của 8, thay vì thực sự thực hiện xoay vòng không mất dữ liệu. Một tiện ích tốt sẽ chỉ làm mất dữ liệu thực tế, tạo tác và tất cả, hoặc giảm một vài pixel, thay vì làm hỏng chất lượng của toàn bộ hình ảnh (và tăng kích thước tệp).


1
không liên quan cho hình ảnh 256x256.
THS

Tôi đã đọc sai và nghĩ rằng vấn đề là dành cho phiên bản 257x257.
R ..

0

Tôi không có câu trả lời chắc chắn nhưng một số lý thuyết có thể về lý do tại sao điều đó xảy ra. Một số loại tệp hoạt động theo cách hai mã khác nhau cho một hình ảnh của loại tệp đó không nhất thiết phải tạo ra các hình ảnh khác nhau. Ví dụ, loại tệp PNG hoạt động theo cách đó vì nó cho phép nền trong suốt nhưng hình ảnh có nền trong suốt và loại tương tự ngoại trừ nền tương tự có màu trắng xuất hiện chính xác theo cùng một cách. Một tệp hình ảnh được cho là được nén nếu nó chiếm ít hơn 3 byte bộ nhớ cho mỗi pixel. Tôi tin rằng ngoại trừ những cái có nền trong suốt, không có hai tệp PNG nào tạo ra cùng một hình ảnh. Khi bạn lưu hình ảnh dưới dạng PNG, nó sẽ chuyển đổi nó thành mã tạo ra hình ảnh gốc và ngoại trừ những hình ảnh rất khác thường như hình ảnh trong đó mỗi pixel là một màu ngẫu nhiên của tất cả 2 ^ 24 màu, mã sẽ chiếm ít bộ nhớ hơn 3 byte mỗi pixel, do đó, việc lưu dưới dạng PNG được cho là nén không mất dữ liệu. Mặt khác, để tiết kiệm bộ nhớ, chỉ có thể tạo một số hình ảnh nhất định bằng mã của tệp hình ảnh JPEG. Có lẽ có nhiều hơn một loại tệp JPEG và tôi không biết liệu có ai trong số chúng có thuộc tính rằng hai hình ảnh khác nhau của loại tệp đó có thể tạo ra cùng một hình ảnh chính xác không. Tôi giả sử rằng một loạt các lần bạn chỉ xoay một hình ảnh sau đó lưu nó dưới dạng JPEG và sẽ đưa ra lời giải thích về những gì đã xảy ra với giả định rằng đó là những gì bạn đã làm mà tôi không biết là có thật hay không. Một vòng quay bạn đã làm là mất mát nếu có cách lấy lại mã tệp hình ảnh chính xác như bạn đã có trước khi bạn xoay nó và lưu nó. Bạn có thể không chính xác rằng bạn thực sự đã làm một vòng quay không mất mát. Nếu nó thực sự là lossless,


-3

Những lý do đằng sau điều này là một vài

cách hình ảnh được mã hóa và nén sẽ thay đổi kích thước đơn giản chỉ vì thuật toán nén. bạn có thể kiểm tra điều này bằng cách lưu nó dưới dạng bitmap và sau đó xoay nó. Trong định dạng đó hoặc bất kỳ định dạng thô nào, kích thước sẽ giữ nguyên. Nếu không thì chương trình lưu hình ảnh sẽ thêm dữ liệu mới có thể là một số siêu dữ liệu hoặc thứ gì đó.

Nhưng tại sao bạn lại quay một jpeg 20 lần?


2
Nếu bạn đọc liên kết trong câu hỏi ban đầu, ít nhất là đối với Windows Picture Viewer , nếu kích thước của JPEG là bội số của 8, thì các phép quay JPEGS trong WPV là các phép biến đổi không mất mát. Một cách đơn giản để kiểm tra đó là xoay 4 lần (dẫn đến cùng hướng với bản gốc) và thực hiện phép trừ hình ảnh theo pixel đơn giản.
scottbb

@scottbb Đây không nhất thiết chỉ là vấn đề với trình xem ảnh windows. Bất cứ điều gì xoay một định dạng mất mát đều phải tính toán lại việc nén. xoay một hình ảnh trong bội số 8 có nghĩa là mọi thứ khớp với các từ 8 bit và có thể không bị nén theo cách thêm các tạo tác. Điều này dựa trên cách thuật toán hoạt động và được thực hiện trong chương trình được sử dụng.
Cc Dd

-3

Bởi vì cách nén hình ảnh hoạt động . Mọi định dạng như PNG hoặc JPG nói chung không bảo toàn kích thước tệp sau khi xoay.

Đối với máy nén, hình ảnh được quay chỉ là một hình ảnh khác, do cách thức hoạt động của công nghệ nén không có gì đảm bảo nó sẽ nén hình ảnh được xoay giống nhau .

Tất nhiên, nếu nén không mất, nếu bạn xoay hình ảnh 4 lần lần thứ 4 thì hình ảnh lại giống nhau (được xoay cho đến khi nó nghiêng như ban đầu): trong trường hợp đó, nó sẽ trở lại cùng kích thước nén, nếu không thì đó là vì một trong những lý do sau :

  • Đã thêm siêu dữ liệu : chương trình đã thêm một số đoạn văn bản vì một số lý do
  • Máy nén đã thay đổi: chương trình có thể chọn chỉ lưu lại hình ảnh như ban đầu nếu không có thay đổi, nhưng nếu bạn áp dụng bất kỳ thay đổi nào (thậm chí 4 góc quay 90 độ), nó có thể quyết định nén lại hình ảnh bằng cách sử dụng máy nén (chương trình không còn biết nó vẫn là hình ảnh giống nhau).
  • Nói chung, cùng một máy nén (libPNG hoặc libJPG) mang lại kết quả rất khác nhau giữa các lần triển khai khác nhau, các phiên bản khác nhau của cùng một thư viện và với các tham số nén khác nhau (đôi khi hệ thống và trình biên dịch cũng tạo ra sự khác biệt ở đây).

Nén hình ảnh hoạt động bằng cách nén hình ảnh thành khối 4 hoặc kích thước khác. Nói chung, máy nén xem hình ảnh được quay như một hình ảnh khác, tuy nhiên vì phần pixel bị nén chỉ là phân rã tuyến tính, nếu các phần trên hình ảnh giống nhau, có thể chỉ cần Transpose / Mirror các ma trận phân rã tuyến tính giữ nguyên hiệu quả phẩm chất:

Lưu ý rằng điều này phải được thực hiện trên cơ sở từng tính năng và điều đó cũng giải thích cho việc tăng kích thước ban đầu => ở lần quay đầu tiên, nó chỉ cố gắng nén hình ảnh thành các khối có thể xoay được:

  • Nếu không làm như vậy: chất lượng hình ảnh xuống cấp
  • Nếu thành công, nó chỉ tăng kích thước một lần thì mọi vòng quay đều giữ nguyên chất lượng.

  • Hoạt động đó chỉ thành công nếu hình ảnh được tạo bởi các khối bằng nhau. (kích thước của hình ảnh là nhiều kích thước của chunk).

Câu trả lời scottbb sai và bạn có thể làm một bài kiểm tra đơn giản:

  • Mở ảnh gốc: Ảnh chụp màn hình
  • Xoay hình ảnh 4 lần với WPV: Ảnh chụp màn hình
  • So sánh 2 ảnh chụp màn hình

Bạn sẽ thấy hình ảnh thay đổi (nó được nén lại trong lần xoay đầu tiên). Tuy nhiên, thay đổi đó bị giới hạn về thời gian, giờ đây bạn có thể xoay nó một lần nữa mà không giảm chất lượng (nếu hình ảnh có kích thước là bội số của 8)

Để trả lời trực tiếp OP:

Tôi biết nó đang quay một cách không mất mát

Không phải nó không quay được losslessy, nó mất chất lượng ít nhất một lần (ở lần quay đầu tiên: vì trước tiên nên nén nó theo cách có thể xoay), sau đó nó duy trì chất lượng của nó.


1
Câu hỏi là về luân chuyển không mất mát, do đó, việc giải nén được tránh.
Đặc vụ_L

5
OP đã hỏi không phải về trường hợp chung mà chính xác là về một phần mềm cụ thể và một trường hợp cụ thể đó. Câu trả lời của bạn không sai, nó chỉ trả lời một câu hỏi khác với những gì OP hỏi.
Đặc vụ_L

1
3 câu đầu tiên vẫn là một câu hỏi khác: "cách nén hình ảnh hoạt động" - không có sự nén trong xoay vòng không mất mát. "Đối với máy nén, hình ảnh được xoay" - một lần nữa, máy nén không được gọi. "Nếu nén là lossless" - nén bị mất. Vòng quay là lossless. Bây giờ, đây là cách tôi sẵn sàng đưa ra lập luận này. Tôi có thể thấy quan điểm của bạn, tôi đồng ý với nó, nhưng nó hoàn toàn không phù hợp ở đây. BTW, tôi cũng là một lập trình viên và tôi đã chia sẻ việc đọc và viết tệp thô.
Đặc vụ_L

1
Tôi đã tạo một hình ảnh trong Paint, xoay nó 4 lần và nó giống hệt nhau, tuy nhiên kích thước vẫn tăng từ 1.6 lên 8.1 KB. Nhị phân nhị phân cho thấy dữ liệu hình ảnh chưa được xử lý, nó chỉ là một khối siêu dữ liệu khổng lồ trong <?xpacketcác thẻ.
Đặc vụ_L

1
Nếu kích thước của JPEG là chia hết cho 8 (hoặc 16 với lấy mẫu con), nó có thể được luân chuyển trong từng bước của 90 độ losslessly . Điều quan trọng là không giải mã được tất cả các cách thành RGB, nhưng hoạt động trực tiếp với các hệ số DCT. Đây là một chức năng chuyên dụng thường không được bao gồm trong trình chỉnh sửa hình ảnh chung. Xem ví dụ vi.wikipedia.org/wiki/Libjpeg#jpegtran . Nếu bạn đã thực hiện thử nghiệm của mình với Windows Photo Viewer như được chỉ định trong câu hỏi, bạn sẽ thấy rằng nó thực sự không mất mát.
Đánh dấu tiền chuộc
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.