pg90
pg90

Reputation: 433

Windows 8 - Save Image in XAML as local file ( inside Application folder )

In my Windows store application, i am displaying a picture using Image control in XAML. Source of the Image control is set, code wise using WriteableBitmap. I am trying to send this image as attachment in email. Is there any easy way for that? I am trying to save that image locally( within application ) and attach that saved image to email. But not able to save locally. Any help is appreciated.

Here is the code.

bitmap = await WriteableBitmapRenderExtensions.Render(dataCanvas);
image.Source = bitmap;

dataCanvas is a Canvas control consists of two images, one place above another. Actually i have to place a sunglass top of users face and display it as another image in xaml. Also email that image.

Upvotes: 1

Views: 1699

Answers (2)

Filip Skakun
Filip Skakun

Reputation: 31724

Check out the WriteableBitmapSaveExtensions class in WinRT XAML Toolkit for all the SaveToFile() extension methods you can use to save your WriteableBitmap.

The core one is this:

public static async Task SaveToFile(
    this WriteableBitmap writeableBitmap,
    StorageFile outputFile,
    Guid encoderId)
{
    Stream stream = writeableBitmap.PixelBuffer.AsStream();
    byte[] pixels = new byte[(uint)stream.Length];
    await stream.ReadAsync(pixels, 0, pixels.Length);

    using (var writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
        encoder.SetPixelData(
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Premultiplied,
            (uint)writeableBitmap.PixelWidth,
            (uint)writeableBitmap.PixelHeight,
            96,
            96,
            pixels);
        await encoder.FlushAsync();

        using (var outputStream = writeStream.GetOutputStreamAt(0))
        {
            await outputStream.FlushAsync();
        }
    }
}

You can get the encoder ID using an overload of the method:

public static async Task<StorageFile> SaveToFile(
    this WriteableBitmap writeableBitmap,
    StorageFolder storageFolder,
    string fileName,
    CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
{
    StorageFile outputFile =
        await storageFolder.CreateFileAsync(
            fileName,
            options);

    Guid encoderId;

    var ext = Path.GetExtension(fileName);

    if (new[] { ".bmp", ".dib" }.Contains(ext))
    {
        encoderId = BitmapEncoder.BmpEncoderId;
    }
    else if (new[] { ".tiff", ".tif" }.Contains(ext))
    {
        encoderId = BitmapEncoder.TiffEncoderId;
    }
    else if (new[] { ".gif" }.Contains(ext))
    {
        encoderId = BitmapEncoder.GifEncoderId;
    }
    else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
    {
        encoderId = BitmapEncoder.JpegEncoderId;
    }
    else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
    {
        encoderId = BitmapEncoder.JpegXREncoderId;
    }
    else //if (new [] {".png"}.Contains(ext))
    {
        encoderId = BitmapEncoder.PngEncoderId;
    }

    await writeableBitmap.SaveToFile(outputFile, encoderId);

    return outputFile;
}

Upvotes: 3

Mitch
Mitch

Reputation: 22311

Any subclass of BitmapSource (including WritableBitmap) can be passed to a BitmapEncoder. A BitmapEncoder takes a Stream to which the encoded JPEG, PNG or other image is written.

You can then use a mailer library to reference the stream used by the encoder, or use the Share contract, and pass the stream directly.

Example:

var bitmap = new WritableBitmap();

// ... draw your bitmap

var tempPath = // path to where you want to save (probably in your appx temp);
var encoder = new PngBitmapEncoder();

encoder.Frames.Add(bitmap);

using (var fs = new FileStream(tempPath))
{
    encoder.Save(fs);
}

// use the image saved to tempPath
// http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh871370.aspx

Upvotes: -1

Related Questions