Can I convert image/bitmap to writeablebitmap?

2020-03-30 04:01发布

I have two bitmap images that i would like to merge together. I found that I can do that with writeablebitmap but how do I first convert these images to writeablebitmaps?

UPDATE: I could not find out a way to convert bitmaps to writeable bitmap directly so what I did was to write my bitmap in isolated storage and read it again in a stream object. After which the code given below by Xyroid can be used to merge the images and convert the merged image to bitmap.

2条回答
Viruses.
2楼-- · 2020-03-30 04:17

I've done a lot of work with Silverlight, which I believe the store apps are similar to in many ways.

Consider this constructor:

WriteableBitmap(BitmapSource)
- Initializes a new instance of the WriteableBitmap class using the
  provided BitmapSource.

The next question is, how to get 'BitmapSource' from an image? You can do it this way:

(BitmapSource)MyImage.Source

Although this assumes that the source (which is of type 'ImageSource') is actually a 'BitmapSource' instance. That said, as of Silverlight 5.0, the only class derived from ImageSource in Silverlight is BitmapSource, so I doubt that would be an issue.

So something like this may work:

WriteableBitmap((BitmapSource)MyImage.Source)

Finally, there's an open source project here which may be of some help: http://writeablebitmapex.codeplex.com/

查看更多
成全新的幸福
3楼-- · 2020-03-30 04:35

Here I am giving you the code to merge two images. WinRT's WriteableBitmap is different, the constructor of it takes height and width as argument. I have used WriteableBitmapEx for some functions.

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;
}

Please note you have to add System.Runtime.InteropServices.WindowsRuntime namespace.

UPDATE 1

Suppose if you have already two BitmapImage img1 and img2, then do like this

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;
}
查看更多
登录 后发表回答