Octopus
Octopus

Reputation: 801

StorageFile.GetImagePropertiesAsync() gives wrong results when using StorageFileQueryResult with image metadata

Unfortunately, unless I am mistaken, it seems that there is a bug in the StorageFile Query api which makes it unreliable.

The following example is simple. The steps to reproduce it are:

-Take a folder and put in only one image, because the sample below assumes you will have only one file.

-This image should be in PEF format, taken from a Pentax 645Z. You can find the entire project as well as a PEF image here. https://github.com/Ponant/StorageFileQueryResultBug . Put the sample image in one folder, in an indexed location, e.g the Desktop.

-Install the Raw Image Extension from the Microsoft Store, https://www.microsoft.com/en-us/p/raw-image-extension/9nctdw2w1bh8?activetab=pivot:overviewtab . This extension is based on https://www.libraw.org/ and they support this camera https://www.libraw.org/supported-cameras

Run the app, you will see two buttons:

1) Button 1 launches a folder picker, creates a StorageFileQueryResult which allows one to fetch the only file in the folder. Then it calls the Api for the Image properties

                var imageProperties = await file.Properties.GetImagePropertiesAsync();

2) Button 2 launches a FilePicker, so you navigate to the folder, pick the same file, and then it runs the same method

                var imageProperties = await file.Properties.GetImagePropertiesAsync();

The two results are displayed in two textblocks. They should be identical, they aren't. The folder query returns empty values.

enter image description here

How can we solve this problem? Why the Filepicker gives the correct result on the same StorageFile? Can anyone confirm if this is a known bug, can we help in solving it?

We rely heavily on StorageFileQueryResult to build an app which allows people to view pictures and get metadata displayed. Having this reliability issue is scaring to say the least, and we cannot prompt the user to use the FilePicker on 10k images :).

Additional note: File explorer, just like the FilePicker, gives the correct answer. We also found a UWP File explorer app on the web which can be run from Win+R and it gives the correct information.

shell:AppsFolder\c5e2524a-ea46-4f67-841f-6a9465d9d515_cw5n1h2txyewy!App

This gives hope that UWP can display the correct information without using the File Picker but rather by querying the folder. We can achieve this by choosing

                IndexerOption = IndexerOption.DoNotUseIndexer,

in the query options, hence not relying on the indexer but that is a pity and will make the app less performant and furthermore will make us add additional code since we do use the indexer heavily.

Thanks

public sealed partial class Scenario4 : Page
{
    public Scenario4()
    {
        this.InitializeComponent();
    }
    private async void FolderPickerButton_Click(object sender, RoutedEventArgs e)
    {
        var folderPicker = new FolderPicker
        {
            SuggestedStartLocation = PickerLocationId.Desktop,
            ViewMode = PickerViewMode.Thumbnail
        };
        folderPicker.FileTypeFilter.Add("*");
        var folder = await folderPicker.PickSingleFolderAsync();
        if (folder == null)
        {
            return;
        }

        var queryOptions = new QueryOptions
        {
            IndexerOption = IndexerOption.UseIndexerWhenAvailable,
        };
        var query = folder.CreateFileQueryWithOptions(queryOptions);

        var files = (await query.GetFilesAsync());
        foreach (var file in files)
        {
            var imageProperties = await file.Properties.GetImagePropertiesAsync();
            folderThenQueryMethodTextBlock.Text =
                $"Dimensions {imageProperties.Width}x{imageProperties.Height} DateTaken {imageProperties.DateTaken}";
        }
    }
    private async void OpenFileAppBarButton_Click(object sender, RoutedEventArgs e)
    {
        FileOpenPicker picker = new FileOpenPicker();
        picker.FileTypeFilter.Add("*");
        picker.SuggestedStartLocation = PickerLocationId.Desktop;

        var file = await picker.PickSingleFileAsync();
        if (file != null)
        {
            var imageProperties = await file.Properties.GetImagePropertiesAsync();
            filePickerMethodTextBlock.Text =
                $"Dimensions {imageProperties.Width}x{imageProperties.Height} DateTaken {imageProperties.DateTaken}";
        }
    }
}

XAML

<Page
x:Class="Virtualization.Scenario4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="using:Virtualization"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"
                BorderBrush="Blue" BorderThickness="2" Margin="0,8,0,0">
        <Button x:Name="FolderPickerButton" Content="Query folder with one file"
                      Click="FolderPickerButton_Click"/>
        <Button Content="File picker"  Click="OpenFileAppBarButton_Click" Margin="16,0,0,0"/>
        <AppBarSeparator/>
    </StackPanel>
    <StackPanel Grid.Row="1" HorizontalAlignment="Center">
        <TextBlock Text="Using Query after Folder Picker"/>
        <TextBlock x:Name="folderThenQueryMethodTextBlock"/>
        <TextBlock Text="Using File Picker"/>
        <TextBlock x:Name="filePickerMethodTextBlock"/>
    </StackPanel>
</Grid>

Upvotes: 2

Views: 330

Answers (1)

Sean O&#39;Neil
Sean O&#39;Neil

Reputation: 1241

I took the time install the extension and try out your code. Everything you said is correct. The StorageFile when acquired from a StorageFileQueryResult results in default (wrong) image properties for the PEF file, but works fine with jpg files. This is clearly a bug. Whether the bug is in the framework or in the RAW image extension I do not know. Note that the extension has a lot of negative feedback on the Windows Store.

There is a reasonable workaround. You don't have to do one file at a time. Instead of using the query you can do this:

var files = await folder.GetFilesAsync();
foreach (var file in files)
{
    var imageProperties = await file.Properties.GetImagePropertiesAsync();
    folderThenQueryMethodTextBlock.Text =
        $"Dimensions {imageProperties.Width}x{imageProperties.Height} DateTaken {imageProperties.DateTaken}";
}

I can confirm that works.

If you need the power of the query, you could use it just to get a list of file names, then use 'StorageFolder.GetFileAsync(fileName)' in a foreach loop. As long as the StorageFile comes from StorageFolder.GetXXX it seems to work fine.

Upvotes: 1

Related Questions