waschinski / photo-stream

Self-hosted, super simple photo stream
https://github.com/waschinski/photo-stream
MIT License
449 stars 70 forks source link

Orientation based on exif info [enhancement] #7

Closed alexkutsan closed 2 years ago

alexkutsan commented 3 years ago

In current version exif is ignored, and vertical photos shown rotated:

image

But exif info about present present in file:

image

Would be good to honor exif orientation information in stream

waschinski commented 3 years ago

The library being used (image_processing) should actually default to using auto rotate as far as I got it and I couldn't reproduce the problem with some sample images I found on the web.

Have you tried playing around with the settings in _config.yml? Maybe it actually does have to be provided there in order to make it work.

notnamed commented 3 years ago

I've run into this issue too, since switching to this nicely Dockerized version from the old repo. This version is much easier to manage, but I can't figure out what's changed that's preventing some of my photos from auto-rotating properly. I've tried tweaking the resize_to_limit in _config.yml but I'm not sure what else to change.

waschinski commented 3 years ago

Mmh... what a bummer. Could someone provide an example image which is not rotating properly? I would love to get this issue sorted.

notnamed commented 3 years ago

I copied one of the not-rotating images from the originals directory that I mount into the Docker container to a web-accessible location to use as an example: https://jordancooks.com/waterfall-not-rotating.jpg

For reference, here is the data from ImageMagick's identify on that file:

$ identify -verbose ./waterfall-not-rotating.jpg | grep -i orientation Orientation: RightTop exif:Orientation: 6

waschinski commented 3 years ago

Thank you very much! I try to have an update on this issue within the next couple days.

waschinski commented 3 years ago

This seems to be a problem with the vips version (v8.9.1) being used in the docker image. On my local machine I was not experiencing the issue with the photo you provided and I am running a newer version of vips there. I also saw that there seems to be some fix for autorotation in v8.10.1.

Please give the dev docker image a go. Bear in mind though that it contains some unfinished code for #2 but it also uses the most recent version of vips. If this fixes your problems I will update latest accordingly.

notnamed commented 3 years ago

I tried pulling the dev tag of the container image, but I'm still seeing the same results. As far as I can tell, I'm running the updated vips too - is this what I should be looking at for the versioning you're citing? It seems there are a lot of things named vips in gems, libraries, and packages, so I'm not sure which version I should be matching (this is looking inside the container):

bash-5.1# apk list | grep vips-8
vips-8.10.5-r0 x86_64 {vips} (LGPL-2.1-or-later)
waschinski commented 3 years ago

That's weird as it should be running vips 8.11.1 now while previously it should have been 8.9.1. I was actually using a simple vips -v to verify the version running locally (which was running 8.11.0 and was working with your photo) and inside the docker container.

One thing I also did though is removing all ENV settings which are automatically set by the image (so basically all but my own settings). Especially VIPSVER which was set from the old image. This is a common problem for me when using Portainer to simply edit the running container with like only changing the tag.

So depending on how you switched the tag you could try a "fresh" docker setup as it might help.

notnamed commented 3 years ago

Thanks for the help! I'm running with Compose, and I did a pull / down / up, so the tag switch was a fresh setup. I also went into the container, re-applied my changes to _config.yml to increase the resize_to_limit, and restarted the container (docker restart).

I'm not sure why the Alpine package shows a different version, but vips -v shows the expected version:


vips-8.11.1-Tue Jun 29 07:30:12 UTC 2021```
waschinski commented 3 years ago

It seems that 8.10.5 is the latest package for libvips in Alpine 3.13. After all I think that's the reason why Tim went with manually downloading and installing it in the Dockerfile.

Anyway, I still don't get why it doesn't work for you but for me running the same Docker image.

This shot is taken while running the dev image: Screenshot 2021-08-18 164213

And that shot is taken after switching back to the latest image: Screenshot 2021-08-18 165146

notnamed commented 3 years ago

How strange! So, I'm mounting in my photos via a bind mount in my Docker Compose file, to the location /photo-stream/photos inside the container. One thing I noticed is that on my host, I'm able to see the EXIF orientation information:

$ identify -verbose img-88.jpg | grep -i orientation
  Orientation: RightTop
    exif:Orientation: 6

Inside the container, though, that same directory doesn't show the EXIF orientation information:

bash-5.1# identify -verbose img-88.jpg | grep -i orientation
  Orientation: RightTop

And when I check the generated site, all the orientation information is missing (this is in /photo-stream/_site/photos/large):

bash-5.1# identify -verbose ./img-88-686656.jpg | grep -i orientation
  Orientation: Undefined

I'm curious just so I can keep troubleshooting on my end, are you seeing the same thing? It's odd that each subsequent location of the same file (or modified file) slowly strips out EXIF data.

waschinski commented 3 years ago

I actually think it is correct that the generated files no longer contain the exif information. The exif information should be used to properly rotate the new images when generating them though.

For reference, locally on my Mac exiftool does show as follows:

photo-stream % exiftool photos/original/waterfall-not-rotating.jpeg | grep -i orientation
Orientation                     : Rotate 90 CW

More or less the same is being shown inside the container on my Docker host:

/photo-stream # exifr photos/original/waterfall-not-rotating.jpeg | grep -i orientation
                orientation = #<EXIFR::TIFF::Orientation:RightTop(6)>

As expected the generated file in _site/photos/large/ does not have any exif information at all but is oriented correctly as can be seen on the screenshot I have posted previously.

Could you check what exifr does say for the original photo inside the container?

notnamed commented 3 years ago

Okay, good to know that the resized files are not expected to have this EXIF data still present.

I'm not familiar with exifr and it wasn't present in the container, but after performing an npm install exifr inside the container, I can see that the EXIF orientation information is present:

bash-5.1# exifr img-88.jpg | grep -i orientation
                orientation = #<EXIFR::TIFF::Orientation:RightTop(6)>

Just to eliminate anything from the environment or my Compose configuration, I also tried spinning up the container with a very minimal set of flags, like so:

docker run -p 8887:4000 -v /my/photo/path/:/photo-stream/photos -e URL=https://domain.com/ -t waschinski/photo-stream:dev

Same result, though. Really baffling that you're not able to reproduce assuming your container is using the same :dev tag that I'm pulling.

waschinski commented 3 years ago

I am actually wondering why in your container the identify command is available while in mine it is not and vice versa with exifr.

Also, since I am running photo-stream using Docker on a different machine (a Synology NAS) I decided to go with a minimal setup on my Mac like you just did:

docker run -p 4000:4000 -v /photo-stream/photos/:/photo-stream/photos -e URL=https://domain.com/ -t waschinski/photo-stream:dev

Same result as on my NAS though and when starting locally using bundle exec jekyll serve. Your image is displayed in proper rotation.

This really is baffling. We must be missing some embarassingly simple thing though...

notnamed commented 3 years ago

Ah, yes, sorry; I went ahead and added ImageMagick to the container at some point to check the EXIF data.

And it turns out, that line of thinking ended up being fruitful, because by setting:

    saver:
      strip: false

All 3 times in _config.yml fixed it. Still baffling, but maybe with the comparison between what works for me and what works for you, someone will be able to figure out the root cause? It's beyond me, I'm afraid.

waschinski commented 3 years ago

With strip: false I wonder if now the browser itself fixes the rotation though. Because that setting will Strip all metadata from image so it no longer does that in your case.

Btw did you previously change anything else in _config.yml?

Anyway, I will raise the libvips version being used in the Docker image and update the latest tag as it sorted out the rotation problem on my side at least. Maybe @alexkutsan is reporting back too.

notnamed commented 3 years ago

The two hypothesis I came up with were either the browser is doing the rotation, or there's an intermediary step in the image processing that has an intermediate state where the metadata has been stripped but some of the file copying/resizing/etc has not yet occurred.

Using the previous non-Compose setup with the older codebase, I had made multiple changes to _config.yml because it's where the site URL variables used to be defined. When I moved to this image, I made no changes to _config.yml until I started troubleshooting this issue.

waschinski commented 3 years ago

Alright, I see. I also had in mind that there might be a step involved where metadata is getting lost on your side but then adding strip: false would probably not help at all too.

It boggles my mind though why it doesn't work for you. I can consistently switch between 1.1.2 and 1.1.3 and in the former the photo you provided is not rotated correctly while in the latter it is. Just by simply reloading the page in the same browser tab after deployment.

This is my compose btw:

version: "3.1"
services:
  photo-stream:
    container_name: photo-stream
    image: waschinski/photo-stream:1.1.3
    restart: unless-stopped
    ports:
      - 4000:4000
    environment:
      - AUTHOR_NAME=COOLNAME
      - CUSTOM_LINK_NAME=CUSTOMTEXT
      - CUSTOM_LINK_URL=CUSTOMURL
      - DESCRIPTION=FANCYDESCRIPTION
      - EMAIL=EMAILADDRESS
      - INSTAGRAM_USERNAME=INSTANAME
      - SHOW_OFFICIAL_GITHUB=0
      - SYNCFOLDER=TOPSECRET
      - SYNCPASS=TOPSECRET
      - SYNCSERVER=TOPSECRET
      - SYNCUSER=TOPSECRET
      - TITLE=FANCYTITLE
      - URL=https://www.DOMAINNAME.de
    volumes:
      - /volume1/docker/photo-stream:/photo-stream/photos
    labels:
      - "diun.enable=true"
networks:
  default:
    external:
      name: ownnetwork

Nothing special and I run this as a stack in Portainer.

alexkutsan commented 2 years ago

Updated to 1.1.4

Modified _config.jml to

     saver:
-      strip: true
+      strip: false

On generation get this errors :

photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:47:39.982: field "exif-data" is too large for a single JPEG marker, ignoring

photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:48:32.842: field "exif-data" is too large for a single JPEG marker, ignoring
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:48:40.338: field "exif-data" is too large for a single JPEG marker, ignoring
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:48:41.281: field "exif-data" is too large for a single JPEG marker, ignoring
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:48:42.244: field "exif-data" is too large for a single JPEG marker, ignoring
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:48:57.076: field "exif-data" is too large for a single JPEG marker, ignoring
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:49:12.339: read gave 1 warnings
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:49:12.339: VipsJpeg: Invalid SOS parameters for sequential JPEG
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:49:57.061: read gave 1 warnings
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:49:57.061: VipsJpeg: Invalid SOS parameters for sequential JPEG
photo-stream    | VipsJpeg: Invalid SOS parameters for sequential JPEG
photo-stream    | 
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:50:19.889: read gave 1 warnings
photo-stream    | 
photo-stream    | (process:1): VIPS-WARNING **: 12:50:19.889: VipsJpeg: Invalid SOS parameters for sequential JPEG
photo-stream    | VipsJpeg: Invalid SOS parameters for sequential JPEG
photo-stream    | VipsJpeg: Invalid SOS parameters for sequential JPEG

How can I find what images triggered this errors?

Orientation is still ignored.

Inside container original image :

/photo-stream/photos/original # exifr stream6.jpg  | grep Ori
    orientation = #<EXIFR::TIFF::Orientation:LeftBottom(8)>

In _site folder :

/photo-stream/_site/photos/large # exifr stream6-ccf7e3.jpg  | grep Orie
    orientation = #<EXIFR::TIFF::Orientation:LeftBottom(8)>

    /photo-stream/_site/photos/thumbnail # exifr stream6-ccf4df.jpg 
stream6-ccf4df.jpg:
   width = 640
  height = 427
    bits = 8

So I can see correct orientation (it takes a moment to get active) on large image, but thumbnail is still broken. Screenshot from 2021-09-14 15-59-59 Screenshot from 2021-09-14 16-00-35 Example available on : https://photo.alexkutsan.xyz/

I can see this not with all images, for example this one :

/photo-stream/photos/original # exifr stream37.jpg  | grep Ori
                orientation = #<EXIFR::TIFF::Orientation:LeftBottom(8)>
/photo-stream/_site/photos/thumbnail # exifr stream37-ccf4df.jpg 
stream37-ccf4df.jpg:
   width = 640
  height = 428
    bits = 8
/photo-stream/_site/photos/large # exifr stream37-ccf7e3.jpg 
stream37-ccf7e3.jpg:
   width = 2048
  height = 1371
    bits = 8

Looks like for this particular image exif info was also lost during transformation to big image.

waschinski commented 2 years ago

Hi @alexkutsan and thanks for reporting back.

Have you actually tried the new version with strip: true?

Also may I ask what camera you are using?

I am by no means an expert with exif data and such but when doing some research on the errors I came across similar problems with other software usually caused by certain manufacturers adding extra information/notes in the JPEG markers. Might be worth a shot taking a look at those markers like EXIF APP1 using exiftool or a similar software. There's a nice online metadata viewer too.

alexkutsan commented 2 years ago

I use different sources (phone, camera, saved images from messengers), and I can't find that images with issues are related to certain source.

There are some images with issues: https://nas.alexkutsan.xyz/sharing/xsG33mHW1

UPD:

New version with strip : true ignores orientation.

waschinski commented 2 years ago

Thanks @alexkutsan for providing the photos Photo Stream was having issues with. I really think this helped me finding the cause of the problem this time!

Looks like I simply missed a dependency of libvips when switching base images to reduce size of the docker image: libexif-dev (which of course adds support for EXIF metadata in JPEG files...) So I just added this dependency and rebuild the dev image on Docker Hub using that. After switching to it all photos have been looking fine!

Please temporarily switch to waschinski/photo-stream:dev if you can and see if this works for you too. You should also be fine to revert back to using strip: true in the config file again.

alexkutsan commented 2 years ago

Cant find waschinski/photo-stream:dev branch or tag

waschinski commented 2 years ago

Cant find waschinski/photo-stream:dev branch or tag

waschinski/photo-stream:dev

alexkutsan commented 2 years ago

Oh, you mean docker image. Could you please give me a branch with changes? I am using RPI for hosting, and it requires some changes in docker file. Not able you use x86 images.

waschinski commented 2 years ago

Oh I see. Just add libexif-dev to the apk add command inside Dockerfile like so:

RUN apk update && apk upgrade &&\
    apk add --update --no-cache build-base glib-dev libexif-dev expat-dev tiff-dev jpeg-dev libgsf-dev git rsync lftp openssh &&\
    rm -rf /var/cache/apk/*

This reminds me of having to look into multi-arch image building.

alexkutsan commented 2 years ago

@waschinski thanks for you help! Looks like adding libexif-dev to the apk add command inside Dockerfile works!

I created PR with minor improvements for easy to hosting on RPI. https://github.com/waschinski/photo-stream/pull/11

waschinski commented 2 years ago

@alexkutsan Thanks for reporting back and great to hear it works for you too!

Also thanks for your PR, looks good and will be merged asap!

waschinski commented 2 years ago

Quite off-topic, but @alexkutsan I actually played around with multi-arch building and there should now be ARM images on Docker Hub if you would like to give them a try.