linuxmint / xviewer

A generic Image viewer
GNU General Public License v2.0
74 stars 37 forks source link

Flip Horizontal - Save and Flip Vertical - Save don't work properly #56

Open ecobabush opened 6 years ago

ecobabush commented 6 years ago

elochnye-igrushki-sssr-sovetskie-foto04 elochnye-igrushki-sssr-sovetskie-foto04 copy

 * Xviewer version 1.6.1 
 * Distribution - Mint 18.3 Sylvia 64bit

Issue When do Edit -> Flip Horizontal -> Close Window -> Save changes to image "..." before closing -> Save OR do Edit -> Flip Horizontal -> File -> Save -> Close THEN reopen the changed image and you would see: An artifact appeared at the right edge of the Image. A strip from up to bottom taken from previous state of the image before flipping.

Flip Vertical issue is the same as Flip Horizontal. After flipping a artifact strip appears at the bottom.

Steps to reproduce See above.

Expected behaviour There mustnot be an artifact (strip).

Other information

ecobabush commented 6 years ago

It looks like flipping works right, but saving the result of flipping makes an issue. When you make flipping an image then it is rendered right. But when you save the changed picture and reload it the issue appears.

And in this case the reload works.

programmer-ceds commented 3 years ago

Firstly - if you do this then reopening the image, repeating the operation and saving the file again will restore it to its original state. The saved file will be an exact binary match with the file as it was to start with.

@icarter09 I don't think that this is a bug in the strict sense - it's more that the code doesn't go far enough to complete the operation. I have looked at the problem and been reading about the basics of jpeg files (apologies to anybody reading this who knows more about this than I do - I'm just trying to explain what the problem is).

The problem lies in the way that xviewer implements the horizontal flip, vertical flip etc by using a lossless transform. This relies on moving MCUs (Minimum Coded Units) to perform the translation. MCUs represent 8x8, 16x8 or 16x16 pixel tiles. Jpeg images have to be an integer number of MCUs wide and high but when the number of pixels is not exactly divisible by the MCU dimension partial MCUs are used at the right-hand side and bottom of the image - the extra pixels not being shown when the image is displayed. Normally an image 600x600 pixels would not exhibit the problem since 600 is exactly divisible by 8. However, in this case the MCUs are 16 wide and 600 is not exactly divisible by 16 - hence the 8-pixel wide strip down the right-hand edge that is not flipped.

Note that the problem only occurs when the image is saved - the view displayed by xviewer after the flip renders correctly.

There are a number of solutions to the problem.

If the image is an integer number of MCUs in the axis where a problem would occur then simply use the code as it is now to perform a lossless transformation. Otherwise one of the following three approaches could be used.

The code could be amended to crop the image to remove the strip that isn't flipped - the user should be warned that this will happen.

The image could be saved in a lossy form by applying jpeg compression to the image as displayed in the viewer - again the user should be warned about this. (Note that Pix seems always to implement a lossy saving whether or not the image is a multiple number of MCUs and whether or not it has EXIF orientation tags)

An alternative would be perform the flip and rotate options using EXIF orientation tags - adding the orientation tags (for the main image and, if applicable, the thumbnail) if necessary. This approach leaves the image data untouched but wouldn't be suitable in situations where the image must be 'physically' transformed. Perhaps the user should be given a say in this?

I could look at implementing one of the approaches noted above if so wished by the project owner.

(The best approach is to make sure that the images are multiples of the MCU size (I guess most cameras will conform to this) or better still use TIFF instead of JPEG)

lytithwyn commented 2 years ago

This issue occurs when rotating as well. The end effect for rotation is that, in the final rotated form, a strip of pixels is shifted off the left side of the image onto the right side. I just spent some time this morning writing a python script that uses PIL and numpy to fix the ones I have already messed up.

mars4science commented 1 year ago

I suggest renaming bug to include rotation issue. I've noted bug for rotation recently and somebody might miss that one and add another for rotation.