mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Fix WebP images not loading on Windows installations without WebP extensions installed
This commit is contained in:
parent
0be1081142
commit
1c609a3d6a
@ -19,6 +19,9 @@ using Wabbajack.Extensions;
|
||||
using Wabbajack.Models;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using System.Drawing;
|
||||
using Catel.IO;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
@ -37,6 +40,32 @@ namespace Wabbajack
|
||||
return img;
|
||||
}
|
||||
|
||||
public static BitmapImage BitmapImageFromWebp(byte[] bytes, bool getThumbnail = false)
|
||||
{
|
||||
using(WebP webp = new())
|
||||
{
|
||||
Bitmap bitmap;
|
||||
if (getThumbnail)
|
||||
bitmap = webp.GetThumbnailFast(bytes, 640, 360);
|
||||
else
|
||||
bitmap = webp.Decode(bytes);
|
||||
|
||||
using(var ms = new MemoryStream())
|
||||
{
|
||||
bitmap.Save(ms, ImageFormat.Png);
|
||||
ms.Position = 0;
|
||||
|
||||
var img = new BitmapImage();
|
||||
img.BeginInit();
|
||||
img.CacheOption = BitmapCacheOption.OnLoad;
|
||||
img.StreamSource = ms;
|
||||
img.EndInit();
|
||||
img.Freeze();
|
||||
return img;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetBitmapImageFromFile(AbsolutePath path, out BitmapImage bitmapImage)
|
||||
{
|
||||
try
|
||||
@ -95,7 +124,7 @@ namespace Wabbajack
|
||||
try
|
||||
{
|
||||
var (found, mstream) = await FindCachedImage(url);
|
||||
if (found) return (ll, mstream);
|
||||
if (found) return (ll, mstream, url);
|
||||
|
||||
var ret = new MemoryStream();
|
||||
using (var client = new HttpClient())
|
||||
@ -107,21 +136,21 @@ namespace Wabbajack
|
||||
ret.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
await WriteCachedImage(url, ret.ToArray());
|
||||
return (ll, ret);
|
||||
return (ll, ret, url);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exceptionHandler(ex);
|
||||
return (ll, default);
|
||||
return (ll, default, url);
|
||||
}
|
||||
})
|
||||
.Select(x =>
|
||||
{
|
||||
var (ll, memStream) = x;
|
||||
var (ll, memStream, url) = x;
|
||||
if (memStream == null) return default;
|
||||
try
|
||||
{
|
||||
return BitmapImageFromStream(memStream);
|
||||
return url.EndsWith("webp", StringComparison.InvariantCultureIgnoreCase) ? BitmapImageFromWebp(memStream.ToArray(), true) : BitmapImageFromStream(memStream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
1976
Wabbajack.App.Wpf/Util/WebPWrapper.cs
Normal file
1976
Wabbajack.App.Wpf/Util/WebPWrapper.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -133,7 +133,8 @@ namespace Wabbajack
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(txt)) return _ => true;
|
||||
return item => item.Metadata.Title.ContainsCaseInsensitive(txt) ||
|
||||
item.Metadata.Description.ContainsCaseInsensitive(txt);
|
||||
item.Metadata.Description.ContainsCaseInsensitive(txt) ||
|
||||
item.Metadata.Tags.Contains(txt);
|
||||
});
|
||||
|
||||
var onlyInstalledGamesFilter = this.ObservableForProperty(vm => vm.OnlyInstalled)
|
||||
@ -169,12 +170,12 @@ namespace Wabbajack
|
||||
})
|
||||
.StartWith(_ => true);
|
||||
|
||||
var searchSorter = this.WhenValueChanged(x => x.Search)
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
var searchSorter = this.WhenValueChanged(vm => vm.Search)
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.Throttle(searchThrottle, RxApp.MainThreadScheduler)
|
||||
.Select(s => SortExpressionComparer<ModListMetadataVM>
|
||||
.Descending(modlist => modlist.Metadata.Title.StartsWith(s, StringComparison.InvariantCultureIgnoreCase))
|
||||
.ThenByDescending(modlist => modlist.Metadata.Title.Contains(s, StringComparison.InvariantCultureIgnoreCase)));
|
||||
.Descending(m => m.Metadata.Title.StartsWith(s, StringComparison.InvariantCultureIgnoreCase))
|
||||
.ThenByDescending(m => m.Metadata.Title.Contains(s, StringComparison.InvariantCultureIgnoreCase)));
|
||||
_modLists.Connect()
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Filter(searchTextPredicates)
|
||||
@ -183,6 +184,7 @@ namespace Wabbajack
|
||||
.Filter(showNSFWFilter)
|
||||
.Filter(gameFilter)
|
||||
.Sort(searchSorter)
|
||||
.Sort(SortExpressionComparer<ModListMetadataVM>.Descending(modlist => !modlist.IsBroken))
|
||||
.TreatMovesAsRemoveAdd()
|
||||
.Bind(out _filteredModLists)
|
||||
.Subscribe((_) =>
|
||||
|
@ -176,7 +176,7 @@ namespace Wabbajack
|
||||
.ToGuiProperty(this, nameof(Exists));
|
||||
|
||||
var imageObs = Observable.Return(Metadata.Links.ImageUri)
|
||||
.DownloadBitmapImage((ex) => _logger.LogError("Error downloading modlist image {Title}", Metadata.Title), LoadingImageLock);
|
||||
.DownloadBitmapImage((ex) => _logger.LogError("Error downloading modlist image {Title} from {ImageUri}: {Exception}", Metadata.Title, Metadata.Links.ImageUri, ex.Message), LoadingImageLock);
|
||||
|
||||
_Image = imageObs
|
||||
.ToGuiProperty(this, nameof(Image));
|
||||
|
@ -17,7 +17,7 @@
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.Column="1"
|
||||
BorderBrush="Transparent"
|
||||
@ -137,25 +137,8 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Grid Grid.Row="2" Margin="0, 10, 0, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox
|
||||
x:Name="ShowNSFW"
|
||||
FontSize="7"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource ForegroundBrush}"
|
||||
ToolTip="Only show Not Safe For Work (NSFW) modlists">
|
||||
<CheckBox.LayoutTransform>
|
||||
<ScaleTransform ScaleX="1.6" ScaleY="1.6"/>
|
||||
</CheckBox.LayoutTransform>
|
||||
</CheckBox>
|
||||
<TextBlock Grid.Column="1" Margin="5, 0, 0, 0" Text="Show NSFW modlists" FontSize="14" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="3" Margin="0, 10, 0, 0">
|
||||
<Grid Grid.Row="2" Margin="0, 10, 0, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@ -172,6 +155,24 @@
|
||||
<TextBlock Grid.Column="1" Margin="5, 0, 0, 0" Text="Show unofficial modlists" FontSize="14" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="3" Margin="0, 10, 0, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox
|
||||
x:Name="ShowNSFW"
|
||||
FontSize="7"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource ForegroundBrush}"
|
||||
ToolTip="Only show Not Safe For Work (NSFW) modlists">
|
||||
<CheckBox.LayoutTransform>
|
||||
<ScaleTransform ScaleX="1.6" ScaleY="1.6"/>
|
||||
</CheckBox.LayoutTransform>
|
||||
</CheckBox>
|
||||
<TextBlock Grid.Column="1" Margin="5, 0, 0, 0" Text="Show only NSFW modlists" FontSize="14" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="4" Margin="0, 10, 0, 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
|
@ -48,14 +48,15 @@
|
||||
</UserControl.Resources>
|
||||
<Border
|
||||
x:Name="ModListTile"
|
||||
Margin="10"
|
||||
Margin="8"
|
||||
Background="Transparent"
|
||||
BorderThickness="1">
|
||||
CornerRadius="8"
|
||||
BorderThickness="0">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect
|
||||
BlurRadius="25"
|
||||
Opacity="0.5"
|
||||
ShadowDepth="5" />
|
||||
Opacity="0.25"
|
||||
ShadowDepth="3" />
|
||||
</Border.Effect>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
@ -68,31 +69,21 @@
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid
|
||||
Width="570"
|
||||
Height="480"
|
||||
Background="{StaticResource DarkBackgroundBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="40" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
BorderBrush="{StaticResource ButtonNormalBorder}"
|
||||
BorderThickness="0,0,0,1">
|
||||
Width="327"
|
||||
Height="184"
|
||||
Background="Transparent">
|
||||
<Grid ClipToBounds="True">
|
||||
<mahapps:ProgressRing x:Name="LoadingProgress" />
|
||||
<Viewbox
|
||||
Height="340"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="UniformToFill">
|
||||
<Image x:Name="ModListImage">
|
||||
<Image.Style>
|
||||
<Style TargetType="Image">
|
||||
<TextBlock Text="{Binding Metadata.Title}" VerticalAlignment="Bottom" FontSize="14" Margin="10, 0, 0, 10" Panel.ZIndex="1"/>
|
||||
<Border
|
||||
BorderThickness="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch">
|
||||
<Border.Background>
|
||||
<ImageBrush x:Name="ModlistImage" Stretch="UniformToFill"/>
|
||||
</Border.Background>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsBroken}" Value="True">
|
||||
<Setter Property="Effect">
|
||||
@ -103,17 +94,16 @@
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Image.Style>
|
||||
</Image>
|
||||
</Viewbox>
|
||||
</Border.Style>
|
||||
</Border>
|
||||
<Ellipse
|
||||
Height="120"
|
||||
Margin="-40,0,-40,-60"
|
||||
VerticalAlignment="Bottom"
|
||||
Fill="Black"
|
||||
Opacity="0.5">
|
||||
Margin="-80,-100,-80,0"
|
||||
VerticalAlignment="Top"
|
||||
Fill="White"
|
||||
Opacity="0.15">
|
||||
<Ellipse.Effect>
|
||||
<BlurEffect Radius="55" />
|
||||
<BlurEffect Radius="75" />
|
||||
</Ellipse.Effect>
|
||||
<Ellipse.Style>
|
||||
<Style TargetType="Ellipse">
|
||||
@ -124,7 +114,7 @@
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.75"
|
||||
To="0.25"
|
||||
Duration="0:0:0.08" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
@ -134,7 +124,7 @@
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
To="0.5"
|
||||
To="0.15"
|
||||
Duration="0:0:0.08" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
@ -285,10 +275,10 @@
|
||||
</Label.Style>
|
||||
</Label>
|
||||
</Grid>
|
||||
</Border>
|
||||
<local:UnderMaintenanceOverlay Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
x:Name="Overlay"
|
||||
Visibility="Collapsed" />
|
||||
<!--
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
|
||||
x:Name="ModListTitleShadow"
|
||||
Margin="5"
|
||||
@ -402,8 +392,8 @@
|
||||
Kind="Exclamation" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
-->
|
||||
</Grid>
|
||||
</Border>
|
||||
</rxui:ReactiveUserControl>
|
||||
|
@ -2,6 +2,8 @@
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Media.Media3D;
|
||||
using MahApps.Metro.IconPacks;
|
||||
using ReactiveUI;
|
||||
@ -19,14 +21,39 @@ namespace Wabbajack
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
ViewModel.WhenAnyValue(vm => vm.Image)
|
||||
.BindToStrict(this, view => view.ModListImage.Source)
|
||||
.BindToStrict(this, v => v.ModlistImage.ImageSource)
|
||||
.DisposeWith(disposables);
|
||||
/*
|
||||
this.WhenAny(x => x.ViewModel.Metadata.Links.ImageUri)
|
||||
.Select(x => new BitmapImage() { UriSource = new Uri(x) })
|
||||
.BindToStrict(this, v => v.ModlistImage.ImageSource)
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
/*
|
||||
ViewModel.WhenAnyValue(x => x.Metadata.Links.ImageUri)
|
||||
.Select(x => {
|
||||
var img = new BitmapImage();
|
||||
img.BeginInit();
|
||||
img.CacheOption = BitmapCacheOption.OnDemand;
|
||||
img.DecodePixelWidth = 327;
|
||||
var uri = new Uri(x, UriKind.Absolute);
|
||||
img.UriSource = uri;
|
||||
img.EndInit();
|
||||
|
||||
return img;
|
||||
})
|
||||
.BindToStrict(this, v => v.ModlistImage.ImageSource)
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
|
||||
|
||||
var textXformed = ViewModel.WhenAnyValue(vm => vm.Metadata.Title)
|
||||
.CombineLatest(ViewModel.WhenAnyValue(vm => vm.Metadata.ImageContainsTitle),
|
||||
ViewModel.WhenAnyValue(vm => vm.IsBroken))
|
||||
.Select(x => x.Second && !x.Third ? "" : x.First);
|
||||
|
||||
|
||||
/*
|
||||
textXformed
|
||||
.BindToStrict(this, view => view.ModListTitle.Text)
|
||||
.DisposeWith(disposables);
|
||||
@ -42,6 +69,7 @@ namespace Wabbajack
|
||||
ViewModel.WhenAnyValue(x => x.ModListTagList)
|
||||
.BindToStrict(this, x => x.TagsList.ItemsSource)
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
|
||||
ViewModel.WhenAnyValue(x => x.LoadingImageLock.IsLoading)
|
||||
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
|
||||
@ -53,6 +81,7 @@ namespace Wabbajack
|
||||
.BindToStrict(this, view => view.Overlay.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
/*
|
||||
ViewModel.WhenAnyValue(x => x.OpenWebsiteCommand)
|
||||
.BindToStrict(this, x => x.OpenWebsiteButton.Command)
|
||||
.DisposeWith(disposables);
|
||||
@ -64,14 +93,18 @@ namespace Wabbajack
|
||||
ViewModel.WhenAnyValue(x => x.ExecuteCommand)
|
||||
.BindToStrict(this, x => x.ExecuteButton.Command)
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
ViewModel.WhenAnyValue(x => x.ProgressPercent)
|
||||
.ObserveOnDispatcher()
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Select(p => p.Value)
|
||||
.BindTo(this, x => x.DownloadProgressBar.Value)
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
|
||||
/*
|
||||
ViewModel.WhenAnyValue(x => x.Status)
|
||||
.ObserveOnGuiThread()
|
||||
.Subscribe(x =>
|
||||
@ -91,6 +124,7 @@ namespace Wabbajack
|
||||
});
|
||||
})
|
||||
.DisposeWith(disposables);
|
||||
*/
|
||||
|
||||
/*
|
||||
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, bool>(this.ViewModel, x => x.IsBroken);
|
||||
|
@ -96,6 +96,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Imazen.WebP" Version="10.0.1" />
|
||||
<PackageReference Include="MahApps.Metro" Version="2.4.10" />
|
||||
<PackageReference Include="MahApps.Metro.IconPacks" Version="4.11.0" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.5" />
|
||||
|
Loading…
Reference in New Issue
Block a user