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

💨 Make image flipping faster #130

Closed
1 of 2 tasks
mrousavy opened this issue May 3, 2021 · 0 comments · Fixed by #1466
Closed
1 of 2 tasks

💨 Make image flipping faster #130

mrousavy opened this issue May 3, 2021 · 0 comments · Fixed by #1466
Assignees
Labels
🤖 android Issue affects the Android platform 💨 performance This issue or pull requests addresses performance issues

Comments

@mrousavy
Copy link
Owner

mrousavy commented May 3, 2021

Type

  • Enhancement for an existing feature
  • An entirely new feature

What

Images from the front camera (selfie) are automatically mirrored (flipped horizontally). The flip function (introduced in #129) works by converting the byte[] to a Bitmap to perform a matrix transformation, then compresses it back into the byte[].

https://github.com/cuvent/react-native-vision-camera/blob/f57714747a2587916c4e7c47bfe2586b1e8966ff/android/src/main/java/com/mrousavy/camera/utils/ImageProxy.save.kt#L44-L52

This byte[] -> Bitmap -> byte[] conversion is a bit of an overhead I'd like to eliminate, even if it only takes 24ms to execute on my Huawai P10. Here are the full benchmarks:

Back camera (no flipping):

2021-05-03 18:57:54.478 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Session configured in 200 ms! Camera: androidx.camera.lifecycle.LifecycleCamera@c475d4
2021-05-03 18:58:17.609 31448-31729/com.mrousavy.camera.example I/CameraView.performance: Finished creating temp file in 1ms
2021-05-03 18:58:18.028 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Finished image capture in 413ms
2021-05-03 18:58:18.033 31448-31729/com.mrousavy.camera.example I/CameraView.performance: Finished image saving in 3ms
2021-05-03 18:58:18.035 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Finished function execution in 444ms

Front camera (flipping):

2021-05-03 18:58:50.155 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Session configured in 129 ms! Camera: androidx.camera.lifecycle.LifecycleCamera@4e5ccc6
2021-05-03 18:58:52.032 31448-31729/com.mrousavy.camera.example I/CameraView.performance: Finished creating temp file in 2ms
2021-05-03 18:58:52.345 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Finished image capture in 314ms
2021-05-03 18:58:52.379 31448-31729/com.mrousavy.camera.example I/CameraView.performance: Flipping Image took 31 ms.
2021-05-03 18:58:52.380 31448-31729/com.mrousavy.camera.example I/CameraView.performance: Finished image saving in 33ms
2021-05-03 18:58:52.381 31448-31448/com.mrousavy.camera.example I/CameraView.performance: Finished function execution in 353ms

Alternatives/Workarounds

I have tried to toggle some flags in the byte[] in-memory, hoping I could flip the relevant Exif flag. I have discovered that the AndroidX ExifInterface does not support writing to in-memory files (why??), so I tried to roll my own approach:

https://github.com/cuvent/react-native-vision-camera/blob/f57714747a2587916c4e7c47bfe2586b1e8966ff/android/src/main/java/com/mrousavy/camera/utils/ImageProxy.save.kt#L19-L41

that unfortunately doesn't work and returns a black image. Maybe this can be of help?

On iOS this can be achieved with no overhead at all by directly mirroring the output connection inside the Camera pipeline, unfortunately CameraX does not provide this functionality.

@mrousavy mrousavy added the 🤖 android Issue affects the Android platform label May 3, 2021
@mrousavy mrousavy self-assigned this May 3, 2021
@mrousavy mrousavy added the 💨 performance This issue or pull requests addresses performance issues label May 3, 2021
@mrousavy mrousavy changed the title ✨ Make image flipping faster 💨 Make image flipping faster May 3, 2021
mrousavy added a commit that referenced this issue Sep 1, 2023
See #1376

## Breaking Changes

* Frame Processors are now **synchronous**. Previously they ran on a
separate Thread. If you want to run something on a separate Thread now,
use `runAsync` inside a Frame Processor
* Frame Processor Plugins are no longer in the global object with the
`__` prefix, but rather stored directly in the `FrameProcessorPlugins`
object exported by react-native-vision-camera. (e.g. replace
`__scanQRCodes(frame)` with `FrameProcessorPlugins.scanQRCodes(frame)`)
* `frameProcessorFps` no longer exists. Use `runAtTargetFps` inside a
Frame Processor to throttle some calls.
* `onFrameProcessorPerformanceSuggestionAvailable` no longer exists. Use
the FPS display (`enableFpsGraph={true}`) to see how your Frame
Processor performs over time. This is more in-line with how React Native
works (Dev Tools / Perf Monitor)
* VisionCamera V3 will not work on RN 0.70 or below. You need to use RN
0.71. This is because the build script got way simpler and smaller,
making it faster to build and way less error prone. Backwards
compatibility is just too complex here.
* Reanimated is no longer used as a Worklet Runtime. Instead,
VisionCamera now uses
[react-native-worklets-core](https://github.com/margelo/react-native-worklets-core).

## Progress

You can test the latest V3 release by creating a new RN project with RN
0.71 and installing VisionCamera + RNWorklets:

```sh
yarn add react-native-vision-camera@3.0.0-rc.5
yarn add react-native-worklets-core
yarn add @shopify/react-native-skia
```

Things to test:

* TensorFlow Lite plugin to load any `.tflite` model!! ✨ (see [this PR
for more
info](#1633),
will be a separate library soon)
* Drawing onto a Frame using Skia!! 🎉 
* Using `frame.toArrayBuffer()` to get the Frame's byte content in JS
* New Android build script. This should drastically speed up the build
time! 💨
* New Worklet library. This replaces Reanimated Worklets. Should be
faster and more stable :)
* New synchronous Frame Processors. Should be faster :)
* `runAtTargetFps` and `runAsync` in Frame Processors
* Using HostObjects or HostFunctions (like models from PyTorch) inside a
Frame Processor. This will probably require a few native bindings on
PyTorch's end to make the integration work (cc @raedle)

Overall V3 is close to completion. I have a few things to do the coming
days so not sure how much work I can put into this. **If anyone wants to
support the development of v3, I'd appreciate donations / sponsors:
https://github.com/sponsors/mrousavy** ❤️ :)


## Related issues 

features

- resolves
#1376
- fixes
#281
- resolves
#211
- resolves
#130
- resolves
#117
- fixes #76
- resolves
#75
- resolves
#562
- resolves
#565
- fixes
#570
- fixes
#287
- resolves
#311
- fixes
#315
- resolves
#323
- fixes
#340
- fixes
#354
- resolves
#420
- fixes
#434
- fixes
#452
- fixes
#496
- fixes
#497
- resolves
#499
- fixes
#516
- fixes
#527
- fixes
#542
- fixes
#548
- fixes
#561
- fixes
#740
- fixes
#770


...and then pretty much every Android issue lol

- fixes
#1675
(**maybe**, please test @PrernaBudhraja)
- fixes
#1671

.. maybe also (not tested):

- fixes
#1698
- fixes
#1687
- fixes
#1685
- fixes
#1681
- fixes
#1650
- fixes
#1646
- fixes
#1635
- fixes
#1631
- fixes
#1621
- fixes
#1615
- fixes
#1612
- fixes
#1605
- fixes
#1599
- fixes
#1585
- fixes
#1581
- fixes
#1569
- fixes
#1568
- fixes
#1565
- fixes
#1561
- fixes
#1558
- fixes
#1554
- fixes
#1551
- fixes
#1547
- fixes
#1543
- fixes
#1538
- fixes
#1536
- fixes
#1534
- fixes
#1528
- fixes
#1520
- fixes
#1498
- fixes
#1489
- fixes
#1477
- fixes
#1474
- fixes
#1463
- fixes
#1462
- fixes
#1449
- fixes
#1443
- fixes
#1437
- fixes
#1431
- fixes
#1429
- fixes
#1427
- fixes
#1423
- fixes
#1416
- fixes
#1407
- fixes
#1403
- fixes
#1402
- fixes
#1398
- fixes
#1396
- fixes
#1395
- fixes
#1379
- fixes
#1377
- fixes
#1374
- fixes
#1373
- fixes
#1365
- fixes
#1356
- fixes
#1353
- fixes
#1352
- fixes
#1351
- fixes
#1343
- fixes
#1340
- fixes
#1334
- fixes
#1330
- fixes
#1322
- fixes
#1296
- fixes
#1283
- fixes
#1260
- fixes
#1253
- fixes
#1251
- fixes
#1245
- fixes
#1238
- fixes
#1227
- fixes
#1226
- fixes
#1225
- fixes
#1222
- fixes
#1211
- fixes
#1208
- fixes
#1193
- fixes
#1191
- fixes
#1184
- fixes
#1164
- fixes
#1143
- fixes
#1128
- fixes
#1122
- fixes
#1120
- fixes
#1110
- fixes
#1097
- fixes
#1081
- fixes
#1080
- fixes
#1064
- fixes
#1053
- fixes
#1047
- fixes
#1044
- fixes
#1032
- fixes
#1026
- fixes
#1023
- fixes
#1015
- fixes
#1012
- fixes
#997
- fixes
#960
- fixes
#959
- fixes
#954
- fixes
#946
- fixes
#945
- fixes
#922
- fixes
#908
- fixes
#907
- fixes
#868
- fixes
#855
- fixes
#834
- fixes
#793
- fixes
#779
- fixes
#746
- fixes
#740
- fixes
#727
- fixes
#671
- fixes
#613
- fixes
#595
- fixes
#588
- fixes
#570
- fixes
#569
- fixes
#542
- fixes
#516
- fixes
#515
- fixes
#434
- fixes
#354
- fixes
#323
- fixes
#315
- fixes
#281
- fixes
#211
- fixes #76
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 android Issue affects the Android platform 💨 performance This issue or pull requests addresses performance issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant