sekoyo/react-image-crop

Exif orientation/rotation is being ignored

raphaelbeckmann opened this issue ยท 17 comments

If the image is rotated or flipped via Exif data, this information is not taken care of. As a result, the image is not shown properly in the cropper.

Example images: https://github.com/recurser/exif-orientation-examples

What do you mean by not shown properly? All this library does is pass the image source into an image src tag.

Try loading one of the rotated images of the given link into the cropper, e.g. Landscape_6.jpg, and you will see what I mean by saying "not shown properly".

I can confirm that, for example image captured from iphone:
vertical: is in exif orientation 6
horizontal: in exif orientation 1
cropping doesn't work correctly.

https://imgur.com/a/7o6TRBo There is a screenshot, at up left corner You can see image uploaded from iphone (made in vertical phone orientation), at bottom is canvas with crop

Sorry I'm still not sure what I'm supposed to be seeing here, Landscape_6 is rotated right? If I look at in GitHub or if I add it to my crop I get the same result?:

screen shot 2018-06-08 at 18 41 17

@dominictobias Try to get result in canvas as u showed in example. Image in canvas is displayed in another orientation than in

@bartoszboruta so which one is correct? The canvas isn't correct?

@dominictobias yes, canvas on ios is in different orientation that original , and when you crop image which is vertical on , cropped fragment is in horizontal orientation, so the cropped fragment is not same as you chose

So it sounds like a bug with the browser. This library doesn't do anything special it just displays the image source in an <img> element and by the looks of it the orientation is correct. If you think canvas isn't displaying the right orientation that isn't a result of this library.

From a google search and answers like this https://stackoverflow.com/questions/20600800/js-client-side-exif-orientation-rotate-and-mirror-jpeg-images

It seems you have to manually rotate the canvas according to the exif orientation: https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image-orientation.js#L54

Here's a blog about using that library if you're stuck: https://nsulistiyawan.github.io/2016/07/11/Fix-image-orientation-with-Javascript.html

To solve this issue you need to use the JavaScript Load Image image loader instead of file reader. The blog provided was excellent. Make sure orientation: true is set up as an option when you use the image loader.

To solve the issue you need to use the JavaScript-Load-Image library: https://github.com/blueimp/JavaScript-Load-Image and load the input file as follows:
loadImage( event.target.files[0], (img) => { var base64data = img.toDataURL('image/jpeg'); this.setState({ imgSrc: base64data }); }, { orientation: true, } );

loadImage( event.target.files[0], (img) => { var base64data = img.toDataURL('image/jpeg'); this.setState({ imgSrc: base64data }); }, { orientation: true, } );

"TypeError: img.toDataURL is not a function" When i use JavaScript-Load-Image , Do you have any codepen example

Did you import blueimp-load-image ?
import loadImage from 'blueimp-load-image/js';

@prashantpatil14 I was having the same issue. When I added canvas: true (which will force img to be a canvas object instead of html img tag) to the options, it worked.

@nirfuchs73 Did you end up finding out how to import it?

@desduvauchelle yes
import loadImage from 'blueimp-load-image/js';

I was getting the same error that @prashantpatil14 was reporting with the correct import, and I also observe it on the stackoverflow example @desduvauchelle posted.

I had to add canvas: true to the options object.

I was able to get it to work using this snippet:

  const onSelectFile = (e) => {
    if (e.target.files && e.target.files.length > 0) {
      loadImage(
        e.target.files[0],
        (img) => {
          var base64data = img.toDataURL(`image/jpeg`);
          setUpImg(base64data);
        },
        { orientation: true, canvas: true }
      );
      // const reader = new FileReader();
      // reader.addEventListener('load', () => setUpImg(reader.result));
      // reader.readAsDataURL(e.target.files[0]);
    }
  };