callstack/react-native-image-editor

`ExifInterface only supports saving attributes on JPEG formats` error when running with react-native-camera

acro5piano opened this issue · 11 comments

Hi, thank you for the great library. I am getting the following error when use with react-native-camera.
Am I missing something? Thank you in advance.

Bug

image

console.error: "Unhandled promise rejection", {"framesToPop":1,"nativeStackAndroid":[{"methodName":"saveAttributes","lineNumber":1770,"file":"ExifInterface.java"},{"methodName":"copyExif","lineNumber":397,"file":"ImageEditorModule.java"},{"methodName":"access$500","lineNumber":55,"file":"ImageEditorModule.java"},{"methodName":"doInBackgroundGuarded","lineNumber":282,"file":"ImageEditorModule.java"},{"methodName":"doInBackgroundGuarded","lineNumber":202,"file":"ImageEditorModule.java"},{"methodName":"doInBackground","lineNumber":32,"file":"GuardedAsyncTask.java"},{"methodName":"doInBackground","lineNumber":20,"file":"GuardedAsyncTask.java"},{"methodName":"call","lineNumber":333,"file":"AsyncTask.java"},{"methodName":"run","lineNumber":266,"file":"FutureTask.java"},{"methodName":"runWorker","lineNumber":1162,"file":"ThreadPoolExecutor.java"}],"userInfo":null,"code":"EUNSPECIFIED","line":11371,"column":26,"sourceURL":"http://10.0.2.2:8081/index.delta?platform=android&dev=true&minify=false"}
error
    index.delta?platform=android&dev=true&minify=false:76687:29
<unknown>
    index.delta?platform=android&dev=true&minify=false:207035:38
<unknown>
    index.delta?platform=android&dev=true&minify=false:5993:26
exports
    index.delta?platform=android&dev=true&minify=false:6427:16
<unknown>
    index.delta?platform=android&dev=true&minify=false:5984:25
_callTimer
    index.delta?platform=android&dev=true&minify=false:37010:17
_callImmediatesPass
    index.delta?platform=android&dev=true&minify=false:37046:19
callImmediates
    index.delta?platform=android&dev=true&minify=false:37265:33
callImmediates
    [native code]
__callImmediates
    index.delta?platform=android&dev=true&minify=false:11811:35
<unknown>
    index.delta?platform=android&dev=true&minify=false:11632:34
__guard
    index.delta?platform=android&dev=true&minify=false:11794:15
flushedQueue
    index.delta?platform=android&dev=true&minify=false:11631:21
flushedQueue
    [native code]
invokeCallbackAndReturnFlushedQueue
    [native code]

Environment info

React native info output:

info 
  React Native Environment Info:
    System:
      OS: macOS 10.14.5
      CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
      Memory: 454.87 MB / 16.00 GB
      Shell: 2.7.1 - /usr/local/bin/fish
    Binaries:
      Node: 10.13.0 - ~/.nvm/versions/node/v10.13.0/bin/node
      Yarn: 1.12.3 - ~/.nvm/versions/node/v10.13.0/bin/yarn
      npm: 6.4.1 - ~/.nvm/versions/node/v10.13.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
    IDEs:
      Android Studio: 3.1 AI-173.4819257
      Xcode: 10.1/10B61 - /usr/bin/xcodebuild
    npmGlobalPackages:
      react-native-cli: 2.0.1
      react-native-git-upgrade: 0.2.7

Library version: ^2.0.1

Steps To Reproduce

  1. Install react-native-image-editor and react-native-camera (^2.11.0)
  2. run the code
takePicture = async () => {
    const data = await this.camera.takePictureAsync({ quality: 0.3, base64: false })
    await ImageEditor.cropImage(data.uri, {
      offset: { x: 10, y: 10 },
      size: { width: 10, height: 10 },
    })
}

