Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Imagescaling looking bad in Ribbon

I'm populating a Ribbon (WPF) programmatically based on MS RibbonControlsLibrary (3.5.41019.1). All images (most noticeable large images) looks very bad and "pixly":

Screenshot from 2 Ribbon

  • The top screenshot is from the "pixly" Ribbon (Image scaling looking bad)
  • The bottom screenshot is taken from the same area in a window based on WinForms with the same source images (Image scaling looking good)
  • All images are saved in 32 bit PNG 48x48

I have tried to set the BitmapScalingMode to "HighQuality" without any effect, source code:

BitmapImage img = new BitmapImage();
try
{
    Uri uri = new Uri("pack://application:,,,/UIMainWindow;component/Resources/" + iPictureName);                
    img.BeginInit();
    img.SetValue(BitmapImage.CacheOptionProperty, BitmapCacheOption.OnLoad);
    RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.HighQuality);
    img.UriSource = uri;
    img.EndInit();
    img.Freeze();
}
catch (Exception ex)
{
    throw new Exception("Creation of image failed: " + ex.Message, ex);
}

Question Why is the scaling of the images looking bad? And how can I solve this?

like image 563
vanos Avatar asked Nov 14 '22 04:11

vanos


1 Answers

None of the other answers above worked for me so I started my own investigation. Resizing the images to 32x32 almost fixed the problem, but we have users with different DPI settings and the images wouldn't scale correctly on their machines. I should also note that I'm using the System.Windows.Controls.Ribbon assemly, which may behave a little differently than the RibbonControlsLibrary.

I found that the default ControlTemplate for the RibbonButton has specifically specified NearestNeighbor as the bitmap scaling option. The good news is that it's easy to override this control template by dropping a style into your Window's resources. The slightly bad news is that the control template is pretty verbose. I dumped the default ControlTemplate for the RibbonButton on my system to a file and just changed the bitmap scaling option.

First, you'll need this namespace declaration at the top of your file if you don't have it already:

xmlns:s="clr-namespace:System;assembly=mscorlib"

Then put this Style in your Window's resources in order to override the RibbonButton appearance:

