image conversion generalized into media conversion.

This commit is contained in:
morkt 2015-06-14 09:05:09 +04:00
parent 227eae0dbe
commit 4c089120d1
10 changed files with 192 additions and 102 deletions

View File

@ -1,28 +1,24 @@
<Window x:Class="GARbro.GUI.ConvertImages"
<Window x:Class="GARbro.GUI.ConvertMedia"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:GARbro.GUI.Strings"
xmlns:p="clr-namespace:GARbro.GUI.Properties"
xmlns:g="clr-namespace:GameRes;assembly=GameRes"
Title="{x:Static s:guiStrings.TextConvertImages}" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
Title="{x:Static s:guiStrings.TextConvertMedia}" ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
ResizeMode="NoResize" SizeToContent="WidthAndHeight"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Margin="20,10,20,10">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Margin="20,10,20,0">
<Label Content="{x:Static s:guiStrings.LabelDestinationFormat}" Target="{Binding ElementName=ImageConversionFormat}" HorizontalAlignment="Left" Padding="0,0,10,0" VerticalAlignment="Center"/>
<ComboBox Name="ImageConversionFormat" DisplayMemberPath="Tag" Width="60" HorizontalAlignment="Left"
ItemsSource="{Binding Source={x:Static g:FormatCatalog.Instance}, Path=ImageFormats, Mode=OneWay}"
SelectedValue="{Binding Source={x:Static p:Settings.Default}, Path=appLastImageFormat, Mode=TwoWay}" SelectedValuePath="Tag"/>
ItemsSource="{Binding Source={x:Static g:FormatCatalog.Instance}, Path=ImageFormats, Mode=OneWay}" SelectedValuePath="Tag"
SelectedValue="{Binding Source={x:Static p:Settings.Default}, Path=appLastImageFormat, Mode=TwoWay}"/>
</StackPanel>
<Separator Grid.Row="1"/>
<StackPanel Orientation="Horizontal" Margin="10,0,10,10" HorizontalAlignment="Right" Grid.Row="2">
<TextBlock Text="{x:Static s:guiStrings.TextAudioConversion}" Margin="20,10"/>
<Separator/>
<StackPanel Orientation="Horizontal" Margin="10,0,10,10" HorizontalAlignment="Right">
<Button Content="{x:Static s:guiStrings.ButtonOK}" Click="ConvertButton_Click" Margin="10" Width="75" IsDefault="True" Height="25"/>
<Button Content="{x:Static s:guiStrings.ButtonCancel}" Margin="10" IsCancel="True" Width="75" Height="25"/>
</StackPanel>
</Grid>
</StackPanel>
</Window>

View File