render() {
    return (
      <View>
        <RNCamera
              ref={ref => {
                this.camera = ref as RNCamera
              }}
              ratio="4:3"
              captureAudio={false}
              type={RNCamera.Constants.Type.back}
          />
          <Button onPress={this.takePicture} title="Snap" />
      </View>
    )
}

Describe what you expected to happen:

  1. can crop image

Reproducible sample code

Sorry my investigation was not enough.
Catch and show the code then it says ExifInterface only supports saving attributes on JPEG formats.

    try {
      const data = await this.camera.takePictureAsync(options)
      const hoge = await ImageEditor.cropImage(data.uri, {
        offset: { x: 10, y: 10 },
        size: { width: 10, height: 10 },
      })
      console.log(hoge)
    } catch (e) {
      console.error(e)
    }

image

@acro5piano What is data returned by takePictureAsync function?

Thanks for your reply.
I'm reinstalling it, so wait a moment please.

data is something like this

{ uri: 'file:///data/user/0/com.mydomain.app/cache/Camera/29488e04-034f-4613-9108-29b42e6206d6.jpg',
  height: 960,
  width: 1280,
  pictureOrientation: 1,
  deviceOrientation: 1 }

I also tried data.base64 but no luck:

const data = await this.camera.takePictureAsync({ quality: 0.3, base64: true })
try {
  const cropped = await ImageEditor.cropImage(`data:image/jpeg;base64,${data.base64}`, {
    offset: { x: 10, y: 10 },
    size: { width: 10, height: 10 },
  })

image

If I commented out the following line, it seems to work correctly.

https://github.com/react-native-community/react-native-image-editor/blob/master/android/src/main/java/com/reactnativecommunity/imageeditor/ImageEditorModule.java#L282

Is it okay to create a PR to disable copyExif when given params is set to do so.
I know that is not the ideal solution but should be the current workaround.

@acro5piano Can you use your workaround for now? I need to dig deeper to apply the correct fix.

Thank you. I will use patch-package for now.

In the iOS lib, the cropped picture is being saved as a PNG instead of a JPEG. I have created a pull request for this. It may possibly solve this issue. #44

Any updates on the topic ?
I'm facing the same issue on Android, althought it probably not related to this library. I use react-native-image-resizer as an input for cropping. I didn't really manage to find the exact patern that trigger the issue, but it seems to be more likely to happen when the image that you try to crop is small (like 100px X 100px ). So I suspect this is related to native-image-resizer not always handling well the resize process. I'm not sure my comments helps a lot, but well, some people might have the same problem.
And indeed commenting the line in JAVA module where the copyExif is done solve the problem.

UPDATE: it solves to issue but brings a new one... Now, sometimes, output pictures are rotated. I don't know that much about exif, but eventually, it seems to be kind of usefull ... I ended up doing a try & catch in the JAVA lines related to copyExif. At least it deals with the 10% of errors I had without side effects on pictures that were doing fine.

Are there any news on this? We're getting the error as well but only on few devices. Can't reproduce this yet but we're using react-native-image-resizer as input for cropping as well. An issue were created there for an related topic too but this was already merged in January and we're running the newest version (just updated from 1.2.3 to 1.2.4 now).

Here the related PR: bamlab/react-native-image-resizer#209

Data looks fine... this is from our logs:

Error while cropping image: ExifInterface only supports saving attributes on JPEG formats. 
uri: file:///data/user/0/XXX/cache/Camera/5deb3737-0c94-4925-bb7f-695a83215ef2.jpg, width: 252, height: 320
resImageUri: file:///data/user/0/XXX/cache/1599207653198.JPEG, width: 180, height: 320

2nd line (uri: ...) contains the data input for react-native-image-resizer and 3rd line the resized image data returned by react-native-image-resizer.

Is the only solution currently to modify the code itself as mentioned by @acro5piano and additionally add the fix for orientation as pointed out by @MebDevelop or is there already a new configuartion option or anything else I may have missed?

react-native-camera is deprecated. Please use react-native-vision-camera instead