fallback for decoding large panorama
This commit is contained in:
parent
2325501f3f
commit
15fe378107
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 {
|
||||
val bitmap: Bitmap? = TiffBitmapFactory.decodeFileDescriptor(fd, options)
|
||||
// calling `TiffBitmapFactory.closeFd(fd)` after decoding yields a segmentation fault
|
||||
|
||||
if (bitmap == null) {
|
||||
callback.onLoadFailed(Exception("Decoding full TIFF yielded null bitmap"))
|
||||
} else if (customSize) {
|
||||
|
|
|
@ -91,7 +91,7 @@ import java.util.regex.Pattern;
|
|||
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.
|
||||
* 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
|
||||
|
|
|
@ -51,15 +51,15 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
|||
|
||||
// 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
|
||||
bool _canDecodeWithFlutter(String mimeType, bool isAnimated) {
|
||||
switch(mimeType) {
|
||||
bool _preferPlatformDecoding(String mimeType, bool isAnimated) {
|
||||
switch (mimeType) {
|
||||
case MimeTypes.bmp:
|
||||
case MimeTypes.wbmp:
|
||||
case MimeTypes.ico:
|
||||
case MimeTypes.svg:
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
return isAnimated;
|
||||
return !isAnimated;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,16 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
|||
},
|
||||
);
|
||||
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`
|
||||
final bytes = await mediaFetchService.getEncodedImage(request);
|
||||
if (bytes.isEmpty) {
|
||||
|
@ -90,14 +99,6 @@ class UriImage extends ImageProvider<UriImage> with EquatableMixin {
|
|||
}
|
||||
final buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
|
||||
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) {
|
||||
// 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');
|
||||
|
|
|
@ -20,7 +20,7 @@ class VideoControlButtonsPage extends StatelessWidget {
|
|||
return AvesScaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: !settings.useTvLayout,
|
||||
title: Text(context.l10n.settingsVideoControlsPageTitle),
|
||||
title: Text(context.l10n.settingsVideoButtonsTile),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Selector<Settings, List<EntryAction>>(
|
||||
|
|
|
@ -58,7 +58,7 @@ class _VideoCoverState extends State<VideoCover> {
|
|||
Size get videoDisplaySize => widget.videoDisplaySize;
|
||||
|
||||
// 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
|
||||
void initState() {
|
||||
|
|
Loading…
Reference in a new issue