Skip to content

Commit 177cec2

Browse files
Added XZ Compression
1 parent 45330b3 commit 177cec2

5 files changed

Lines changed: 248 additions & 2 deletions

File tree

CompressedFileViewer/CompressedFileViewer.plugin.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
<ItemGroup>
4646
<PackageReference Include="DNNE" Version="2.0.6" />
47+
<PackageReference Include="Joveler.Compression.XZ" Version="4.3.0" />
4748
<PackageReference Include="SharpZipLib" Version="1.4.2" />
4849
<PackageReference Include="System.Drawing.Common" Version="8.0.3" />
4950
<PackageReference Include="ZstdSharp.Port" Version="0.7.6" />
@@ -60,6 +61,9 @@
6061
<Compile Update="Windows\DecompressDialog.xaml.cs">
6162
<SubType>Code</SubType>
6263
</Compile>
64+
<Compile Update="Windows\XZSettingsDialog.xaml.cs">
65+
<SubType>Code</SubType>
66+
</Compile>
6367
<Compile Update="Windows\ZstdSettingsDialog.xaml.cs">
6468
<SubType>Code</SubType>
6569
</Compile>

CompressedFileViewer/Preferences.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ public static Preferences Deserialize(Stream from)
125125
{
126126
pref.ZstdSettings = Default.ZstdSettings;
127127
}
128+
if(pref.Version < 3)
129+
{
130+
pref.XZSettings = Default.XZSettings;
131+
}
128132

129133
return pref;
130134
}
@@ -145,7 +149,7 @@ public static Preferences Deserialize(Stream from)
145149
/// </summary>
146150
/// <param name="path">The file path to get the compression settings for.</param>
147151
/// <returns>The compression settings for the file.</returns>
148-
public CompressionSettings? GetCompressionBySuffix(string path)
152+
public CompressionSettings? GetCompressionBySuffix(string? path)
149153
{
150154
return SupportedCompressionAlgorithms.FirstOrDefault(comp => comp.Extensions.Any(ext => path?.EndsWith(ext, StringComparison.OrdinalIgnoreCase) ?? false));
151155
}
@@ -162,8 +166,8 @@ public static Preferences Deserialize(Stream from)
162166
#region Compression Algorithms
163167
public BZip2Settings BZip2Settings { get; set; } = new();
164168
public GZipSettings GZipSettings { get; set; } = new();
165-
166169
public ZstdSettings ZstdSettings { get; set; } = new();
170+
public XZSettings XZSettings { get; set; } = new();
167171
#endregion
168172

