Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align pixel orientation with exif:Orientation in HEIC decoder #1233

Merged
merged 2 commits into from
Sep 3, 2018

Conversation

rudchenkos
Copy link
Contributor

@rudchenkos rudchenkos commented Jul 31, 2018

It turns out that in HEIC the pixels are never rotated and the metadata only
indicates the orientation of the sensor when the photo was taken.

Hence, there was a discrepancy between Image->orientation and actual pixel
orientation in images loaded with the heic coder. Particularly, this led to
incorrect behavior of the -auto-orient which in this case tried to compensate
non-existing pixel rotation.

This is a fix for #1232

The fix provides two solutions for the problem described above: reset exif:Orientation to "1" in HEIC decoder output (default behavior) or rotate pixels to match the original exif:Orientation, as some application might rely on the original sensor rotation. The latter is enabled by heic:preserve-orientation read define.

It turns out that in HEIC the pixels are never rotated and the metadata only
indicates the orientation of the sensor when the photo was taken.

Hence, there was a discrepancy between `Image->orientation` and actual pixel
orientation in images loaded with the `heic` coder. Particularly, this led to
incorrect behavior of the `-auto-orient` which in this case tried to compensate
non-existing pixel rotation.

ImageMagick#1232
@rudchenkos
Copy link
Contributor Author

A question to the maintainers: where in the docs is the best place to describe the new option heic:preserve-orientation?

@dlemstra
Copy link
Member

Is it not enough to call SetImageProperty(image,"exif:orientation","1",exception); after the image has been read? The exif profile will be updated before the image is written with the new value.

@rudchenkos
Copy link
Contributor Author

@dlemstra Absolutely. In most common cases it is really enough to reset exif:Orientation after the image is read. This is is the default behavior after my patch.

Unfortunately, there are application which rely on the original pixel rotation for historical reasons. This is why I have also implemented the option heic:preserve-orientation.

Copy link
Member

@dlemstra dlemstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you do the final tweaks so we can merge this?

coders/heic.c Outdated
@@ -85,6 +86,8 @@ static MagickBooleanType
WriteHEICImage(const ImageInfo *,Image *,ExceptionInfo *);
#endif

static Image *CompensateOrientation(Image *image, ExceptionInfo *exception);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you move this method above the ReadHEICImage method, near IsHeifSuccess? We can then remove this line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, will do 👍

coders/heic.c Outdated
*/
option=GetImageOption(image_info,"heic:preserve-orientation");
if (IsStringTrue(option) == MagickTrue)
image = CompensateOrientation(image, exception);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement leaks memory. The methods FlipImage, RotateImage return a new image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, my. That's right, I will free the old image here

coders/heic.c Outdated
return(GetFirstImageInList(image));
}

/* An inverse of AutoOrientImage */
static Image *CompensateOrientation(Image *image, ExceptionInfo *exception)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image *image should be const Image *image.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I will change it to a const pointer type

Copy link
Contributor Author

@rudchenkos rudchenkos Sep 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a problem. There is a bypass statement which needs to return a non-const result from the const parameter:

  value=GetImageProperty(image,"exif:Orientation",exception);
  if (value == NULL)
  {
    return image;
  }

So I can factor this EXIF check out of this function (to the call site at ReadHEICImage) or simply don't put the const. Which way do you think is better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I missed that, probably better to not change the signature to a const.

@rudchenkos
Copy link
Contributor Author

Hi @dlemstra,
I have applied the suggestions in the fixup commit (to be squashed).

About the docs, it seems the most appropriate place to document heic:preserve-orientation is command-line-options.html right after hough-lines:accumulator description. One thing is confusing me though, that line (www/command-line-options.html:84) is very long which makes me think it is generated by a tool, rather than written manually. But, from the other hand I cannot find where from and how could it have been generated.

Should I just edit that command-line-options.html?

@dlemstra
Copy link
Member

dlemstra commented Sep 3, 2018

You should edit the command line options here: https://github.com/ImageMagick/Website

coders/heic.c Outdated
Image
*original_image = image;
image = CompensateOrientation(original_image, exception);
DestroyImageList(original_image);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should handle this inside the CompensateOrientation method. You are now destroying the image when exif:Orientation is not set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, true. Fill fix promptly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed.
I am sorry for the silly mistake

@rudchenkos
Copy link
Contributor Author

Pull request for docs: ImageMagick/Website#19

Copy link
Member

@dlemstra dlemstra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch. Needs a few code style tweaks but I will apply them myself.

@dlemstra dlemstra merged commit 41fa21a into ImageMagick:master Sep 3, 2018
@rudchenkos
Copy link
Contributor Author

Dank u wel, Dirk!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants