ivpusic / react-native-image-crop-picker

iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping
MIT License
6.12k stars 1.56k forks source link

how to keep exif inside image after crop or resize or compression ? #799

Open alainib opened 6 years ago

alainib commented 6 years ago

Version

Platform

Expected behaviour

Cropping or compressing image remove the exif from the output image. How to keep exif inside the output image ?

this is my code :

ImagePicker.openCamera({
  includeExif: true,   // i need exif inside the output file not in json
  cropping: true ,
  compressImageMaxWidth: 900,
  compressImageMaxHeight: 900,
  compressImageQuality: 0.72
}).then(image => {
  // ... 
});
BigPun86 commented 6 years ago

Any progress on this?

alainib commented 6 years ago

i use many libs to do it. On android i can read the exif but reading the file itself take most of the time ( for example 3 secondes when compressing and writing take only 0.5) On ios i get empty exif , compression is also slow

my compress function with full exif

import ImageResizer from "react-native-image-resizer";
var piexif = require("piexifjs");

import * as tools from "path/to/src/tools";

  // path an object with path attribut
  compressImage = async image => {
    // image.path is the full path to jpg
    const prefixe = "data:image/jpeg;base64,";
    try {

      let srcdata = await tools.readFile(image.path, "base64");
      var srcexifs = piexif.load(prefixe + srcdata);

      /* compresse l'image */
      const compressedImage = await ImageResizer.createResizedImage(
        image.path,
        900,
        900,
        "JPEG",
        72
      );

      const compressedImageb64 = await tools.readFile(compressedImage.uri, "base64");

      /* on récupère les anciennes sous parties des exif pour les recrire
         0th, 1st,Exif et GPS sont des sous groupes de meta
        */
      const _zero = srcexifs["0th"];
      const _first = srcexifs["1st"];
      const _Exif = srcexifs["Exif"];
      const _GPS = srcexifs["GPS"];
      var exifObj = { "0th": _zero, "1st": _first, Exif: _Exif, GPS: _GPS };
      var exifbytes = piexif.dump(exifObj);
      /* pour remettre les exifs il faut la base64 et rajouter devant le prefixe sinon piexif ne l'accepte pas, il faudrat enlever le prefixe avant de recrire le fichier  */
      var bs64Exif = piexif.insert(exifbytes, prefixe + compressedImageb64).substring(prefixe.length);

      await tools.writeFile(compressedImage.uri, bs64Exif, "base64");

      // this.setState({ compressedImage :compressedImage .uri }) ;

    } catch (e) {
      console.error(e);
      this.setState({ compressingImage: false, errormsg: "cannot compress image" });
    }
  };

my tools.js file

    var RNFS = require("react-native-fs"); // slow with IOS
    import RNFetchBlob from "react-native-fetch-blob"; // slow with ANDROID

    /**
     * @param {string} path to file with filename
     * @param {*} content to write
     * @param {string} encoding  utf8, base64
     */
    export async function writeFile(path, content, encoding = "utf8") {
      // console.log("writeFile", path);
      return RNFS.writeFile(path, content, encoding)
        .then(() => {
          return true;
        })
        .catch(err => {
          console.log(err.message);
          return false;
        });
    }

    /**
     */
    export async function readFile(path, encoding = "utf8") {
      return await RNFetchBlob.fs.readFile(path, encoding);
    }

    /**
     * @param {string} path to file with filename
     * @param {*} content to write
     * @param {string} encoding "utf8" "base64"
     */
    export async function writeStream(path, content, encoding = "utf8") {
      return new Promise(function(resolve, reject) {
        RNFetchBlob.fs.writeFile(path, "", encoding).then(res => {
          RNFetchBlob.fs.writeStream(path, encoding).then(ofstream => {
            ofstream.write(content);
            ofstream.close();
            console.log("writestream finish");
            return resolve(true);
          });
        });
      });
    }
alainib commented 6 years ago

so in IOS i use react-native-image-crop-picker to compress and resize and in Android the code above, not so clean but it's faster i found so far. i will be happy to get improvement on the code abose. maybe i miss some lines in the comment

alainib commented 6 years ago

@BigPun86 if you improve the code below tell me please. i need to improve it too because too slow (take 3seconde to read/compress/write exif) how does snapchat or facebook handle this problem ? i didn't found anything on it but it's a very common task for them

jasongaare commented 5 years ago

Also experiencing that the exif data from the originalImage is not passed on to the image located at compressedImagePath... the compressor lib claims that exif should be forwarded... but the only way we can get the exif in practice is to use compressImageQuality: 1 for Android

jasongaare commented 5 years ago

I've also opened an issue in the Compressor library https://github.com/zetbaitsu/Compressor/issues/125

ycchanau commented 3 years ago

Same problem in ios. The exif data is missing in the temp file even though no cropping