mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
126 lines
3.9 KiB
Dart
126 lines
3.9 KiB
Dart
import 'dart:io' as io;
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:exifdart/exifdart.dart' as exifdart;
|
|
import 'package:exifdart/exifdart_io.dart';
|
|
import 'package:exifdart/exifdart_memory.dart';
|
|
import 'package:image_size_getter/image_size_getter.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:nc_photos/account.dart';
|
|
import 'package:nc_photos/debug_util.dart';
|
|
import 'package:nc_photos/entity/exif.dart';
|
|
import 'package:nc_photos/entity/file.dart' as app;
|
|
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
|
import 'package:nc_photos/file_extension.dart';
|
|
import 'package:nc_photos/image_size_getter_util.dart';
|
|
import 'package:np_codegen/np_codegen.dart';
|
|
|
|
part 'load_metadata.g.dart';
|
|
|
|
@npLog
|
|
class LoadMetadata {
|
|
/// Load metadata of [binary], which is the content of [file]
|
|
Future<app.Metadata> loadRemote(
|
|
Account account, app.File file, Uint8List binary) {
|
|
return _loadMetadata(
|
|
mime: file.contentType ?? "",
|
|
exifdartReaderBuilder: () => MemoryBlobReader(binary),
|
|
imageSizeGetterInputBuilder: () => AsyncMemoryInput(binary),
|
|
filename: file.path,
|
|
);
|
|
}
|
|
|
|
Future<app.Metadata> loadLocal(
|
|
io.File file, {
|
|
String? mime,
|
|
}) async {
|
|
mime = mime ?? await file.readMime();
|
|
return _loadMetadata(
|
|
mime: mime ?? "",
|
|
exifdartReaderBuilder: () => FileReader(file),
|
|
imageSizeGetterInputBuilder: () => AsyncFileInput(file),
|
|
filename: file.path,
|
|
);
|
|
}
|
|
|
|
Future<app.Metadata> _loadMetadata({
|
|
required String mime,
|
|
required exifdart.AbstractBlobReader Function() exifdartReaderBuilder,
|
|
required AsyncImageInput Function() imageSizeGetterInputBuilder,
|
|
String? filename,
|
|
}) async {
|
|
var metadata = exifdart.Metadata();
|
|
if (file_util.isMetadataSupportedMime(mime)) {
|
|
try {
|
|
metadata = await exifdart.readMetadata(exifdartReaderBuilder());
|
|
} catch (e, stacktrace) {
|
|
_log.shout(
|
|
"[_loadMetadata] Failed while readMetadata for $mime file: ${logFilename(filename)}",
|
|
e,
|
|
stacktrace);
|
|
// ignore exif
|
|
}
|
|
}
|
|
|
|
int imageWidth = 0, imageHeight = 0;
|
|
if (metadata.imageWidth == null || metadata.imageHeight == null) {
|
|
try {
|
|
final resolution =
|
|
await AsyncImageSizeGetter.getSize(imageSizeGetterInputBuilder());
|
|
// image size getter doesn't handle exif orientation
|
|
if (metadata.exif?.containsKey("Orientation") == true &&
|
|
metadata.exif!["Orientation"] >= 5 &&
|
|
metadata.exif!["Orientation"] <= 8) {
|
|
// 90 deg CW/CCW
|
|
imageWidth = resolution.height;
|
|
imageHeight = resolution.width;
|
|
} else {
|
|
imageWidth = resolution.width;
|
|
imageHeight = resolution.height;
|
|
}
|
|
} catch (e, stacktrace) {
|
|
// is this even an image file?
|
|
_log.shout(
|
|
"[_loadMetadata] Failed while getSize for $mime file: ${logFilename(filename)}",
|
|
e,
|
|
stacktrace);
|
|
}
|
|
} else {
|
|
if (metadata.rotateAngleCcw != null &&
|
|
metadata.rotateAngleCcw! % 180 != 0) {
|
|
imageWidth = metadata.imageHeight!;
|
|
imageHeight = metadata.imageWidth!;
|
|
} else {
|
|
imageWidth = metadata.imageWidth!;
|
|
imageHeight = metadata.imageHeight!;
|
|
}
|
|
}
|
|
|
|
final map = {
|
|
if (metadata.exif != null) "exif": metadata.exif,
|
|
if (imageWidth > 0 && imageHeight > 0)
|
|
"resolution": {
|
|
"width": imageWidth,
|
|
"height": imageHeight,
|
|
},
|
|
};
|
|
return _buildMetadata(map);
|
|
}
|
|
|
|
app.Metadata _buildMetadata(Map<String, dynamic> map) {
|
|
int? imageWidth, imageHeight;
|
|
Exif? exif;
|
|
if (map.containsKey("resolution")) {
|
|
imageWidth = map["resolution"]["width"];
|
|
imageHeight = map["resolution"]["height"];
|
|
}
|
|
if (map.containsKey("exif")) {
|
|
exif = Exif(map["exif"]);
|
|
}
|
|
return app.Metadata(
|
|
imageWidth: imageWidth,
|
|
imageHeight: imageHeight,
|
|
exif: exif,
|
|
);
|
|
}
|
|
}
|