Skip to content

Commit

Permalink
Moved Rotate filter to before the crop/scale filter. This means that …
Browse files Browse the repository at this point in the history
…output sizes/cropping are applied after rotation.

Added ability to reflect deinterlace/detelecine/grayscale in picture preview.
Updated HandBrake core.
  • Loading branch information
RandomEngy committed May 24, 2021
1 parent 37e1354 commit 1abdf0d
Show file tree
Hide file tree
Showing 16 changed files with 245 additions and 229 deletions.
Binary file modified Lib/HandBrake.Interop.dll
Binary file not shown.
Binary file modified Lib/HandBrake.Interop.pdb
Binary file not shown.
Binary file modified Lib/hb.dll
Binary file not shown.
34 changes: 0 additions & 34 deletions VidCoder/Extensions/VCProfileExtensions.cs

This file was deleted.

2 changes: 1 addition & 1 deletion VidCoder/Model/PreviewImageJob.cs
Expand Up @@ -20,7 +20,7 @@ public class PreviewImageJob
/// </summary>
public object ImageFileSync { get; set; }

public VCProfile Profile { get; set; }
public VCJob Job { get; set; }

public SourceTitle Title { get; set; }
}
Expand Down
61 changes: 19 additions & 42 deletions VidCoder/Services/PreviewImageService.cs
Expand Up @@ -12,6 +12,7 @@
using System.Windows.Media.Imaging;
using DynamicData;
using HandBrake.Interop.Interop;
using HandBrake.Interop.Interop.Json.Encode;
using Microsoft.AnyContainer;
using ReactiveUI;
using VidCoder.Extensions;
Expand Down Expand Up @@ -408,7 +409,7 @@ private void EnqueueWork(int previewNumber)
UpdateVersion = updateVersion,
ScanInstance = this.ScanInstance,
PreviewIndex = previewNumber,
Profile = this.job.EncodingProfile,
Job = this.job,
Title = this.mainViewModel.SelectedTitle.Title,
ImageFileSync = this.imageFileSync[previewNumber]
});
Expand Down Expand Up @@ -475,16 +476,24 @@ private void ProcessPreviewImageWork(object state)
}

if (imageSource == null && !imageJob.ScanInstance.IsDisposed)
{
// Make a HandBrake call to get the image
imageSource = BitmapUtilities.ConvertToBitmapImage(BitmapUtilities.ConvertByteArrayToBitmap(imageJob.ScanInstance.GetPreview(imageJob.Profile.CreatePreviewSettings(imageJob.Title), imageJob.PreviewIndex, imageJob.Profile.DeinterlaceType != VCDeinterlace.Off)));
{
// Create the JsonEncodeObject
JsonEncodeFactory factory = new JsonEncodeFactory(new StubLogger());

JsonEncodeObject jsonEncodeObject = factory.CreateJsonObject(
imageJob.Job,
imageJob.Title,
EncodingRes.DefaultChapterName);

// Make a HandBrake call to get the image
imageSource = BitmapUtilities.ConvertToBitmapImage(BitmapUtilities.ConvertByteArrayToBitmap(imageJob.ScanInstance.GetPreview(jsonEncodeObject, imageJob.PreviewIndex)));

// Transform the image as per rotation and reflection settings
VCProfile profile = imageJob.Profile;
if (profile.FlipHorizontal || profile.FlipVertical || profile.Rotation != VCPictureRotation.None)
{
imageSource = CreateTransformedBitmap(imageSource, profile);
}
//// Transform the image as per rotation and reflection settings
//VCProfile profile = imageJob.Job.EncodingProfile;
//if (profile.FlipHorizontal || profile.FlipVertical || profile.Rotation != VCPictureRotation.None)
//{
// imageSource = CreateTransformedBitmap(imageSource, profile);
//}

// Start saving the image file in the background and continue to process the queue.
ThreadPool.QueueUserWorkItem(this.BackgroundFileSave, new SaveImageJob
Expand Down Expand Up @@ -518,38 +527,6 @@ private void ProcessPreviewImageWork(object state)
}
}

private static TransformedBitmap CreateTransformedBitmap(BitmapSource source, VCProfile profile)
{
var transformedBitmap = new TransformedBitmap();
transformedBitmap.BeginInit();
transformedBitmap.Source = source;
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(profile.FlipHorizontal ? -1 : 1, profile.FlipVertical ? -1 : 1));
transformGroup.Children.Add(new RotateTransform(ConvertRotationToDegrees(profile.Rotation)));
transformedBitmap.Transform = transformGroup;
transformedBitmap.EndInit();
transformedBitmap.Freeze();

return transformedBitmap;
}

private static double ConvertRotationToDegrees(VCPictureRotation rotation)
{
switch (rotation)
{
case VCPictureRotation.None:
return 0;
case VCPictureRotation.Clockwise90:
return 90;
case VCPictureRotation.Clockwise180:
return 180;
case VCPictureRotation.Clockwise270:
return 270;
}

return 0;
}

private void BackgroundFileSave(object state)
{
var job = state as SaveImageJob;
Expand Down
1 change: 0 additions & 1 deletion VidCoder/Utilities/PresetConverter.cs
Expand Up @@ -33,7 +33,6 @@ public static Preset ConvertHandBrakePresetToVC(HBPreset hbPreset)
profile.Width = hbPreset.PictureWidth ?? 0;
profile.Height = hbPreset.PictureHeight ?? 0;
profile.PaddingMode = VCPaddingMode.None;
profile.Modulus = hbPreset.PictureModulus;
profile.Rotation = VCPictureRotation.None;
profile.FlipHorizontal = false;
profile.FlipVertical = false;
Expand Down
110 changes: 55 additions & 55 deletions VidCoder/View/Panels/SizingPanel.xaml
Expand Up @@ -21,6 +21,61 @@
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<WrapPanel>
<!-- Rotation section -->
<StackPanel
MinWidth="180"
Orientation="Vertical"
Style="{StaticResource SizingSectionStyle}">
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource SectionHeader}"
Text="{x:Static res:EncodingRes.RotationLabel}" />
<ComboBox
MinWidth="140"
Margin="3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
ItemsSource="{Binding RotationChoices}"
SelectedValue="{Binding Rotation}"
SelectedValuePath="Rotation"
ToolTipService.ShowDuration="20000">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel d:DataContext="{d:DesignInstance dataModels:RotationViewModel}" Orientation="Horizontal">
<Image
Width="20"
Height="20"
Margin="0 0 6 0"
Source="{Binding Image}"
Visibility="{Binding ShowImage,
Converter={StaticResource VisibilityConverter}}" />
<TextBlock VerticalAlignment="Center" Text="{Binding Display}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.RotationToolTip}" />
</ComboBox.ToolTip>
</ComboBox>
<CheckBox
Margin="3"
Content="{x:Static res:EncodingRes.FlipHorizontalCheckBox}"
IsChecked="{Binding FlipHorizontal}">
<CheckBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.FlipHorizontalToolTip}" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox
Margin="3"
Content="{x:Static res:EncodingRes.FlipVerticalCheckBox}"
IsChecked="{Binding FlipVertical}">
<CheckBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.FlipVerticalToolTip}" />
</CheckBox.ToolTip>
</CheckBox>
</StackPanel>

<!-- Cropping section -->
<Grid Style="{StaticResource SizingSectionStyle}">
<TextBlock
Expand Down Expand Up @@ -269,61 +324,6 @@
</StackPanel>
</StackPanel>

<!-- Rotation section -->
<StackPanel
MinWidth="180"
Orientation="Vertical"
Style="{StaticResource SizingSectionStyle}">
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource SectionHeader}"
Text="{x:Static res:EncodingRes.RotationLabel}" />
<ComboBox
MinWidth="140"
Margin="3"
HorizontalAlignment="Left"
VerticalAlignment="Center"
ItemsSource="{Binding RotationChoices}"
SelectedValue="{Binding Rotation}"
SelectedValuePath="Rotation"
ToolTipService.ShowDuration="20000">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel d:DataContext="{d:DesignInstance dataModels:RotationViewModel}" Orientation="Horizontal">
<Image
Width="20"
Height="20"
Margin="0 0 6 0"
Source="{Binding Image}"
Visibility="{Binding ShowImage,
Converter={StaticResource VisibilityConverter}}" />
<TextBlock VerticalAlignment="Center" Text="{Binding Display}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.RotationToolTip}" />
</ComboBox.ToolTip>
</ComboBox>
<CheckBox
Margin="3"
Content="{x:Static res:EncodingRes.FlipHorizontalCheckBox}"
IsChecked="{Binding FlipHorizontal}">
<CheckBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.FlipHorizontalToolTip}" />
</CheckBox.ToolTip>
</CheckBox>
<CheckBox
Margin="3"
Content="{x:Static res:EncodingRes.FlipVerticalCheckBox}"
IsChecked="{Binding FlipVertical}">
<CheckBox.ToolTip>
<TextBlock Style="{StaticResource LongToolTip}" Text="{x:Static res:EncodingRes.FlipVerticalToolTip}" />
</CheckBox.ToolTip>
</CheckBox>
</StackPanel>

<!-- Padding section -->
<StackPanel Style="{StaticResource SizingSectionStyle}">
<TextBlock
Expand Down
68 changes: 44 additions & 24 deletions VidCoder/ViewModel/Panels/SizingPanelViewModel.cs
Expand Up @@ -260,20 +260,7 @@ public SizingPanelViewModel(EncodingWindowViewModel encodingWindowViewModel)
{
this.AutomaticChange = true;
if (x.selectedTitle == null)
{
this.CropTop = 0;
this.CropBottom = 0;
this.CropLeft = 0;
this.CropRight = 0;
}
else
{
this.CropTop = x.selectedTitle.Crop[0];
this.CropBottom = x.selectedTitle.Crop[1];
this.CropLeft = x.selectedTitle.Crop[2];
this.CropRight = x.selectedTitle.Crop[3];
}
this.RefreshCropping();
}
this.AutomaticChange = oldAutoValue;
Expand Down Expand Up @@ -428,7 +415,6 @@ private void RegisterProfileProperties()
// These actions fire when the user changes a property.
this.RegisterProfileProperty(nameof(this.Profile.Width), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Profile.Height), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Profile.Modulus), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Profile.PixelAspectX), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Profile.PixelAspectY), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Profile.CroppingType), () =>
Expand Down Expand Up @@ -471,9 +457,18 @@ private void RegisterProfileProperties()
this.RegisterProfileProperty(nameof(this.CropBottom), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.CropLeft), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.CropRight), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.Rotation), this.RefreshOutputSize);
this.RegisterProfileProperty(nameof(this.FlipHorizontal), () => this.previewUpdateService.RefreshPreview());
this.RegisterProfileProperty(nameof(this.FlipVertical), () => this.previewUpdateService.RefreshPreview());
this.RegisterProfileProperty(nameof(this.Rotation), () => {
this.RefreshOutputSize();
this.RefreshCropping();
});
this.RegisterProfileProperty(nameof(this.FlipHorizontal), () => {
this.previewUpdateService.RefreshPreview();
this.RefreshCropping();
});
this.RegisterProfileProperty(nameof(this.FlipVertical), () => {
this.previewUpdateService.RefreshPreview();
this.RefreshCropping();
});
this.RegisterProfileProperty(nameof(this.SizingMode), () =>
{
if (this.SizingMode == VCSizingMode.Manual)
Expand Down Expand Up @@ -611,12 +606,6 @@ public string PadColor
private ObservableAsPropertyHelper<bool> padColorEnabled;
public bool PadColorEnabled => this.padColorEnabled.Value;

public int Modulus
{
get { return this.Profile.Modulus; }
set { this.UpdateProfileProperty(nameof(this.Profile.Modulus), value); }
}

public int PixelAspectX
{
get { return this.Profile.PixelAspectX; }
Expand Down Expand Up @@ -704,6 +693,37 @@ public void RefreshOutputSize()
this.previewUpdateService.RefreshPreview();
}

private void RefreshCropping()
{
if (this.CroppingType != VCCroppingType.Automatic)
{
return;
}

bool oldAutoValue = this.AutomaticChange;
this.AutomaticChange = true;

SourceTitleViewModel sourceTitle = this.MainViewModel.SelectedTitle;
if (sourceTitle == null)
{
this.CropTop = 0;
this.CropBottom = 0;
this.CropLeft = 0;
this.CropRight = 0;
}
else
{
VCCropping autoCropping = JsonEncodeFactory.GetAutomaticCropping(this.Rotation, this.FlipHorizontal, this.FlipVertical, this.MainViewModel.SelectedTitle.Title);

this.CropTop = autoCropping.Top;
this.CropBottom = autoCropping.Bottom;
this.CropLeft = autoCropping.Left;
this.CropRight = autoCropping.Right;
}

this.AutomaticChange = oldAutoValue;
}

private void EnsureResolutionPopulatedIfRequired()
{
if (!this.AllowEmptyResolution && (this.Width == 0 || this.Height == 0))
Expand Down

0 comments on commit 1abdf0d

Please sign in to comment.