c# - 我可以将图像/位图转换为可写位图吗?

标签 c# windows-runtime windows-store-apps

我有两个位图图像,我想将它们合并在一起。我发现我可以用 writeablebitmap 做到这一点,但我如何首先将这些图像转换为 writeablebitmaps?

更新:我找不到直接将位图转换为可写位图的方法,所以我所做的是将我的位图写入隔离存储并在流对象中再次读取它。之后,可以使用 Xyroid 下面给出的代码来合并图像并将合并后的图像转换为位图。

最佳答案

在这里,我为您提供了合并两张图片的代码。 WinRT 的 WriteableBitmap 则不同,它的构造函数将高度和宽度作为参数。我用过WriteableBitmapEx对于某些功能。

XAML

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Canvas x:Name="BaseCanvas" Width="683" Height="768">
        <Image Source="Assets/img1.png" />
        <Image Source="Assets/img2.png" Canvas.Top="308" />
    </Canvas>
    <Image x:Name="imgTarget" Grid.Column="1" Stretch="None"/>
</Grid>

C#

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    StorageFile destiFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("Merged.png", CreationCollisionOption.ReplaceExisting);

    WriteableBitmap wb;

    wb = await Render();

    using (IRandomAccessStream stream = await destiFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
            BitmapEncoder.PngEncoderId, stream);
        Stream pixelStream = wb.PixelBuffer.AsStream();
        byte[] pixels = new byte[pixelStream.Length];
        await pixelStream.ReadAsync(pixels, 0, pixels.Length);

        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
            (uint)wb.PixelWidth, (uint)wb.PixelHeight, 96.0, 96.0, pixels);
        await encoder.FlushAsync();
    }

    var bitmp = new BitmapImage();
    using (var strm = await destiFile.OpenReadAsync())
    {
        bitmp.SetSource(strm);
        imgTarget.Source = bitmp;
    }
}

private async Task<WriteableBitmap> Render()
{
    var Assets = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");

    StorageFile file1 = await Assets.GetFileAsync("img1.png");
    StorageFile file2 = await Assets.GetFileAsync("img2.png");

    BitmapImage i1 = new BitmapImage();
    BitmapImage i2 = new BitmapImage();

    using (IRandomAccessStream strm = await file1.OpenReadAsync())
    {
        i1.SetSource(strm);
    }

    using (IRandomAccessStream strm = await file2.OpenReadAsync())
    {
        i2.SetSource(strm);
    }

    WriteableBitmap img1 = new WriteableBitmap(i1.PixelWidth, i1.PixelHeight);
    WriteableBitmap img2 = new WriteableBitmap(i2.PixelWidth, i2.PixelHeight);
    using (IRandomAccessStream strm = await file1.OpenReadAsync())
    {
        img1.SetSource(strm);
    }

    using (IRandomAccessStream strm = await file2.OpenReadAsync())
    {
        img2.SetSource(strm);
    }


    WriteableBitmap destination = new WriteableBitmap((int)(img1.PixelWidth > img2.PixelWidth ? img1.PixelWidth : img2.PixelWidth), (int)(img1.PixelHeight + img1.PixelHeight));
    destination.Clear(Colors.White);
    destination.Blit(new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight),img1,new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight));
    destination.Blit(new Rect(0, (int)img1.PixelHeight, (int)img2.PixelWidth, (int)img2.PixelHeight), img2, new Rect(0, 0, (int)img2.PixelWidth, (int)img2.PixelHeight));
    return destination;
}

请注意,您必须添加 System.Runtime.InteropServices.WindowsRuntime 命名空间。

更新 1

假设你已经有两个BitmapImage img1img2,那么这样做

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    StorageFile destiFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("Merged.png", CreationCollisionOption.ReplaceExisting);

    WriteableBitmap wb;

    wb = await Render();

    using (IRandomAccessStream stream = await destiFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(
            BitmapEncoder.PngEncoderId, stream);
        Stream pixelStream = wb.PixelBuffer.AsStream();
        byte[] pixels = new byte[pixelStream.Length];
        await pixelStream.ReadAsync(pixels, 0, pixels.Length);

        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
            (uint)wb.PixelWidth, (uint)wb.PixelHeight, 96.0, 96.0, pixels);
        await encoder.FlushAsync();
    }

    var bitmp = new BitmapImage();
    using (var strm = await destiFile.OpenReadAsync())
    {
        bitmp.SetSource(strm);
        imgTarget.Source = bitmp;
    }
}

private async Task<WriteableBitmap> Render()
{  
    WriteableBitmap destination = new WriteableBitmap((int)(img1.PixelWidth > img2.PixelWidth ? img1.PixelWidth : img2.PixelWidth), (int)(img1.PixelHeight + img1.PixelHeight));
    destination.Clear(Colors.White);
    destination.Blit(new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight),img1,new Rect(0, 0, (int)img1.PixelWidth, (int)img1.PixelHeight));
    destination.Blit(new Rect(0, (int)img1.PixelHeight, (int)img2.PixelWidth, (int)img2.PixelHeight), img2, new Rect(0, 0, (int)img2.PixelWidth, (int)img2.PixelHeight));
    return destination;
}

关于c# - 我可以将图像/位图转换为可写位图吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15729164/

相关文章:

c# - 进程没有以正确的用户名开头

c# - Linq - 获取数组最后一个非零数的索引

c# - 如何在 C# 中捕获 Windows 应用商店应用程序的窗口内容

c# - 以编程方式关闭 MessageDialog

c# - 具有搜索模式的 StorageFolder.GetFilesAsync() 方法?

c# - C# 任务是否在一个内核上运行?

c# - 无法确定条件表达式的类型,因为 System.DateTime 和 null 之间没有隐式转换

xaml - 按钮样式看起来像应用栏按钮

c++ - Windows Metro 模式 (C++) : Waiting on semaphore (WaitForSingleObjectEx): failed with Access Denied [partially solved]