React-native-image-crop-picker: how to keep exif inside image after crop or resize or compression ?

Created on 22 Aug 2018  路  6Comments  路  Source: ivpusic/react-native-image-crop-picker

Version

  • react-native-image-crop-picker v0.21.1

    • react-native v0.55.4

Platform

  • Android

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 => {
  // ... 
});

Most helpful comment

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

All 6 comments

Any progress on this?

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);
          });
        });
      });
    }

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

@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

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

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

Was this page helpful?
0 / 5 - 0 ratings