diff --git a/lib/model/image_entry.dart b/lib/model/image_entry.dart index 1c6e1d02c..a4b55a66d 100644 --- a/lib/model/image_entry.dart +++ b/lib/model/image_entry.dart @@ -217,7 +217,12 @@ class ImageEntry { } } - bool get isPortrait => rotationDegrees % 180 == 90; + // The additional comparison of width to height is a workaround for badly registered entries. + // e.g. a portrait FHD video should be registered as width=1920, height=1080, orientation=90, + // but is incorrectly registered in the Media Store as width=1080, height=1920, orientation=0 + // Double-checking the width/height during loading or cataloguing is the proper solution, + // but it would take space and time, so a basic workaround will do. + bool get isPortrait => rotationDegrees % 180 == 90 && (catalogMetadata?.rotationDegrees == null || width > height); String get resolutionText { final w = width ?? '?'; diff --git a/lib/utils/math_utils.dart b/lib/utils/math_utils.dart index c83bde20b..299404753 100644 --- a/lib/utils/math_utils.dart +++ b/lib/utils/math_utils.dart @@ -1,11 +1,16 @@ import 'dart:math'; +final double _log2 = log(2); const double _piOver180 = pi / 180.0; -final double log2 = log(2); - double toDegrees(num radians) => radians / _piOver180; double toRadians(num degrees) => degrees * _piOver180; -int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / log2).floor()); +int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / _log2).floor()); + +// e.g. x=12345, precision=3 should return 13000 +int ceilBy(num x, int precision) { + final factor = pow(10, precision); + return (x / factor).ceil() * factor; +} diff --git a/lib/widgets/common/data_providers/media_store_collection_provider.dart b/lib/widgets/common/data_providers/media_store_collection_provider.dart index f10dd760b..ec6ab0e35 100644 --- a/lib/widgets/common/data_providers/media_store_collection_provider.dart +++ b/lib/widgets/common/data_providers/media_store_collection_provider.dart @@ -6,6 +6,7 @@ import 'package:aves/model/metadata_db.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/services/image_file_service.dart'; +import 'package:aves/utils/math_utils.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:flutter/material.dart'; import 'package:flutter_native_timezone/flutter_native_timezone.dart'; @@ -91,10 +92,4 @@ class MediaStoreSource extends CollectionSource { onError: (error) => debugPrint('$runtimeType stream error=$error'), ); } - - // e.g. x=12345, precision=3 should return 13000 - int ceilBy(num x, int precision) { - final factor = pow(10, precision); - return (x / factor).ceil() * factor; - } } diff --git a/test/utils/math_utils_test.dart b/test/utils/math_utils_test.dart new file mode 100644 index 000000000..13eed0641 --- /dev/null +++ b/test/utils/math_utils_test.dart @@ -0,0 +1,31 @@ +import 'dart:math'; + +import 'package:aves/utils/math_utils.dart'; +import 'package:test/test.dart'; + +void main() { + test('convert angles in radians to degrees', () { + expect(toDegrees(pi), 180); + expect(toDegrees(-pi / 2), -90); + }); + + test('convert angles in degrees to radians', () { + expect(toRadians(180), pi); + expect(toRadians(-270), pi * -3 / 2); + }); + + test('highest power of 2 that is smaller than or equal to the number', () { + expect(highestPowerOf2(1024), 1024); + expect(highestPowerOf2(42), 32); + expect(highestPowerOf2(0), 0); + expect(highestPowerOf2(-42), 0); + }); + + test('rounding up to a given precision before the decimal', () { + expect(ceilBy(12345.678, 3), 13000); + expect(ceilBy(42, 3), 1000); + expect(ceilBy(0, 3), 0); + expect(ceilBy(-42, 3), 0); + expect(ceilBy(-12345.678, 3), -12000); + }); +}