Lossless JPEG rotation only lossless at 360 degrees?

Ask for help and post your question on how to use XnView Classic.

Moderators: XnTriq, xnview

Post Reply
btriffles
Posts: 2
Joined: Wed May 13, 2009 3:22 am

Lossless JPEG rotation only lossless at 360 degrees?

Post by btriffles » Tue Dec 01, 2009 5:47 am

Potential Problem:
While trying out the lossless JPEG rotation feature in XnView 1.97, I found something strange:

The rotation appears to be "lossy" for rotations of 90, 180, and 270 (e.g. 90 + 90 + 90) degrees. However, if I continue rotating until the image has the original orientation (e.g. 360 degrees), the result is identical to the original image.

This suggests that the pixel data is being rotated losslessly, but something else in the file (e.g. quantization matrix) isn't being correctly changed to accommodate the rotation.

Steps to Reproduce:
1) Download http://commons.wikimedia.org/wiki/File:Notre.JPEG or use another image whose dimensions are divisible by 16.
2) Make a copy of the file for comparison purposes.
3) In XnView, check all boxes under Options -> Browser -> Misc.
4) From the XnView browser, right-click the file and choose JPEG Lossless transformations -> Rotate 90 degrees right.
5) Open the rotated file in an image editor, e.g. GIMP or Paint.NET.
6) In the image editor, rotate the modified image 90 degrees to the left. It should have its original orientation.
7) Open the copy of the original file in the image editor.
8) Paste the modified image into a new layer on top of the original image.
9) Set the top (modified) layer to use the "Difference" blending mode. The image should turn black.
10) Merge down or flatten the layers to a single black layer.
11) Check for pixels that aren't completely black, indicating a lossy change. In GIMP, you can use the histogram to look for any pixels with a value greater than 0. In Paint.NET, you can adjust the levels (or use auto-level) to look for non-zero pixels.

Related Information:
I searched the forums and noticed that some people have complained of lossy rotations, while others say it is lossless. Perhaps the discrepancy is caused by some people doing 360 degrees of rotation before checking if it is lossless.

To compare an image that is rotated less than 360 degrees with the original image, you have to rotate the result back to the original orientation using a third party program, such as Photoshop or GIMP. To ensure the error is not caused by a third party program, I used multiple programs to verify the result and tested their rotation ability with lossless PNGs.

User avatar
DOS386
Posts: 291
Joined: Sun Jun 11, 2006 2:43 pm

Re: Lossless JPEG rotation only lossless at 360 degrees?

Post by DOS386 » Tue Dec 01, 2009 12:43 pm

I have to confirm this, using NCONVERT:

Code: Select all

NC -jpegtrans rot90 a.jpg


2 problems:

1.
Lossless transformation of a.jpg : OK


But output file is smaller, big loss !!! The trans isn't rejected if file dimensions don't meet divisibility criteria :bug:

2.

Now divisibility is good. Dimensions are exchanged as supposed, but after rotating back and saving both as BMP -> files are NOT identical :bug:
There is indeed no WinZIP under my rock.

simon
Posts: 35
Joined: Wed Aug 23, 2006 4:51 pm

Re: Lossless JPEG rotation only lossless at 360 degrees?

Post by simon » Sun Dec 06, 2009 1:04 pm

Hello

It seems that the problem is as follows

(1) When asking for a lossless rotation (maybe except 360° for which the program is not assumet to do anything), the file is losslessly rotated, but systematically encoded in a standard way (Huffman) even if the initial file was progressively encoded.

(2) when a JPEG file is chromasubsampled, different programs use different algorithm to re-generate the missing chroma information, and some of them (at least Paint Shop Pro) do not use the same algorithm to re-generate the missing chroma information for Huffman coded and progressively coded files.

As a consequence, if a chroma-subsampled, progressively coded JPEG file is losslessly rotated with XnView in one direction and a second time in the reverse direction, the resulting file will be excatly the same in terms of image content but Huffman coded (so that the size of the file will increase, as the Huffman coding is less compact than the progressive coding). Then comparing the two files with Paint Sho Pro (and probably some other programs) by using the arithmetic function for computing the difference between the two files pixel by pixel and then counting the number of colors used will lead to an artefactual difference (the result should be 1 color, correspond to pure black R=0, G=0, B=0, but in fact there several hundred of colors). If the two JPEG files are saved in TIFF using XnView (not PSP as the result would be the same) and then compared using PSP, there is then no difference, showing that the rotations were really lossless.

I would like to suggest to Pierre to keep the original JPEG coding in lossless rotations and croping, that is, if a file is progressively coded, it should remain progressively coded after rotation or croping. Ideally, the choice may be let to the user to change or keep the inital type of coding when performing a lossless rotation or croping, as in jpegcrop.exe, the program made by the independant JPEG group.

Regards
Simon

btriffles
Posts: 2
Joined: Wed May 13, 2009 3:22 am

Re: Lossless JPEG rotation only lossless at 360 degrees?

Post by btriffles » Mon Dec 07, 2009 3:49 am

I have carried out additional tests that shed more light on the situation. It seems that XnView produces an output identical to jpegtran, which is the set of lossless algorithms in the libjpeg library. I suspect the problem is either caused by some orientation-dependent decoding step (which I have yet to identify) or a bug in jpegtran. I posted a comment at ImpulseAdventure (http://www.impulseadventure.com/photo/l ... -test.html), and Calvin Hass says he will look into the problem.
simon wrote:(1) When asking for a lossless rotation (maybe except 360° for which the program is not assumet to do anything), the file is losslessly rotated, but systematically encoded in a standard way (Huffman) even if the initial file was progressively encoded.
I can do 4 separate 90 degree rotations, and the program is modifying the JPG for each step. The first 3 rotations have decoding discrepancies of up to 3 in each RGB color channel, but the final rotation results in no differences. I'm fairly certain the program is not detecting 360 degrees and just restoring the original JPG.

I don't know what you mean by "encoding in Huffman even if the initial file was progressive". I'm not a JPEG expert, but I believe all JPG files use (lossless) Huffman coding for the quantized DCT coefficients. I also believe progressive JPGs are basically the same as standard ones (just with a different coefficient ordering) and can be losslessly converted to the standard format.

Furthermore, I found the problem to occur when using a non-progressive JPG.
simon wrote:(2) when a JPEG file is chromasubsampled, different programs use different algorithm to re-generate the missing chroma information, and some of them (at least Paint Shop Pro) do not use the same algorithm to re-generate the missing chroma information for Huffman coded and progressively coded files.
I also had the problem occur with a JPG with no chroma subsampling.
simon wrote:As a consequence, if a chroma-subsampled, progressively coded JPEG file is losslessly rotated with XnView in one direction and a second time in the reverse direction, the resulting file will be excatly the same in terms of image content but Huffman coded (so that the size of the file will increase, as the Huffman coding is less compact than the progressive coding). Then comparing the two files with Paint Sho Pro (and probably some other programs) by using the arithmetic function for computing the difference between the two files pixel by pixel and then counting the number of colors used will lead to an artefactual difference (the result should be 1 color, correspond to pure black R=0, G=0, B=0, but in fact there several hundred of colors). If the two JPEG files are saved in TIFF using XnView (not PSP as the result would be the same) and then compared using PSP, there is then no difference, showing that the rotations were really lossless.
Again, I'm not sure what you mean by Huffman vs. progressive, but the problem does not manifest itself when you restore the original orientation via lossless JPEG rotations (e.g. 90+90+90+90, 180+180, 90-90, etc.). The problem is that a 90, 180, or 270 degree losslessly rotated JPG does not decode as having identical (but rotated) pixel values as the original image.

For example, try losslessly rotating a JPEG +90 degrees, saving a result to a lossless PNG or TIFF, and rotating the PNG/TIFF -90 degrees. The result will not match the original JPG.

I have verified the same problem using Paint.NET 1.5.1, Photoshop CS1, and GimPhoto 1.4.3 (which uses the mature libjpeg library).
simon wrote:I would like to suggest to Pierre to keep the original JPEG coding in lossless rotations and croping, that is, if a file is progressively coded, it should remain progressively coded after rotation or croping. Ideally, the choice may be let to the user to change or keep the inital type of coding when performing a lossless rotation or croping, as in jpegcrop.exe, the program made by the independant JPEG group.
You're right; it does appear to convert progressive files to standard (baseline) ones. It would be nice if XnView could maintain the original coding.

Post Reply