169173
/// <summary>
@@ -205,6 +209,7 @@ public static Preferences Default
205209
preferences.GZipSettings.Extensions.AddRange([".gz", ".gzip"]);
206210
preferences.BZip2Settings.Extensions.AddRange([".bz2", ".bzip2"]);
207211
preferences.ZstdSettings.Extensions.Add(".zst");
212+
preferences.XZSettings.Extensions.Add(".xz");
208213
return preferences;
209214
}
210215
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using Joveler.Compression.XZ;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Runtime.InteropServices;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
10+
namespace CompressedFileViewer.Settings;
11+
[Serializable]
12+
public class XZSettings : CompressionSettings
13+
{
14+
public static readonly string ALGORITHM_NAME = "xz";
15+
static bool isSupported = false;
16+
static XZSettings()
17+
{
18+
try
19+
{
20+
string currentDir = System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location)!;
21+
string libPath = "";
22+
/*switch (RuntimeInformation.ProcessArchitecture)
23+
{
24+
case Architecture.X86:
25+
libPath = System.IO.Path.Combine(currentDir, "x86", "liblzma.dll");
26+
break;
27+
case Architecture.X64:
28+
libPath = System.IO.Path.Combine(currentDir, "x64", "liblzma.dll");
29+
break;
30+
case Architecture.Arm64:
31+
libPath = System.IO.Path.Combine(currentDir, "arm64", "liblzma.dll");
32+
break;
33+
}*/
34+
libPath = System.IO.Path.Combine(currentDir, "liblzma.dll");
35+
XZInit.GlobalInit(libPath);
36+
Logging.Log("Finished loading liblzma.dll", $"Version: {XZInit.VersionString()}");
37+
isSupported = true;
38+
} catch (Exception ex)
39+
{
40+
isSupported = false;
41+
Logging.Log(ex);
42+
}
43+
}
44+
45+
public override string AlgorithmName => ALGORITHM_NAME;
46+
47+
public int BufferSize { get; set; } = 1024 * 1024;
48+
49+
public LzmaCheck ChecksumType { get; set; }
50+
51+
public bool ExtremeFlag { get; set; } = false;
52+
53+
public LzmaCompLevel CompressionLevel { get; set; } = LzmaCompLevel.Default;
54+
55+
private XZCompressOptions CompressionOptions => new XZCompressOptions()
56+
{
57+
BufferSize = BufferSize,
58+
Check = ChecksumType,
59+
ExtremeFlag = ExtremeFlag,
60+
LeaveOpen = true,
61+
Level = CompressionLevel,
62+
63+
};
64+
private XZDecompressOptions DecompressOptions => new XZDecompressOptions()
65+
{
66+
BufferSize = BufferSize,
67+
LeaveOpen = true,
68+
};
69+
70+
public bool MultiThreading { get; set; } = false;
71+
public int Threads { get; set; } = Environment.ProcessorCount;
72+
73+
private XZThreadedCompressOptions ThreadOptions => new XZThreadedCompressOptions() { BlockSize = (uint)BufferSize, Threads = Threads };
74+
private XZThreadedDecompressOptions ThreadDecompressOptions => new XZThreadedDecompressOptions() { Threads = Threads };
75+
76+
public override bool IsSupported => isSupported;
77+
78+
public override Stream GetCompressionStream(Stream outStream)
79+
{
80+
if (!MultiThreading)
81+
return new XZStream(outStream, CompressionOptions);
82+
else
83+
return new XZStream(outStream, CompressionOptions, ThreadOptions);
84+
}
85+
public override Stream GetDecompressionStream(Stream inStream)
86+
{
87+
if (!MultiThreading)
88+
return new XZStream(inStream, DecompressOptions);
89+
return new XZStream(inStream, DecompressOptions, ThreadDecompressOptions);
90+
}
91+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<Window x:Class="CompressedFileViewer.Windows.XZSettingsDialog"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:local="clr-namespace:CompressedFileViewer.Windows"
7+
mc:Ignorable="d"
8+
Title="GZipSettingsDialog" Height="450" Width="523">
9+
<Grid>
10+
<TextBlock Text="Compression Level:" Margin="10,10,149,0" Height="21" FontSize="14" VerticalAlignment="Top" />
11+
<TextBox FontSize="14" Margin="0,10,10,0" Height="21" VerticalAlignment="Top" HorizontalAlignment="Right" Width="134" Name="txtComprLevel">
12+
<TextBox.ToolTip>
13+
The compression level used when compressing a file. (0-9, Default 6)
14+
</TextBox.ToolTip>
15+
</TextBox>
16+
<TextBlock Text="Buffer Size:" Margin="10,36,149,0" Height="21" FontSize="14" VerticalAlignment="Top">
17+
<TextBlock.ToolTip>
18+
The size of the internal buffer used.
19+
</TextBlock.ToolTip>
20+
</TextBlock>
21+
<TextBox FontSize="14" Margin="0,36,10,0" Height="21" VerticalAlignment="Top" HorizontalAlignment="Right" Width="134" Name="txtBufferSize" />
22+
<TextBlock Text="Multi-Threading:" Margin="10,62,149,0" Height="21" FontSize="14" VerticalAlignment="Top">
23+
<TextBlock.ToolTip>
24+
If Multi-Threading is enabled or not.
25+
</TextBlock.ToolTip>
26+
</TextBlock>
27+
<CheckBox FontSize="14" Margin="0,62,10,0" Height="21" VerticalAlignment="Top" HorizontalAlignment="Right" Width="134" Name="chkMultiThreading" />
28+
<TextBlock Text="Threads:" Margin="10,88,149,0" Height="21" FontSize="14" VerticalAlignment="Top">
29+
<TextBlock.ToolTip>
30+
Number of worker threads to use.
31+
NOTE: You must use threaded compression to let xz-utils decompress in parallel, even if you are using only 1 thread.
32+
</TextBlock.ToolTip>
33+
</TextBlock>
34+
<TextBox FontSize="14" Margin="0,88,10,0" Height="21" VerticalAlignment="Top" HorizontalAlignment="Right" Width="134" Name="txtThreads" />
35+
36+
37+
38+
<ListBox Margin="10,130,10,73" Name="lstSuffix" SelectionMode="Single"/>
39+
<TextBox Name="txtSuffix" Margin="10,0,226,47" Height="21" VerticalAlignment="Bottom" />
40+
<Button Margin="0,0,121,47" Height="21" VerticalAlignment="Bottom" Content="Add Suffix" HorizontalAlignment="Right" Width="100" Click="AddSuffix"/>
41+
<Button Margin="0,0,10,47" Height="21" VerticalAlignment="Bottom" Content="Delete" HorizontalAlignment="Right" Width="100" Click="DeleteSuffix"/>
42+
<Button Margin="10,0,0,10" Height="21" VerticalAlignment="Bottom" Content="OK" HorizontalAlignment="Left" Width="100" Click="Button_Click"/>
43+
<Button Margin="129,0,0,10" Height="21" VerticalAlignment="Bottom" Content="Default" HorizontalAlignment="Left" Width="100" Click="Default"/>
44+
<Button Margin="0,0,10,10" Height="21" VerticalAlignment="Bottom" Content="Cancel" HorizontalAlignment="Right" Width="100" Click="Cancel"/>
45+
</Grid>
46+
</Window>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using CompressedFileViewer.Settings;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.Windows;
8+
using System.Windows.Controls;
9+
using System.Windows.Data;
10+
using System.Windows.Documents;
11+
using System.Windows.Input;
12+
using System.Windows.Media;
13+
using System.Windows.Media.Imaging;
14+
using System.Windows.Shapes;
15+
16+
namespace CompressedFileViewer.Windows;
17+
/// <summary>
18+
/// Interaktionslogik für XZSettingsDialog.xaml
19+
/// </summary>
20+
public partial class XZSettingsDialog : Window, ISettingsDialog
21+
{
22+
static XZSettingsDialog()
23+
{
24+
SettingsDialog.RegistSettingsDialog(XZSettings.ALGORITHM_NAME, typeof(XZSettingsDialog));
25+
}
26+
27+
public XZSettingsDialog()
28+
{
29+
InitializeComponent();
30+
}
31+
32+
Settings.XZSettings? settings;
33+
34+
public CompressionSettings? CompressionSettings
35+
{
36+
get => settings;
37+
set
38+
{
39+
settings = (Settings.XZSettings?)value;
40+
txtBufferSize.Text = settings!.BufferSize.ToString();
41+
txtComprLevel.Text = ((int)settings.CompressionLevel).ToString();
42+
txtThreads.Text = settings.Threads.ToString();
43+
chkMultiThreading.IsChecked = settings.MultiThreading;
44+
lstSuffix.Items.Clear();
45+
foreach (var suffix in settings.Extensions)
46+
_ = lstSuffix.Items.Add(suffix);
47+
}
48+
}
49+
50+
private void AddSuffix(object sender, RoutedEventArgs e)
51+
{
52+
string suffix = txtSuffix.Text.Trim();
53+
if (string.IsNullOrWhiteSpace(suffix)) return;
54+
if (!suffix.StartsWith('.'))
55+
suffix = '.' + suffix;
56+
foreach (string items in lstSuffix.Items)
57+
if (items.Equals(suffix, StringComparison.OrdinalIgnoreCase))
58+
return;
59+
_ = lstSuffix.Items.Add(suffix);
60+
}
61+
62+
private void DeleteSuffix(object sender, RoutedEventArgs e)
63+
{
64+
if(lstSuffix.SelectedIndex != -1)
65+
lstSuffix.Items.RemoveAt(lstSuffix.SelectedIndex);
66+
}
67+
68+
private void Button_Click(object sender, RoutedEventArgs e)
69+
{
70+
int comprLevel = int.Parse(txtComprLevel.Text);
71+
int bufferSize = int.Parse(txtBufferSize.Text);
72+
int threads = int.Parse(txtThreads.Text);
73+
74+
settings!.Extensions.Clear();
75+
settings.Extensions.AddRange(lstSuffix.Items.Cast<string>());
76+
settings.CompressionLevel = (Joveler.Compression.XZ.LzmaCompLevel)comprLevel;
77+
settings.BufferSize = bufferSize;
78+
settings.MultiThreading = chkMultiThreading.IsChecked == true;
79+
settings.Threads = threads;
80+
this.DialogResult = true;
81+
Close();
82+
}
83+
84+
private void Cancel(object sender, RoutedEventArgs e)
85+
{
86+
this.DialogResult = false;
87+
Close();
88+
}
89+
90+
private void Default(object sender, RoutedEventArgs e)
91+
{
92+
var settings = Preferences.Default.XZSettings;
93+
txtBufferSize.Text = settings!.BufferSize.ToString();
94+
txtComprLevel.Text = settings.CompressionLevel.ToString();
95+
lstSuffix.Items.Clear();
96+
foreach (var suffix in settings.Extensions)
97+
_ = lstSuffix.Items.Add(suffix);
98+
99+
}
100+
}

0 commit comments

Comments
 (0)