【问题标题】:Transform a colored image to a grayscale image using XAML?使用 XAML 将彩色图像转换为灰度图像?
【发布时间】:2018-02-18 04:38:01
【问题描述】:

最好使用 XAML,

我需要动态地在彩色图像上从下到上应用灰度滤镜。也就是说,我希望能够以编程方式更改应用于我的图像的灰度滤镜的偏移值。

例如,我想以编程方式将图像的 50% 设置为彩色(从图像底部到其中间),而将其他 50% 的图像设置为灰度(例如,从图像的中间图片到顶部)。

我已经阅读了很多不同的答案,尝试了很多不同的事情,并且想了很多不同的方法来做到这一点。

  • 我可以有两张图像,一张在另一张上面。一个是灰度的,另一个是彩色的。然后,我将以编程方式更改灰度图像的大小,以便其下方的彩色图像部分显示并为用户创建一种半半视图。

但是,此解决方案提出了一个我似乎无法解决的问题。更改灰度图像的高度值时,由于“拉伸”属性设置为“均匀”(我不希望更改为“无”),图像会自动重新缩放。

  • 另一种方法是通过编程更改图像的颜色像素。过去我在这方面取得了一些成功,但是,这对于我在这里尝试做的事情来说太慢了(理想情况下,我会将图像的颜色从灰度更改为选择的图像的原始颜色用户每 50 毫秒,直到达到某个高度)。

  • 第三种方法是在图像上应用不透明蒙版并使用LinearGradientBrush 将偏移值更改为所需位置。这是我目前正在使用的代码,它可以工作,但只需将灰色应用于图像,而不会将图像的原始颜色更改为灰度(导致一种褪色的彩色图像):

XAML:

<Image x:Name="myImage" HorizontalAlignment="Left" VerticalAlignment="Top" Source="C:\Users\Clement\Desktop\test.png" Canvas.Left="159" Canvas.Top="81" Width="500" Height="375" >
            <Image.OpacityMask>
                <LinearGradientBrush EndPoint="0.5,0" MappingMode="RelativeToBoundingBox" StartPoint="0.5,1">
                    <GradientStop x:Name="myImageLinearGradientBrushStop" Color="Black"/>
                    <GradientStop Color="Transparent" Offset="1"/>
                </LinearGradientBrush>
            </Image.OpacityMask>
</Image>

代码隐藏(在每 50 毫秒重复一次的 timerEventProcessor 中):

myImageLinearGradientBrushStop.Offset = percent * 0.01;

如前所述,我浏览了很多不同的网站,阅读了很多类似的问题,尝试了很多不同的答案,但仍然无法令人满意地解决问题。

【问题讨论】:

  • 听起来像是想要做出自己的影响,虽然我不知道你是否可以绑定到它们,或者从图像派生并可能在位图级别添加渐变
  • 嗨,Michael,感谢您抽出宝贵时间回答我的问题。在 XAML 中将我自己的灰度效果绑定到我的图像控件确实是我想要实现的。但是,不幸的是,我不确定从哪里开始。如果您有任何想法,请告诉我。

标签: c# wpf image xaml grayscale


【解决方案1】:

下面的 XAML 使用具有两行的 Grid 来在彼此的顶部显示两个图像。顶部 Image 的 Width 和 Heigh 绑定到底部 Image 的大小,它跨越两个 Grid 行。内部 Grid 用于剪切顶部图像。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Image x:Name="image" Grid.RowSpan="2" Source="..."/>

    <Grid>
        <Image Width="{Binding ActualWidth, ElementName=image}"
               Height="{Binding ActualHeight, ElementName=image}"
               HorizontalAlignment="Center" VerticalAlignment="Top">
            <Image.Source>
                <FormatConvertedBitmap Source="{Binding Source, ElementName=image}"
                                       DestinationFormat="Gray8"/>
            </Image.Source>
        </Image>
    </Grid>
</Grid>

【讨论】:

  • 嗨 Clemens,非常感谢您为我调查这个问题。不幸的是,您的 sn-p 代码并没有真正解决我的问题。第二张图像(灰度)似乎没有正确生成并且似乎不可见。但是,我一直在考虑完成此任务的第 4 种方法: - 生成 101 个图像(原始彩色图像高度的 0 到 100%)。我会说这可能需要一分钟,具体取决于用于创建灰度图像的算法。 - 将这些图像存储在列表中。 - 根据所需的高度百分比在正确的图像之间快速切换。
  • “似乎没有正确生成并且似乎不可见”不是一个非常清晰的问题描述。 FormatConvertedBitmap 对我来说很好。
  • 嗨克莱门斯,如果我没有成功地表达自己的意思,我深表歉意。我所说的“第二张图像(灰度)似乎没有正确生成并且似乎不可见”的意思是,使用您的代码,我可以通过替换“Source =”来显示我希望显示的图像。 ."" 具有正确的图像路径,但是,应该是 Gray8 的第二个图像不会显示在表单上(仅表示与原始图像相同大小的空矩形)。不过,现在想来,可能是因为我使用的图片(透明背景的 png)。
  • 如果您使用上面的确切 XAML,如果是彩色图像,它将在顶部显示灰度图像的上半部分(即第一行)。通过改变相对行高,可以改变可见分数。
  • 嗨克莱门斯,我让它工作了!但是,我仍然在努力解决两件事:在不缩小图像的情况下更改灰度图像的高度(例如,如果我将 Height="{Binding ActualHeight, ElementName=image}" 更改为 Height="200" ,它会重新缩放图像到一个较小的,这违背了将两个图像放在一起的目的,但我认为我一定做错了)。其次,我相信这里更困难的是,Gray8 图像失去了透明度,这在我的场景中是一个问题。无论如何,非常感谢您迄今为止的所有帮助!
【解决方案2】:

感谢 Clemens 的帮助,我得以解决我的问题!

这是最终的 XAML 代码,供可能感兴趣的人使用:

<Grid Width="500" Height="375">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Image x:Name="image" Grid.RowSpan="2" Source="C:\Users\Clement\Desktop\test_image.png" />

            <Grid Margin="0,0,0,166" Grid.RowSpan="2">
                <Image Width="{Binding ActualWidth, ElementName=image}"
           Height="{Binding ActualHeight, ElementName=image}"
           HorizontalAlignment="Center" VerticalAlignment="Top">
                    <Image.Source>
                        <FormatConvertedBitmap Source="{Binding Source, ElementName=image}"
                                   DestinationFormat="Gray8"/>
                    </Image.Source>
                    <Image.OpacityMask>
                        <ImageBrush ImageSource="C:\Users\Clement\Desktop\test_image.png"/>
                    </Image.OpacityMask>
                </Image>
            </Grid>
        </Grid>

这里我只是将 OpacityMask 添加到 Gray8 图像以恢复其透明度。

编码愉快!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-24
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 2015-10-07
    • 1970-01-01
    相关资源
    最近更新 更多