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

The image is rotated in iPhone #123

Closed
KarlosQ opened this issue Nov 7, 2016 · 16 comments
Closed

The image is rotated in iPhone #123

KarlosQ opened this issue Nov 7, 2016 · 16 comments

Comments

@KarlosQ
Copy link

KarlosQ commented Nov 7, 2016

The image is rotated in iPhone either in Chrome or Safari. In Android is OK in PC is OK but in iPhone the image is auto rotated 90 grades.

@focus0802
Copy link

Same problem here, hope to fix it.

@thisbejim
Copy link

Just chiming in that I also have this issue.

@mosch
Copy link
Owner

mosch commented Dec 12, 2016

I'll like to fix that. Can someone tell me how to reproduce?

looks to for me:

haha

@KarlosQ
Copy link
Author

KarlosQ commented Dec 12, 2016

I try in two iPhone 6.

  • The first iPhone (iOS 10.0.1) and works fine

  • The second iPhone (iOS 10.0.2) auto rotated 90 grades.

What version do you have?

@kukagg
Copy link
Contributor

kukagg commented Feb 6, 2017

Rotated for me on iOS 10.2.1. Don’t think it’s an issue once rotate functionality is in. Relying on EXIF is not an option in all cases as it’s not 100% reliable.

@stolinski
Copy link

I'm not sure you'll see it reproduced in the simulator. It's rotated when taking a photo and uploading.

@stolinski
Copy link

I fixed this using

https://github.com/blueimp/JavaScript-Load-Image

    this.refs.drop.onchange = (e) => {
      e.preventDefault();
      loadImage(
          e.target.files[0],
          (img) => {
            img.toBlob((blob) => {
              this.setImage(blob);
              this.onDrop(URL.createObjectURL(blob));
            });
          },
          { maxWidth: 400, canvas: true, orientation: true }
      );
    };

Where onDrop is setting state, used in the cropper.

@hu9o
Copy link
Contributor

hu9o commented Feb 18, 2017

Besides EXIF detection not being substitutable to the rotation feature, the library @stolinski mentioned dedicates 300 lines of code to the task... Worth the trouble ?

@jljorgenson18
Copy link

This is not really an issue with react-avatar-editor but rather an issue with mobile browsers when using your camera. In order to get around it, you need some way to parse the EXIF data, transform the image with a canvas based off of the Orientation, and then use the transformed image with react-avatar-editor. I used https://github.com/exif-js/exif-js and then I used http://chariotsolutions.com/blog/post/take-and-manipulate-photo-with-web-page/ and https://gist.github.com/ammulder/5120103 for reference. If JavaScript-Load-Image isn't working for somebody then I can publish an npm module with the minimum workaround.

@Andriy-Kulak
Copy link

Andriy-Kulak commented May 15, 2017

@stolinski can you explain how you ended up the JavaScript-Load-Image package in React? if I follow the package instructions and add the package as a script tag in index.html file, then I cannot use loadImage because it is undefined in my specific component. Also, I cannot import the package in my Component properly. Any quick tips would be greatly appreciated!

when I try importing the package as a component, I get 'windows is not defined' as the error in the package because I am using server side rendering for react.

@jljorgenson18 if you have a spare minute, can you explain your workaround in more detail?

@Andriy-Kulak
Copy link

I figured out how to use Javascript-Load-Image. My problem was that my app is isomorphic. Since the window object was referenced in the package, the server code broke on compilation before it can be used in the client. I fixed it by adding the following in index.js file

if(typeof window != 'undefined'){
  module.exports = require('./load-image')
  require('./load-image-scale')
  require('./load-image-meta')
  require('./load-image-fetch')
  require('./load-image-exif')
  require('./load-image-exif-map')
  require('./load-image-orientation')
}

@Andriy-Kulak
Copy link

By the way, for anyone else that came across this issue, I ended up not using Javascript-Load-Image for ex-if rotation in the browser. The reason is that if I wanted to the retain the original image size while rotating, in would drastically increase in size most of the time (from 2.9mb to 17mb).

The alternatives that did work for me are both on server side:

In both cases the resulting images where close enough to the original size of the image and seem to work on the few test cases that I tried them.

@pkenglish
Copy link

I'm having difficulty with rotation in general on iPhone, if you use rotate it appears to pivot around the bottom right corner drawing the image off screen. Has anyone else experienced this?
image

@innoist
Copy link

innoist commented Jan 2, 2018

As rightly said above this is not a bug with this control, it happens with mobile browser. I was able to resolve this easily with npm package exif-js

onDrop(files) {
    
      var that = this;
      EXIF.getData(files[0], function () {
        var orientation = EXIF.getTag(this, "Orientation");
        let rotatePic = 0;
        switch (orientation) {
          case 8:
            rotatePic = 270;
            break;
          case 6:
            rotatePic = 90;
            break;
          case 3:
            rotatePic = 180;
            break;
          default:
            rotatePic = 0;

        }
        that.setState({ rotate: rotatePic });
      });
 
    }
  }


//using Rotate property of AvatarEditor
<AvatarEditor image={this.props.profileImageDropped}   rotate={this.state.rotate} />

The code can be viewed at:
https://github.com/innoist/PictureEXIF/blob/master/src/components/HomePage.js

Happy to help if something is not clear

@kevinthecity
Copy link

kevinthecity commented Oct 26, 2018

I ran into this issue myself, created this Utils method in Typescript which was inspired by @innoist's suggestion. Does not require any external code.

ImageUtils.ts

/**
 * Based on StackOverflow answer: https://stackoverflow.com/a/32490603
 *
 * @param imageFile The image file to inspect
 * @param onRotationFound callback when the rotation is discovered. Will return 0 if if it fails, otherwise 0, 90, 180, or 270
 */
export function getOrientation(imageFile: File, onRotationFound: (roation: number) => void) {
  const reader = new FileReader();
  reader.onload = (event: ProgressEvent) => {
    if (!event.target) {
      return;
    }

    const innerFile = event.target as FileReader;
    const view = new DataView(innerFile.result as ArrayBuffer);

    if (view.getUint16(0, false) !== 0xffd8) {
      return onRotationFound(convertRotationToDegrees(-2));
    }

    const length = view.byteLength;
    let offset = 2;

    while (offset < length) {
      if (view.getUint16(offset + 2, false) <= 8) {
        return onRotationFound(convertRotationToDegrees(-1));
      }
      const marker = view.getUint16(offset, false);
      offset += 2;

      if (marker === 0xffe1) {
        if (view.getUint32((offset += 2), false) !== 0x45786966) {
          return onRotationFound(convertRotationToDegrees(-1));
        }

        const little = view.getUint16((offset += 6), false) === 0x4949;
        offset += view.getUint32(offset + 4, little);
        const tags = view.getUint16(offset, little);
        offset += 2;
        for (let i = 0; i < tags; i++) {
          if (view.getUint16(offset + i * 12, little) === 0x0112) {
            return onRotationFound(view.getUint16(offset + i * 12 + 8, little));
          }
        }
        // tslint:disable-next-line:no-bitwise
      } else if ((marker & 0xff00) !== 0xff00) {
        break;
      } else {
        offset += view.getUint16(offset, false);
      }
    }
    return onRotationFound(convertRotationToDegrees(-1));
  };
  reader.readAsArrayBuffer(imageFile);
}

/**
 * Based off snippet here: https://github.com/mosch/react-avatar-editor/issues/123#issuecomment-354896008
 * @param rotation converts the int into a degrees rotation.
 */
function convertRotationToDegrees(rotation: number): number {
  let rotatePic = 0;
  switch (rotation) {
    case 8:
      rotatePic = 270;
      break;
    case 6:
      rotatePic = 90;
      break;
    case 3:
      rotatePic = 180;
      break;
    default:
      rotatePic = 0;
  }
  return rotatePic;
}

Usage:

import { getOrientation } from './ImageUtils';
...
onDrop = (pics: any) => {
  getOrientation(pics[0], rotationInDegrees => {
    this.setState({ image: pics[0], rotate: rotationInDegrees });
  });
};
...
<AvatarEditor
  image={this.state.image}
  rotate={this.state.rotate}
  ...etc
/>

@stale
Copy link

stale bot commented Jan 24, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

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

No branches or pull requests