flutter_fast_exif_reader 1.0.1
flutter_fast_exif_reader: ^1.0.1 copied to clipboard
High-performance EXIF and MakerNote reader for camera RAW and JPEG images. Operates 100% in-memory with zero disk re-reads.
flutter_fast_exif_reader #
A blazing-fast, universal EXIF & MakerNote reader for Flutter with zero disk re-reads, powered by native C++17 FFI.
Designed for high-throughput photo pipelines, face clustering engines, gallery viewers, and batch scanners where extracting metadata from thousands of photos must take < 0.1ms per file.
π Supported Platforms #
| Platform | Support | Backend Architecture |
|---|---|---|
| Windows | β Supported | Native C++17 DLL FFI |
| Android | β Supported | Native C++17 NDK .so FFI (armeabi-v7a, arm64-v8a, x86_64) |
π Key Features #
- β‘ Ultra-Fast (< 0.1ms per file): Direct in-memory C++ pointer operations with 0 bytes written to disk.
- π· Multi-Brand RAW & Image Format Support:
- Canon:
.CR3(ISOBMFF multi-blockCMT1βCMT4),.CR2 - Nikon:
.NEF,.NRW(Type 3 MakerNotes, Shutter Count, Lens Data) - Sony:
.ARW,.SR2 - Olympus / OM System:
.ORF(IIRO/IIRSheaders) - Fujifilm:
.RAF(Embedded container & Film Simulation modes) - Panasonic / Lumix:
.RW2(IIU\0headers) - Leica / Adobe / Ricoh / Pentax:
.DNG,.PEF - Standard:
.JPG,.JPEG,.JFIF
- Canon:
- π·οΈ Deep Vendor MakerNotes Extraction:
- Canon: Shooting mode, LensModel, CameraSettings, ShotInfo
- Nikon: Total Shutter Count (
MakerNote TotalShutterReleases), ISO settings, Lens Data - Sony: Sony Model ID, Creative Style, DRO, Long Exposure NR
- Fujifilm: Film Simulation, Dynamic Range, Film Mode
- Olympus & Panasonic: Equipment, Quality, Macro, Firmware
- π GPS Geolocation Telemetry: Latitude, Longitude, Altitude, TimeStamp.
- π Dual Dart API:
- Strongly-typed
FastExifDatawith parsed getters. - 1:1 exact drop-in replacement for
package:exif(readExifFromBytes,IfdTag,Ratio).
- Strongly-typed
- π οΈ C++ Photo Pipeline Interface: Direct
fast_exif::Reader::extractandfast_exif::Reader::sniffFormatfor native C++ pipelines.
π¦ Getting Started #
Add flutter_fast_exif_reader to your pubspec.yaml:
dependencies:
flutter_fast_exif_reader: ^0.1.0
π± Android Setup (GPS & Media Location Permissions) #
Starting in Android 10 (API 29) and reinforced in Android 11β14, Android OS Scoped Storage automatically redacts GPS geolocation metadata from image streams (substituting 0 deg 0' 0.0000" for coordinates) unless the application declares and requests the ACCESS_MEDIA_LOCATION permission.
1. Declare Permissions in AndroidManifest.xml #
Add the following to your android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required for unredacted GPS EXIF metadata access on Android 10+ (API 29..36) -->
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<application ...>
...
</application>
</manifest>
2. Request Runtime Permission #
Before picking or opening photos on Android, request the permission using permission_handler:
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
Future<void> requestMediaLocationPermission() async {
if (Platform.isAndroid) {
await [
Permission.photos,
Permission.storage,
Permission.accessMediaLocation,
].request();
}
}
π‘ Usage #
1. Modern Strongly-Typed API #
import 'dart:typed_data';
import 'package:flutter_fast_exif_reader/flutter_fast_exif_reader.dart';
void parsePhoto(Uint8List imageBytes) {
final FastExifData? exif = FlutterFastExifReader.readFromBytes(imageBytes);
if (exif != null) {
print('Camera: ${exif.make} ${exif.model}');
print('Lens: ${exif.lensModel}');
print('Settings: ${exif.fNumberString}, ${exif.exposureTimeString}, ${exif.isoString}');
print('GPS: ${exif.latitude}, ${exif.longitude}');
print('Process time: ${exif.processTimeMs.toStringAsFixed(2)} ms');
}
}
2. 1:1 package:exif Drop-In Replacement #
Migrate legacy code by simply updating the import statement with zero code changes:
import 'package:flutter_fast_exif_reader/flutter_fast_exif_reader.dart';
void readLegacyExif(List<int> bytes) async {
final Map<String, IfdTag> tags = await readExifFromBytes(bytes);
print('Make: ${tags['Image Make']}');
print('Orientation: ${tags['Image Orientation']}');
print('Shutter: ${tags['EXIF ExposureTime']}');
print('Date: ${tags['EXIF DateTimeOriginal']}');
}
3. Native C++ Pipeline Integration #
Include fast_exif_reader.h directly in your native processing pipeline:
#include "fast_exif_reader.h"
void processBuffer(const uint8_t* bytes, size_t len) {
fast_exif::ExifInfo info;
if (fast_exif::Reader::extract(bytes, len, info)) {
printf("Camera: %s %s\n", info.make.c_str(), info.model.c_str());
printf("Shutter: %s, Aperture: %s\n", info.getShutterSpeedString().c_str(), info.getApertureString().c_str());
printf("Total Tags: %zu\n", info.tags.size());
}
}
π Benchmark #
Tested across 15 real camera RAW files (16.9MB - 85.4MB):
| Format | Camera Model | legacy package:exif |
flutter_fast_exif_reader |
Speedup |
|---|---|---|---|---|
| Sony ARW | Sony ILCE-7RM6 (75.2MB) | 85.4 ms (97 tags) | 0.20 ms (168 tags) | 419x faster |
| Leica DNG | Leica Q3 Mono (85.4MB) | 23.5 ms (74 tags) | 0.05 ms (73 tags) | 508x faster |
| Leica DNG | Leica M11-P (47.6MB) | 5.3 ms (90 tags) | 0.06 ms (89 tags) | 87x faster |
| Sony ARW | Sony ILCE-7M5 (19.4MB) | 8.0 ms (97 tags) | 0.10 ms (167 tags) | 76x faster |
| Ricoh DNG | Ricoh GR IV (30.4MB) | 1.6 ms (62 tags) | 0.05 ms (63 tags) | 32x faster |
| Sony ARW | Sony ILCE-7M2 (46.9MB) | 4.7 ms (73 tags) | 0.09 ms (137 tags) | 52x faster |
| Nikon NEF | Nikon Z 8 (30.5MB) | 22.4 ms (145 tags) | 0.09 ms (109 tags) | 239x faster |
| Sony ARW | Sony DSC-RX10M5 (25.4MB) | 4.2 ms (96 tags) | 0.10 ms (164 tags) | 41x faster |
| Olympus ORF | OM-5 Mark II (16.9MB) | FAILED (0 tags) | 0.04 ms (61 tags) | Instant (vs Fail) |
| Canon CR3 | Canon EOS R5m2 (45.9MB) | FAILED (0 tags) | 0.07 ms (104 tags) | Instant (vs Fail) |
| Olympus ORF | OM-5 Mark II (20.1MB) | FAILED (0 tags) | 0.04 ms (61 tags) | Instant (vs Fail) |
| Fujifilm RAF | Fujifilm X-T30 III (55MB) | FAILED (0 tags) | 0.11 ms (156 tags) | Instant (vs Fail) |
| Panasonic RW2 | Lumix S1M2 (26.9MB) | FAILED (0 tags) | 0.05 ms (88 tags) | Instant (vs Fail) |
| Leica DNG | Leica SL3-P (56.9MB) | 3.9 ms (77 tags) | 0.06 ms (77 tags) | 66x faster |
| Panasonic RW2 | Lumix S1RM2 (52.3MB) | FAILED (0 tags) | 0.06 ms (88 tags) | Instant (vs Fail) |
π License #
This project is licensed under the MIT License - see the LICENSE file for details.