Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
b09fe6de55
5 changed files with 22 additions and 19 deletions
|
@ -84,6 +84,8 @@ internal class TiffFetcher(val model: TiffImage, val width: Int, val height: Int
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
val bitmap: Bitmap? = TiffBitmapFactory.decodeFileDescriptor(fd, options)
|
val bitmap: Bitmap? = TiffBitmapFactory.decodeFileDescriptor(fd, options)
|
||||||
|
// calling `TiffBitmapFactory.closeFd(fd)` after decoding yields a segmentation fault
|
||||||
|
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
callback.onLoadFailed(Exception("Decoding full TIFF yielded null bitmap"))
|
callback.onLoadFailed(Exception("Decoding full TIFF yielded null bitmap"))
|
||||||
} else if (customSize) {
|
} else if (customSize) {
|
||||||
|
|
|
@ -91,7 +91,7 @@ import java.util.regex.Pattern;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forked from 'androidx.exifinterface:exifinterface:1.4.0-beta01' on 2025/01/21
|
* Forked from 'androidx.exifinterface:exifinterface:1.4.0'
|
||||||
* Named differently to let ExifInterface be loaded as subdependency.
|
* Named differently to let ExifInterface be loaded as subdependency.
|
||||||
* cf https://maven.google.com/web/index.html?q=exifinterface#androidx.exifinterface:exifinterface
|
* cf https://maven.google.com/web/index.html?q=exifinterface#androidx.exifinterface:exifinterface
|
||||||
* cf https://github.com/androidx/androidx/tree/androidx-main/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media
|
* cf https://github.com/androidx/androidx/tree/androidx-main/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media
|
||||||
|
|
|
@ -51,15 +51,15 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
||||||
|
|
||||||
// prefer Flutter for animation, as well as niche formats and SVG
|
// prefer Flutter for animation, as well as niche formats and SVG
|
||||||
// prefer Android for the rest, to rely on device codecs and handle config conversion
|
// prefer Android for the rest, to rely on device codecs and handle config conversion
|
||||||
bool _canDecodeWithFlutter(String mimeType, bool isAnimated) {
|
bool _preferPlatformDecoding(String mimeType, bool isAnimated) {
|
||||||
switch(mimeType) {
|
switch (mimeType) {
|
||||||
case MimeTypes.bmp:
|
case MimeTypes.bmp:
|
||||||
case MimeTypes.wbmp:
|
case MimeTypes.wbmp:
|
||||||
case MimeTypes.ico:
|
case MimeTypes.ico:
|
||||||
case MimeTypes.svg:
|
case MimeTypes.svg:
|
||||||
return true;
|
return false;
|
||||||
default:
|
default:
|
||||||
return isAnimated;
|
return !isAnimated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,16 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
if (_canDecodeWithFlutter(mimeType, isAnimated)) {
|
if (_preferPlatformDecoding(mimeType, isAnimated)) {
|
||||||
|
// get decoded media bytes from platform, and rely on a codec instantiated from raw bytes
|
||||||
|
final descriptor = await mediaFetchService.getDecodedImage(request);
|
||||||
|
if (descriptor != null) {
|
||||||
|
return descriptor.instantiateCodec();
|
||||||
|
}
|
||||||
|
debugPrint('failed to load decoded image for mimeType=$mimeType uri=$uri, falling back to loading encoded image');
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
// get original media bytes from platform, and rely on a codec instantiated by `ImageProvider`
|
// get original media bytes from platform, and rely on a codec instantiated by `ImageProvider`
|
||||||
final bytes = await mediaFetchService.getEncodedImage(request);
|
final bytes = await mediaFetchService.getEncodedImage(request);
|
||||||
if (bytes.isEmpty) {
|
if (bytes.isEmpty) {
|
||||||
|
@ -90,14 +99,6 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
||||||
}
|
}
|
||||||
final buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
|
final buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
|
||||||
return await decode(buffer);
|
return await decode(buffer);
|
||||||
} else {
|
|
||||||
// get decoded media bytes from platform, and rely on a codec instantiated from raw bytes
|
|
||||||
final descriptor = await mediaFetchService.getDecodedImage(request);
|
|
||||||
if (descriptor == null) {
|
|
||||||
throw UnreportedStateError('$uri ($mimeType) image loading failed');
|
|
||||||
}
|
|
||||||
return descriptor.instantiateCodec();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// loading may fail if the provided MIME type is incorrect (e.g. the Media Store may report a JPEG as a TIFF)
|
// loading may fail if the provided MIME type is incorrect (e.g. the Media Store may report a JPEG as a TIFF)
|
||||||
debugPrint('$runtimeType _loadAsync failed with mimeType=$mimeType, uri=$uri, error=$error');
|
debugPrint('$runtimeType _loadAsync failed with mimeType=$mimeType, uri=$uri, error=$error');
|
||||||
|
|
|
@ -20,7 +20,7 @@ class VideoControlButtonsPage extends StatelessWidget {
|
||||||
return AvesScaffold(
|
return AvesScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
automaticallyImplyLeading: !settings.useTvLayout,
|
automaticallyImplyLeading: !settings.useTvLayout,
|
||||||
title: Text(context.l10n.settingsVideoControlsPageTitle),
|
title: Text(context.l10n.settingsVideoButtonsTile),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Selector<Settings, List<EntryAction>>(
|
child: Selector<Settings, List<EntryAction>>(
|
||||||
|
|
|
@ -58,7 +58,7 @@ class _VideoCoverState extends State<VideoCover> {
|
||||||
Size get videoDisplaySize => widget.videoDisplaySize;
|
Size get videoDisplaySize => widget.videoDisplaySize;
|
||||||
|
|
||||||
// use the high res photo as cover for the video part of a motion photo
|
// use the high res photo as cover for the video part of a motion photo
|
||||||
ImageProvider get videoCoverUriImage => mainEntry.isMotionPhoto ? mainEntry.uriImage : entry.uriImage;
|
ImageProvider get videoCoverUriImage => (mainEntry.isMotionPhoto ? mainEntry : entry).uriImage;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
|
Loading…
Reference in a new issue