繁体   English   中英

在WPF中创建一个复合BitmapImage

[英]Create a Composite BitmapImage in WPF

我想将三个BitmapImage缝合在一起以创建一个合成图像。 将要缝合在一起的三个图像按以下方式对齐:

图像的类型为System.Windows.Media.Imaging.BitmapImage。 我看过以下解决方案 ,但它使用System.Drawing.Graphics进行拼接。 我发现每次我想将它们映射在一起时,将我的BitmapImage转换为System.Drawing.Bitmap是不直观的。

是否有一种简单的方法将三个System.Windows.Media.Imaging.BitmapImage类型的图像拼接在一起?

除了其他答案中描述的选项之外,下面的代码将三个BitmapSource缝合到一个WriteableBitmap中:

public BitmapSource StitchBitmaps(BitmapSource b1, BitmapSource b2, BitmapSource b3)
{
    if (b1.Format != b2.Format || b1.Format != b3.Format)
    {
        throw new ArgumentException("All input bitmaps must have the same pixel format");
    }

    var width = Math.Max(b1.PixelWidth, b2.PixelWidth + b3.PixelWidth);
    var height = b1.PixelHeight + Math.Max(b2.PixelHeight, b3.PixelHeight);
    var wb = new WriteableBitmap(width, height, 96, 96, b1.Format, null);
    var stride1 = (b1.PixelWidth * b1.Format.BitsPerPixel + 7) / 8;
    var stride2 = (b2.PixelWidth * b2.Format.BitsPerPixel + 7) / 8;
    var stride3 = (b3.PixelWidth * b3.Format.BitsPerPixel + 7) / 8;
    var size = b1.PixelHeight * stride1;
    size = Math.Max(size, b2.PixelHeight * stride2);
    size = Math.Max(size, b3.PixelHeight * stride3);

    var buffer = new byte[size];
    b1.CopyPixels(buffer, stride1, 0);
    wb.WritePixels(
        new Int32Rect(0, 0, b1.PixelWidth, b1.PixelHeight),
        buffer, stride1, 0);

    b2.CopyPixels(buffer, stride2, 0);
    wb.WritePixels(
        new Int32Rect(0, b1.PixelHeight, b2.PixelWidth, b2.PixelHeight),
        buffer, stride2, 0);

    b3.CopyPixels(buffer, stride3, 0);
    wb.WritePixels(
        new Int32Rect(b2.PixelWidth, b1.PixelHeight, b3.PixelWidth, b3.PixelHeight),
        buffer, stride3, 0);

    return wb;
}

这实际上取决于所需的输出类型。 这里有一些选择。

DrawingVisual

如果只需要将它们呈现为视觉效果,则可以使用DrawingVisual并呈现三个图像。 然后,可以根据您的用例(例如,使用VisualBrush )以各种方式呈现视觉效果。

Rect bounds = new Rect(0.0, 0.0, 400.0, 300.0);
DrawingVisual visual = new DrawingVisual();
DrawingContext dc = visual.RenderOpen();
dc.DrawImage(mImage, new Rect(bounds.X, bounds.Y, bounds.Width, bounds.Height * 0.5));
dc.DrawImage(mImage, new Rect(bounds.X, bounds.Y + bounds.Height * 0.5, bounds.Width * 0.75, bounds.Height * 0.5));
dc.DrawImage(mImage, new Rect(bounds.X + bounds.Width * 0.75, bounds.Y + bounds.Height * 0.5, bounds.Width * 0.25, bounds.Height * 0.5));
dc.Close();

自订元素

如果需要可以直接放置在UI中的元素,则可以创建扩展FrameworkElement的自定义元素。

class CustomElement : FrameworkElement
{
    public ImageSource Image1
    {
        get { return (ImageSource)GetValue(Image1Property); }
        set { SetValue(Image1Property, value); }
    }
    public static readonly DependencyProperty Image1Property = DependencyProperty.Register("Image1", typeof(ImageSource), typeof(CustomElement),
        new FrameworkPropertyMetadata((ImageSource)null, FrameworkPropertyMetadataOptions.AffectsRender));

    public ImageSource Image2
    {
        get { return (ImageSource)GetValue(Image2Property); }
        set { SetValue(Image2Property, value); }
    }
    public static readonly DependencyProperty Image2Property = DependencyProperty.Register("Image2", typeof(ImageSource), typeof(CustomElement),
        new FrameworkPropertyMetadata((ImageSource)null, FrameworkPropertyMetadataOptions.AffectsRender));

    public ImageSource Image3
    {
        get { return (ImageSource)GetValue(Image3Property); }
        set { SetValue(Image3Property, value); }
    }
    public static readonly DependencyProperty Image3Property = DependencyProperty.Register("Image3", typeof(ImageSource), typeof(CustomElement),
        new FrameworkPropertyMetadata((ImageSource)null, FrameworkPropertyMetadataOptions.AffectsRender));

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawImage(Image1, new Rect(0.0, 0.0, ActualWidth, ActualHeight * 0.5));
        drawingContext.DrawImage(Image2, new Rect(0.0, ActualHeight * 0.5, ActualWidth * 0.75, ActualHeight * 0.5));
        drawingContext.DrawImage(Image3, new Rect(ActualWidth * 0.75, ActualHeight * 0.5, ActualWidth * 0.25, ActualHeight * 0.5));
    }
}

然后,您可以像这样使用它:

<local:CustomElement
    Image1="{Binding SomeImage}"
    Image2="{Binding SomeOtherImage}"
    Image3="http://stackoverflow.com/favicon.ico" />

网格中的图像

您始终可以选择在Grid中放置三个Image控件。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Image
        Grid.ColumnSpan="2"
        Source="{Binding SomeImage}" />
    <Image
        Grid.Row="1"
        Source="{Binding SomeOtherImage}" />
    <Image
        Grid.Row="1"
        Grid.Column="1"
        Source="http://stackexchange.com/favicon.ico" />
</Grid>

创建一个图像源

如果出于某种原因需要将三个图像组合到一个ImageSource中,则可以渲染为DrawingVisual (如上所述),然后将该视觉效果渲染为RenderTargetBitmap

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM