nc-photos/lib/entity/exif.dart

129 lines
3.7 KiB
Dart
Raw Normal View History

2021-04-15 20:44:25 +02:00
import 'package:equatable/equatable.dart';
2021-04-10 06:28:12 +02:00
import 'package:exifdart/exifdart.dart';
import 'package:intl/intl.dart';
2021-08-06 19:11:00 +02:00
import 'package:nc_photos/type.dart';
2021-04-10 06:28:12 +02:00
2021-04-15 20:44:25 +02:00
class Exif with EquatableMixin {
2021-04-10 06:28:12 +02:00
Exif(this.data);
dynamic operator [](String key) => data[key];
@override
// ignore: hash_and_equals
2021-07-23 22:05:57 +02:00
bool operator ==(Object? other) => equals(other, isDeep: true);
/// Compare two Exif objects
///
/// If [isDeep] is false, two Exif objects are considered identical if they
/// contain the same number of fields. This hack is to save time comparing a
/// large amount of data that are mostly immutable
2021-07-23 22:05:57 +02:00
bool equals(Object? other, {bool isDeep = false}) {
if (isDeep) {
return super == other;
} else {
return identical(this, other) ||
other is Exif && data.keys.length == other.data.keys.length;
}
}
2021-04-10 06:28:12 +02:00
bool containsKey(String key) => data.containsKey(key);
2021-08-06 19:11:00 +02:00
JsonObj toJson() {
return Map.fromIterable(
data.entries.where((e) => e.key != "MakerNote").map((e) {
var jsonValue;
if (e.value is Rational) {
jsonValue = e.value.toJson();
} else if (e.value is List) {
jsonValue = e.value.map((e) {
if (e is Rational) {
return e.toJson();
} else {
return e;
}
}).toList();
} else {
jsonValue = e.value;
}
return MapEntry(e.key, jsonValue);
}),
key: (e) => e.key,
value: (e) => e.value,
);
2021-04-10 06:28:12 +02:00
}
2021-08-06 19:11:00 +02:00
factory Exif.fromJson(JsonObj json) {
return Exif(Map.fromIterable(
// we are filtering out MakerNote here because it's generally very large
// and could exceed the 1MB cursor size limit on Android. Second, the
// content is proprietary and thus useless to us anyway
json.entries.where((e) => e.key != "MakerNote").map((e) {
var exifValue;
if (e.value is Map) {
exifValue = Rational.fromJson(e.value.cast<String, dynamic>());
} else if (e.value is List) {
exifValue = e.value.map((e) {
if (e is Map) {
return Rational.fromJson(e.cast<String, dynamic>());
} else {
return e;
}
}).toList();
} else {
exifValue = e.value;
}
return MapEntry(e.key, exifValue);
}),
key: (e) => e.key,
value: (e) => e.value,
));
2021-04-10 06:28:12 +02:00
}
@override
toString() {
final dataStr = data.entries.map((e) {
return "${e.key}: '${e.value}'";
2021-04-10 06:28:12 +02:00
}).join(", ");
return "$runtimeType {$dataStr}";
}
/// 0x010f Make
2021-07-23 22:05:57 +02:00
String? get make => data["Make"];
2021-04-10 06:28:12 +02:00
/// 0x0110 Model
2021-07-23 22:05:57 +02:00
String? get model => data["Model"];
2021-04-10 06:28:12 +02:00
/// 0x9003 DateTimeOriginal
2021-09-04 17:13:52 +02:00
DateTime? get dateTimeOriginal => data.containsKey("DateTimeOriginal") &&
(data["DateTimeOriginal"] as String).isNotEmpty
2021-06-27 16:32:12 +02:00
? dateTimeFormat.parse(data["DateTimeOriginal"]).toUtc()
2021-04-10 06:28:12 +02:00
: null;
/// 0x829a ExposureTime
2021-07-23 22:05:57 +02:00
Rational? get exposureTime => data["ExposureTime"];
2021-04-10 06:28:12 +02:00
/// 0x829d FNumber
2021-07-23 22:05:57 +02:00
Rational? get fNumber => data["FNumber"];
2021-04-10 06:28:12 +02:00
/// 0x8827 ISO/ISOSpeedRatings/PhotographicSensitivity
2021-07-23 22:05:57 +02:00
int? get isoSpeedRatings => data["ISOSpeedRatings"];
2021-04-10 06:28:12 +02:00
/// 0x920a FocalLength
2021-07-23 22:05:57 +02:00
Rational? get focalLength => data["FocalLength"];
2021-04-10 06:28:12 +02:00
/// 0x8825 GPS tags
2021-07-23 22:05:57 +02:00
String? get gpsLatitudeRef => data["GPSLatitudeRef"];
List<Rational>? get gpsLatitude => data["GPSLatitude"].cast<Rational>();
String? get gpsLongitudeRef => data["GPSLongitudeRef"];
List<Rational>? get gpsLongitude => data["GPSLongitude"].cast<Rational>();
2021-04-15 20:44:25 +02:00
@override
get props => [
data,
];
2021-04-10 06:28:12 +02:00
final Map<String, dynamic> data;
2021-04-15 20:44:25 +02:00
static final dateTimeFormat = DateFormat("yyyy:MM:dd HH:mm:ss");
2021-04-10 06:28:12 +02:00
}