@ -3,11 +3,11 @@
namespace GARbro.GUI
{
/// <summary>
/// Interaction logic for ConvertImages.xaml
/// Interaction logic for ConvertMedia.xaml
/// </summary>
public partial class ConvertImages : Window
public partial class ConvertMedia : Window
{
public ConvertImages ()
public ConvertMedia ()
{
InitializeComponent ();
}

View File

@ -126,8 +126,8 @@
<Compile Include="ArcParameters.xaml.cs">
<DependentUpon>ArcParameters.xaml</DependentUpon>
</Compile>
<Compile Include="ConvertImages.xaml.cs">
<DependentUpon>ConvertImages.xaml</DependentUpon>
<Compile Include="ConvertMedia.xaml.cs">
<DependentUpon>ConvertMedia.xaml</DependentUpon>
</Compile>
<Compile Include="CreateArchive.xaml.cs">
<DependentUpon>CreateArchive.xaml</DependentUpon>
@ -168,7 +168,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ConvertImages.xaml">
<Page Include="ConvertMedia.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -2,6 +2,26 @@
//! \date Fri Aug 22 08:22:47 2014
//! \brief Game resources conversion methods.
//
// Copyright (C) 2014-2015 by morkt
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
using System;
using System.IO;
@ -23,53 +43,61 @@ namespace GARbro.GUI
/// <summary>
/// Convert selected images to another format.
/// </summary>
void ConvertImageExec (object sender, ExecutedRoutedEventArgs e)
void ConvertMediaExec (object sender, ExecutedRoutedEventArgs e)
{
if (ViewModel.IsArchive)
return;
var source = CurrentDirectory.SelectedItems.Cast<EntryViewModel>()
.Where (f => f.Type == "image").Select (f => f.Name);
var convert_dialog = new ConvertImages();
.Where (f => f.Type == "image" || f.Type == "audio")
.Select (f => f.Source);
if (!source.Any())
{
PopupError (guiStrings.MsgNoMediaFiles, guiStrings.TextMediaConvertError);
return;
}
var convert_dialog = new ConvertMedia();
convert_dialog.Owner = this;
var result = convert_dialog.ShowDialog() ?? false;
if (!result)
return;
var selected = convert_dialog.ImageConversionFormat.SelectedValue as string;
var format = FormatCatalog.Instance.ImageFormats.FirstOrDefault (f => f.Tag == selected);
var format = convert_dialog.ImageConversionFormat.SelectedItem as ImageFormat;
// var format = FormatCatalog.Instance.ImageFormats.FirstOrDefault (f => f.Tag == selected);
if (null == format)
{
Trace.WriteLine ("Format is not selected", "ConvertImageExec");
Trace.WriteLine ("Format is not selected", "ConvertMediaExec");
return;
}
try
{
Directory.SetCurrentDirectory (ViewModel.Path);
var converter = new GarConvertImages (this);
var converter = new GarConvertMedia (this);
converter.Convert (source, format);
}
catch (Exception X)
{
PopupError (X.Message, guiStrings.TextImageConvertError);
PopupError (X.Message, guiStrings.TextMediaConvertError);
}
}
}
internal class GarConvertImages
internal class GarConvertMedia
{
private MainWindow m_main;
private ProgressDialog m_progress_dialog;
private IEnumerable<string> m_source;
private IEnumerable<Entry> m_source;
private ImageFormat m_image_format;
private Exception m_pending_error;
private List<Tuple<string,string>> m_failed = new List<Tuple<string,string>>();
public bool IgnoreErrors { get; set; }
public IEnumerable<Tuple<string,string>> FailedFiles { get { return m_failed; } }
public GarConvertImages (MainWindow parent)
public GarConvertMedia (MainWindow parent)
{
m_main = parent;
}
public void Convert (IEnumerable<string> images, ImageFormat format)
public void Convert (IEnumerable<Entry> images, ImageFormat format)
{
m_main.StopWatchDirectoryChanges();
m_source = images;
@ -91,46 +119,28 @@ namespace GARbro.GUI
m_pending_error = null;
try
{
string target_ext = m_image_format.Extensions.First();
int total = m_source.Count();
int i = 0;
foreach (var filename in m_source)
foreach (var entry in m_source)
{
if (m_progress_dialog.CancellationPending)
throw new OperationCanceledException();
var filename = entry.Name;
int progress = i++*100/total;
string target_name = Path.ChangeExtension (filename, target_ext);
if (filename == target_name)
continue;
string source_ext = Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant();
if (m_image_format.Extensions.Any (ext => ext == source_ext))
continue;
m_progress_dialog.ReportProgress (progress, string.Format (guiStrings.MsgConvertingFile,
Path.GetFileName (filename)), null);
try
{
using (var file = File.OpenRead (filename))
{
m_progress_dialog.ReportProgress (progress, string.Format (guiStrings.MsgConvertingImage,
filename), target_name);
var image = ImageFormat.Read (file);
if (null == image)
continue;
try
{
using (var output = File.Create (target_name))
m_image_format.Write (output, image);
}
catch // delete destination file on conversion failure
{
File.Delete (target_name);
throw;
}
}
if ("image" == entry.Type)
ConvertImage (filename);
else if ("audio" == entry.Type)
ConvertAudio (filename);
}
catch (Exception X)
{
if (!IgnoreErrors)
throw;
m_pending_error = X;
m_failed.Add (Tuple.Create (Path.GetFileName (filename), X.Message));
}
}
}
@ -140,6 +150,67 @@ namespace GARbro.GUI
}
}
public static readonly HashSet<string> CommonAudioFormats = new HashSet<string> { "wav", "mp3", "ogg" };
public static readonly AudioFormat WavFormat = FormatCatalog.Instance.AudioFormats.First (f => f.Tag == "WAV");
void ConvertAudio (string filename)
{
using (var file = File.OpenRead (filename))
using (var input = AudioFormat.Read (file))
{
if (null == input)
return;
var source_ext = Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant();
string source_format = input.SourceFormat;
if (CommonAudioFormats.Contains (source_format))
{
if (source_ext == source_format)
return;
string output_name = Path.ChangeExtension (filename, source_format);
using (var output = File.Create (output_name))
{
input.Source.Position = 0;
input.Source.CopyTo (output);
}
}
else
{
if (source_ext == "wav")
return;
string output_name = Path.ChangeExtension (filename, "wav");
using (var output = File.Create (output_name))
WavFormat.Write (input, output);
}
}
}
void ConvertImage (string filename)
{
string target_ext = m_image_format.Extensions.First();
string target_name = Path.ChangeExtension (filename, target_ext);
if (filename == target_name)
return;
string source_ext = Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant();
if (m_image_format.Extensions.Any (ext => ext == source_ext))
return;
using (var file = File.OpenRead (filename))
{
var image = ImageFormat.Read (file);
if (null == image)
return;
try
{
using (var output = File.Create (target_name))
m_image_format.Write (output, image);
}
catch // delete destination file on conversion failure
{
File.Delete (target_name);
throw;
}
}
}
void OnConvertComplete (object sender, RunWorkerCompletedEventArgs e)
{
m_main.ResumeWatchDirectoryChanges();
@ -149,7 +220,7 @@ namespace GARbro.GUI
if (m_pending_error is OperationCanceledException)
m_main.SetStatusText (m_pending_error.Message);
else
m_main.PopupError (m_pending_error.Message, guiStrings.TextImageConvertError);
m_main.PopupError (m_pending_error.Message, guiStrings.TextMediaConvertError);
}
m_main.Activate();
m_main.RefreshView();

View File

@ -113,8 +113,6 @@ namespace GARbro.GUI
private ProgressDialog m_progress_dialog;
private Exception m_pending_error;
public static readonly HashSet<string> CommonAudioFormats = new HashSet<string> { "wav", "mp3", "ogg" };
public bool IsActive { get { return m_extract_in_progress; } }
public GarExtract (MainWindow parent, string source)
@ -365,7 +363,7 @@ namespace GARbro.GUI
public static void ConvertAudio (string entry_name, SoundInput input)
{
string source_format = input.SourceFormat;
if (CommonAudioFormats.Contains (source_format))
if (GarConvertMedia.CommonAudioFormats.Contains (source_format))
{
string output_name = Path.ChangeExtension (entry_name, source_format);
using (var output = ArchiveFormat.CreateFile (output_name))
@ -376,10 +374,9 @@ namespace GARbro.GUI
}
else
{
var wav_format = FormatCatalog.Instance.AudioFormats.First (f => f.Tag == "WAV");
string output_name = Path.ChangeExtension (entry_name, "wav");
using (var output = ArchiveFormat.CreateFile (output_name))
wav_format.Write (input, output);
GarConvertMedia.WavFormat.Write (input, output);
}
}

View File

@ -94,7 +94,7 @@
Command="{x:Static local:Commands.Refresh}"/>
<MenuItem Header="{x:Static s:guiStrings.CtxMenuConvert}" InputGestureText="F6"
Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource booleanToCollapsedVisibilityConverter}}"
Command="{x:Static local:Commands.ConvertImage}" />
Command="{x:Static local:Commands.ConvertMedia}" />
</ContextMenu>
</Window.Resources>
@ -107,7 +107,7 @@
<MenuItem Header="{x:Static s:guiStrings.CtxMenuCreate}" InputGestureText="F3"
Command="{x:Static local:Commands.CreateArchive}" />
<MenuItem Header="{x:Static s:guiStrings.CtxMenuConvert}" InputGestureText="F6"
Command="{x:Static local:Commands.ConvertImage}" />
Command="{x:Static local:Commands.ConvertMedia}" />
<MenuItem Header="{x:Static s:guiStrings.MenuRecent}" x:Name="RecentFilesMenu">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
@ -265,7 +265,7 @@
<KeyBinding Gesture="F2" Command="{x:Static local:Commands.RenameItem}"/>
<KeyBinding Gesture="F4" Command="{x:Static local:Commands.ExtractItem}"/>
<KeyBinding Gesture="F5" Command="{x:Static local:Commands.Refresh}"/>
<KeyBinding Gesture="F6" Command="{x:Static local:Commands.ConvertImage}"/>
<KeyBinding Gesture="F6" Command="{x:Static local:Commands.ConvertMedia}"/>
<KeyBinding Gesture="Delete" Command="{x:Static local:Commands.DeleteItem}"/>
<KeyBinding Gesture="Backspace" Command="{x:Static local:Commands.GoBack}"/>
<MouseBinding Gesture="LeftDoubleClick" Command="{x:Static local:Commands.OpenItem}" />
@ -366,7 +366,7 @@
<CommandBinding Command="{x:Static local:Commands.DeleteItem}" Executed="DeleteItemExec" CanExecute="CanExecuteOnPhysicalFile" />
<CommandBinding Command="{x:Static local:Commands.RenameItem}" Executed="RenameItemExec" CanExecute="CanExecuteInDirectory" />
<CommandBinding Command="{x:Static local:Commands.ExploreItem}" Executed="ExploreItemExec" CanExecute="CanExecuteInDirectory" />
<CommandBinding Command="{x:Static local:Commands.ConvertImage}" Executed="ConvertImageExec" CanExecute="CanExecuteConvertImage" />
<CommandBinding Command="{x:Static local:Commands.ConvertMedia}" Executed="ConvertMediaExec" CanExecute="CanExecuteConvertMedia" />
<CommandBinding Command="{x:Static local:Commands.SortBy}" Executed="SortByExec" CanExecute="CanExecuteAlways"/>
<CommandBinding Command="{x:Static local:Commands.GoBack}" Executed="GoBackExec" CanExecute="CanExecuteGoBack"/>
<CommandBinding Command="{x:Static local:Commands.GoForward}" Executed="GoForwardExec" CanExecute="CanExecuteGoForward"/>

View File

@ -1075,16 +1075,12 @@ namespace GARbro.GUI
e.CanExecute = CurrentDirectory.SelectedIndex != -1;
}
private void CanExecuteConvertImage (object sender, CanExecuteRoutedEventArgs e)
private void CanExecuteConvertMedia (object sender, CanExecuteRoutedEventArgs e)
{
if (CurrentDirectory.SelectedItems.Count > 1)
if (CurrentDirectory.SelectedItems.Count >= 1)
{
e.CanExecute = !ViewModel.IsArchive;
}
else
{
CanExecuteOnImage (sender, e);
}
}
private void CanExecuteOnImage (object sender, CanExecuteRoutedEventArgs e)
@ -1302,7 +1298,7 @@ namespace GARbro.GUI
public static readonly RoutedCommand DeleteItem = new RoutedCommand();
public static readonly RoutedCommand RenameItem = new RoutedCommand();
public static readonly RoutedCommand ExploreItem = new RoutedCommand();
public static readonly RoutedCommand ConvertImage = new RoutedCommand();
public static readonly RoutedCommand ConvertMedia = new RoutedCommand();
public static readonly RoutedCommand Refresh = new RoutedCommand();
public static readonly RoutedCommand Browse = new RoutedCommand();
public static readonly RoutedCommand FitWindow = new RoutedCommand();

View File

@ -106,7 +106,7 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Convert images....
/// Looks up a localized string similar to Convert multimedia....
/// </summary>
public static string CtxMenuConvert {
get {
@ -304,7 +304,7 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Choose destination format.
/// Looks up a localized string similar to Choose destination format for images.
/// </summary>
public static string LabelDestinationFormat {
get {
@ -457,11 +457,11 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Converting image {0}.
/// Looks up a localized string similar to Converting file {0}.
/// </summary>
public static string MsgConvertingImage {
public static string MsgConvertingFile {
get {
return ResourceManager.GetString("MsgConvertingImage", resourceCulture);
return ResourceManager.GetString("MsgConvertingFile", resourceCulture);
}
}
@ -627,6 +627,15 @@ namespace GARbro.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to No media files selected..
/// </summary>
public static string MsgNoMediaFiles {
get {
return ResourceManager.GetString("MsgNoMediaFiles", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File {0}
///already exists.
@ -756,6 +765,15 @@ namespace GARbro.GUI.Strings {
}
}
/// <summary>
/// Looks up a localized string similar to Audio will be converted to either WAV, MP3 or OGG..
/// </summary>
public static string TextAudioConversion {
get {
return ResourceManager.GetString("TextAudioConversion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Choose archive location.
/// </summary>
@ -793,11 +811,11 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Convert images.
/// Looks up a localized string similar to Convert media.
/// </summary>
public static string TextConvertImages {
public static string TextConvertMedia {
get {
return ResourceManager.GetString("TextConvertImages", resourceCulture);
return ResourceManager.GetString("TextConvertMedia", resourceCulture);
}
}
@ -874,11 +892,11 @@ namespace GARbro.GUI.Strings {
}
/// <summary>
/// Looks up a localized string similar to Image conversion error.
/// Looks up a localized string similar to Multimedia conversion error.
/// </summary>
public static string TextImageConvertError {
public static string TextMediaConvertError {
get {
return ResourceManager.GetString("TextImageConvertError", resourceCulture);
return ResourceManager.GetString("TextMediaConvertError", resourceCulture);
}
}

View File

@ -379,22 +379,22 @@ Overwrite?</value>
<value>_View</value>
</data>
<data name="CtxMenuConvert" xml:space="preserve">
<value>Convert images...</value>
<value>Convert multimedia...</value>
</data>
<data name="ButtonConvert" xml:space="preserve">
<value>Convert</value>
</data>
<data name="LabelDestinationFormat" xml:space="preserve">
<value>Choose destination format</value>
<value>Choose destination format for images</value>
</data>
<data name="TextConvertImages" xml:space="preserve">
<value>Convert images</value>
<data name="TextConvertMedia" xml:space="preserve">
<value>Convert media</value>
</data>
<data name="MsgConvertingImage" xml:space="preserve">
<value>Converting image {0}</value>
<data name="MsgConvertingFile" xml:space="preserve">
<value>Converting file {0}</value>
</data>
<data name="TextImageConvertError" xml:space="preserve">
<value>Image conversion error</value>
<data name="TextMediaConvertError" xml:space="preserve">
<value>Multimedia conversion error</value>
</data>
<data name="LabelEncoding" xml:space="preserve">
<value>Encoding</value>
@ -417,4 +417,10 @@ Overwrite?</value>
<data name="MsgUnableInterpretAudio" xml:space="preserve">
<value>unable to interpret audio format</value>
</data>
<data name="MsgNoMediaFiles" xml:space="preserve">
<value>No media files selected.</value>
</data>
<data name="TextAudioConversion" xml:space="preserve">
<value>Audio will be converted to either WAV, MP3 or OGG.</value>
</data>
</root>

View File

@ -394,22 +394,22 @@
<value>Просмотр</value>
</data>
<data name="CtxMenuConvert" xml:space="preserve">
<value>Конверсия изображений...</value>
<value>Конверсия мультимедиа...</value>
</data>
<data name="ButtonConvert" xml:space="preserve">
<value>Преобразовать</value>
</data>
<data name="LabelDestinationFormat" xml:space="preserve">
<value>Формат преобразования</value>
<value>Формат преобразования изображений</value>
</data>
<data name="TextConvertImages" xml:space="preserve">
<value>Преобразовать изображения</value>
<data name="TextConvertMedia" xml:space="preserve">
<value>Преобразовать мультимедиа</value>
</data>
<data name="MsgConvertingImage" xml:space="preserve">
<data name="MsgConvertingFile" xml:space="preserve">
<value>Преобразование файла {0}</value>
</data>
<data name="TextImageConvertError" xml:space="preserve">
<value>Ошибка конверсии изображения</value>
<data name="TextMediaConvertError" xml:space="preserve">
<value>Ошибка конверсии мультимедиа</value>
</data>
<data name="LabelEncoding" xml:space="preserve">
<value>Кодировка</value>
@ -435,4 +435,10 @@
<data name="MsgUnableInterpretAudio" xml:space="preserve">
<value>не удалось интерпретировать формат аудио</value>
</data>
<data name="MsgNoMediaFiles" xml:space="preserve">
<value>Среди выбранных файлов нет мультиемедиа.</value>
</data>
<data name="TextAudioConversion" xml:space="preserve">
<value>Аудио-файлы будут преобразованы в WAV, MP3 или OGG.</value>
</data>
</root>