web-dev-qa-db-fra.com

Rotation de l'image sur le type d'entrée = "fichier"

J'utilise react-firebase-file-uploader pour télécharger un avatar sur le stockage firebase. Cependant, chaque fois que je télécharge une image de Portrait Orientation (en particulier, les images prises sur les appareils Android et IOS - elles ont généralement OrientationRotate 90 CW dans leurs métadonnées), l'image est pivotée de 90 degrés. 

J'ai déjà lu ce qui précède et je pense que ces images de smartphone prises sont toujours dans Paysage mais l'orientation est enregistrée EXIF ​​méta. S'il vous plaît corrigez-moi si je me trompe?

Vous trouverez ci-dessous un exemple de composant qui télécharge l'image à l'aide de react -firebase-file-uploader. Je sais que ce package ne pose pas de problème et que la solution à cette question est probablement applicable à de nombreuses applications.

Alors, que dois-je faire pour lire l'orientation EXIF ​​, modifier la rotation (si nécessaire, ou dois-je passer la méta avec le téléchargement de fichier?) Tout en continuant le téléchargement?

class ProfilePage extends Component {
  state = {
    avatar: "",
    isUploading: false,
    progress: 0,
    avatarURL: ""
  };

  handleProgress = progress => this.setState({ progress });
  handleUploadError = error => {
    this.setState({ isUploading: false });
    console.error(error);
  };
  handleUploadSuccess = filename => {
    this.setState({ avatar: filename, progress: 100, isUploading: false });
    firebase
      .storage()
      .ref("images")
      .child(filename)
      .getDownloadURL()
      .then(url => this.setState({ avatarURL: url }));
  };

  render() {
    return (
      <div>
        <form>
          {this.state.isUploading && <p>Progress: {this.state.progress}</p>}
          {this.state.avatarURL && <img src={this.state.avatarURL} />}
          <FileUploader
            accept="image/*"
            name="avatar"
            randomizeFilename
            storageRef={firebase.storage().ref("images")}
            onUploadStart={this.handleUploadStart}
            onUploadError={this.handleUploadError}
            onUploadSuccess={this.handleUploadSuccess}
            onProgress={this.handleProgress}
          />
        </form>
      </div>
    );
  }
}

export default ProfilePage;
5
Darren

Vous devriez jeter un oeil à la bibliothèque javascript moderne JavaScript-Load-Image qui a déjà une solution complète à l'orientation EXIF ​​inclus le correction automatique.

Vous pouvez utiliser la mise à l'échelle de l'image (méthode .scale()) pour convertir l'image en toile et fixer l'orientation de votre image.

Jetez un oeil à Correction de l'orientation de l'image avec Javascript .

Voici une autre bibliothèque intéressante: react-exif-orientation-img

2
Zakaria Acharki

Voici l'adaptation de la solution @ German Plebani mentionnée dans les commentaires pour vos besoins:

import React, {Component} from "react";
import FileUploader from "react-firebase-file-uploader";
import exif from 'exif-js';

function readFile(file) {
  return new Promise(resolve => {
    var reader = new FileReader();
    reader.onload = e => resolve(e.target.result);
    reader.readAsDataURL(file);
  });
};

function createImage(data) {
  return new Promise(resolve => {
    const img = document.createElement('img');
    img.onload = () => resolve(img);
    img.src = data;
  })
}

function rotate(type, img) {
  return new Promise(resolve => {
    const canvas = document.createElement('canvas');

    exif.getData(img, function () {
      var orientation = exif.getAllTags(this).Orientation;

      if ([5, 6, 7, 8].indexOf(orientation) > -1) {
        canvas.width = img.height;
        canvas.height = img.width;
      } else {
        canvas.width = img.width;
        canvas.height = img.height;
      }

      var ctx = canvas.getContext("2d");

      switch (orientation) {
        case 2:
          ctx.transform(-1, 0, 0, 1, img.width, 0);
          break;
        case 3:
          ctx.transform(-1, 0, 0, -1, img.width, img.height);
          break;
        case 4:
          ctx.transform(1, 0, 0, -1, 0, img.height);
          break;
        case 5:
          ctx.transform(0, 1, 1, 0, 0, 0);
          break;
        case 6:
          ctx.transform(0, 1, -1, 0, img.height, 0);
          break;
        case 7:
          ctx.transform(0, -1, -1, 0, img.height, img.width);
          break;
        case 8:
          ctx.transform(0, -1, 1, 0, 0, img.width);
          break;
        default:
          ctx.transform(1, 0, 0, 1, 0, 0);
      }

      ctx.drawImage(img, 0, 0, img.width, img.height);
      ctx.toBlob(resolve, type);
    });
  })
}


class OrientationAwareFirebaseImageUploader extends Component {
  handleChange = (event) => {
    event.target.files.forEach(
      file => readFile(file)
        .then(createImage)
        .then(rotate.bind(undefined, file.type))
        .then(blob => {
          blob.name = file.name;
          this.uploader.startUpload(blob);
        })
    );
  }

  render() {
    return (
      <FileUploader
        {...this.props}
        ref={ref => this.uploader = ref}
        onChange={this.handleChange}
        accept="image/*"
      />
    );
  }
}

export default OrientationAwareFirebaseImageUploader;
0
Olim Saidov