<Style TargetType="RibbonButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RibbonButton">
                <Border BorderThickness="{TemplateBinding Border.BorderThickness}" CornerRadius="{TemplateBinding RibbonControlService.CornerRadius}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="OuterBorder" SnapsToDevicePixels="True">
                    <Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" CornerRadius="{TemplateBinding RibbonControlService.CornerRadius}" BorderBrush="#00FFFFFF" Name="InnerBorder">
                        <StackPanel Name="StackPanel">
                            <Image Source="{TemplateBinding RibbonControlService.LargeImageSource}" Name="PART_Image" Width="32" Height="32" Margin="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=Ribbon, ResourceId=LargeImageMargin}}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="Center" RenderOptions.BitmapScalingMode="HighQuality" />
                            <Grid Name="Grid" HorizontalAlignment="Center" VerticalAlignment="Center">
                                <RibbonTwoLineText TextAlignment="Center" LineHeight="13" LineStackingStrategy="BlockLineHeight" Text="{TemplateBinding RibbonControlService.Label}" Name="TwoLineText" Margin="1,1,1,0" HorizontalAlignment="Center" VerticalAlignment="Top" />
                            </Grid>
                        </StackPanel>
                    </Border>
                </Border>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Large">
                        <Setter Property="FrameworkElement.MinWidth">
                            <Setter.Value>
                                <s:Double>44</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.Height">
                            <Setter.Value>
                                <s:Double>66</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.MinHeight" TargetName="Grid">
                            <Setter.Value>
                                <s:Double>26</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="RibbonTwoLineText.HasTwoLines" TargetName="TwoLineText">
                            <Setter.Value>
                                <s:Boolean>True</s:Boolean>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Small">
                        <Setter Property="FrameworkElement.Height">
                            <Setter.Value>
                                <s:Double>22</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.Margin" TargetName="PART_Image">
                            <Setter.Value>
                                <Thickness>1,0,1,0</Thickness>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Image.Source" TargetName="PART_Image">
                            <Setter.Value>
                                <Binding Path="SmallImageSource" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.Width" TargetName="PART_Image">
                            <Setter.Value>
                                <s:Double>16</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.Height" TargetName="PART_Image">
                            <Setter.Value>
                                <s:Double>16</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.HorizontalAlignment" TargetName="TwoLineText">
                            <Setter.Value>
                                <x:Static Member="HorizontalAlignment.Left" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="FrameworkElement.Margin" TargetName="TwoLineText">
                            <Setter.Value>
                                <Thickness>1,1,1,1</Thickness>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="StackPanel.Orientation" TargetName="StackPanel">
                            <Setter.Value>
                                <x:Static Member="Orientation.Horizontal" />
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Small" />
                            <Condition Binding="{Binding Path=IsInQuickAccessToolBar, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="FrameworkElement.Height">
                            <Setter.Value>
                                <s:Double>NaN</s:Double>
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <DataTrigger Binding="{Binding Path=ControlSizeDefinition.IsLabelVisible, RelativeSource={RelativeSource Mode=Self}}" Value="False">
                        <Setter Property="UIElement.Visibility" TargetName="TwoLineText">
                            <Setter.Value>
                                <x:Static Member="Visibility.Collapsed" />
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=ControlSizeDefinition.ImageSize, RelativeSource={RelativeSource Mode=Self}}" Value="Collapsed">
                        <Setter Property="UIElement.Visibility" TargetName="PART_Image">
                            <Setter.Value>
                                <x:Static Member="Visibility.Collapsed" />
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <Trigger Property="UIElement.IsMouseOver">
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="MouseOverBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="MouseOverBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="InnerBorder">
                            <Setter.Value>
                                <SolidColorBrush>#80FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>True</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <Trigger Property="UIElement.IsKeyboardFocused">
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="FocusedBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="FocusedBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="InnerBorder">
                            <Setter.Value>
                                <SolidColorBrush>#80FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>True</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <Trigger Property="ButtonBase.IsPressed">
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="PressedBackground" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="PressedBorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="InnerBorder">
                            <Setter.Value>
                                <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>True</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <Trigger Property="RibbonControlService.IsInControlGroup">
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <Binding Path="Ribbon.BorderBrush" RelativeSource="{RelativeSource Mode=TemplatedParent}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderThickness" TargetName="OuterBorder">
                            <Setter.Value>
                                <Thickness>0,0,1,0</Thickness>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="OuterBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="InnerBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>True</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <Trigger Property="UIElement.IsEnabled">
                        <Setter Property="UIElement.Opacity" TargetName="PART_Image">
                            <Setter.Value>
                                <s:Double>0.5</s:Double>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <SolidColorBrush>#FF9E9E9E</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Trigger.Value>
                            <s:Boolean>False</s:Boolean>
                        </Trigger.Value>
                    </Trigger>
                    <DataTrigger Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True">
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.MenuTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="OuterBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True" />
                            <Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource Mode=TemplatedParent}, FallbackValue=false}" Value="True" />
                            <Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="OuterBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="InnerBorder">
                            <Setter.Value>
                                <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlLightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="OuterBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="InnerBorder">
                            <Setter.Value>
                                <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsPressed, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Panel.Background" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlDarkBrushKey}" />
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Border.CornerRadius" TargetName="OuterBorder">
                            <Setter.Value>
                                <CornerRadius>0,0,0,0</CornerRadius>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsInControlGroup, RelativeSource={RelativeSource Mode=Self}}" Value="True" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Border.BorderBrush" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.ControlLightLightBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Path=IsEnabled, RelativeSource={RelativeSource Mode=Self}}" Value="False" />
                            <Condition Binding="{Binding Path=(SystemParameters.HighContrast)}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="TextElement.Foreground" TargetName="OuterBorder">
                            <Setter.Value>
                                <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                            </Setter.Value>
                        </Setter>
                    </MultiDataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
like image 53
RogerN Avatar answered Dec 09 '22 03:12

RogerN